11#if DETWS_ENABLE_OPENADR
19void put_json_str(
DetSb *b,
const char *s)
22 for (
const char *p = s ? s :
""; *p; p++)
24 if (*p ==
'"' || *p ==
'\\')
26 char esc[3] = {
'\\', *p,
'\0'};
44void put_u64(
DetSb *b, uint64_t v)
50 tmp[n++] = (char)(
'0' + (
int)(v % 10));
54 for (
int i = 0; i < n; i++)
55 out[i] = tmp[n - 1 - i];
61void put_double(
DetSb *b,
double v)
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);
75 char f[4] = {(char)(
'0' + (frac / 100) % 10), (
char)(
'0' + (frac / 10) % 10), (char)(
'0' + frac % 10),
'\0'};
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)
83 if (!out || (count && !intervals))
85 DetSb b = {out, cap, 0, cap > 0};
86 det_sb_put(&b,
"{\"objectType\":\"EVENT\",\"programID\":");
87 put_json_str(&b, program_id);
89 put_json_str(&b, event_name);
91 for (
size_t i = 0; i < count; i++)
98 put_u64(&b, intervals[i].start);
100 put_u64(&b, intervals[i].duration);
102 put_json_str(&b, intervals[i].type);
104 put_double(&b, intervals[i].value);
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)
116 DetSb b = {out, cap, 0, cap > 0};
117 det_sb_put(&b,
"{\"objectType\":\"REPORT\",\"programID\":");
118 put_json_str(&b, program_id);
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);
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.
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.
Bump-append target; ok latches false once an append would overflow cap.