DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
senml.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 senml.h
6 * @brief SenML (RFC 8428) sensor-measurement pack builder (DETWS_ENABLE_SENML) - zero-heap
7 * SenML-JSON and SenML-CBOR encoders over the shipped JSON / CBOR codecs. SenML is
8 * the standard measurement format for CoAP / LwM2M / HTTP telemetry.
9 *
10 * A SenML pack is an array of records. Each record carries an optional base name / base time
11 * (applied to the records that follow), a name, a unit, and exactly one value (a number, a
12 * string, or a boolean), plus an optional time:
13 * @code
14 * [{"bn":"urn:dev:ow:10e2073a01080063","u":"Cel","v":23.1}]
15 * @endcode
16 * SenML-JSON uses the text labels (bn/bt/n/u/v/vs/vb/t); SenML-CBOR uses the integer labels
17 * (n=0 u=1 v=2 vs=3 vb=4 t=6, bn=-2 bt=-3) in a CBOR map per record. Numbers that are
18 * integral are emitted as integers (so timestamps keep full precision); otherwise as floats.
19 *
20 * The caller fills a @ref SenmlRecord array and the builder emits the whole pack into a
21 * caller buffer (fail-closed on overflow). Verified against the RFC 8428 example.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef DETERMINISTICESPASYNCWEBSERVER_SENML_H
28#define DETERMINISTICESPASYNCWEBSERVER_SENML_H
29
30#include "ServerConfig.h"
31
32#if DETWS_ENABLE_SENML
33
34#include <stddef.h>
35#include <stdint.h>
36
37/** @brief Which value field a record carries. */
38enum class SenmlValueKind : uint8_t
39{
40 SENML_V_NONE, ///< no value (e.g. a base-only record)
41 SENML_V_FLOAT, ///< numeric value (v) - emitted as int when integral, else float
42 SENML_V_STRING, ///< string value (vs)
43 SENML_V_BOOL ///< boolean value (vb)
44};
45
46/** @brief One SenML record. String pointers are borrowed (not copied); nullptr fields are skipped. */
47struct SenmlRecord
48{
49 const char *base_name; ///< bn (optional)
50 bool has_base_time;
51 double base_time; ///< bt (optional)
52 const char *name; ///< n (optional)
53 const char *unit; ///< u (optional)
54 SenmlValueKind value_kind;
55 double value; ///< v (when value_kind == SenmlValueKind::SENML_V_FLOAT)
56 const char *value_str; ///< vs (when value_kind == SenmlValueKind::SENML_V_STRING)
57 bool value_bool; ///< vb (when value_kind == SenmlValueKind::SENML_V_BOOL)
58 bool has_time;
59 double time; ///< t (optional)
60};
61
62/** @brief Build a SenML-JSON pack. Returns bytes written (excluding NUL), or 0 on overflow. */
63size_t senml_json_build(char *buf, size_t cap, const SenmlRecord *records, size_t count);
64
65/** @brief Build a SenML-CBOR pack (a CBOR array of integer-keyed maps). Returns bytes, or 0. */
66size_t senml_cbor_build(uint8_t *buf, size_t cap, const SenmlRecord *records, size_t count);
67
68#endif // DETWS_ENABLE_SENML
69
70#endif // DETERMINISTICESPASYNCWEBSERVER_SENML_H
User-facing configuration for DeterministicESPAsyncWebServer.