Skip to content

Commit 856a76d

Browse files
committed
Improve error reporting
1 parent 015d751 commit 856a76d

File tree

4 files changed

+28
-24
lines changed

4 files changed

+28
-24
lines changed

arduino-modbus-rtu-tcp-gateway/02-modbus-tcp.ino

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121
deleteRequest
2222
- deletes requests from queue
2323
24-
getSlaveResponding, setSlaveResponding
24+
getSlaveStatus, setSlaveStatus
2525
- read from and write to bool array
2626
2727
***************************************************************** */
2828

29-
// bool array for storing Modbus RTU status (responging or not responding). Array index corresponds to slave address.
30-
uint8_t slavesResponding[(maxSlaves + 1 + 7) / 8];
29+
// bool arrays for storing Modbus RTU status (responging or not responding). Array index corresponds to slave address.
30+
uint8_t responding[(maxSlaves + 1 + 7) / 8];
31+
uint8_t error[(maxSlaves + 1 + 7) / 8];
3132
uint8_t masks[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
3233

3334
typedef struct {
@@ -45,6 +46,7 @@ CircularBuffer<byte, reqQueueSize> queuePDUs; // queue of PDU data (funct
4546
CircularBuffer<byte, reqQueueCount> queueRetries; // queue of retry counters
4647
byte pduStart; // first byte of Protocol Data Unit (i.e. Function code)
4748

49+
4850
void recvUdp() {
4951
unsigned int packetSize = Udp.parsePacket();
5052
if (packetSize) {
@@ -146,7 +148,7 @@ void processRequests() {
146148
if (!queueHeaders.isEmpty()) {
147149
boolean queueHasRespondingSlaves; // true if queue holds at least one request to responding slaves
148150
for (byte i = 0; i < queueHeaders.size(); i++) {
149-
if (getSlaveResponding(queueHeaders[i].uid) == true) {
151+
if (getSlaveStatus(queueHeaders[i].uid, responding) == true) {
150152
queueHasRespondingSlaves = true;
151153
break;
152154
} else {
@@ -194,15 +196,13 @@ void deleteRequest() // delete request from queue
194196
queueRetries.shift();
195197
}
196198

197-
198-
bool getSlaveResponding(const uint8_t index) {
199+
bool getSlaveStatus(const uint8_t index, const uint8_t status[]) {
199200
if (index >= maxSlaves) return false; // error
200-
return (slavesResponding[index / 8] & masks[index & 7]) > 0;
201+
return (status[index / 8] & masks[index & 7]) > 0;
201202
}
202203

203-
204-
void setSlaveResponding(const uint8_t index, const bool value) {
204+
void setSlaveStatus(const uint8_t index, uint8_t status[], const bool value) {
205205
if (index >= maxSlaves) return; // error
206-
if (value == 0) slavesResponding[index / 8] &= ~masks[index & 7];
207-
else slavesResponding[index / 8] |= masks[index & 7];
206+
if (value == 0) status[index / 8] &= ~masks[index & 7];
207+
else status[index / 8] |= masks[index & 7];
208208
}

arduino-modbus-rtu-tcp-gateway/03-modbus-rtu.ino

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ void recvSerial() {
9696
// Checks: 1) RTU frame is without errors; 2) CRC; 3) address of incoming packet against first request in queue; 4) only expected responses are forwarded to TCP/UDP
9797
header myHeader = queueHeaders.first();
9898
if (!rxErr && checkCRC(serialIn, rxNdx) == true && serialIn[0] == myHeader.uid && serialState == WAITING) {
99-
setSlaveResponding(serialIn[0], true); // flag slave as responding
100-
99+
setSlaveStatus(serialIn[0], responding, true); // flag slave as responding
100+
setSlaveStatus(serialIn[0], error, false); // flag slave as without error
101101
byte MBAP[] = { myHeader.tid[0], myHeader.tid[1], 0x00, 0x00, highByte(rxNdx - 2), lowByte(rxNdx - 2) };
102102
if (myHeader.clientNum == UDP_REQUEST) {
103103
Udp.beginPacket(myHeader.remIP, myHeader.remPort);
@@ -113,8 +113,7 @@ void recvSerial() {
113113
#endif /* ENABLE_EXTRA_DIAG */
114114
} else if (myHeader.clientNum != SCAN_REQUEST) {
115115
EthernetClient client = EthernetClient(myHeader.clientNum);
116-
// make sure that this is really our socket
117-
if (client.localPort() == localConfig.tcpPort && (client.status() == SnSR::ESTABLISHED || client.status() == SnSR::CLOSE_WAIT)) {
116+
if (client.connected()) {
118117
if (localConfig.enableRtuOverTcp) client.write(serialIn, rxNdx);
119118
else {
120119
client.write(MBAP, 6);
@@ -137,7 +136,8 @@ void recvSerial() {
137136
// Deal with Serial timeouts (i.e. Modbus RTU timeouts)
138137
if (serialState == WAITING && requestTimeout.isOver()) {
139138
header myHeader = queueHeaders.first();
140-
setSlaveResponding(myHeader.uid, false); // flag slave as nonresponding
139+
setSlaveStatus(myHeader.uid, responding, false); // flag slave as nonresponding
140+
if (myHeader.clientNum != SCAN_REQUEST) setSlaveStatus(myHeader.uid, error, true); // flag slave as error
141141
if (queueRetries.first() >= localConfig.serialAttempts) {
142142
// send modbus error 11 (Gateway Target Device Failed to Respond) - usually means that target device (address) is not present
143143
byte MBAP[] = { myHeader.tid[0], myHeader.tid[1], 0x00, 0x00, 0x00, 0x03 };
@@ -168,8 +168,7 @@ void recvSerial() {
168168
default: // Ethernet client
169169
{
170170
EthernetClient client = EthernetClient(myHeader.clientNum);
171-
// make sure that this is really our socket
172-
if (client.localPort() == localConfig.tcpPort && (client.status() == SnSR::ESTABLISHED || client.status() == SnSR::CLOSE_WAIT)) {
171+
if (client.connected()) {
173172
if (!localConfig.enableRtuOverTcp) {
174173
client.write(MBAP, 6);
175174
}

arduino-modbus-rtu-tcp-gateway/04-webserver.ino

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ void processPost(char postParameter[]) {
332332
break;
333333
case SCAN:
334334
scanCounter = 1;
335+
memset(responding, 0, sizeof(responding)); // clear status flags
336+
memset(error, 0, sizeof(error));
335337
break;
336338
default:
337339
break;

arduino-modbus-rtu-tcp-gateway/05-pages.ino

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void sendPage(EthernetClient &client, byte reqPage) {
3838
chunked.print(F("<!DOCTYPE html>"
3939
"<html>"
4040
"<head>"
41-
"<meta charset=utf-8"));
41+
"<meta"));
4242
if (reqPage == PAGE_STATUS || reqPage == PAGE_WAIT) chunked.print(F(" http-equiv=refresh content=5"));
4343
if (reqPage == PAGE_WAIT) { // redirect to new IP and web port
4444
chunked.print(F(";url=http://"));
@@ -82,7 +82,7 @@ void sendPage(EthernetClient &client, byte reqPage) {
8282
menuItem(chunked, i);
8383
chunked.print(F("</a>"));
8484
}
85-
chunked.print(F("</table><td valign=top style=padding:0px>"));
85+
chunked.print(F("</table><td style=padding:0>"));
8686

8787
// Main Page
8888
chunked.print(F("<form action=/"));
@@ -334,11 +334,11 @@ void contentStatus(ChunkedPrint &chunked) {
334334
if (ipTemp != 0 && ipTemp != 0xFFFFFFFF) {
335335
if (clientDiag.status() == SnSR::UDP && clientDiag.localPort() == localConfig.udpPort) {
336336
chunked.print(F("<td><tr><td>UDP:<td>"));
337-
chunked.print(ipTemp);
337+
chunked.print((IPAddress)ipTemp);
338338
countMasters++;
339339
} else if (clientDiag.localPort() == localConfig.tcpPort) {
340340
chunked.print(F("<td><tr><td>TCP:<td>"));
341-
chunked.print(ipTemp);
341+
chunked.print((IPAddress)ipTemp);
342342
countMasters++;
343343
}
344344
}
@@ -352,13 +352,16 @@ void contentStatus(ChunkedPrint &chunked) {
352352
chunked.print(F(">Scan</button>"));
353353
byte countSlaves = 0;
354354
for (int k = 1; k < maxSlaves; k++) {
355-
if (getSlaveResponding(k) == true || k == scanCounter) {
355+
if (getSlaveStatus(k, responding) == true || getSlaveStatus(k, error) == true || k == scanCounter) {
356356
chunked.print(F("<tr><td><td>0x"));
357357
if (k < 16) chunked.print(F("0"));
358358
chunked.print(k, HEX);
359-
if (getSlaveResponding(k) == true) {
359+
if (getSlaveStatus(k, responding) == true) {
360360
chunked.print(F(" OK"));
361361
countSlaves++;
362+
} else if (getSlaveStatus(k, error) == true) {
363+
chunked.print(F(" Failed to respond"));
364+
countSlaves++;
362365
} else chunked.print(F(" scanning..."));
363366
}
364367
}

0 commit comments

Comments
 (0)