Skip to content

Commit

Permalink
docs/esp32: UDP multicast client/server example.
Browse files Browse the repository at this point in the history
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
  • Loading branch information
IhorNehrutsa authored and IhorNehrutsa committed Dec 10, 2023
1 parent e1a7aa2 commit b29c78f
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 1 deletion.
7 changes: 6 additions & 1 deletion docs/esp32/quickref.rst
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ These are working configurations for LAN interfaces of popular boards::
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)

lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
phy_type=network.PHY_LAN8720, phy_addr=0,
ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT)

Expand All @@ -161,6 +161,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
----------------

Expand Down
1 change: 1 addition & 0 deletions docs/esp32/tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ to `<https://www.python.org>`__.
intro.rst
pwm.rst
peripheral_access.rst
udp_multicast.rst
141 changes: 141 additions & 0 deletions docs/esp32/tutorial/udp_multicast.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
.. _esp32_udp_multicast:

UDP MULTICAST
=============

Use UDP MULTICAST connections to communicate between different networks.

* udp_multicast_client.py::

import network, socket, errno, struct, time

# connect to AP
SSID = 'SSID'
PASSWORD = 'PASSWORD'

wlan = network.WLAN(network.STA_IF)
wlan.ifconfig(('172.16.55.55', '255.255.255.0', '172.16.55.1', '172.16.55.1')) # class B network
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while not wlan.isconnected():
pass

print("udp_multicast_client.py")
# send and receive

def inet_aton(str_addr):
return bytes(map(int, str_addr.split(".")))

#TIMEOUT = None # block
#TIMEOUT = 5 # s
TIMEOUT = 0 # non blocking

IP = '224.0.0.111' # MULTICAST
PORT = 5555
sockaddr = (IP, PORT)

wlan = network.WLAN(network.STA_IF)
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(IP), inet_aton(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()
str_to_send = f'ip:{ip}\t mac:{wlan.config("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)

Output is::

GET to ('224.0.0.111', 5555) sent "ip:172.16.55.55 mac:b'\xb8\xd6\x1aZ\xc2\xe4'"
ACK from ('192.168.44.44', 5555) received "ip:192.168.44.44 mac:b'$o(z\xf3\x9c'"
GET to ('224.0.0.111', 5555) sent "ip:172.16.55.55 mac:b'\xb8\xd6\x1aZ\xc2\xe4'"
ACK from ('192.168.44.44', 5555) received "ip:192.168.44.44 mac:b'$o(z\xf3\x9c'"
...

* udp_multicast_server.py::

import network, socket, errno, struct, time

# connect to AP
SSID = 'SSID'
PASSWORD = 'PASSWORD'

wlan = network.WLAN(network.STA_IF)
wlan.ifconfig(('192.168.44.44', '255.255.255.0', '192.168.44.1', '192.168.44.1')) # class C network
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while not wlan.isconnected():
pass

print("udp_multicast_server.py")
# receive and send

def inet_aton(str_addr):
return bytes(map(int, str_addr.split(".")))

#TIMEOUT = None # block
#TIMEOUT = 5 # s
TIMEOUT = 0 # non blocking

IP = '224.0.0.111' # MULTICAST
PORT = 5555
sockaddr = (IP, PORT)

wlan = network.WLAN(network.STA_IF)
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(IP), inet_aton(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()}"')

str_to_send = f'ip:{ip}\t mac:{wlan.config("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)

Output is::

GET from ('172.16.55.55', 5555) received "ip:172.16.55.55 mac:b'\xb8\xd6\x1aZ\xc2\xe4'"
ACK to ('224.0.0.111', 5555) sent "ip:192.168.44.44 mac:b'$o(z\xf3\x9c'"
GET from ('172.16.55.55', 5555) received "ip:172.16.55.55 mac:b'\xb8\xd6\x1aZ\xc2\xe4'"
ACK to ('224.0.0.111', 5555) sent "ip:192.168.44.44 mac:b'$o(z\xf3\x9c'"
...

0 comments on commit b29c78f

Please sign in to comment.