docs/library/espnow: Update espnow docs for WLAN.config(pm=x) options.

Update docs/library/espnow.rst to add:
- guidance on using WLAN.config(pm=WLAN.PM_NONE) for reliable
  espnow performance while also connected to a wifi access point;
- guidance on receiving encrypted messages;
- correction for default value of "encrypt" parameter (add_peer());
- guidance on use of ESPNow.irq(): recommand users readout all messages
  in the buffer each time the callback is called.

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
This commit is contained in:
glenn20 2023-05-10 13:06:52 +10:00 committed by Damien George
parent ea7031faff
commit 12dbbc8065

View File

@ -110,14 +110,14 @@ Configuration
.. method:: ESPNow.active([flag]) .. method:: ESPNow.active([flag])
Initialise or de-initialise the ESPNow communication protocol depending on Initialise or de-initialise the ESP-NOW communication protocol depending on
the value of the ``flag`` optional argument. the value of the ``flag`` optional argument.
.. data:: Arguments: .. data:: Arguments:
- *flag*: Any python value which can be converted to a boolean type. - *flag*: Any python value which can be converted to a boolean type.
- ``True``: Prepare the software and hardware for use of the ESPNow - ``True``: Prepare the software and hardware for use of the ESP-NOW
communication protocol, including: communication protocol, including:
- initialise the ESPNow data structures, - initialise the ESPNow data structures,
@ -125,7 +125,7 @@ Configuration
- invoke esp_now_init() and - invoke esp_now_init() and
- register the send and recv callbacks. - register the send and recv callbacks.
- ``False``: De-initialise the Espressif ESPNow software stack - ``False``: De-initialise the Espressif ESP-NOW software stack
(esp_now_deinit()), disable callbacks, deallocate the recv (esp_now_deinit()), disable callbacks, deallocate the recv
data buffer and deregister all peers. data buffer and deregister all peers.
@ -160,12 +160,12 @@ Configuration
`ESPNow.active(True)<ESPNow.active()>`. `ESPNow.active(True)<ESPNow.active()>`.
*timeout_ms*: (default=300,000) Default timeout (in milliseconds) *timeout_ms*: (default=300,000) Default timeout (in milliseconds)
for receiving ESPNOW messages. If *timeout_ms* is less than zero, then for receiving ESPNow messages. If *timeout_ms* is less than zero, then
wait forever. The timeout can also be provided as arg to wait forever. The timeout can also be provided as arg to
`recv()`/`irecv()`/`recvinto()`. `recv()`/`irecv()`/`recvinto()`.
*rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for *rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for
espnow packets. Must be set to a number from the allowed numeric values ESPNow packets. Must be set to a number from the allowed numeric values
in `enum wifi_phy_rate_t in `enum wifi_phy_rate_t
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/ <https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_. api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_.
@ -243,8 +243,8 @@ after reboot/reset). This reduces the reliability of receiving ESP-NOW messages
**Note**: A peer will respond with success if its wifi interface is **Note**: A peer will respond with success if its wifi interface is
`active()<network.WLAN.active>` and set to the same channel as the sender, `active()<network.WLAN.active>` and set to the same channel as the sender,
regardless of whether it has initialised it's ESP-Now system or is regardless of whether it has initialised it's ESP-NOW system or is
actively listening for ESP-Now traffic (see the Espressif ESP-Now docs). actively listening for ESP-NOW traffic (see the Espressif ESP-NOW docs).
.. method:: ESPNow.recv([timeout_ms]) .. method:: ESPNow.recv([timeout_ms])
@ -383,15 +383,21 @@ after reboot/reset). This reduces the reliability of receiving ESP-NOW messages
Peer Management Peer Management
--------------- ---------------
The Espressif ESP-Now software requires that other devices (peers) must be On ESP32 devices, the Espressif ESP-NOW software requires that other devices
*registered* before we can `send()<ESPNow.send()>` them messages. It is (peers) must be *registered* using `add_peer()` before we can
**not** necessary to *register* a peer to receive a message from that peer. `send()<ESPNow.send()>` them messages (this is *not* enforced on ESP8266
devices). It is **not** necessary to register a peer to receive an
un-encrypted message from that peer.
**Encrypted messages**: To receive an *encrypted* message, the receiving device
must first register the sender and use the same encryption keys as the sender
(PMK and LMK) (see `set_pmk()` and `add_peer()`.
.. method:: ESPNow.set_pmk(pmk) .. method:: ESPNow.set_pmk(pmk)
Set the Primary Master Key (PMK) which is used to encrypt the Local Master Set the Primary Master Key (PMK) which is used to encrypt the Local Master
Keys (LMK) for encrypting ESPNow data traffic. If this is not set, a Keys (LMK) for encrypting messages. If this is not set, a default PMK is
default PMK is used by the underlying Espressif esp_now software stack. used by the underlying Espressif ESP-NOW software stack.
**Note:** messages will only be encrypted if *lmk* is also set in **Note:** messages will only be encrypted if *lmk* is also set in
`ESPNow.add_peer()` (see `Security `ESPNow.add_peer()` (see `Security
@ -415,8 +421,9 @@ The Espressif ESP-Now software requires that other devices (peers) must be
.. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt]) .. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt])
ESPNow.add_peer(mac, param=value, ...) (ESP32 only) ESPNow.add_peer(mac, param=value, ...) (ESP32 only)
Add/register the provided *mac* address as a peer. Additional parameters Add/register the provided *mac* address as a peer. Additional parameters may
may also be specified as positional or keyword arguments: also be specified as positional or keyword arguments (any parameter set to
``None`` will be set to it's default value):
.. data:: Arguments: .. data:: Arguments:
@ -444,7 +451,7 @@ The Espressif ESP-Now software requires that other devices (peers) must be
- *encrypt*: (ESP32 only) If set to ``True`` data exchanged with - *encrypt*: (ESP32 only) If set to ``True`` data exchanged with
this peer will be encrypted with the PMK and LMK. (default = this peer will be encrypted with the PMK and LMK. (default =
``False``) ``True`` if *lmk* is set to a valid key, else ``False``)
**ESP8266**: Keyword args may not be used on the ESP8266. **ESP8266**: Keyword args may not be used on the ESP8266.
@ -515,7 +522,8 @@ The Espressif ESP-Now software requires that other devices (peers) must be
Modify the parameters of the peer associated with the provided *mac* Modify the parameters of the peer associated with the provided *mac*
address. Parameters may be provided as positional or keyword arguments address. Parameters may be provided as positional or keyword arguments
(see `ESPNow.add_peer()`). (see `ESPNow.add_peer()`). Any parameter that is not set (or set to
``None``) will retain the existing value for that parameter.
Callback Methods Callback Methods
---------------- ----------------
@ -524,14 +532,20 @@ Callback Methods
Set a callback function to be called *as soon as possible* after a message has Set a callback function to be called *as soon as possible* after a message has
been received from another ESPNow device. The callback function will be called been received from another ESPNow device. The callback function will be called
with the `ESPNow` instance object as an argument, eg: :: with the `ESPNow` instance object as an argument. For more reliable operation,
it is recommended to read out as many messages as are available when the
callback is invoked and to set the read timeout to zero, eg: ::
def recv_cb(e): def recv_cb(e):
print(e.irecv(0)) while True: # Read out all messages waiting in the buffer
e.irq(recv_cb) mac, msg = e.irecv(0) # Don't wait if no messages left
if mac is None:
return
print(mac, msg)
e.irq(recv_cb)
The `irq()<ESPNow.irq()>` callback method is an alternative method for The `irq()<ESPNow.irq()>` callback method is an alternative method for
processing incoming espnow messages, especially if the data rate is moderate processing incoming messages, especially if the data rate is moderate
and the device is *not too busy* but there are some caveats: and the device is *not too busy* but there are some caveats:
- The scheduler stack *can* overflow and callbacks will be missed if - The scheduler stack *can* overflow and callbacks will be missed if
@ -556,11 +570,11 @@ Constants
Exceptions Exceptions
---------- ----------
If the underlying Espressif ESPNow software stack returns an error code, If the underlying Espressif ESP-NOW software stack returns an error code,
the MicroPython ESPNow module will raise an ``OSError(errnum, errstring)`` the MicroPython espnow module will raise an ``OSError(errnum, errstring)``
exception where ``errstring`` is set to the name of one of the error codes exception where ``errstring`` is set to the name of one of the error codes
identified in the identified in the
`Espressif ESP-Now docs `Espressif ESP-NOW docs
<https://docs.espressif.com/projects/esp-idf/en/latest/ <https://docs.espressif.com/projects/esp-idf/en/latest/
api-reference/network/esp_now.html#api-reference>`_. For example:: api-reference/network/esp_now.html#api-reference>`_. For example::
@ -705,12 +719,12 @@ A small async server example::
Broadcast and Multicast Broadcast and Multicast
----------------------- -----------------------
All active ESP-Now clients will receive messages sent to their MAC address and All active ESPNow clients will receive messages sent to their MAC address and
all devices (**except ESP8266 devices**) will also receive messages sent to the all devices (**except ESP8266 devices**) will also receive messages sent to the
*broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast *broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast
MAC address. MAC address.
All ESP-Now devices (including ESP8266 devices) can also send messages to the All ESPNow devices (including ESP8266 devices) can also send messages to the
broadcast MAC address or any multicast MAC address. broadcast MAC address or any multicast MAC address.
To `send()<ESPNow.send()>` a broadcast message, the broadcast (or To `send()<ESPNow.send()>` a broadcast message, the broadcast (or
@ -739,7 +753,8 @@ point. When an ESP32 or ESP8266 device connects to a Wifi Access Point (see
`ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things `ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things
happen which affect ESPNow communications: happen which affect ESPNow communications:
1. Wifi Power-saving Mode is automatically activated and 1. Wifi Power-saving Mode (`network.WLAN.PM_PERFORMANCE`)
is automatically activated and
2. The radio on the esp device changes wifi ``channel`` to match the channel 2. The radio on the esp device changes wifi ``channel`` to match the channel
used by the Access Point. used by the Access Point.
@ -750,27 +765,31 @@ device to turn off the radio periodically (typically for hundreds of
milliseconds), making it unreliable in receiving ESPNow messages. This can be milliseconds), making it unreliable in receiving ESPNow messages. This can be
resolved by either of: resolved by either of:
1. Turning on the AP_IF interface, which will disable the power saving mode. 1. Disabling the power-saving mode on the STA_IF interface;
- Use ``sta.config(pm=sta.PM_NONE)``
2. Turning on the AP_IF interface, which will disable the power saving mode.
However, the device will then be advertising an active wifi access point. However, the device will then be advertising an active wifi access point.
- You **may** also choose to send your messages via the AP_IF interface, but - You **may** also choose to send your messages via the AP_IF interface, but
this is not necessary. this is not necessary.
- ESP8266 peers must send messages to this AP_IF interface (see below). - ESP8266 peers must send messages to this AP_IF interface (see below).
2. Configuring ESPNow clients to retry sending messages. 3. Configuring ESPNow clients to retry sending messages.
**Receiving messages from an ESP8266 device:** Strangely, an ESP32 device **Receiving messages from an ESP8266 device:** Strangely, an ESP32 device
connected to a wifi network using method 1 or 2 above, will receive ESP-Now connected to a wifi network using method 1 or 2 above, will receive ESPNow
messages sent to the STA_IF MAC address from another ESP32 device, but will messages sent to the STA_IF MAC address from another ESP32 device, but will
**reject** messages from an ESP8266 device!!!. To receive messages from an **reject** messages from an ESP8266 device!!!. To receive messages from an
ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and** ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and**
messages must be sent to the AP_IF MAC address. messages must be sent to the AP_IF MAC address.
**Managing wifi channels:** Any other espnow devices wishing to communicate with **Managing wifi channels:** Any other ESPNow devices wishing to communicate with
a device which is also connected to a Wifi Access Point MUST use the same a device which is also connected to a Wifi Access Point MUST use the same
channel. A common scenario is where one espnow device is connected to a wifi channel. A common scenario is where one ESPNow device is connected to a wifi
router and acts as a proxy for messages from a group of sensors connected via router and acts as a proxy for messages from a group of sensors connected via
espnow: ESPNow:
**Proxy:** :: **Proxy:** ::
@ -780,7 +799,7 @@ espnow:
sta.connect('myssid', 'mypassword') sta.connect('myssid', 'mypassword')
while not sta.isconnected(): # Wait until connected... while not sta.isconnected(): # Wait until connected...
time.sleep(0.1) time.sleep(0.1)
ap.active(True) # Disable power-saving mode sta.config(pm=sta.PM_NONE) # ..then disable power saving
# Print the wifi channel used AFTER finished connecting to access point # Print the wifi channel used AFTER finished connecting to access point
print("Proxy running on channel:", sta.config("channel")) print("Proxy running on channel:", sta.config("channel"))
@ -850,7 +869,7 @@ Other issues to take care with when using ESPNow with wifi are:
- **MicroPython re-scans wifi channels when trying to reconnect:** If the esp - **MicroPython re-scans wifi channels when trying to reconnect:** If the esp
device is connected to a Wifi Access Point that goes down, MicroPython will device is connected to a Wifi Access Point that goes down, MicroPython will
automatically start scanning channels in an attempt to reconnect to the automatically start scanning channels in an attempt to reconnect to the
Access Point. This means espnow messages will be lost while scanning for the Access Point. This means ESPNow messages will be lost while scanning for the
AP. This can be disabled by ``sta.config(reconnects=0)``, which will also AP. This can be disabled by ``sta.config(reconnects=0)``, which will also
disable the automatic reconnection after losing connection. disable the automatic reconnection after losing connection.