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 pc_sunspec_check_marker(
const uint8_t *regs,
size_t len)
27 return regs && len >= 4 && be32(regs) == SUNSPEC_MARKER;
30bool pc_sunspec_begin(
const uint8_t *regs,
size_t len,
size_t *offset)
32 if (!offset || !pc_sunspec_check_marker(regs, len))
40bool pc_sunspec_next_model(
const uint8_t *regs,
size_t len,
size_t *offset, SunSpecModel *out)
42 if (!regs || !offset || !out)
51 uint16_t
id = be16(regs + o);
52 uint16_t length = be16(regs + o + 2);
53 if (
id == SUNSPEC_END_MODEL)
57 size_t body_len = (size_t)length * 2;
58 if (o + 4 + body_len > len)
64 out->body = regs + o + 4;
65 out->body_len = body_len;
66 *offset = o + 4 + body_len;
70uint16_t pc_sunspec_u16(
const uint8_t *body,
size_t reg)
72 return be16(body + reg * 2);
75int16_t pc_sunspec_i16(
const uint8_t *body,
size_t reg)
77 return (int16_t)be16(body + reg * 2);
80uint32_t pc_sunspec_u32(
const uint8_t *body,
size_t reg)
82 return be32(body + reg * 2);
85int32_t pc_sunspec_i32(
const uint8_t *body,
size_t reg)
87 return (int32_t)be32(body + reg * 2);
90bool pc_sunspec_string(
const uint8_t *body,
size_t reg,
size_t nregs,
char *out,
size_t out_cap)
92 if (!body || !out || out_cap == 0)
96 size_t avail = nregs * 2;
98 const uint8_t *p = body + reg * 2;
99 for (; i < avail && i < out_cap - 1; i++)
113void pc_sunspec_writer_init(SunSpecWriter *w, uint8_t *buf,
size_t cap)
121static bool ss_put(SunSpecWriter *w,
const uint8_t *p,
size_t n)
127 if (w->pos + n > w->cap)
132 memcpy(w->buf + w->pos, p, n);
137bool pc_sunspec_write_u16(SunSpecWriter *w, uint16_t v)
139 uint8_t b[2] = {(uint8_t)(v >> 8), (uint8_t)v};
140 return ss_put(w, b, 2);
143bool pc_sunspec_write_i16(SunSpecWriter *w, int16_t v)
145 return pc_sunspec_write_u16(w, (uint16_t)v);
148bool pc_sunspec_write_u32(SunSpecWriter *w, uint32_t v)
150 uint8_t b[4] = {(uint8_t)(v >> 24), (uint8_t)(v >> 16), (uint8_t)(v >> 8), (uint8_t)v};
151 return ss_put(w, b, 4);
154bool pc_sunspec_write_i32(SunSpecWriter *w, int32_t v)
156 return pc_sunspec_write_u32(w, (uint32_t)v);
159bool pc_sunspec_write_marker(SunSpecWriter *w)
161 return pc_sunspec_write_u32(w, SUNSPEC_MARKER);
164bool pc_sunspec_write_model_header(SunSpecWriter *w, uint16_t
id, uint16_t length)
166 return pc_sunspec_write_u16(w,
id) && pc_sunspec_write_u16(w, length);
169bool pc_sunspec_write_string(SunSpecWriter *w,
const char *s,
size_t nregs)
175 size_t field = nregs * 2;
180 if (w->pos + field > w->cap)
185 size_t slen = strnlen(s, field);
186 for (
size_t i = 0; i < field; i++)
188 w->buf[w->pos + i] = (i < slen) ? (uint8_t)s[i] : 0;
194bool pc_sunspec_write_end_model(SunSpecWriter *w)
196 return pc_sunspec_write_u16(w, SUNSPEC_END_MODEL) && pc_sunspec_write_u16(w, 0);
199size_t pc_sunspec_writer_finish(SunSpecWriter *w)
201 return w->error ? 0 : w->pos;
SunSpec Modbus device-information-model codec (PC_ENABLE_SUNSPEC) - zero-heap model-chain walker + re...