跳转到内容

ESPNow 通信组件

ESPNow 组件让 ESPHome 能够以一种简单且不受限制的方式与 ESP32 设备进行通信。 它使你能够通过乐鑫(Espressif)的 ESP-NOW 协议与其他 ESP32 设备交互,参见 文档。 它可以与数据包传输组件一起使用来共享 传感器数据;参见ESP-NOW 数据包传输平台。

# Example configuration entry
espnow:
  • channel (Optional, int): ESP-NOW 通信用于发送/接收数据包所使用的 Wi-Fi 信道。 当使用 Wi-Fi 时不能设置,因为 ESP-NOW 会使用与 Wi-Fi 网络相同的信道。
  • auto_add_peer (Optional, boolean): 设置为 true 时,ESP-NOW 组件会自动将任何新接入的 设备添加为对等设备(peer)。参见下面的对等设备。默认为 false。
  • enable_on_boot (Optional, boolean): 在启动时启用 ESP-NOW 组件。默认为 true。
  • max_payload_size (Optional, int): 此设备在一帧中可以发送和接收的最大载荷(以字节为单位)。 大于 250 的值使用 ESP-NOW v2 帧(最大 1470 字节),仅适用于同样支持它们的对等设备,并且 会为数据包缓冲区保留成比例地更多的 RAM。这仅设置此设备缓冲区的大小;协议版本 本身会与每个对等设备自动协商。默认为 250。
  • peers (Optional, list of MAC Address): 此设备允许与其通信的设备 MAC 地址列表。参见下面的对等设备。

自动化:

  • on_receive (Optional, Automation): 从已注册的对等设备收到定向(非广播)数据包时执行的自动化。可以指定多次。参见 on_receive。
  • on_unknown_peer (Optional, Automation): 从未注册为对等设备的设备收到数据包时执行的自动化。参见 on_unknown_peer。
  • on_broadcast (Optional, Automation): 收到广播数据包时执行的自动化。 可以指定多次。参见 on_broadcast。

所有三个触发器(on_receive、on_unknown_peer 和 on_broadcast)都会暴露描述所收到数据包的相同的三个 lambda 变量:

  • info (API 参考:espnow::ESPNowRecvInfo): 关于所收到 数据包的信息。最有用的成员是:
    • info.src_addr — uint8_t[6] 数据包的源 MAC 地址。
    • info.des_addr — uint8_t[6] 目标 MAC 地址(对于广播为 FF:FF:FF:FF:FF:FF)。
    • info.rx_ctrl — 指向 Wi-Fi wifi_pkt_rx_ctrl_t 结构的指针,包含底层接收细节,例如 info.rx_ctrl->rssi(信号强度,单位为 dBm)。
  • data: 指向所接收载荷的 const uint8_t * 指针。
  • size: 给出载荷长度(以字节为单位)的 uint16_t。

这些变量仅在自动化的同步部分执行期间有效。如果自动化 包含任何异步操作(例如 delay),到自动化恢复执行时,底层内存可能已被回收; 如果之后还需要这些值,请先将其复制到你自己的缓冲区中。

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);

当从内部对等设备列表中注册的对等设备收到定向(非广播)数据包时,将触发此自动化。广播数据包会分发到 on_broadcast,而未注册对等设备的数据包会分发到 on_unknown_peer。

可以配置多个 on_receive 自动化;每个都可以选择性地按源地址进行过滤。它们会按照声明的顺序进行评估。

  • address (Optional, MAC 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"

当从 MAC 地址不在已注册对等设备列表中的设备收到数据包时,将触发此自动化。它让配置有机会检查数据包并决定是否将发送者注册为对等设备(通常通过调用 espnow.peer.add 操作)。如果在触发器执行期间添加了对等设备,则在处理下一个数据包之前,同一个数据包会被传递给 on_receive(或 on_broadcast)。

如果未配置 on_unknown_peer 自动化,则除非 auto_add_peer 设置为 true,否则该数据包会被静默丢弃;当 auto_add_peer 为 true 时,发送者会被添加到对等设备列表,并且该数据包会按情况传递给 on_receive 或 on_broadcast。只允许配置一个 on_unknown_peer 自动化,并且它不接受 address 过滤器。

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]};

当从已注册的对等设备收到发送到广播地址(FF:FF:FF:FF:FF:FF)的数据包时,将触发此自动化。来自未注册为对等设备的设备的广播会首先被分发到 on_unknown_peer;一旦该对等设备被添加,来自它的广播就会到达此触发器。

可以配置多个 on_broadcast 自动化;每个都可以选择性地按源地址进行过滤。

  • address (Optional, MAC Address): 仅当数据包的源地址匹配时才触发此触发器。如果未设置, 则任何源地址都会触发。
espnow:
auto_add_peer: true
on_broadcast:
- lambda: |-
ESP_LOGD("espnow", "Broadcast of %u bytes received, RSSI %ddBm",
size, info.rx_ctrl->rssi);

