11#if DETWS_ENABLE_S7COMM
15static size_t put16(uint8_t *p, uint16_t v)
17 p[0] = (uint8_t)(v >> 8);
22static uint16_t get16(
const uint8_t *p)
24 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
28static size_t write_job_header(uint8_t *buf, uint16_t pdu_ref, uint16_t param_len, uint16_t data_len)
31 buf[p++] = S7_PROTOCOL_ID;
32 buf[p++] = S7_ROSCTR_JOB;
33 p += put16(buf + p, 0);
34 p += put16(buf + p, pdu_ref);
35 p += put16(buf + p, param_len);
36 p += put16(buf + p, data_len);
40size_t s7_build_setup(uint8_t *buf,
size_t cap, uint16_t pdu_ref, uint16_t max_amq_calling, uint16_t max_amq_called,
45 const uint16_t param_len = 8;
46 size_t total = 10 + param_len;
49 size_t p = write_job_header(buf, pdu_ref, param_len, 0);
50 buf[p++] = S7_FUNC_SETUP_COMM;
52 p += put16(buf + p, max_amq_calling);
53 p += put16(buf + p, max_amq_called);
54 p += put16(buf + p, pdu_size);
58size_t s7_build_read_request(uint8_t *buf,
size_t cap, uint16_t pdu_ref,
const S7ReadItem *items,
size_t n)
60 if (!buf || !items || n == 0 || n > 0xFF)
62 uint16_t param_len = (uint16_t)(2 + 12 * n);
63 size_t total = 10 + param_len;
66 size_t p = write_job_header(buf, pdu_ref, param_len, 0);
67 buf[p++] = S7_FUNC_READ_VAR;
68 buf[p++] = (uint8_t)n;
69 for (
size_t i = 0; i < n; i++)
71 const S7ReadItem &it = items[i];
74 buf[p++] = S7_SYNTAX_S7ANY;
75 buf[p++] = it.transport_size;
76 p += put16(buf + p, it.count);
77 p += put16(buf + p, it.db_number);
79 uint32_t addr = it.byte_address << 3;
80 buf[p++] = (uint8_t)(addr >> 16);
81 buf[p++] = (uint8_t)(addr >> 8);
82 buf[p++] = (uint8_t)(addr & 0xFF);
87bool s7_parse_header(
const uint8_t *buf,
size_t len, S7Header *out)
89 if (!buf || !out || len < 10)
91 if (buf[0] != S7_PROTOCOL_ID)
94 out->pdu_ref = get16(buf + 4);
95 out->param_len = get16(buf + 6);
96 out->data_len = get16(buf + 8);
99 out->header_len = (out->rosctr == S7_ROSCTR_ACK_DATA) ? 12 : 10;
100 if (out->header_len == 12)
104 out->error_class = buf[10];
105 out->error_code = buf[11];
107 if (out->header_len + (
size_t)out->param_len + (
size_t)out->data_len > len)
109 out->param = buf + out->header_len;
110 out->data = out->param + out->param_len;
114bool s7_read_next_item(
const uint8_t *data,
size_t data_len,
size_t *offset, S7DataItem *out)
116 if (!data || !offset || !out)
119 if (o + 4 > data_len)
121 out->return_code = data[o];
122 out->transport_size = data[o + 1];
123 uint16_t raw_len = get16(data + o + 2);
127 if (out->transport_size == S7_DTS_BIT || out->transport_size == S7_DTS_BYTE || out->transport_size == S7_DTS_INT)
128 bytes = (raw_len + 7) / 8;
132 if (o + 4 + bytes > data_len)
134 out->data = data + o + 4;
135 out->data_len = bytes;
139 if (o < data_len && (bytes & 1))
Siemens S7comm PDU codec (DETWS_ENABLE_S7COMM) - zero-heap builder + parser for the S7-300/400 commun...