ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
espnow_packet.h
Go to the documentation of this file.
1#pragma once
2
3#if defined(USE_ESP32) || defined(USE_ESP8266)
4
5#include "espnow_err.h"
6#include "espnow_types.h"
7
8#include <cstdint>
9#include <cstring>
10#include <functional>
11#include <memory>
12#include <utility>
13#include <vector>
14
15namespace esphome::espnow {
16
17static const uint8_t ESPNOW_BROADCAST_ADDR[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
18static const uint8_t ESPNOW_MULTICAST_ADDR[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE};
19
20// Maximum payload this component sends and receives, from the
21// ``max_payload_size`` option. The radio stack speaks ESP-NOW v2 regardless
22// (negotiated per peer); payloads beyond the v1 limit (250 bytes) are opt-in
23// because the packet pools are statically sized from this, so their RAM cost
24// is proportional (~8 KB at 250 bytes, ~44 KB at the v2 limit of 1470).
25#ifndef USE_ESPNOW_MAX_PAYLOAD_SIZE
26#define USE_ESPNOW_MAX_PAYLOAD_SIZE ESP_NOW_MAX_DATA_LEN
27#endif
28static constexpr uint16_t ESPNOW_MAX_DATA_LEN = USE_ESPNOW_MAX_PAYLOAD_SIZE;
29#ifdef ESP_NOW_MAX_DATA_LEN_V2
30static_assert(ESPNOW_MAX_DATA_LEN <= ESP_NOW_MAX_DATA_LEN_V2,
31 "espnow max_payload_size cannot exceed the ESP-NOW v2 frame limit");
32#else
33static_assert(ESPNOW_MAX_DATA_LEN <= ESP_NOW_MAX_DATA_LEN,
34 "espnow max_payload_size beyond 250 bytes requires an ESP-IDF with ESP-NOW v2 support (5.4+)");
35#endif
36
38 uint8_t src_addr[ESP_NOW_ETH_ALEN];
39 uint8_t des_addr[ESP_NOW_ETH_ALEN];
41};
42
43using send_callback_t = std::function<void(esp_err_t)>;
44
46 public:
47 // NOLINTNEXTLINE(readability-identifier-naming)
48 enum esp_now_packet_type_t : uint8_t {
51 };
52
53 // Default constructor for pre-allocation in pool
55
56 void release() {}
57
58 void load_received_data(const uint8_t *src_addr, const uint8_t *des_addr, const uint8_t *data, uint16_t size,
59 int8_t rssi, uint32_t timestamp) {
60 this->type_ = RECEIVED;
61 memcpy(this->packet_.receive.info.src_addr, src_addr, ESP_NOW_ETH_ALEN);
62 memcpy(this->packet_.receive.info.des_addr, des_addr, ESP_NOW_ETH_ALEN);
63 memcpy(this->packet_.receive.data, data, size);
64 this->packet_.receive.size = size;
65
66 this->packet_.receive.rx_ctrl.rssi = rssi;
67 this->packet_.receive.rx_ctrl.timestamp = timestamp;
68 this->packet_.receive.info.rx_ctrl = reinterpret_cast<rx_ctrl_t *>(&this->packet_.receive.rx_ctrl);
69 }
70
71 void load_sent_data(const uint8_t *mac_addr, esp_now_send_status_t status) {
72 this->type_ = SENT;
73 memcpy(this->packet_.sent.address, mac_addr, ESP_NOW_ETH_ALEN);
74 this->packet_.sent.status = status;
75 }
76
77 // Disable copy to prevent double-delete
78 ESPNowPacket(const ESPNowPacket &) = delete;
80
81 union {
82 // NOLINTNEXTLINE(readability-identifier-naming)
83 struct received_data {
84 ESPNowRecvInfo info; // Information about the received packet
85 uint8_t data[ESPNOW_MAX_DATA_LEN]; // Data received in the packet
86 uint16_t size; // Size of the received data
87 WifiPacketRxControl rx_ctrl; // Status of the received packet
89
90 // NOLINTNEXTLINE(readability-identifier-naming)
91 struct sent_data {
92 uint8_t address[ESP_NOW_ETH_ALEN];
96
98
99 esp_now_packet_type_t type() const { return this->type_; }
100 const ESPNowRecvInfo &get_receive_info() const { return this->packet_.receive.info; }
101};
102
104 public:
105 ESPNowSendPacket(const uint8_t *peer_address, const uint8_t *payload, size_t size, const send_callback_t &&callback)
106 : callback_(callback) {
107 this->init_data_(peer_address, payload, size);
108 }
109 ESPNowSendPacket(const uint8_t *peer_address, const uint8_t *payload, size_t size) {
110 this->init_data_(peer_address, payload, size);
111 }
112
113 // Default constructor for pre-allocation in pool
115
116 void release() {}
117
118 // Disable copy to prevent double-delete
121
122 void load_data(const uint8_t *peer_address, const uint8_t *payload, size_t size, send_callback_t &&callback) {
123 this->init_data_(peer_address, payload, size);
124 this->callback_ = std::move(callback);
125 }
126
127 void load_data(const uint8_t *peer_address, const uint8_t *payload, size_t size) {
128 this->init_data_(peer_address, payload, size);
129 this->callback_ = nullptr; // Reset callback
130 }
131
132 uint8_t address_[ESP_NOW_ETH_ALEN]{0}; // MAC address of the peer to send the packet to
133 uint8_t data_[ESPNOW_MAX_DATA_LEN]{0}; // Data to send
134 uint16_t size_{0}; // Size of the data to send, must be <= ESPNOW_MAX_DATA_LEN
135 send_callback_t callback_{nullptr}; // Callback to call when the send operation is complete
136
137 private:
138 void init_data_(const uint8_t *peer_address, const uint8_t *payload, size_t size) {
139 memcpy(this->address_, peer_address, ESP_NOW_ETH_ALEN);
140 if (size > ESPNOW_MAX_DATA_LEN) {
141 this->size_ = 0;
142 return;
143 }
144 this->size_ = size;
145 memcpy(this->data_, payload, this->size_);
146 }
147};
148
149} // namespace esphome::espnow
150
151#endif // USE_ESP32 || USE_ESP8266
uint8_t address
Definition bl0906.h:4
ESPNowPacket(const ESPNowPacket &)=delete
uint8_t data[ESPNOW_MAX_DATA_LEN]
esp_now_send_status_t status
void load_sent_data(const uint8_t *mac_addr, esp_now_send_status_t status)
ESPNowPacket & operator=(const ESPNowPacket &)=delete
union esphome::espnow::ESPNowPacket::@88 packet_
struct esphome::espnow::ESPNowPacket::@88::sent_data sent
esp_now_packet_type_t type_
esp_now_packet_type_t type() const
const ESPNowRecvInfo & get_receive_info() const
struct esphome::espnow::ESPNowPacket::@88::received_data receive
WifiPacketRxControl rx_ctrl
void load_received_data(const uint8_t *src_addr, const uint8_t *des_addr, const uint8_t *data, uint16_t size, int8_t rssi, uint32_t timestamp)
uint8_t data_[ESPNOW_MAX_DATA_LEN]
ESPNowSendPacket & operator=(const ESPNowSendPacket &)=delete
void load_data(const uint8_t *peer_address, const uint8_t *payload, size_t size)
ESPNowSendPacket(const ESPNowSendPacket &)=delete
void load_data(const uint8_t *peer_address, const uint8_t *payload, size_t size, send_callback_t &&callback)
uint8_t address_[ESP_NOW_ETH_ALEN]
ESPNowSendPacket(const uint8_t *peer_address, const uint8_t *payload, size_t size, const send_callback_t &&callback)
ESPNowSendPacket(const uint8_t *peer_address, const uint8_t *payload, size_t size)
wifi_pkt_rx_ctrl_t rx_ctrl_t
std::function< void(esp_err_t)> send_callback_t
uint16_t size
Definition helpers.cpp:34
static void uint32_t
rx_ctrl_t * rx_ctrl
Rx control info of ESPNOW packet.
uint8_t des_addr[ESP_NOW_ETH_ALEN]
Destination address of ESPNOW packet.
uint8_t src_addr[ESP_NOW_ETH_ALEN]
Source address of ESPNOW packet.
uint16_t timestamp
Definition tt21100.cpp:2