Skip to content

ESPNow communication Component

The ESPNow component allows ESPHome to communicate with ESP32 devices in a simple and unrestricted way. It enables the option to interact with other ESP32 devices over Espressif’s ESP-NOW protocol, see documentation. It can be used with the Packet Transport Component to share sensor data; see ESP-NOW Packet Transport Platform.

# Example configuration entry
espnow:
  • channel (Optional, int): The Wi-Fi channel that the ESP-NOW communication will use to send/receive data packets. Cannot be set when Wi-Fi is used, as ESP-NOW will use the same channel as the Wi-Fi network.
  • auto_add_peer (Optional, boolean): When set to true, the ESP-NOW component will automatically add any new incoming device as a peer. See Peers below. Defaults to false.
  • enable_on_boot (Optional, boolean): Enable the ESP-NOW component on boot. Defaults to true.
  • peers (Optional, list of MAC Address): The list of MAC addresses of the devices that this device is allowed to communicate with. See Peers below.

Automations:

  • on_receive (Optional, Automation): An automation to perform when a directed (non-broadcast) packet is received from a registered peer. May be specified multiple times. See on_receive.
  • on_unknown_peer (Optional, Automation): An automation to perform when a packet is received from a device that is not registered as a peer. See on_unknown_peer.
  • on_broadcast (Optional, Automation): An automation to perform when a broadcast packet is received. May be specified multiple times. See on_broadcast.

All three triggers (on_receive, on_unknown_peer, and on_broadcast) expose the same three lambda variables describing the received packet:

  • info (API Reference: espnow::ESPNowRecvInfo): Information about the received packet. The most useful members are:
    • info.src_addruint8_t[6] source MAC address of the packet.
    • info.des_addruint8_t[6] destination MAC address (will be FF:FF:FF:FF:FF:FF for broadcasts).
    • info.rx_ctrl — pointer to a Wi-Fi wifi_pkt_rx_ctrl_t structure containing low-level reception details such as info.rx_ctrl->rssi (signal strength in dBm).
  • data: A const uint8_t * pointer to the received payload.
  • size: A uint8_t giving the length of the payload in bytes.

These variables are only valid for the duration of the synchronous part of the automation. If the automation includes any asynchronous actions (such as delay), the underlying memory may have been recycled by the time the automation resumes; copy the values into your own buffer first if they are needed later.

