add_support_for_modbus_relays (#24812)

This commit is contained in:
Jacek Ziółkowski
2026-06-01 17:23:20 +02:00
committed by GitHub
parent 7a2fbbe7ba
commit 4690b4b2ed
30 changed files with 453 additions and 1 deletions
+12 -1
View File
@@ -238,6 +238,10 @@ enum UserSelectablePins {
GPIO_VID6608_F, GPIO_VID6608_CW, // VID6608
GPIO_MKSKYBLU_TX, GPIO_MKSKYBLU_RX, // MakeSkyBlue solar charge controller
GPIO_MBS_RX_ENA, // Modbus Bridge Serial Receive Enable
#ifdef USE_MODBUS_RELAY // Modbus RTU Relay modules
GPIO_MODBUSRELAY_TX, GPIO_MODBUSRELAY_TX_ENA,
GPIO_MODBUSRELAY_RX, GPIO_MODBUSRELAY_RX_ENA,
#endif
GPIO_SENSOR_END };
// Error as warning to rethink GPIO usage with max 2045
@@ -517,7 +521,7 @@ const char kSensorNames[] PROGMEM =
#endif
D_VID6608_F "|" D_VID6608_CW "|"
D_SENSOR_MKSKYBLU_TX "|" D_SENSOR_MKSKYBLU_RX "|"
D_SENSOR_MBS_RX_ENA "|"
D_SENSOR_MBS_RX_ENA "|" D_MODBUSRELAY_TX "|" D_MODBUSRELAY_TX_ENA "|" D_MODBUSRELAY_RX "|" D_MODBUSRELAY_RX_ENA "|"
;
const char kSensorNamesFixed[] PROGMEM =
@@ -1279,6 +1283,13 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_PIPSOLAR_RX), // pipsolar inverter Serial interface
#endif
#ifdef USE_MODBUS_RELAY
AGPIO(GPIO_MODBUSRELAY_TX),
AGPIO(GPIO_MODBUSRELAY_TX_ENA),
AGPIO(GPIO_MODBUSRELAY_RX),
AGPIO(GPIO_MODBUSRELAY_RX_ENA),
#endif
/*-------------------------------------------------------------------------------------------*\
* ESP32 specifics
\*-------------------------------------------------------------------------------------------*/
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_AF_AF_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_BG_BG_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_CA_AD_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_CS_CZ_H_
+7
View File
@@ -1343,4 +1343,11 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_DE_DE_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_EL_GR_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_EN_GB_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_ES_ES_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_FR_FR_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_FY_NL_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_HE_HE_H_
+6
View File
@@ -1350,4 +1350,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_HU_HU_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr - RX ON"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_IT_IT_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_KO_KO_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_LT_LT_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_NL_NL_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_PL_PL_D_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_PT_BR_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_PT_PT_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_RO_RO_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_RU_RU_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_SK_SK_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_SV_SE_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_TR_TR_H_
+6
View File
@@ -1344,4 +1344,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_UK_UA_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_VI_VN_H_
+6
View File
@@ -1343,4 +1343,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_ZH_CN_H_
+6
View File
@@ -1345,4 +1345,10 @@
#define D_SENSOR_MBS_RX_ENA "ModBr Rx Ena"
// xdrv_94_modbus_relay.ino
#define D_MODBUSRELAY_TX "MbsRelay TX"
#define D_MODBUSRELAY_TX_ENA "MbsRelay TX Ena"
#define D_MODBUSRELAY_RX "MbsRelay RX"
#define D_MODBUSRELAY_RX_ENA "MbsRelay RX Ena"
#endif // _LANGUAGE_ZH_TW_H_
@@ -0,0 +1,272 @@
/*
xdrv_94_modbus_relay.ino - Modbus RTU relay boards support for Tasmota
Copyright (C) 2026 Jacek Ziółkowski
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_MODBUS_RELAY
/*********************************************************************************************\
* Modbus RTU relay boards
*
* Adds support for Modbus RTU relay boards, such as those from Waveshare or generic no-name brands.
* They typically use the same modbus chip, therefore they share the same modbus instruction set and register map.
*
* The module allows control of up to 8 Modbus RTU relay devices, each with a configurable number of outputs.
* The total number of outputs is limited to 32 reduced by the number of already cofigured power outputs in Tasmota.
* The modbus connection settinga and relay devices are defined in a JSON template that can be loaded from
* a file, rule, or script.
*
* Template syntax:
* {"Baud": <baud>, "Devices": [{"A": <address>, "O": <outputs>}, ...]}
*
* Where:
* - <baud> is the configured baud rate for the module (boards have 9600 by default)
* - <address> is the modbus address of the relay device (1-247)
* - <outputs> is the number of outputs for the relay device
*
* Note: These modules have harcoded N81 serial configuration.
*
* Example template for 2 devices with 4 outputs each ):
* {"Baud":9600, "Devices":[{"A":1,"O":4}, {"A":2,"O":4}]}
* Example template for 1 device with 8 outputs:
* {"Baud":9600, "Devices":[{"A":1,"O":8}]}
*
* Note: the addresses don't have to be sequential, neither have to start from 1.
*
* Store the template in a file called modbusrelay.dat, or in a rule called modbusrelay:
*
* rule3 on file#modbusrelay do {"Baud":9600, "Devices": [{"A": 1, "O": 8}]} endon
*
* or in a script section >y.
* *********************************************************************************************/
#define XDRV_94 94
//#define MODBUS_RELAY_DEBUG
#define MODBUS_RELAY_MAX_DEVICES 8
#include <TasmotaModbus.h>
TasmotaModbus *RelayModbus;
typedef struct {
uint8_t address;
uint8_t outputs;
} tModbusRelayDevice;
struct MODBUS_RELAY {
tModbusRelayDevice device[MODBUS_RELAY_MAX_DEVICES];
uint32_t baud_rate;
uint8_t relay_offset;
uint8_t devices;
uint8_t max_outputs;
} ModbusRelay;
uint8_t ModbusRelayDevicesFromTemplate(void) {
String mbrtmplt = "";
#ifdef USE_UFILESYS
mbrtmplt = TfsLoadString("/modbusrelay.dat");
if (mbrtmplt.length()) {
AddLog(LOG_LEVEL_DEBUG, PSTR("MBR: Modbus relay definition loaded from file"));
}
#endif // USE_UFILESYS
#ifdef USE_RULES
if (!mbrtmplt.length()) {
mbrtmplt = RuleLoadFile("MODBUSRELAY");
AddLog(LOG_LEVEL_DEBUG, PSTR("MBR: Modbus relay definition loaded from rule"));
}
#endif // USE_RULES
#ifdef USE_SCRIPT
if (!mbrtmplt.length()) {
mbrtmplt = ScriptLoadSection(">y");
AddLog(LOG_LEVEL_DEBUG, PSTR("MBR: Modbus relay definition loaded from script"));
}
#endif // USE_SCRIPT
uint32_t len = mbrtmplt.length() + 1;
if (len < 7) {
return 0;
}
JsonParser parser((char *)mbrtmplt.c_str());
JsonParserObject root = parser.getRootObject();
if (!root) {
AddLog(LOG_LEVEL_ERROR, PSTR("MBR: JSON template invalid"));
return 0;
}
JsonParserToken val = root[PSTR("Baud")];
uint32_t baud = val ? val.getUInt() : 9600;
ModbusRelay.baud_rate = baud;
JsonParserArray devices = root[PSTR("Devices")].getArray();
if (!devices) {
#ifdef MODBUS_RELAY_DEBUG
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: no devices"));
#endif
return 0;
}
uint8_t count = 0;
uint8_t total_outputs = 0;
for (auto dev : devices) {
if (count >= MODBUS_RELAY_MAX_DEVICES) {
#ifdef MODBUS_RELAY_DEBUG
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: max devices reached"));
#endif
break;
}
JsonParserObject obj = dev.getObject();
if (!obj) {
#ifdef MODBUS_RELAY_DEBUG
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: invalid device object"));
#endif
continue;
}
uint8_t addr = obj[PSTR("A")].getUInt();
uint8_t outs = obj[PSTR("O")].getUInt();
if (addr < 1 || addr > 247 || outs == 0) {
AddLog(LOG_LEVEL_ERROR, PSTR("MBR: invalid device address %d"), addr);
break;
}
ModbusRelay.device[count].address = addr;
ModbusRelay.device[count].outputs = outs;
#ifdef MODBUS_RELAY_DEBUG
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: Created device at address %d with %d outputs"), addr, outs);
#endif
total_outputs += outs;
count++;
}
ModbusRelay.devices = count;
ModbusRelay.max_outputs = total_outputs;
return ModbusRelay.devices;
} // ModbusRelayDevicesFromTemplate
void ModbusRelayModuleInit(void) {
if (PinUsed(GPIO_MODBUSRELAY_TX) && PinUsed(GPIO_MODBUSRELAY_RX)) {
uint8_t num_devices = ModbusRelayDevicesFromTemplate();
if (num_devices > 0) {
RelayModbus = new TasmotaModbus(Pin(GPIO_MODBUSRELAY_RX), Pin(GPIO_MODBUSRELAY_TX), Pin(GPIO_MODBUSRELAY_TX_ENA), Pin(GPIO_MODBUSRELAY_RX_ENA));
RelayModbus->Begin(ModbusRelay.baud_rate, SERIAL_8N1);
ModbusRelay.relay_offset = TasmotaGlobal.devices_present;
UpdateDevicesPresent(ModbusRelay.max_outputs);
}
}
} // ModbusRelayModuleInit
void ModbusRelaySwitchRelay(void) {
power_t rpower = XdrvMailbox.index;
uint32_t max_outputs = ModbusRelay.max_outputs;
DevicesPresentNonDisplayOrLight(max_outputs); // Skip display and/or light(s)
uint32_t relay_offset = ModbusRelay.max_outputs - max_outputs + ModbusRelay.relay_offset;
rpower >>= relay_offset;
for (uint8_t i = 0; i < ModbusRelay.devices; i++) {
uint8_t outs = ModbusRelay.device[i].outputs;
uint8_t addr = ModbusRelay.device[i].address;
uint32_t mask = (outs == 32) ? 0xFFFFFFFF : ((1UL << outs) - 1);
uint32_t state = rpower & mask;
uint16_t writeData[2] = {0};
uint16_t raw_wd0 = (uint16_t)(state & 0xFFFF);
writeData[0] = ((raw_wd0 & 0x00FF) << 8) | ((raw_wd0 & 0xFF00) >> 8);
if (outs > 16) {
uint16_t raw_wd1 = (uint16_t)((state >> 16) & 0xFFFF);
writeData[1] = ((raw_wd1 & 0x00FF) << 8) | ((raw_wd1 & 0xFF00) >> 8);
}
uint8_t err = RelayModbus->Send(addr, 0x0F, 0x0000, outs, writeData);
#ifdef MODBUS_RELAY_DEBUG
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: Send device %d, outputs %d, state %08X, err %u"), addr, outs, state, err);
#endif
if (err) {
AddLog(LOG_LEVEL_ERROR, PSTR("MBR: Send err %u to device %u"), err, addr);
}
else {
uint32_t timeout = millis() + 35;
bool data_ready = false;
while (millis() < timeout) {
if (RelayModbus->ReceiveReady()) {
data_ready = true;
break;
}
yield();
}
if (data_ready) {
uint8_t buf[16] = {0};
uint8_t recv_err = RelayModbus->ReceiveBuffer(buf, 2);
if (recv_err) {
AddLog(LOG_LEVEL_DEBUG, PSTR("MBR: Recv parsing err %u from device %u"), recv_err, addr);
}
else {
uint16_t start = (buf[2] << 8) | buf[3];
uint16_t qty = (buf[4] << 8) | buf[5];
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MBR: Reply deviceAddress: %02X, function: %02X, start:%u count:%u"),
buf[0], buf[1], start, qty);
}
}
else {
AddLog(LOG_LEVEL_DEBUG, PSTR("MBR: Device %u timed out or CRC failed"), addr);
}
}
if (outs == 32) {
rpower = 0;
}
else {
rpower >>= outs;
}
delay(10);
}
} // ModbusRelaySwitchRelay
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv94(uint32_t function) {
bool result = false;
if (FUNC_SETUP_RING2 == function) {
ModbusRelayModuleInit();
}
else if (ModbusRelay.devices > 0) {
switch (function) {
case FUNC_SET_POWER:
ModbusRelaySwitchRelay();
break;
case FUNC_ACTIVE:
result = true;
break;
}
}
return result;
}
#endif // USE_MODBUS_RELAY