DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
openadr.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 openadr.cpp
6 * @brief OpenADR 3.0 JSON codec (see openadr.h).
7 */
8
10
11#if DETWS_ENABLE_OPENADR
12
13#include <string.h>
14
16
17namespace
18{
19void put_json_str(DetSb *b, const char *s)
20{
21 det_sb_put(b, "\"");
22 for (const char *p = s ? s : ""; *p; p++)
23 {
24 if (*p == '"' || *p == '\\')
25 {
26 char esc[3] = {'\\', *p, '\0'};
27 det_sb_put(b, esc);
28 }
29 else if (*p == '\n')
30 det_sb_put(b, "\\n");
31 else
32 {
33 if (b->len + 1 >= b->cap)
34 {
35 b->ok = false;
36 return;
37 }
38 b->p[b->len++] = *p;
39 }
40 }
41 det_sb_put(b, "\"");
42}
43
44void put_u64(DetSb *b, uint64_t v)
45{
46 char tmp[21];
47 int n = 0;
48 do
49 {
50 tmp[n++] = (char)('0' + (int)(v % 10));
51 v /= 10;
52 } while (v);
53 char out[22];
54 for (int i = 0; i < n; i++)
55 out[i] = tmp[n - 1 - i];
56 out[n] = '\0';
57 det_sb_put(b, out);
58}
59
60// Format a double with 3 decimal places (no stdlib). Rounds to milli-units; handles the sign.
61void put_double(DetSb *b, double v)
62{
63 if (v < 0)
64 {
65 det_sb_put(b, "-");
66 v = -v;
67 }
68 // scale by 1000 and round.
69 uint64_t scaled = (uint64_t)(v * 1000.0 + 0.5);
70 uint64_t whole = scaled / 1000;
71 uint32_t frac = (uint32_t)(scaled % 1000);
72 put_u64(b, whole);
73 det_sb_put(b, ".");
74 // three digits, zero-padded.
75 char f[4] = {(char)('0' + (frac / 100) % 10), (char)('0' + (frac / 10) % 10), (char)('0' + frac % 10), '\0'};
76 det_sb_put(b, f);
77}
78} // namespace
79
80size_t detws_openadr_event(const char *program_id, const char *event_name, const OpenAdrInterval *intervals,
81 size_t count, char *out, size_t cap)
82{
83 if (!out || (count && !intervals))
84 return 0;
85 DetSb b = {out, cap, 0, cap > 0};
86 det_sb_put(&b, "{\"objectType\":\"EVENT\",\"programID\":");
87 put_json_str(&b, program_id);
88 det_sb_put(&b, ",\"eventName\":");
89 put_json_str(&b, event_name);
90 det_sb_put(&b, ",\"intervals\":[");
91 for (size_t i = 0; i < count; i++)
92 {
93 if (i)
94 det_sb_put(&b, ",");
95 det_sb_put(&b, "{\"id\":");
96 put_u64(&b, i);
97 det_sb_put(&b, ",\"interval\":{\"start\":");
98 put_u64(&b, intervals[i].start);
99 det_sb_put(&b, ",\"duration\":");
100 put_u64(&b, intervals[i].duration);
101 det_sb_put(&b, "},\"payloads\":[{\"type\":");
102 put_json_str(&b, intervals[i].type);
103 det_sb_put(&b, ",\"values\":[");
104 put_double(&b, intervals[i].value);
105 det_sb_put(&b, "]}]}");
106 }
107 det_sb_put(&b, "]}");
108 return det_sb_finish(&b);
109}
110
111size_t detws_openadr_report(const char *program_id, const char *event_id, const char *resource_name, double value,
112 uint32_t timestamp, char *out, size_t cap)
113{
114 if (!out)
115 return 0;
116 DetSb b = {out, cap, 0, cap > 0};
117 det_sb_put(&b, "{\"objectType\":\"REPORT\",\"programID\":");
118 put_json_str(&b, program_id);
119 det_sb_put(&b, ",\"eventID\":");
120 put_json_str(&b, event_id);
121 det_sb_put(&b, ",\"resources\":[{\"resourceName\":");
122 put_json_str(&b, resource_name);
123 det_sb_put(&b, ",\"intervals\":[{\"interval\":{\"start\":");
124 put_u64(&b, timestamp);
125 det_sb_put(&b, "},\"payloads\":[{\"type\":\"READING\",\"values\":[");
126 put_double(&b, value);
127 det_sb_put(&b, "]}]}]}]}");
128 return det_sb_finish(&b);
129}
130
131#endif // DETWS_ENABLE_OPENADR
OpenADR 3.0 (Open Automated Demand Response) JSON codec (DETWS_ENABLE_OPENADR).
Bounded no-heap string builder that fails closed on overflow (one shared copy).
size_t det_sb_finish(DetSb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
Definition strbuf.h:90
void det_sb_put(DetSb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
Definition strbuf.h:36
Bump-append target; ok latches false once an append would overflow cap.
Definition strbuf.h:28
size_t len
Definition strbuf.h:31
char * p
Definition strbuf.h:29
bool ok
Definition strbuf.h:32
size_t cap
Definition strbuf.h:30