Pico W: Problem binding a socket to a UDP Multicast Group

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
Beormund
Posts: 7
Joined: Wed Jul 27, 2022 2:31 pm

Pico W: Problem binding a socket to a UDP Multicast Group

Post by Beormund » Wed Aug 24, 2022 11:38 am

I'm trying to get uPyEcho (Wemo emulator for Alexa discovery) to work on Pico W. I'm connected to wifi and MQTT using the async mqtt module. The following code is supposed to bind the socket to th UDP Multicast group ("239.255.255.250", 1900) which is what Alexa uses to discover Wemo devices. But I only receive broadcasts with a destination group ("255.255.255.255", 1900). I've checked my network using WireShark and Alexa is broadcasting discovery messages to 239.255.255.250. Any suggestions on how to resolve please?

Code: Select all

    def inet_aton(self, addr):
        ip_as_bytes = bytes(map(int, addr.split(".")))
        return ip_as_bytes

    async def init_socket(self):
        ok = True
        self.ip = "239.255.255.250"
        self.port = 1900
        try:
            # This is needed to join a multicast group
            self.mreq = struct.pack("4sl", self.inet_aton(self.ip), 0)
            # Set up server socket
            self.ssock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            try:
                self.ssock.bind((self.ip, self.port)) # Also tried ("", self.port)
            except Exception as e:
                dbg("WARNING: Failed to bind %s:%d: %s", (self.ip, self.port, e))
                ok = False
            try:
                self.ssock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, self.mreq)
            except Exception as e:
                dbg("WARNING: Failed to join multicast group!: " + str(e))
                ok = False
        except Exception as e:
            dbg("Failed to initialize UPnP sockets!")
            return False
        if ok:
            dbg("Listening for UPnP broadcasts")

Beormund
Posts: 7
Joined: Wed Jul 27, 2022 2:31 pm

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by Beormund » Wed Aug 24, 2022 12:44 pm

I suspect there is a bug preventing the socket joining a UDP multicast group

Code: Select all

# self.mreq = b'\xef\xff\xff\xfa\x00\x00\x00\x00'
self.ssock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, self.mreq)

Beormund
Posts: 7
Joined: Wed Jul 27, 2022 2:31 pm

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by Beormund » Wed Aug 24, 2022 3:41 pm

Here's a stripped down test case for listening to UDP multicast broadcasts on 239.255.255.250:1900:

Code: Select all

# wlan access
SSID = '<ROUTER>'
WPA2_PASS = "<PASSWORD>"

ssid_ = SSID
wpa2_pass = WPA2_PASS

def do_connect():
    import network

    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("connecting to network...")
        sta_if.active(True)
        sta_if.connect(ssid_, wpa2_pass)
        while not sta_if.isconnected():
            pass
    print("network config:", sta_if.ifconfig())

do_connect()

import socket
try:
    from socket import sockaddr
except:
    sockaddr = lambda x: x

def inet_aton(addr):
    ip_as_bytes = bytes(map(int, addr.split(".")))
    return ip_as_bytes

UPNP_MCAST_IP = "239.255.255.250"
UPNP_PORT = 1900
BIND_IP = "0.0.0.0"
REUSE_SOCKET = 0

serv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = socket.getaddrinfo(BIND_IP, UPNP_PORT, socket.AF_INET, socket.SOCK_DGRAM)[0][4]
serv_sock.bind(addr)
serv_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, inet_aton(UPNP_MCAST_IP) + inet_aton(BIND_IP));
if REUSE_SOCKET:
    resp_sock = serv_sock
else:
    resp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    data, addr = resp_sock.recvfrom(1024)
    if data.startswith(b"M-SEARCH"):
        print("From: ", sockaddr(addr))
        print(data)
This should publish quite a bit of udp broadcasting but doesn't on the pico w. If you have Alexa: "Alexa, discover devices..."
MicroPython firmware: rp2-pico-w-20220824-unstable-v1.19.1-316-g8139cbcf6.uf2

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by jimmo » Thu Aug 25, 2022 2:03 pm

Beormund wrote:
Wed Aug 24, 2022 3:41 pm
Here's a stripped down test case for listening to UDP multicast broadcasts on 239.255.255.250:1900:
Thanks for the detailed info and repro!

I have a working example (running in CPython) than can pick up the SDDP multicasts on my network, but also unable to get this working on my Pico W.

It also works fine on an ESP32, so I think there's definitely a bug here. I have raised https://github.com/micropython/micropython/issues/9105 to track, please see updates there.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by jimmo » Fri Aug 26, 2022 2:06 pm

Beormund wrote:
Wed Aug 24, 2022 3:41 pm
Here's a stripped down test case for listening to UDP multicast broadcasts on 239.255.255.250:1900:
Thanks again for raising this. I've submitted a PR to fix the wifi driver.

Beormund
Posts: 7
Joined: Wed Jul 27, 2022 2:31 pm

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by Beormund » Sun Aug 28, 2022 3:45 pm

Cheers jimmo

Beormund
Posts: 7
Joined: Wed Jul 27, 2022 2:31 pm

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by Beormund » Tue Sep 20, 2022 9:11 am

jimmo wrote:
Fri Aug 26, 2022 2:06 pm
Beormund wrote:
Wed Aug 24, 2022 3:41 pm
Here's a stripped down test case for listening to UDP multicast broadcasts on 239.255.255.250:1900:
Thanks again for raising this. I've submitted a PR to fix the wifi driver.
The PR doesn't appear to have been approved upstream. Would it be possible to fork the driver, incorporate the fix locally and re-sync later?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Pico W: Problem binding a socket to a UDP Multicast Group

Post by jimmo » Tue Sep 20, 2022 10:23 pm

Beormund wrote:
Tue Sep 20, 2022 9:11 am
The PR doesn't appear to have been approved upstream. Would it be possible to fork the driver, incorporate the fix locally and re-sync later?
Yes, absolutely.

No fork necessary, just fetch the PR into the lib/cyw43-driver submodule. (cd lib/cyw43-driver: git fetch origin pull/25/head:multicast-register; git checkout multicast-register)

Post Reply