espnow:
on_receive:
- lambda: |-
char des_mac[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
char src_mac[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
char hex[256];
ESP_LOGD("espnow", "Received from %s to %s: %s RSSI: %ddBm",
format_mac_addr_upper(info.src_addr, src_mac),
format_mac_addr_upper(info.des_addr, des_mac),
format_hex_pretty_to(hex, data, size),
info.rx_ctrl->rssi);

This automation is triggered when a directed (non-broadcast) packet is received from a peer that is registered in the internal peer list. Broadcast packets are dispatched to on_broadcast instead, and packets from unregistered peers are dispatched to on_unknown_peer.

Multiple on_receive automations may be configured; each can optionally filter on the source address. They are evaluated in the order they are declared.

  • address (Optional, MAC Address): Only fire this trigger when the packet’s source address matches. If not set, the trigger fires for any source address.
espnow:
peers:
- 11:22:33:44:55:66
on_receive:
# Fires for any registered peer
- lambda: |-
ESP_LOGD("espnow", "Got %u bytes", size);
# Fires only for packets from this specific peer
- address: 11:22:33:44:55:66
then:
- logger.log: "Message from the kitchen sensor"

This automation is triggered when a packet is received from a device whose MAC address is not in the registered peer list. It gives the configuration an opportunity to inspect the packet and decide whether to register the sender as a peer (typically by calling the espnow.peer.add action). If the peer is added during the trigger, the same packet is then delivered to on_receive (or on_broadcast) before the next packet is processed.

If no on_unknown_peer automation is configured, the packet is silently dropped unless auto_add_peer is set to true, in which case the sender is added to the peer list and the packet is delivered to on_receive or on_broadcast as appropriate. Only one on_unknown_peer automation may be configured, and it does not accept an address filter.

espnow:
on_unknown_peer:
then:
# Accept the new peer only if the payload starts with a known magic byte.
- if:
condition:
lambda: "return size >= 1 && data[0] == 0x42;"
then:
- espnow.peer.add:
address: !lambda |-
return {info.src_addr[0], info.src_addr[1], info.src_addr[2],
info.src_addr[3], info.src_addr[4], info.src_addr[5]};

This automation is triggered when a packet sent to the broadcast address (FF:FF:FF:FF:FF:FF) is received from a registered peer. Broadcasts from devices that are not registered peers are dispatched to on_unknown_peer first; once the peer has been added, broadcasts from it will reach this trigger.

Multiple on_broadcast automations may be configured; each can optionally filter on the source address.

  • address (Optional, MAC Address): Only fire this trigger when the packet’s source address matches. If not set, the trigger fires for any source address.
espnow:
auto_add_peer: true
on_broadcast:
- lambda: |-
ESP_LOGD("espnow", "Broadcast of %u bytes received, RSSI %ddBm",
size, info.rx_ctrl->rssi);

This is an Action for sending a data packet over the ESP-NOW protocol to a specific peer.

on_...:
- espnow.send:
address: 11:22:33:44:55:66
data: "The big angry wolf awakens"
- espnow.send:
address: 11:22:33:44:55:66
data: !lambda "return {0x00, 0x00, 0x34, 0x5d};"
- espnow.send:
address: !lambda "return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};"
data: [0x00, 0x00, 0x34, 0x5d]
- espnow.send:
address: !lambda "return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};"
data: !lambda "return {0x00, 0x00, 0x34, 0x5d};"
  • address (Required, MAC Address, templatable): The MAC address of the receiving device to send to. Must already be registered as a peer, or auto_add_peer must be set to true.
  • data (Required, string or list of bytes, templatable): The data to be sent. The maximum payload size is 250 bytes.
  • wait_for_sent (Optional, boolean): If true, the automation will wait for the underlying send operation to complete (and for any on_sent or on_error actions to finish) before continuing with the next action. Defaults to true.
  • continue_on_error (Optional, boolean): If set to false, the surrounding automation will be aborted if the send fails. Cannot be false when wait_for_sent is false. Defaults to true.

Automations:

  • on_sent (Optional, Automation): An automation to perform when the data is sent successfully (the receiver has acknowledged the packet).
  • on_error (Optional, Automation): An automation to perform when the data could not be sent.

This is an Action for sending a data packet over the ESP-NOW protocol to every device on the same Wi-Fi channel that is listening for ESP-NOW broadcasts. It is equivalent to using espnow.send with the address FF:FF:FF:FF:FF:FF. See Broadcasting below for a discussion of when broadcasts are appropriate.

on_...:
- espnow.broadcast:
data: "The big angry wolf awakens"
- espnow.broadcast:
data: !lambda "return {0x00, 0x00, 0x34, 0x5d};"
- espnow.broadcast:
data: [0x00, 0x00, 0x34, 0x5d]
  • data (Required, string or list of bytes, templatable): The data to be sent. The maximum payload size is 250 bytes.
  • All other options from espnow.send (wait_for_sent, continue_on_error, on_sent, on_error) are also accepted.

This is an Action to add a new peer to the internal allowed peers list.

on_...:
- espnow.peer.add:
address: 11:22:33:44:55:66
- espnow.peer.add:
address: !lambda "return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};"
  • address (Required, MAC Address, templatable): The peer address to add to the list of allowed peers.

This is an Action to remove a known peer from the internal allowed peers list.

on_...:
- espnow.peer.delete:
address: 11:22:33:44:55:66
- espnow.peer.delete:
address: !lambda "return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};"
  • address (Required, MAC Address, templatable): The peer address to remove from the list of allowed peers.

This is an Action to change the Wi-Fi channel that ESP-NOW is sending and receiving on. It has no effect when the Wi-Fi component is enabled, since the channel is then determined by the associated Wi-Fi network.

on_...:
- espnow.set_channel:
channel: 1
- espnow.set_channel: 1
  • channel (Required, int, templatable): The Wi-Fi channel to switch to. Valid values are 1 to 14; the highest channel actually allowed depends on the country or region where the device is being used (for example, channels 1-11 are allowed in the US and most of Europe, 1-13 in many other countries, and 1-14 in Japan). For details, see the Wi-Fi channel regulations by country or consult the Espressif ESP-NOW documentation. Both peers must be on the same channel for ESP-NOW packets to be exchanged.

A peer is a device that this device is allowed to send to. Broadcast and unencrypted unicast data can be received from any device without explicitly adding it as a peer; however, only packets whose source address is in the registered peer list are delivered to the on_receive and on_broadcast triggers. Packets from any other device are first offered to on_unknown_peer.

If auto_add_peer is set to false and you have not added any peers, then only broadcasts can be sent and there will be an error when trying to send data to a non-broadcast address.

Setting auto_add_peer to true will allow the component to automatically add any incoming device as a peer, and will automatically add any peer that data is sent to.

The ESP-NOW protocol supports both directed (unicast) frames addressed to a specific peer and broadcast frames sent to the special address FF:FF:FF:FF:FF:FF. Each style has different trade-offs:

Benefits of broadcasting:

  • A single broadcast frame can deliver the same data to any number of listening devices, instead of repeating the transmission once per peer.
  • Broadcast frames are not acknowledged by receivers, which means they use less radio airtime than directed messages of the same length and never trigger retransmissions.
  • No prior pairing is required between sender and receiver, which simplifies one-to-many designs such as sensor beacons.
  • It is not necessary to know the MAC addresses of the receiving devices in advance, which can be an advantage when devices are frequently added or removed.

Drawbacks of broadcasting:

  • Every ESP-NOW capable device on the same Wi-Fi channel will receive and partially process each broadcast frame, even if it ultimately discards the payload. This wakes the radio and CPU on those devices and can noticeably increase power consumption on battery-powered nodes that share the channel.
  • Because there is no acknowledgement, there is no built-in delivery confirmation; the application must accept occasional packet loss or implement its own retransmission/heartbeat scheme on top.

There are no additional security implications to using broadcasts: directed ESP-NOW packets sent in clear text can be captured by any device within range just as easily as broadcast packets, and ESPHome’s espnow component does not implement ESP-NOW’s optional link-layer encryption. If you need encryption, use the ESP-NOW Packet Transport Platform, which layers the Packet Transport component’s encryption on top of espnow and works equally well over unicast and broadcast.