9
9
- receives Modbus TCP (or Modbus RTU over TCP) messages
10
10
- calls checkRequest
11
11
12
- processRequests
12
+ scanRequest
13
13
- inserts scan request into queue
14
- - optimizes queue
15
14
16
15
checkRequest
17
16
- checks Modbus TCP/UDP requests (correct MBAP header, CRC in case of Modbus RTU over TCP/UDP)
@@ -50,8 +49,10 @@ bool scanReqInQueue = false;
50
49
byte priorityReqInQueue;
51
50
52
51
// array for storing error counts
53
- uint16_t errorCount[STAT_NUM];
54
- uint16_t errorInvalid;
52
+ uint16_t errorCount[STAT_ERROR_0B_QUEUE]; // there is no counter for STAT_ERROR_0B_QUEUE
53
+ uint16_t errorTcpCount;
54
+ uint16_t errorRtuCount;
55
+ uint16_t errorTimeoutCount;
55
56
56
57
uint16_t queueDataSize;
57
58
uint8_t queueHeadersSize;
@@ -68,15 +69,15 @@ typedef struct {
68
69
} header;
69
70
70
71
// each request is stored in 3 queues (all queues are written to, read and deleted in sync)
71
- CircularBuffer<header, MAX_QUEUE_REQUESTS> queueHeaders; // queue of requests' headers and metadata
72
+ CircularBuffer<header, MAX_QUEUE_REQUESTS> queueHeaders; // queue of requests' headers and metadata
72
73
CircularBuffer<byte, MAX_QUEUE_DATA> queueData; // queue of PDU data
73
74
74
75
void recvUdp () {
75
76
unsigned int msgLength = Udp.parsePacket ();
76
77
if (msgLength) {
77
78
#ifdef ENABLE_EXTRA_DIAG
78
79
ethRxCount += msgLength;
79
- #endif /* ENABLE_EXTRA_DIAG */
80
+ #endif /* ENABLE_EXTRA_DIAG */
80
81
byte inBuffer[MODBUS_SIZE + 4 ]; // Modbus TCP frame is 4 bytes longer than Modbus RTU frame
81
82
// Modbus TCP/UDP frame: [0][1] transaction ID, [2][3] protocol ID, [4][5] length and [6] unit ID (address)..... no CRC
82
83
// Modbus RTU frame: [0] address.....[n-1][n] CRC
@@ -117,7 +118,7 @@ void recvTcp() {
117
118
unsigned int msgLength = client.available ();
118
119
#ifdef ENABLE_EXTRA_DIAG
119
120
ethRxCount += msgLength;
120
- #endif /* ENABLE_EXTRA_DIAG */
121
+ #endif /* ENABLE_EXTRA_DIAG */
121
122
byte inBuffer[MODBUS_SIZE + 4 ]; // Modbus TCP frame is 4 bytes longer than Modbus RTU frame
122
123
// Modbus TCP/UDP frame: [0][1] transaction ID, [2][3] protocol ID, [4][5] length and [6] unit ID (address).....
123
124
// Modbus RTU frame: [0] address.....
@@ -150,18 +151,18 @@ void recvTcp() {
150
151
}
151
152
}
152
153
153
- void processRequests () {
154
+ void scanRequest () {
154
155
// Insert scan request into queue, allow only one scan request in a queue
155
156
if (scanCounter != 0 && queueHeaders.available () > 1 && queueData.available () > sizeof (SCAN_COMMAND) + 1 && scanReqInQueue == false ) {
156
157
scanReqInQueue = true ;
157
158
// Store scan request in request queue
158
159
queueHeaders.push (header{
159
- { 0x00 , 0x00 }, // tid[2]
160
+ { 0x00 , 0x00 }, // tid[2]
160
161
sizeof (SCAN_COMMAND) + 1 , // msgLen
161
- {}, // remIP
162
- 0 , // remPort
163
- SCAN_REQUEST, // requestType
164
- 0 , // atts
162
+ {}, // remIP
163
+ 0 , // remPort
164
+ SCAN_REQUEST, // requestType
165
+ 0 , // atts
165
166
});
166
167
queueData.push (scanCounter); // address of the scanned slave
167
168
for (byte i = 0 ; i < sizeof (SCAN_COMMAND); i++) {
@@ -170,32 +171,19 @@ void processRequests() {
170
171
scanCounter++;
171
172
if (scanCounter == MAX_SLAVES + 1 ) scanCounter = 0 ;
172
173
}
173
- // Optimize queue (prioritize requests from responding slaves) and trigger sending via serial
174
- if (serialState == IDLE) { // send new data over serial only if we are not waiting for response
175
- if (!queueHeaders.isEmpty ()) {
176
- while (priorityReqInQueue && (queueHeaders.first ().requestType & PRIORITY_REQUEST) == false ) {
177
- // move requests to non responding slaves to the tail of the queue
178
- for (byte i = 0 ; i < queueHeaders.first ().msgLen ; i++) {
179
- queueData.push (queueData.shift ());
180
- }
181
- queueHeaders.push (queueHeaders.shift ());
182
- }
183
- serialState = SENDING; // trigger sendSerial()
184
- }
185
- }
186
174
}
187
175
188
176
byte checkRequest (const byte inBuffer[], unsigned int msgLength, const IPAddress remoteIP, const unsigned int remotePort, byte requestType) {
189
177
byte addressPos = 6 * !localConfig.enableRtuOverTcp ; // position of slave address in the incoming TCP/UDP message (0 for Modbus RTU over TCP/UDP and 6 for Modbus RTU over TCP/UDP)
190
178
if (localConfig.enableRtuOverTcp ) { // check CRC for Modbus RTU over TCP/UDP
191
179
if (checkCRC (inBuffer, msgLength) == false ) {
192
- errorInvalid ++;
193
- return 0 ; // drop request and do not return an code
180
+ errorTcpCount ++;
181
+ return 0 ; // drop request and do not return any error code
194
182
}
195
183
} else { // check MBAP header structure for Modbus TCP/UDP
196
184
if (inBuffer[2 ] != 0x00 || inBuffer[3 ] != 0x00 || inBuffer[4 ] != 0x00 || inBuffer[5 ] != msgLength - 6 ) {
197
- errorInvalid ++;
198
- return 0 ; // drop request and do not return an code
185
+ errorTcpCount ++;
186
+ return 0 ; // drop request and do not return any error code
199
187
}
200
188
}
201
189
msgLength = msgLength - addressPos - (2 * localConfig.enableRtuOverTcp ); // in Modbus RTU over TCP/UDP do not store CRC
@@ -215,7 +203,9 @@ byte checkRequest(const byte inBuffer[], unsigned int msgLength, const IPAddress
215
203
requestType = requestType | PRIORITY_REQUEST;
216
204
priorityReqInQueue++;
217
205
}
218
-
206
+ if (inBuffer[addressPos] == 0x00 ) { // Modbus Broadcast
207
+ requestType = requestType | SCAN_REQUEST; // Treat broadcast as scan (only one attempt, short timeout, do not expect response)
208
+ }
219
209
// all checkes passed OK, we can store the incoming data in request queue
220
210
// Store in request queue
221
211
queueHeaders.push (header{
@@ -259,6 +249,6 @@ void setSlaveStatus(const uint8_t slave, byte status, const bool value) {
259
249
stat[i][slave / 8 ] &= ~masks[slave & 7 ]; // set all other flags to false
260
250
}
261
251
stat[status][slave / 8 ] |= masks[slave & 7 ];
262
- errorCount[status]++;
252
+ if (status != STAT_ERROR_0B_QUEUE) errorCount[status]++; // there is no counter for STAT_ERROR_0B_QUEUE
263
253
}
264
254
}
0 commit comments