ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
sep2.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 sep2.cpp
6 * @brief IEEE 2030.5 resource codec (see sep2.h).
7 */
8
10#include "shared_primitives/strbuf.h" // pc_sb frame builder
11
12#if PC_ENABLE_SEP2
13
14#include <string.h>
15
16namespace
17{
18void put_i64(pc_sb *b, int64_t v)
19{
20 if (!b->ok)
21 {
22 return;
23 }
24 char tmp[21];
25 int n = 0;
26 bool neg = v < 0;
27 uint64_t u = neg ? (uint64_t)(-(v + 1)) + 1 : (uint64_t)v;
28 do
29 {
30 tmp[n++] = (char)('0' + (int)(u % 10));
31 u /= 10;
32 } while (u);
33 char out[22];
34 int k = 0;
35 if (neg)
36 {
37 out[k++] = '-';
38 }
39 for (int i = 0; i < n; i++)
40 {
41 out[k++] = tmp[n - 1 - i];
42 }
43 out[k] = '\0';
44 pc_sb_put(b, out);
45}
46
47const char *NS = " xmlns=\"urn:ieee:std:2030.5:ns\"";
48const char *DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
49} // namespace
50
51size_t pc_sep2_device_capability(uint32_t poll_rate, const char *edev_list_href, const char *derp_list_href, char *out,
52 size_t cap)
53{
54 pc_sb b = {out, cap, 0, out != nullptr && cap > 0};
55 pc_sb_put(&b, DECL);
56 pc_sb_put(&b, "<DeviceCapability");
57 pc_sb_put(&b, NS);
58 pc_sb_put(&b, " pollRate=\"");
59 put_i64(&b, poll_rate);
60 pc_sb_put(&b, "\">");
61 pc_sb_put(&b, "<EndDeviceListLink href=\"");
62 pc_sb_xml(&b, edev_list_href);
63 pc_sb_put(&b, "\"/>");
64 pc_sb_put(&b, "<DERProgramListLink href=\"");
65 pc_sb_xml(&b, derp_list_href);
66 pc_sb_put(&b, "\"/>");
67 pc_sb_put(&b, "</DeviceCapability>");
68 return pc_sb_finish(&b);
69}
70
71size_t pc_sep2_end_device(uint64_t sfdi, const char *lfdi, const char *href, char *out, size_t cap)
72{
73 pc_sb b2 = {out, cap, 0, out != nullptr && cap > 0};
74 pc_sb_put(&b2, DECL);
75 pc_sb_put(&b2, "<EndDevice");
76 pc_sb_put(&b2, NS);
77 pc_sb_put(&b2, " href=\"");
78 pc_sb_xml(&b2, href);
79 pc_sb_put(&b2, "\"><sFDI>");
80 put_i64(&b2, (int64_t)sfdi);
81 pc_sb_put(&b2, "</sFDI><lFDI>");
82 pc_sb_xml(&b2, lfdi);
83 pc_sb_put(&b2, "</lFDI></EndDevice>");
84 return pc_sb_finish(&b2);
85}
86
87size_t pc_sep2_der_control(const char *mrid, uint32_t start, uint32_t duration, int32_t opmod_target_w, char *out,
88 size_t cap)
89{
90 pc_sb b3 = {out, cap, 0, out != nullptr && cap > 0};
91 pc_sb_put(&b3, DECL);
92 pc_sb_put(&b3, "<DERControl");
93 pc_sb_put(&b3, NS);
94 pc_sb_put(&b3, "><mRID>");
95 pc_sb_xml(&b3, mrid);
96 pc_sb_put(&b3, "</mRID><interval><start>");
97 put_i64(&b3, start);
98 pc_sb_put(&b3, "</start><duration>");
99 put_i64(&b3, duration);
100 pc_sb_put(&b3, "</duration></interval><DERControlBase><opModFixedW>");
101 put_i64(&b3, opmod_target_w);
102 pc_sb_put(&b3, "</opModFixedW></DERControlBase></DERControl>");
103 return pc_sb_finish(&b3);
104}
105
106#endif // PC_ENABLE_SEP2
IEEE 2030.5 (Smart Energy Profile 2.0) resource codec (PC_ENABLE_SEP2).
Bounded no-heap string builder that fails closed on overflow (one shared copy).
size_t pc_sb_finish(pc_sb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
Definition strbuf.h:648
void pc_sb_xml(pc_sb *b, const char *s)
Append s XML-escaped (& < > "); a NULL s appends nothing.
Definition strbuf.h:143
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
Definition strbuf.h:60
Bump-append target; ok latches false once an append would overflow cap.
Definition strbuf.h:30
bool ok
Definition strbuf.h:34