From bf0f7316b91fefee536a6b5dba1325cb6420fd63 Mon Sep 17 00:00:00 2001 From: Damian Wrobel Date: Wed, 2 Oct 2024 21:34:48 +0200 Subject: [PATCH] Avoid sending more then one Modbus TCP response (#22223) Prevent from sending more then one Modbus TCP response for a single request. This might happen in the following scenario where, shortly after the first response has been sent (4), the second one will be send (8) (note the same 'TransactionId') triggered by the response to the 'ModbusSend' request issued by Berry (5). The log excerpt from such a situation: (1) 21:13:20.510 MBS: MBRTCP to Modbus TransactionId:520, deviceAddress:4, functionCode:3, startAddress:8193, count:1, recvCount:1, recvBytes:2 (2) 21:13:20.523 MBS: Serial Send: 04 03 20 01 00 01 DE 5F (3) 21:13:20.647 MBS: Serial Received: 04 03 02 0A 28 72 FA (4) 21:13:20.652 MBS: MBRTCP from Modbus TransactionId:520, deviceAddress:4, writing:11 bytes to client (error:0) (5) 21:13:20.724 CMD: Grp 0, Cmd 'MODBUSSEND', Idx 1, Len 89, Pld -99, Data '{"deviceAddress":4, "functionCode":6, "startAddress":8192, "type":"uint16", "Values":[6]}' (6) 21:13:20.743 MBS: Serial Send: 04 06 20 00 00 06 02 5D (7) 21:13:21.009 MBS: Serial Received: 04 06 20 00 00 06 02 5D (8) 21:13:21.014 MBS: MBRTCP from Modbus TransactionId:520, deviceAddress:4, writing:12 bytes to client (error:0) Use 'tcp_transaction_id' field to denote that we already sent a response. Signed-off-by: Damian Wrobel --- tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino index 9de7ae10e..0e9cf07d9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino @@ -98,7 +98,11 @@ struct ModbusBridgeTCP uint8_t client_next = 0; uint8_t *tcp_buf = nullptr; // data transfer buffer IPAddress ip_filter; - uint16_t tcp_transaction_id = 0; +# define MODBUS_TCP_INVALID_TRANSACTION_ID UINT32_MAX + // Invalid ID value denotes, that the data 'tcp_buf' points to + // should not be used to send Modbus TCP response (very likely + // the response was already sent). + uint32_t tcp_transaction_id = MODBUS_TCP_INVALID_TRANSACTION_ID; bool output_mqtt = false; }; @@ -336,7 +340,7 @@ void ModbusBridgeHandle(void) for (uint32_t i = 0; i < nitems(modbusBridgeTCP.client_tcp); i++) { WiFiClient &client = modbusBridgeTCP.client_tcp[i]; - if (client) + if (client && modbusBridgeTCP.tcp_transaction_id != MODBUS_TCP_INVALID_TRANSACTION_ID) { uint8_t header[9]; uint8_t nrOfBytes = 8; @@ -376,6 +380,7 @@ void ModbusBridgeHandle(void) } client.flush(); AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBRTCP from Modbus TransactionId:%d, deviceAddress:%d, writing:%d bytes to client (error:%d)"), (static_cast(header[0]) << 8) + header[1], modbusBridge.buffer[0], nrOfBytes, error); + modbusBridgeTCP.tcp_transaction_id = MODBUS_TCP_INVALID_TRANSACTION_ID; } } #endif @@ -727,6 +732,8 @@ void ModbusTCPHandle(void) client.stop(); client = new_client; } + + modbusBridgeTCP.tcp_transaction_id = MODBUS_TCP_INVALID_TRANSACTION_ID; } do