From a68bc49cabff8239a5854c0b79c705bf062f28fa Mon Sep 17 00:00:00 2001 From: Jeroen Date: Tue, 21 Mar 2023 09:39:32 +0100 Subject: [PATCH] Added option to output TCP requested modbus data to MQTT (#18231) https://github.com/arendst/Tasmota/discussions/17369 Co-authored-by: JeroenSt --- .../xdrv_63_modbus_bridge.ino | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino index ff9a139f95f1..f75217fd15bf 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino @@ -81,12 +81,13 @@ void (*const ModbusBridgeCommand[])(void) PROGMEM = { #define D_CMND_MODBUS_TCP_START "TCPStart" #define D_CMND_MODBUS_TCP_CONNECT "TCPConnect" +#define D_CMND_MODBUS_TCP_MQTT "TCPMqtt" const char kModbusBridgeCommands[] PROGMEM = "Modbus|" // Prefix - D_CMND_MODBUS_TCP_START "|" D_CMND_MODBUS_TCP_CONNECT "|" D_CMND_MODBUS_SEND "|" D_CMND_MODBUS_SETBAUDRATE "|" D_CMND_MODBUS_SETSERIALCONFIG; + D_CMND_MODBUS_TCP_START "|" D_CMND_MODBUS_TCP_CONNECT "|" D_CMND_MODBUS_TCP_MQTT "|" D_CMND_MODBUS_SEND "|" D_CMND_MODBUS_SETBAUDRATE "|" D_CMND_MODBUS_SETSERIALCONFIG; void (*const ModbusBridgeCommand[])(void) PROGMEM = { - &CmndModbusTCPStart, &CmndModbusTCPConnect, + &CmndModbusTCPStart, &CmndModbusTCPConnect, &CmndModbusTCPMqtt, &CmndModbusBridgeSend, &CmndModbusBridgeSetBaudrate, &CmndModbusBridgeSetConfig}; struct ModbusBridgeTCP @@ -97,6 +98,7 @@ struct ModbusBridgeTCP uint8_t *tcp_buf = nullptr; // data transfer buffer IPAddress ip_filter; uint16_t tcp_transaction_id = 0; + bool output_mqtt = false; }; ModbusBridgeTCP modbusBridgeTCP; @@ -328,7 +330,7 @@ void ModbusBridgeHandle(void) { #ifdef USE_MODBUS_BRIDGE_TCP // If tcp client connected don't log error and exit this function (do not process) - if (nitems(modbusBridgeTCP.client_tcp)) + if (nitems(modbusBridgeTCP.client_tcp) && !modbusBridgeTCP.output_mqtt) { return; } @@ -657,25 +659,28 @@ void ModbusTCPHandle(void) modbusBridgeTCP.tcp_transaction_id = (uint16_t)((((uint16_t)modbusBridgeTCP.tcp_buf[0]) << 8) | ((uint16_t)modbusBridgeTCP.tcp_buf[1])); - if (mbfunctioncode <= 2) + if (mbfunctioncode <= 2) // Multiple Coils, Inputs { count = (uint16_t)((((uint16_t)modbusBridgeTCP.tcp_buf[10]) << 8) | ((uint16_t)modbusBridgeTCP.tcp_buf[11])); modbusBridge.byteCount = ((count - 1) >> 3) + 1; - modbusBridge.dataCount = ((count - 1) >> 4) + 1; + modbusBridge.dataCount = count; + modbusBridge.type = ModbusBridgeType::mb_bit; } - else if (mbfunctioncode <= 4) + else if (mbfunctioncode <= 4) // Multiple Holding or input registers { count = (uint16_t)((((uint16_t)modbusBridgeTCP.tcp_buf[10]) << 8) | ((uint16_t)modbusBridgeTCP.tcp_buf[11])); modbusBridge.byteCount = count * 2; modbusBridge.dataCount = count; + modbusBridge.type = ModbusBridgeType::mb_uint16; } - else + else // Write coil(s) or register(s) { // For functioncode 15 & 16 ignore bytecount, modbusBridgeModbus does calculate this uint8_t dataStartByte = mbfunctioncode <= 6 ? 10 : 13; uint16_t byteCount = (buf_len - dataStartByte); modbusBridge.byteCount = 2; modbusBridge.dataCount = 1; + modbusBridge.type = ModbusBridgeType::mb_uint16; writeData = (uint16_t *)malloc((byteCount / 2)+1); if (nullptr == writeData) @@ -705,6 +710,14 @@ void ModbusTCPHandle(void) modbusBridgeModbus->Send(mbdeviceaddress, mbfunctioncode, mbstartaddress, count, writeData); + if (modbusBridgeTCP.output_mqtt) + { + modbusBridge.deviceAddress = mbdeviceaddress; + modbusBridge.functionCode = (ModbusBridgeFunctionCode)mbfunctioncode; + modbusBridge.startAddress = mbstartaddress; + modbusBridge.count = count; + } + free(writeData); } } @@ -1111,6 +1124,12 @@ void CmndModbusTCPConnect(void) ResponseCmndDone(); } + +void CmndModbusTCPMqtt(void) +{ + modbusBridgeTCP.output_mqtt = XdrvMailbox.payload; + ResponseCmndDone(); +} #endif /*********************************************************************************************\