DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
espnow.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file espnow.h
6 * @brief ESP-NOW peer messaging with a typed envelope (DETWS_ENABLE_ESPNOW).
7 *
8 * Connectionless ESP32 peer-to-peer radio messaging (no AP, no IP) wrapped in a
9 * small typed envelope so a receiver can demux by message type and reject a
10 * truncated frame. Two layers:
11 *
12 * - **Host-testable core (pure):** the 3-byte envelope codec
13 * (detws_espnow_encode / decode) and a bounded peer registry
14 * (DETWS_ESPNOW_MAX_PEERS, no heap). Same on host and ESP32.
15 * - **ESP32 binding (ARDUINO):** detws_espnow_begin / add_peer / send /
16 * broadcast over the esp_now API, delivering decoded frames to a callback -
17 * which the application can bridge to WebSocket/SSE.
18 *
19 * ESP-NOW's raw payload is capped at 250 bytes; the 3-byte envelope leaves
20 * DETWS_ESPNOW_MAX_PAYLOAD for data. No stdlib, no heap.
21 *
22 * @author Douglas Quigg (dstroy0)
23 * @date 2026
24 */
25
26#ifndef DETERMINISTICESPASYNCWEBSERVER_ESPNOW_H
27#define DETERMINISTICESPASYNCWEBSERVER_ESPNOW_H
28
29#include "ServerConfig.h"
30#include <stddef.h>
31#include <stdint.h>
32
33#if DETWS_ENABLE_ESPNOW
34
35/** @brief Envelope header size (magic + type + length). */
36#define DETWS_ESPNOW_HDR 3
37/** @brief Magic byte marking a library envelope. */
38#define DETWS_ESPNOW_MAGIC 0xE5
39/** @brief Max application payload per frame (250-byte radio MTU minus the header). */
40#define DETWS_ESPNOW_MAX_PAYLOAD 247
41
42/** @brief 6-byte broadcast address (send to all peers in range). */
43extern const uint8_t DETWS_ESPNOW_BROADCAST[6];
44
45// ---------------------------------------------------------------------------
46// Host-testable core: envelope codec
47// ---------------------------------------------------------------------------
48
49/**
50 * @brief Frame a message: [magic][type][len] + payload.
51 * @return total bytes written to @p out, or 0 if it does not fit / payload too big.
52 */
53size_t detws_espnow_encode(uint8_t type, const uint8_t *payload, size_t len, uint8_t *out, size_t cap);
54
55/**
56 * @brief Validate and unpack a framed message.
57 *
58 * Checks the magic and that the declared length matches @p len exactly.
59 * @param payload set to point inside @p buf (no copy).
60 * @return true on a well-formed envelope.
61 */
62bool detws_espnow_decode(const uint8_t *buf, size_t len, uint8_t *type, const uint8_t **payload, size_t *plen);
63
64// ---------------------------------------------------------------------------
65// Host-testable core: bounded peer registry
66// ---------------------------------------------------------------------------
67
68/** @brief Forget all registered peers. */
69void detws_espnow_peers_reset(void);
70/** @brief Register @p mac (idempotent). @return false if the table is full. */
71bool detws_espnow_peer_add(const uint8_t mac[6]);
72/** @brief @return true if @p mac is in the peer registry. */
73bool detws_espnow_peer_has(const uint8_t mac[6]);
74/** @brief Remove @p mac from the registry. @return true if it was present. */
75bool detws_espnow_peer_remove(const uint8_t mac[6]);
76/** @brief @return the number of registered peers. */
77int detws_espnow_peer_count(void);
78
79// ---------------------------------------------------------------------------
80// ESP32 radio binding (returns false on host)
81// ---------------------------------------------------------------------------
82
83/** @brief Decoded-frame callback: sender MAC, message type, payload. */
84typedef void (*detws_espnow_recv_fn)(const uint8_t mac[6], uint8_t type, const uint8_t *payload, size_t len);
85
86/**
87 * @brief Initialize ESP-NOW on @p channel and deliver decoded frames to @p cb.
88 *
89 * WiFi must already be started (STA or AP). Registers the broadcast peer.
90 * @return true on success (ESP32 only).
91 */
92bool detws_espnow_begin(uint8_t channel, detws_espnow_recv_fn cb);
93
94/** @brief Add a unicast peer to both the registry and the radio. */
95bool detws_espnow_add_peer(const uint8_t mac[6]);
96
97/** @brief Encode and transmit a message to @p mac. @return true if queued to the radio. */
98bool detws_espnow_send(const uint8_t mac[6], uint8_t type, const uint8_t *payload, size_t len);
99
100/** @brief Send to the broadcast address (all peers in range). */
101bool detws_espnow_broadcast(uint8_t type, const uint8_t *payload, size_t len);
102
103#endif // DETWS_ENABLE_ESPNOW
104#endif // DETERMINISTICESPASYNCWEBSERVER_ESPNOW_H
User-facing configuration for DeterministicESPAsyncWebServer.