DeterministicESPAsyncWebServer
v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
s7comm.h
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 s7comm.h
6
* @brief Siemens S7comm PDU codec (DETWS_ENABLE_S7COMM) - zero-heap builder + parser for the
7
* S7-300/400 communication PDUs, carried inside a COTP Data TPDU (services/cotp) over
8
* ISO-on-TCP (port 102).
9
*
10
* An S7comm PDU starts with a header then a parameter section then an optional data section:
11
* @code
12
* 0x32 ROSCTR redundancy(2) pdu-ref(2) param-len(2) data-len(2) [err-class err-code]
13
* <parameter ...> <data ...>
14
* @endcode
15
* The header is 10 octets, or 12 for an Ack_Data response (which adds a 2-octet error code).
16
* A Read Var job (function 0x04) carries one or more S7-ANY request items (area / DB / byte
17
* address / element count); the Ack_Data response carries, per item, a return code + a data
18
* transport size + a length + the value bytes. Per the protocol, the response length is in
19
* BITS for the bit/byte/int transport sizes (3/4/5) and in BYTES otherwise, and each item
20
* is padded to an even length except the last.
21
*
22
* Constants and the length rule are verified against the Wireshark S7comm dissector. This
23
* codec produces / consumes the S7 PDU; wrap it with `cotp_build_dt` + `tpkt_build`.
24
*
25
* @author Douglas Quigg (dstroy0)
26
* @date 2026
27
*/
28
29
#ifndef DETERMINISTICESPASYNCWEBSERVER_S7COMM_H
30
#define DETERMINISTICESPASYNCWEBSERVER_S7COMM_H
31
32
#include "
ServerConfig.h
"
33
34
#if DETWS_ENABLE_S7COMM
35
36
#include <stddef.h>
37
#include <stdint.h>
38
39
#define S7_PROTOCOL_ID 0x32
///< constant first octet of every S7comm PDU
40
41
// ROSCTR (message type).
42
#define S7_ROSCTR_JOB 0x01
43
#define S7_ROSCTR_ACK 0x02
44
#define S7_ROSCTR_ACK_DATA 0x03
45
#define S7_ROSCTR_USERDATA 0x07
46
47
// Parameter function codes.
48
#define S7_FUNC_SETUP_COMM 0xF0
49
#define S7_FUNC_READ_VAR 0x04
50
#define S7_FUNC_WRITE_VAR 0x05
51
52
// Memory area codes (in an S7-ANY item).
53
#define S7_AREA_INPUTS 0x81
///< process inputs (I/E)
54
#define S7_AREA_OUTPUTS 0x82
///< process outputs (Q/A)
55
#define S7_AREA_FLAGS 0x83
///< flags / merker (M)
56
#define S7_AREA_DB 0x84
///< data blocks (DB)
57
#define S7_AREA_COUNTER 0x1C
58
#define S7_AREA_TIMER 0x1D
59
60
// Request-item transport sizes (the element type).
61
#define S7_TS_BIT 1
62
#define S7_TS_BYTE 2
63
#define S7_TS_CHAR 3
64
#define S7_TS_WORD 4
65
#define S7_TS_INT 5
66
#define S7_TS_DWORD 6
67
#define S7_TS_DINT 7
68
#define S7_TS_REAL 8
69
70
// Response data transport sizes (length-in-bits for BIT/BYTE/INT = 3/4/5).
71
#define S7_DTS_NULL 0
72
#define S7_DTS_BIT 3
73
#define S7_DTS_BYTE 4
74
#define S7_DTS_INT 5
75
#define S7_DTS_DINT 6
76
#define S7_DTS_REAL 7
77
#define S7_DTS_OCTET 9
78
79
#define S7_SYNTAX_S7ANY 0x10
///< S7-ANY address syntax id
80
#define S7_RET_OK 0xFF
///< data item return code: success
81
82
/** @brief Build a Setup Communication job. Returns the PDU length, or 0 on overflow. */
83
size_t
s7_build_setup(uint8_t *buf,
size_t
cap, uint16_t pdu_ref, uint16_t max_amq_calling, uint16_t max_amq_called,
84
uint16_t pdu_size);
85
86
/** @brief One Read Var item (an S7-ANY pointer). */
87
struct
S7ReadItem
88
{
89
uint8_t area;
///< S7_AREA_*
90
uint16_t db_number;
///< DB number (0 for non-DB areas)
91
uint32_t byte_address;
///< starting byte address
92
uint8_t transport_size;
///< S7_TS_* (element type)
93
uint16_t count;
///< number of elements
94
};
95
96
/** @brief Build a Read Var job for @p n items. Returns the PDU length, or 0 on overflow. */
97
size_t
s7_build_read_request(uint8_t *buf,
size_t
cap, uint16_t pdu_ref,
const
S7ReadItem *items,
size_t
n);
98
99
/** @brief A parsed S7comm header. @ref param / @ref data point INTO the source buffer. */
100
struct
S7Header
101
{
102
uint8_t rosctr;
103
uint16_t pdu_ref;
104
uint16_t param_len;
105
uint16_t data_len;
106
uint8_t error_class;
///< Ack_Data only
107
uint8_t error_code;
///< Ack_Data only
108
size_t
header_len;
///< 10 or 12
109
const
uint8_t *param;
110
const
uint8_t *data;
111
};
112
113
/** @brief Parse + validate an S7comm header (protocol id, lengths). */
114
bool
s7_parse_header(
const
uint8_t *buf,
size_t
len, S7Header *out);
115
116
/** @brief One Read Var response data item. @ref data points INTO the source buffer. */
117
struct
S7DataItem
118
{
119
uint8_t return_code;
///< S7_RET_OK on success
120
uint8_t transport_size;
///< S7_DTS_*
121
const
uint8_t *data;
///< value bytes
122
size_t
data_len;
///< value length in BYTES (the bit length is converted)
123
};
124
125
/**
126
* @brief Read the next Read Var response data item from the data section.
127
* @param data the @ref S7Header data pointer; @param data_len its data_len.
128
* @param offset in/out cursor, start at 0; advanced past the item (and its even-pad).
129
* @return true on a complete item; false at end-of-section or on truncation.
130
*/
131
bool
s7_read_next_item(
const
uint8_t *data,
size_t
data_len,
size_t
*offset, S7DataItem *out);
132
133
#endif
// DETWS_ENABLE_S7COMM
134
135
#endif
// DETERMINISTICESPASYNCWEBSERVER_S7COMM_H
ServerConfig.h
User-facing configuration for DeterministicESPAsyncWebServer.
src
services
s7comm
s7comm.h
Generated by
1.9.8