11#if DETWS_ENABLE_SUNSPEC
15static uint16_t be16(
const uint8_t *p)
17 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
20static uint32_t
be32(
const uint8_t *p)
22 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
25bool sunspec_check_marker(
const uint8_t *regs,
size_t len)
27 return regs && len >= 4 &&
be32(regs) == SUNSPEC_MARKER;
30bool sunspec_begin(
const uint8_t *regs,
size_t len,
size_t *offset)
32 if (!offset || !sunspec_check_marker(regs, len))
38bool sunspec_next_model(
const uint8_t *regs,
size_t len,
size_t *offset, SunSpecModel *out)
40 if (!regs || !offset || !out)
45 uint16_t
id = be16(regs + o);
46 uint16_t length = be16(regs + o + 2);
47 if (
id == SUNSPEC_END_MODEL)
49 size_t body_len = (size_t)length * 2;
50 if (o + 4 + body_len > len)
54 out->body = regs + o + 4;
55 out->body_len = body_len;
56 *offset = o + 4 + body_len;
60uint16_t sunspec_u16(
const uint8_t *body,
size_t reg)
62 return be16(body + reg * 2);
65int16_t sunspec_i16(
const uint8_t *body,
size_t reg)
67 return (int16_t)be16(body + reg * 2);
70uint32_t sunspec_u32(
const uint8_t *body,
size_t reg)
72 return be32(body + reg * 2);
75int32_t sunspec_i32(
const uint8_t *body,
size_t reg)
77 return (int32_t)
be32(body + reg * 2);
80bool sunspec_string(
const uint8_t *body,
size_t reg,
size_t nregs,
char *out,
size_t out_cap)
82 if (!body || !out || out_cap == 0)
84 size_t avail = nregs * 2;
86 const uint8_t *p = body + reg * 2;
87 for (; i < avail && i < out_cap - 1; i++)
99void sunspec_writer_init(SunSpecWriter *w, uint8_t *buf,
size_t cap)
107static bool ss_put(SunSpecWriter *w,
const uint8_t *p,
size_t n)
111 if (w->pos + n > w->cap)
116 memcpy(w->buf + w->pos, p, n);
121bool sunspec_write_u16(SunSpecWriter *w, uint16_t v)
123 uint8_t b[2] = {(uint8_t)(v >> 8), (uint8_t)v};
124 return ss_put(w, b, 2);
127bool sunspec_write_i16(SunSpecWriter *w, int16_t v)
129 return sunspec_write_u16(w, (uint16_t)v);
132bool sunspec_write_u32(SunSpecWriter *w, uint32_t v)
134 uint8_t b[4] = {(uint8_t)(v >> 24), (uint8_t)(v >> 16), (uint8_t)(v >> 8), (uint8_t)v};
135 return ss_put(w, b, 4);
138bool sunspec_write_i32(SunSpecWriter *w, int32_t v)
140 return sunspec_write_u32(w, (uint32_t)v);
143bool sunspec_write_marker(SunSpecWriter *w)
145 return sunspec_write_u32(w, SUNSPEC_MARKER);
148bool sunspec_write_model_header(SunSpecWriter *w, uint16_t
id, uint16_t length)
150 return sunspec_write_u16(w,
id) && sunspec_write_u16(w, length);
153bool sunspec_write_string(SunSpecWriter *w,
const char *s,
size_t nregs)
157 size_t field = nregs * 2;
160 if (w->pos + field > w->cap)
165 size_t slen = strnlen(s, field);
166 for (
size_t i = 0; i < field; i++)
167 w->buf[w->pos + i] = (i < slen) ? (uint8_t)s[i] : 0;
172bool sunspec_write_end_model(SunSpecWriter *w)
174 return sunspec_write_u16(w, SUNSPEC_END_MODEL) && sunspec_write_u16(w, 0);
177size_t sunspec_writer_finish(SunSpecWriter *w)
179 return w->error ? 0 : w->pos;
uint32_t be32(const uint8_t *p)
SunSpec Modbus device-information-model codec (DETWS_ENABLE_SUNSPEC) - zero-heap model-chain walker +...