DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
enocean.cpp
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 enocean.cpp
6 * @brief EnOcean ESP3 serial codec - implementation.
7 *
8 * ESP3 telegram: 0x55 | data-len(2) | opt-len(1) | type(1) | CRC8H | data | opt | CRC8D.
9 * CRC-8 is polynomial 0x07, MSB-first, init 0x00 (the ESP3 u8CRC8Table generator).
10 */
11
13
14#if DETWS_ENABLE_ENOCEAN
15
16#include <string.h>
17
18uint8_t esp3_crc8(const uint8_t *buf, uint16_t len)
19{
20 uint8_t crc = 0;
21 for (uint16_t i = 0; i < len; i++)
22 {
23 crc ^= buf[i];
24 for (uint8_t b = 0; b < 8; b++)
25 crc = (crc & 0x80) ? (uint8_t)((crc << 1) ^ 0x07) : (uint8_t)(crc << 1);
26 }
27 return crc;
28}
29
30int esp3_parse(const uint8_t *raw, uint16_t len, esp3_packet *out)
31{
32 if (!raw || len < 1)
33 return 0;
34 if (raw[0] != ESP3_SYNC)
35 return -1; // not a telegram start
36 if (len < 6)
37 return 0; // need sync + 4-byte header + CRC8H
38 uint16_t data_len = (uint16_t)((raw[1] << 8) | raw[2]);
39 uint8_t opt_len = raw[3];
40 uint8_t type = raw[4];
41 if (data_len > DETWS_ENOCEAN_MAX_DATA)
42 return -1; // implausible length -> resynchronise
43 if (esp3_crc8(&raw[1], 4) != raw[5])
44 return -1; // header CRC mismatch
45 uint32_t total = 6u + data_len + opt_len + 1u;
46 if (len < total)
47 return 0; // wait for the rest of the telegram
48 if (esp3_crc8(&raw[6], (uint16_t)(data_len + opt_len)) != raw[6 + data_len + opt_len])
49 return -1; // data CRC mismatch
50 if (out)
51 {
52 out->type = (esp3_type)type;
53 out->data = &raw[6];
54 out->data_len = data_len;
55 out->opt = &raw[6 + data_len];
56 out->opt_len = opt_len;
57 }
58 return (int)total;
59}
60
61uint16_t esp3_build(esp3_type type, const uint8_t *data, uint16_t data_len, const uint8_t *opt, uint8_t opt_len,
62 uint8_t *out, uint16_t cap)
63{
64 if (!out || data_len > DETWS_ENOCEAN_MAX_DATA)
65 return 0;
66 uint32_t total = 6u + data_len + opt_len + 1u;
67 if (total > cap)
68 return 0;
69 out[0] = ESP3_SYNC;
70 out[1] = (uint8_t)(data_len >> 8);
71 out[2] = (uint8_t)(data_len & 0xFF);
72 out[3] = opt_len;
73 out[4] = (uint8_t)type;
74 out[5] = esp3_crc8(&out[1], 4);
75 for (uint16_t i = 0; i < data_len; i++)
76 out[6 + i] = data[i];
77 for (uint8_t i = 0; i < opt_len; i++)
78 out[6 + data_len + i] = opt[i];
79 out[6 + data_len + opt_len] = esp3_crc8(&out[6], (uint16_t)(data_len + opt_len));
80 return (uint16_t)total;
81}
82
83#endif // DETWS_ENABLE_ENOCEAN
#define DETWS_ENOCEAN_MAX_DATA
Reject an ESP3 telegram whose declared data length exceeds this (framing sanity).
EnOcean ESP3 serial codec (DETWS_ENABLE_ENOCEAN) - energy-harvesting 868 MHz.