11#if DETWS_ENABLE_ESPNOW
15const uint8_t DETWS_ESPNOW_BROADCAST[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
20size_t detws_espnow_encode(uint8_t type,
const uint8_t *payload,
size_t len, uint8_t *out,
size_t cap)
22 if (!out || len > DETWS_ESPNOW_MAX_PAYLOAD || cap < len + DETWS_ESPNOW_HDR)
24 out[0] = DETWS_ESPNOW_MAGIC;
26 out[2] = (uint8_t)len;
28 memcpy(out + DETWS_ESPNOW_HDR, payload, len);
29 return len + DETWS_ESPNOW_HDR;
32bool detws_espnow_decode(
const uint8_t *buf,
size_t len, uint8_t *type,
const uint8_t **payload,
size_t *plen)
34 if (!buf || len < DETWS_ESPNOW_HDR || buf[0] != DETWS_ESPNOW_MAGIC)
36 size_t declared = buf[2];
37 if (declared + DETWS_ESPNOW_HDR != len)
42 *payload = buf + DETWS_ESPNOW_HDR;
64 Peer peers[DETWS_ESPNOW_MAX_PEERS];
66 detws_espnow_recv_fn recv =
nullptr;
72int peer_find(
const EspnowCtx &c,
const uint8_t mac[6])
74 for (
int i = 0; i < DETWS_ESPNOW_MAX_PEERS; i++)
75 if (c.peers[i].used && memcmp(c.peers[i].mac, mac, 6) == 0)
81void detws_espnow_peers_reset(
void)
83 for (
int i = 0; i < DETWS_ESPNOW_MAX_PEERS; i++)
84 s_espnow.peers[i].used =
false;
87bool detws_espnow_peer_add(
const uint8_t mac[6])
91 if (peer_find(s_espnow, mac) >= 0)
93 for (
int i = 0; i < DETWS_ESPNOW_MAX_PEERS; i++)
94 if (!s_espnow.peers[i].used)
96 memcpy(s_espnow.peers[i].mac, mac, 6);
97 s_espnow.peers[i].used =
true;
103bool detws_espnow_peer_has(
const uint8_t mac[6])
105 return mac && peer_find(s_espnow, mac) >= 0;
108bool detws_espnow_peer_remove(
const uint8_t mac[6])
110 int i = mac ? peer_find(s_espnow, mac) : -1;
113 s_espnow.peers[i].used =
false;
117int detws_espnow_peer_count(
void)
120 for (
int i = 0; i < DETWS_ESPNOW_MAX_PEERS; i++)
121 if (s_espnow.peers[i].used)
131#include <esp_idf_version.h>
139#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
140void on_recv(
const esp_now_recv_info_t *info,
const uint8_t *data,
int len)
142 const uint8_t *mac = info ? info->src_addr :
nullptr;
144void on_recv(
const uint8_t *mac,
const uint8_t *data,
int len)
147 if (!s_espnow.recv || len < 0 || !mac)
150 const uint8_t *payload;
152 if (detws_espnow_decode(data, (
size_t)len, &type, &payload, &plen))
153 s_espnow.recv(mac, type, payload, plen);
156bool radio_add_peer(
const uint8_t mac[6], uint8_t channel)
158 esp_now_peer_info_t p;
159 memset(&p, 0,
sizeof(p));
160 memcpy(p.peer_addr, mac, 6);
163 if (esp_now_is_peer_exist(mac))
165 return esp_now_add_peer(&p) == ESP_OK;
169bool detws_espnow_begin(uint8_t channel, detws_espnow_recv_fn cb)
171 s_espnow.channel = channel;
173 if (esp_now_init() != ESP_OK)
175 esp_now_register_recv_cb(on_recv);
176 detws_espnow_peers_reset();
177 return radio_add_peer(DETWS_ESPNOW_BROADCAST, channel);
180bool detws_espnow_add_peer(
const uint8_t mac[6])
182 if (!detws_espnow_peer_add(mac))
184 return radio_add_peer(mac, s_espnow.channel);
187bool detws_espnow_send(
const uint8_t mac[6], uint8_t type,
const uint8_t *payload,
size_t len)
189 uint8_t frame[DETWS_ESPNOW_HDR + DETWS_ESPNOW_MAX_PAYLOAD];
190 size_t n = detws_espnow_encode(type, payload, len, frame,
sizeof(frame));
193 return esp_now_send(mac, frame, n) == ESP_OK;
196bool detws_espnow_broadcast(uint8_t type,
const uint8_t *payload,
size_t len)
198 return detws_espnow_send(DETWS_ESPNOW_BROADCAST, type, payload, len);
203bool detws_espnow_begin(uint8_t, detws_espnow_recv_fn)
207bool detws_espnow_add_peer(
const uint8_t mac[6])
209 return detws_espnow_peer_add(mac);
211bool detws_espnow_send(
const uint8_t *, uint8_t,
const uint8_t *,
size_t)
215bool detws_espnow_broadcast(uint8_t,
const uint8_t *,
size_t)
ESP-NOW peer messaging with a typed envelope (DETWS_ENABLE_ESPNOW).