DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
zigbee.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 zigbee.h
6 * @brief Zigbee EZSP / ASH framing codec (DETWS_ENABLE_ZIGBEE) - Silicon Labs NCP.
7 *
8 * The ASH (Asynchronous Serial Host, UG101) data-link layer that carries EZSP frames to a
9 * Silicon Labs EmberZNet network co-processor over UART - a Zigbee network bridged to the
10 * web. Each ASH frame is a control byte + payload + a CRC-16/CCITT, byte-stuffed so the
11 * reserved control bytes never appear in the body, and terminated by a Flag byte (0x7E):
12 *
13 * [control | payload | CRC16(hi,lo)] --byte-stuffed--> ... | 0x7E
14 *
15 * The reserved bytes that get stuffed (as 0x7D followed by byte XOR 0x20) are the Flag
16 * 0x7E, the Escape 0x7D, XON 0x11, XOFF 0x13, Substitute 0x18, and Cancel 0x1A.
17 *
18 * ash_frame_encode() wraps a control byte + payload into a stuffed, CRC'd, flag-terminated
19 * frame; ash_frame_decode() finds the flag, removes the stuffing, and verifies the CRC.
20 * ash_crc16() is the shared CRC. The EZSP command the payload carries (version query, an
21 * incoming APS message, a network-init) is the application's. Pure - you carry the bytes
22 * over your UART - so it is fully host-testable.
23 *
24 * @author Douglas Quigg (dstroy0)
25 * @date 2026
26 */
27
28#ifndef DETERMINISTICESPASYNCWEBSERVER_ZIGBEE_H
29#define DETERMINISTICESPASYNCWEBSERVER_ZIGBEE_H
30
31#include "ServerConfig.h"
32
33#if DETWS_ENABLE_ZIGBEE
34
35#include <stddef.h>
36#include <stdint.h>
37
38/** @brief ASH markers / reset control bytes. */
39struct Ash
40{
41 static constexpr uint8_t ASH_FLAG = 0x7E; ///< frame delimiter
42 static constexpr uint8_t ASH_ESCAPE = 0x7D; ///< byte-stuffing escape
43 static constexpr uint8_t ASH_RST = 0xC0; ///< reset control byte
44 static constexpr uint8_t ASH_RSTACK = 0xC1; ///< reset acknowledge
45 static constexpr uint8_t ASH_ERROR = 0xC2; ///< error
46};
47
48/** @brief CRC-16/CCITT (polynomial 0x1021, MSB-first, init 0xFFFF) over @p buf. */
49uint16_t ash_crc16(const uint8_t *buf, uint16_t len);
50
51/**
52 * @brief Encode an ASH frame: [control | payload] + CRC-16, byte-stuffed, flag-terminated.
53 * @return the encoded frame length, or 0 if @p len exceeds DETWS_ZIGBEE_MAX_DATA or the
54 * stuffed frame would not fit @p cap.
55 */
56uint16_t ash_frame_encode(uint8_t control, const uint8_t *payload, uint16_t len, uint8_t *out, uint16_t cap);
57
58/**
59 * @brief Decode one ASH frame from the front of @p raw: find the flag, remove the stuffing,
60 * verify the CRC, and copy the payload to @p payload (up to @p pay_cap).
61 * @param[out] control set to the frame's control byte.
62 * @param[out] pay_len set to the payload length.
63 * @return the bytes consumed up to and including the flag (> 0), 0 if no flag is present yet
64 * (need more), or -1 if the framed content is malformed (too short, bad CRC, or the
65 * payload overflows @p pay_cap) - the caller drops one byte and retries.
66 */
67int ash_frame_decode(const uint8_t *raw, uint16_t len, uint8_t *control, uint8_t *payload, uint16_t pay_cap,
68 uint16_t *pay_len);
69
70#endif // DETWS_ENABLE_ZIGBEE
71
72#endif // DETERMINISTICESPASYNCWEBSERVER_ZIGBEE_H
User-facing configuration for DeterministicESPAsyncWebServer.