这是一个通过 ESP-NOW 协议向特定对等设备发送数据包的操作。

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): 要发送到的接收设备的 MAC 地址。必须已经注册为对等设备,或者必须将 auto_add_peer 设置为 true。
  • data (Required, string or list of bytes, templatable): 要发送的数据。最大载荷大小为配置的 max_payload_size(默认为 250 字节)。
  • wait_for_sent (Optional, boolean): 如果为 true,自动化将等待底层发送操作完成(以及任何 on_sent 或 on_error 操作结束),然后再继续执行下一个操作。默认为 true。
  • continue_on_error (Optional, boolean): 如果设置为 false,当发送失败时,周围的自动化将被中止。当 wait_for_sent 为 false 时,不能为 false。默认为 true。

自动化:

  • on_sent (Optional, Automation): 当数据成功发送时执行的自动化(接收方已确认数据包)。
  • on_error (Optional, Automation): 当数据无法发送时执行的自动化。

这是一个通过 ESP-NOW 协议向同一 Wi-Fi 信道上所有正在侦听 ESP-NOW 广播的设备发送数据包的操作。它等同于使用地址 FF:FF:FF:FF:FF:FF 的 espnow.send。有关何时适合使用广播,请参阅下面的广播。

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): 要发送的数据。最大载荷大小为配置的 max_payload_size(默认为 250 字节)。
  • 来自 espnow.send 的所有其他选项(wait_for_sent、continue_on_error、on_sent、on_error)也都被接受。

这是一个向内部允许的对等设备列表中添加新对等设备的操作。

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): 要添加到允许对等设备列表中的对等设备地址。

这是一个从内部允许的对等设备列表中移除已知对等设备的操作。

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): 要从允许对等设备列表中移除的对等设备地址。

这是一个更改 ESP-NOW 发送和接收所使用 Wi-Fi 信道的操作。当 Wi-Fi 组件启用时它没有效果,因为此时信道由关联的 Wi-Fi 网络决定。

on_...:
- espnow.set_channel:
channel: 1
- espnow.set_channel: 1
  • channel (Required, int, templatable): 要切换到的 Wi-Fi 信道。有效值为 1 到 14;实际允许的最高信道取决于设备所在的国家或地区(例如,美国和大部分欧洲地区允许信道 1-11,许多其他国家允许 1-13,日本允许 1-14)。有关详细信息,请参阅各国 Wi-Fi 信道法规或查阅 Espressif ESP-NOW 文档。两个对等设备必须处于同一信道,ESP-NOW 数据包才能被交换。

对等设备是此设备允许向其发送数据的设备。可以从任何设备接收广播和未加密的单播数据,而无需显式将其添加为对等设备;但是,只有源地址在已注册对等设备列表中的数据包才会被传递给 on_receive 和 on_broadcast 触发器。来自任何其他设备的数据包会首先提供给 on_unknown_peer。

如果 auto_add_peer 设置为 false 且你尚未添加任何对等设备,那么只能发送广播,尝试向非广播地址发送数据时会出错。

将 auto_add_peer 设置为 true 将允许组件自动将任何接入的设备添加为对等设备,并会自动添加任何向其发送过数据的对等设备。

ESP-NOW 协议既支持定向(单播)帧(寻址到特定对等设备),也支持发送到特殊地址 FF:FF:FF:FF:FF:FF 的广播帧。每种方式各有权衡:

广播的优点:

  • 单个广播帧可以向任意数量的侦听设备传递相同的数据,而不是每个对等设备重复发送一次。
  • 广播帧不会被接收方确认,这意味着与相同长度的定向消息相比,它们使用更少的无线电空中时间,并且永远不会触发重传。
  • 发送方和接收方之间无需预先配对,这简化了传感器信标等一对多设计。
  • 无需事先知道接收设备的 MAC 地址,这在设备频繁添加或移除时可能是一个优势。

广播的缺点:

  • 同一 Wi-Fi 信道上的每个支持 ESP-NOW 的设备都会接收并部分处理每个广播帧,即使它最终会丢弃载荷。这会唤醒这些设备上的无线电和 CPU,并且可以明显增加共享该信道的电池供电节点的功耗。
  • 由于没有确认机制,因此没有内置的投递确认;应用程序必须接受偶尔的数据包丢失,或在其之上实现自己的重传/心跳方案。

使用广播没有额外的安全影响:以明文发送的定向 ESP-NOW 数据包可以被范围内任何设备捕获,与广播数据包一样容易,而且 ESPHome 的 espnow 组件没有实现 ESP-NOW 的可选链路层加密。如果你需要加密,请使用 ESP-NOW 数据包传输平台,它会在 espnow 之上叠加 数据包传输 组件的加密,并且在单播和广播上都能同样出色的工作。