adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
MIT License
3.96k stars 1.16k forks source link

espnow cannot send to a broadcast address #9380

Open gitcnd opened 1 week ago

gitcnd commented 1 week ago

CircuitPython version

Adafruit CircuitPython 9.1.0-beta.1-18-g781c577745 on 2024-05-11; sunton_esp32_2432S028 with ESP32

Code/REPL

import wifi
import espnow
import time

# Disable WiFi
wifi.radio.enabled = False

# Initialize ESPNOW
esp = espnow.ESPNow()
esp.phy_rate = 0  # Default physical layer rate

if 0: # enabling this line makes the problem go away
    peer = espnow.Peer(b'\x24\xdc\xc3\x8b\xe1\xc8')
    esp.peers.append(peer)

# Add a broadcast peer 
peer = espnow.Peer(b'\xff\xff\xff\xff\xff\xff')
esp.peers.append(peer)

print("Broadcasting message...")

while True:
    try:
        esp.send(b'hello world')
        print("Sent.")
    except Exception as e:
        print(f"esp.read() error: {e}")
    time.sleep(5)  # Send the message every 5 seconds

# exec(open("espnowsender.py").read())

Behavior

Adafruit CircuitPython 9.1.0-beta.1-18-g781c577745 on 2024-05-11; sunton_esp32_2432S028 with ESP32
>>> 
>>> exec(open("estnowtst1.py").read())
Broadcasting message...
esp.read() error: ESP-NOW error 0x3069
esp.read() error: ESP-NOW error 0x3069
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 28, in <module>
KeyboardInterrupt: 
>>> 

Description

Change the "if 0:" to "if 1:" and this is what we see:-

>>> exec(open("estnowtst2.py").read())
Broadcasting message...
Sent.
Sent.
Sent.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 28, in <module>
KeyboardInterrupt: 
>>> 

The logically identical code in micropython works fine

MicroPython version:

import network
import espnow

sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()
e = espnow.ESPNow()
e.active(True)
peer = b'\xff\xff\xff\xff\xff\xff' # broadcast mac address to all esp32's (not esp8266)
e.add_peer(peer)      # Must add_peer() before send()

e.send(peer, "Starting...")
for i in range(100):
    e.send(peer, str(i)*20, True) # Supposedly capable of 89250bytes/sec
e.send(peer, b'end')

Additional information

It also does not allow channel numbers - the below errors out:- peer = espnow.Peer(b'\x24\xdc\xc3\x8b\xe1\xc8', channel=9) as mentioned in https://github.com/adafruit/circuitpython/issues/7903

The "receiver" side of the code does seem to semi-work (gets packets from my micro-python version) but experiences a very high number of read error exceptions

espnowclient.py

import wifi
import espnow
import binascii

# Disable WiFi
#wifi.radio.enabled = False

# Initialize ESPNOW
esp = espnow.ESPNow()
esp.phy_rate = 0  # Default physical layer rate

# Add a broadcast peer
#peer = espnow.Peer(b'\xff\xff\xff\xff\xff\xff', channel=9) # bug - crashes it
peer = espnow.Peer(b'\xff\xff\xff\xff\xff\xff') 
esp.peers.append(peer)

def packet_to_hex_and_ascii(packet):
    hex_data = binascii.hexlify(packet.msg)
    ascii_data = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in packet.msg)
    return hex_data, ascii_data

#print("\033[2J\033[HListening for ESPNOW packets on channel 9...")
print("\033[2J\033[HListening for ESPNOW packets on wifi channel...")

while True:
    try:
        packet = esp.read()
    except Exception as e:
        print(f"esp.read() error: {e}")
    if packet:
        hex_data, ascii_data = packet_to_hex_and_ascii(packet)
        print("Received packet:")
        print("Hex: ", hex_data)
        print("ASCII: ", ascii_data)
        print("sender mac: ",  binascii.hexlify(packet.mac)  )
        print("rssi: ", packet.rssi )
        print("time: ", packet.time )

# exec(open("espnowclient.py").read())
gitcnd commented 1 week ago

Update; while adding b'\xff\xff\xff\xff\xff\xff' as a peer seems to stop the error - the corresponding receiver listening to broadcast traffic does not receive anything.

gitcnd commented 6 days ago

I'm planning to take a look at this and https://github.com/adafruit/circuitpython/issues/7903. For reference: ( https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/error-codes.html )

ESP_ERR_ESPNOW_INTERNAL (0x306a): Internal error

ESP_ERR_ESPNOW_NOT_FOUND (0x3069): ESPNOW peer is not found

leave a note here if you've done (or are doing) any work on it, so no effort gets duplicated.

gitcnd commented 7 hours ago

I was unable to get circuitpython to reliably (or in most cases - at all) communicate with micropython over espnow (packet corruption and loss mostly when it semi-worked, or nothing at all most of the time probably due to code issue in the peer address setup/handling). I was unable to work out where/how in the code to fix this, or where the issue might be (I used "printf()" in the C to emit debug info - couldn't work it out still). For now - I'm giving up on this.