diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst old mode 100644 new mode 100755 index 6c07c584d3..3c580cee19 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -162,6 +162,11 @@ These are working configurations for LAN interfaces of popular boards:: lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5), phy_type=network.PHY_IP101, phy_addr=1) +UDP MULTICAST +^^^^^^^^^^^^^ + +See client/server example in the :ref:`esp32_udp_multicast` tutorial. + Delay and timing ---------------- diff --git a/docs/esp32/tutorial/index.rst b/docs/esp32/tutorial/index.rst index c6242d731f..dbd90d16c0 100644 --- a/docs/esp32/tutorial/index.rst +++ b/docs/esp32/tutorial/index.rst @@ -16,8 +16,8 @@ to ``__. .. toctree:: :maxdepth: 1 - :numbered: intro.rst pwm.rst peripheral_access.rst + udp_multicast.rst diff --git a/docs/esp32/tutorial/udp_multicast.rst b/docs/esp32/tutorial/udp_multicast.rst new file mode 100644 index 0000000000..437b8706f1 --- /dev/null +++ b/docs/esp32/tutorial/udp_multicast.rst @@ -0,0 +1,27 @@ +.. _esp32_udp_multicast: + +UDP MULTICAST +============= + +Use UDP MULTICAST connections to communicate between two devices in different networks +with IP-addresses 172.16.55.55 and 192.168.44.44. + +Run `udp_multicast_client.py `_ on one device. +Client send GET and receive ACK from the server. +Output is:: + + GET to ('224.0.0.111', 5555) sent "client_ip:172.16.55.55 mac:b8-d6-1a-5a-c2-e4" + ACK from ('192.168.44.44', 5555) received "server_ip:192.168.44.44 mac:24-6f-28-7a-f3-9c" + GET to ('224.0.0.111', 5555) sent "client_ip:172.16.55.55 mac:b8-d6-1a-5a-c2-e4" + ACK from ('192.168.44.44', 5555) received "server_ip:192.168.44.44 mac:24-6f-28-7a-f3-9c" + ... + +Run `udp_multicast_server.py `_ on another device. +Server receive GET and send ACK to the client. +Output is:: + + GET from ('172.16.55.55', 5555) received "client_ip:172.16.55.55 mac:b8-d6-1a-5a-c2-e4" + ACK to ('224.0.0.111', 5555) sent "server_ip:192.168.44.44 mac:24-6f-28-7a-f3-9c" + GET from ('172.16.55.55', 5555) received "client_ip:172.16.55.55 mac:b8-d6-1a-5a-c2-e4" + ACK to ('224.0.0.111', 5555) sent "server_ip:192.168.44.44 mac:24-6f-28-7a-f3-9c" + ... diff --git a/examples/network/udp_multicast_client.py b/examples/network/udp_multicast_client.py new file mode 100755 index 0000000000..d7d12e01a6 --- /dev/null +++ b/examples/network/udp_multicast_client.py @@ -0,0 +1,70 @@ +# udp_multicast_client.py:: + +import network, socket, errno, struct, time + +print("connect to AP") + +SSID = "SSID" +PASSWORD = "PASSWORD" + +wlan = network.WLAN(network.STA_IF) +# class B network +wlan.ifconfig(("172.16.55.55", "255.255.255.0", "172.16.55.1", "172.16.55.1")) +wlan.active(True) +wlan.connect(SSID, PASSWORD) +while not wlan.isconnected(): + pass + +print("udp_multicast_client.py") +print("client send GET and receive ACK from the server") + + +def inet_aton(str_addr): + return bytes(map(int, str_addr.split("."))) + + +# TIMEOUT = None # block +# TIMEOUT = 5 # seconds +TIMEOUT = 0 # non blocking + +MULTICAST_IP = "224.0.0.111" +PORT = 5555 +sockaddr = (MULTICAST_IP, PORT) + +wlan = network.WLAN(network.STA_IF) +client_ip = wlan.ifconfig()[0] + +skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP +skt.settimeout(None) +skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +skt.setsockopt( + socket.IPPROTO_IP, + socket.IP_ADD_MEMBERSHIP, + struct.pack(">4s4s", inet_aton(MULTICAST_IP), inet_aton(client_ip)), +) # join to the multicast address +skt.bind(sockaddr) # not skt.connect(sockaddr) +skt.settimeout(TIMEOUT) + +t = 0 +while True: + try: + if time.time() - t >= 3: + t = time.time() + + mac = wlan.config("mac") + str_to_send = f"client_ip:{client_ip}\t mac:{'-'.join(map('{:02x}'.format, mac))}" + skt.sendto(str_to_send, sockaddr) + print(f'GET to {sockaddr}\t sent "{str_to_send}"') + + received, addr = skt.recvfrom(1024) + if received: + print(f'ACK from {addr}\t received "{received.decode()}"') + except OSError as e: + if e.args[0] in (errno.EAGAIN, errno.ETIMEDOUT): + pass + else: + try: + skt.close() + except: + pass + raise (e) diff --git a/examples/network/udp_multicast_server.py b/examples/network/udp_multicast_server.py new file mode 100755 index 0000000000..ffdb756e0c --- /dev/null +++ b/examples/network/udp_multicast_server.py @@ -0,0 +1,66 @@ +# udp_multicast_server.py:: + +import network, socket, errno, struct, time + +print("connect to AP") + +SSID = "SSID" +PASSWORD = "PASSWORD" + +wlan = network.WLAN(network.STA_IF) +# class C network +wlan.ifconfig(("192.168.44.44", "255.255.255.0", "192.168.44.1", "192.168.44.1")) +wlan.active(True) +wlan.connect(SSID, PASSWORD) +while not wlan.isconnected(): + pass + +print("udp_multicast_server.py") +print("server receive GET and send ACK to the client") + + +def inet_aton(str_addr): + return bytes(map(int, str_addr.split("."))) + + +# TIMEOUT = None # block +# TIMEOUT = 5 # seconds +TIMEOUT = 0 # non blocking + +MULTICAST_IP = "224.0.0.111" +PORT = 5555 +sockaddr = (MULTICAST_IP, PORT) + +wlan = network.WLAN(network.STA_IF) +server_ip = wlan.ifconfig()[0] + +skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP +skt.settimeout(None) +skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +skt.setsockopt( + socket.IPPROTO_IP, + socket.IP_ADD_MEMBERSHIP, + struct.pack(">4s4s", inet_aton(MULTICAST_IP), inet_aton(server_ip)), +) # join to the multicast address +skt.bind(sockaddr) +skt.settimeout(TIMEOUT) + +while True: + try: + received, addr = skt.recvfrom(1024) + if received: + print(f'GET from {addr}\t received "{received.decode()}"') + + mac = wlan.config("mac") + str_to_send = f"server_ip:{server_ip}\t mac:{'-'.join(map('{:02x}'.format, mac))}" + skt.sendto(str_to_send, sockaddr) + print(f'ACK to {sockaddr}\t sent "{str_to_send}"') + except OSError as e: + if e.args[0] in (errno.EAGAIN, errno.ETIMEDOUT): + pass + else: + try: + skt.close() + except: + pass + raise (e)