diff --git a/src/modules/exec/EctoControlAdapter/lib/AdapterCommon.h b/src/modules/exec/EctoControlAdapter/AdapterCommon.h similarity index 100% rename from src/modules/exec/EctoControlAdapter/lib/AdapterCommon.h rename to src/modules/exec/EctoControlAdapter/AdapterCommon.h diff --git a/src/modules/exec/EctoControlAdapter/EctoControlAdapter.cpp b/src/modules/exec/EctoControlAdapter/EctoControlAdapter.cpp index 2069027f..c721fa1f 100644 --- a/src/modules/exec/EctoControlAdapter/EctoControlAdapter.cpp +++ b/src/modules/exec/EctoControlAdapter/EctoControlAdapter.cpp @@ -3,13 +3,17 @@ #include #include -#include "lib/rsEctoControl.h" +#include "ModbusEC.h" +#include "AdapterCommon.h" +// #include "Stream.h" +#include + // class ModbusUart; -Stream *_mbUART = nullptr; +Stream *_modbusUART = nullptr; #define UART_LINE 2 - +uint8_t _DIR_PIN = 0; // Modbus stuff // Данные Modbus по умолчанию @@ -17,25 +21,26 @@ Stream *_mbUART = nullptr; #define MODBUS_TX_PIN 19 // Tx pin #define MODBUS_SERIAL_BAUD 9600 // Baud rate for esp32 and max485 communication -// void modbusPreTransmission() -// { -// // delay(500); -// if (_DIR_PIN) -// digitalWrite(_DIR_PIN, HIGH); -// } -// // Pin 4 made low for Modbus receive mode -// // Контакт 4 установлен на низком уровне для режима приема Modbus -// void modbusPostTransmission() -// { -// if (_DIR_PIN) -// digitalWrite(_DIR_PIN, LOW); -// // delay(500); -// } +void modbusPreTransmission() +{ + // delay(500); + if (_DIR_PIN) + digitalWrite(_DIR_PIN, HIGH); +} + +// Pin 4 made low for Modbus receive mode +// Контакт 4 установлен на низком уровне для режима приема Modbus +void modbusPostTransmission() +{ + if (_DIR_PIN) + digitalWrite(_DIR_PIN, LOW); + // delay(500); +} // ModbusMaster node; -RsEctoControl *rsEC; +//RsEctoControl *rsEC; class EctoControlAdapter : public IoTItem { @@ -48,16 +53,43 @@ private: uint8_t _addr = 0xF0; // Адрес слейва от 1 до 247 uint8_t _type = 0x14; // Тип устройства: 0x14 – адаптер OpenTherm (вторая версия); 0x11 – адаптер OpenTherm (первая версия, снята с производства) bool _debugLevel; // Дебаг - //uint8_t _dir_pin; + + ModbusMaster node; + uint8_t _debug; + //Stream *_modbusUART; + + BoilerInfo info; + BoilerStatus status; + + uint16_t code; + uint16_t codeExt; + uint8_t flagErr; + float flow; + float maxSetCH; + float maxSetDHW; + float minSetCH; + float minSetDHW; + float modLevel; + float press; + float tCH; + float tDHW; + float tOut; + bool enableCH; + bool enableDHW; + bool enableCH2; + bool _isNetworkActive; + bool _mqttIsConnect; + + public: EctoControlAdapter(String parameters) : IoTItem(parameters) { - //_dir_pin = 0; + _DIR_PIN = 0; _addr = jsonReadInt(parameters, "addr"); // адреса slave прочитаем с веба _rx = jsonReadInt(parameters, "RX"); // прочитаем с веба _tx = jsonReadInt(parameters, "TX"); - //_dir_pin = jsonReadInt(parameters, "DIR_PIN"); + _DIR_PIN = jsonReadInt(parameters, "DIR_PIN"); _baud = jsonReadInt(parameters, "baud"); _prot = jsonReadStr(parameters, "protocol"); jsonRead(parameters, "debug", _debugLevel); @@ -73,163 +105,200 @@ public: // Serial2.begin(baud-rate, protocol, RX pin, TX pin); - _mbUART = new HardwareSerial(UART_LINE); + _modbusUART = new HardwareSerial(UART_LINE); if (_debugLevel > 2) { SerialPrint("I", "EctoControlAdapter", "baud: " + String(_baud) + ", protocol: " + String(protocol, HEX) + ", RX: " + String(_rx) + ", TX: " + String(_tx)); } - ((HardwareSerial *)_mbUART)->begin(_baud, protocol, _rx, _tx); // выбираем тип протокола, скорость и все пины с веба - ((HardwareSerial *)_mbUART)->setTimeout(200); - rsEC = new RsEctoControl(parameters); - rsEC->begin(_addr, (Stream &)*_mbUART); + ((HardwareSerial *)_modbusUART)->begin(_baud, protocol, _rx, _tx); // выбираем тип протокола, скорость и все пины с веба + ((HardwareSerial *)_modbusUART)->setTimeout(200); + //_modbusUART = &serial; + node.begin(_addr, _modbusUART); + + node.preTransmission(modbusPreTransmission); + node.postTransmission(modbusPostTransmission); + + + if (_DIR_PIN) + { + _DIR_PIN = _DIR_PIN; + pinMode(_DIR_PIN, OUTPUT); + digitalWrite(_DIR_PIN, LOW); + } + + // 0x14 – адаптер OpenTherm (вторая версия) + // 0x15 – адаптер eBus + // 0x16 – адаптер Navien + uint16_t type; + readFunctionModBus(0x0000, type); + if (0x14 != (uint8_t)type || 0x15 != (uint8_t)type || 0x16 != (uint8_t)type) + { + SerialPrint("E", "EctoControlAdapter", "Не подходящее устройство, type: " + String(type, HEX)); + } + + uint8_t addr = node.readAddresEctoControl(); + SerialPrint("I", "EctoControlAdapter", "readAddresEctoControl, addr: " + String(addr, HEX) + " - Enter to configuration"); + + getModelVersion(); + getBoilerInfo(); + getBoilerStatus(); } void doByInterval() { - if (rsEC) - rsEC->doByInterval(); + // readBoilerInfo(); + getBoilerStatus(); + + getCodeError(); + getCodeErrorExt(); + if (info.adapterType == 0) + getFlagErrorOT(); + // getFlowRate(); + // getMaxSetCH(); + // getMaxSetDHW(); + // getMinSetCH(); + // getMinSetDHW(); + getModLevel(); + getPressure(); + getTempCH(); + getTempDHW(); + getTempOutside(); } void loop() { - if (rsEC) - rsEC->loop(isNetworkActive(), mqttIsConnect()); // для новых версий IoTManager IoTItem::loop(); } IoTValue execute(String command, std::vector ¶m) { - if (rsEC) - rsEC->execute(command, param); - else - return {}; if (command == "getModelVersion") { - rsEC->getModelVersion(); + getModelVersion(); } if (command == "getModelVersion") { - rsEC->getModelVersion(); + getModelVersion(); } if (command == "getBoilerInfo") { - rsEC->getBoilerInfo(); + getBoilerInfo(); } if (command == "getBoilerStatus") { - rsEC->getBoilerStatus(); + getBoilerStatus(); } if (command == "getCodeError") { - rsEC->getCodeError(); + getCodeError(); } if (command == "getCodeErrorExt") { - rsEC->getCodeErrorExt(); + getCodeErrorExt(); } if (command == "getFlagErrorOT") { - rsEC->getFlagErrorOT(); + getFlagErrorOT(); } if (command == "getFlowRate") { - rsEC->getFlowRate(); + getFlowRate(); } if (command == "getMaxSetCH") { - rsEC->getMaxSetCH(); + getMaxSetCH(); } if (command == "getMaxSetDHW") { - rsEC->getMaxSetDHW(); + getMaxSetDHW(); } if (command == "getMinSetCH") { - rsEC->getMinSetCH(); + getMinSetCH(); } if (command == "getMinSetDHW") { - rsEC->getMinSetDHW(); + getMinSetDHW(); } if (command == "getModLevel") { - rsEC->getModLevel(); + getModLevel(); } if (command == "getPressure") { - rsEC->getPressure(); + getPressure(); } if (command == "getTempCH") { - rsEC->getTempCH(); + getTempCH(); } if (command == "getTempDHW") { - rsEC->getTempDHW(); + getTempDHW(); } if (command == "getTempOutside") { - rsEC->getTempOutside(); + getTempOutside(); } if (command == "setTypeConnect") { - rsEC->setTypeConnect(param[0].valD); + setTypeConnect(param[0].valD); } if (command == "setTCH") { - rsEC->setTCH(param[0].valD); + setTCH(param[0].valD); } if (command == "setTCHFaultConn") { - rsEC->setTCHFaultConn(param[0].valD); + setTCHFaultConn(param[0].valD); } if (command == "setMinCH") { - rsEC->setMinCH(param[0].valD); + setMinCH(param[0].valD); } if (command == "setMaxCH") { - rsEC->setMaxCH(param[0].valD); + setMaxCH(param[0].valD); } if (command == "setMinDHW") { - rsEC->setMinDHW(param[0].valD); + setMinDHW(param[0].valD); } if (command == "setMaxDHW") { - rsEC->setMaxDHW(param[0].valD); + setMaxDHW(param[0].valD); } if (command == "setTDHW") { - rsEC->setTDHW(param[0].valD); + setTDHW(param[0].valD); } if (command == "setMaxModLevel") { - rsEC->setMaxModLevel(param[0].valD); + setMaxModLevel(param[0].valD); } if (command == "setStatusCH") { - rsEC->setStatusCH((bool)param[0].valD); + setStatusCH((bool)param[0].valD); } if (command == "setStatusDHW") { - rsEC->setStatusDHW((bool)param[0].valD); + setStatusDHW((bool)param[0].valD); } if (command == "setStatusCH2") { - rsEC->setStatusCH2((bool)param[0].valD); + setStatusCH2((bool)param[0].valD); } if (command == "lockOutReset") { - rsEC->lockOutReset(); + lockOutReset(); } if (command == "rebootAdapter") { - rsEC->rebootAdapter(); + rebootAdapter(); } return {}; } @@ -255,9 +324,477 @@ public: ~EctoControlAdapter() { - delete rsEC; - rsEC = nullptr; }; + + bool writeFunctionModBus(const uint16_t ®, uint16_t &data) + { + // set word 0 of TX buffer to least-significant word of counter (bits 15..0) + node.setTransmitBuffer(1, lowWord(data)); + // set word 1 of TX buffer to most-significant word of counter (bits 31..16) + node.setTransmitBuffer(0, highWord(data)); + // slave: write TX buffer to (2) 16-bit registers starting at register 0 + uint8_t result = node.writeMultipleRegisters(0, 2); + if (_debug > 2) + { + SerialPrint("I", "EctoControlAdapter", "writeSingleRegister, addr: " + String((uint8_t)_addr, HEX) + ", reg: " + String(reg, HEX) + ", state: " + String(data) + " = result: " + String(result, HEX)); + } + if (result == 0) + return true; + else + return false; + } + + bool readFunctionModBus(const uint16_t ®, uint16_t &reading) + { + // float retValue = 0; + if (_modbusUART) + { + // if (!addr) + // addr = _addr; + node.begin(_addr, _modbusUART); + uint8_t result; + // uint32_t reading; + + if (reg == 0x0000) + result = node.readHoldingRegisters(reg, 4); + else + result = node.readHoldingRegisters(reg, 1); + if (_debug > 2) + SerialPrint("I", "EctoControlAdapter", "readHoldingRegisters, addr: " + String(_addr, HEX) + ", reg: " + String(reg, HEX) + " = result: " + String(result, HEX)); + // break; + if (result == node.ku8MBSuccess) + { + if (reg == 0x0000) + { + reading = node.getResponseBuffer(0x03); + reading = (uint16_t)((uint8_t)(reading) >> 8); + SerialPrint("I", "EctoControlAdapter", "read info, addr: " + String(_addr, HEX) + ", type: " + String(reading, HEX)); + } + else + { + reading = node.getResponseBuffer(0x00); + if (_debug > 2) + SerialPrint("I", "EctoControlAdapter", "Success, Received data, register: " + String(reg) + " = " + String(reading, HEX)); + } + node.clearResponseBuffer(); + } + else + { + if (_debug > 2) + SerialPrint("E", "EctoControlAdapter", "Failed, Response Code: " + String(result, HEX)); + return false; + } + + if (reading != 0x7FFF) + return true; + else + return false; + } + return false; + } + + bool getModelVersion() + { + uint16_t reqData; + info.boilerMemberCode = readFunctionModBus(ReadDataEctoControl::ecR_MemberCode, info.boilerMemberCode); + info.boilerModelCode = readFunctionModBus(ReadDataEctoControl::ecR_ModelCode, info.boilerModelCode); + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_AdaperVersion, reqData); + info.adapterHardVer = highByte(reqData); + info.adapterSoftVer = lowByte(reqData); + return ret; + } + + bool getBoilerInfo() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_AdapterInfo, reqData); + info.adapterType = highByte(reqData) & 0xF8; + info.boilerStatus = (highByte(reqData) >> 3) & 1u; + info.rebootStatus = lowByte(reqData); + if (ret) + { + publishData("adapterType", String(info.adapterType)); + publishData("boilerStatus", String(info.boilerStatus)); + publishData("rebootStatus", String(info.rebootStatus)); + } + return ret; + } + bool getBoilerStatus() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_BoilerStatus, reqData); + status.burnStatus = (lowByte(reqData) >> 0) & 1u; + status.CHStatus = (lowByte(reqData) >> 1) & 1u; + status.DHWStatus = (lowByte(reqData) >> 2) & 1u; + if (ret) + { + publishData("burnStatus", String(status.burnStatus)); + publishData("CHStatus", String(status.CHStatus)); + publishData("DHWStatus", String(status.DHWStatus)); + } + return ret; + } + bool getCodeError() + { + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_CodeError, code); + if (ret) + { + publishData("codeError", String(code)); + if (codeExt) + sendTelegramm("EctoControlAdapter: код ошибки: " + String((int)codeExt)); + } + return ret; + } + bool getCodeErrorExt() + { + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_CodeErrorExt, codeExt); + if (ret) + { + publishData("codeErrorExt", String(codeExt)); + if (codeExt) + sendTelegramm("EctoControlAdapter: код ошибки: " + String((int)codeExt)); + } + return ret; + } + bool getFlagErrorOT() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_FlagErrorOT, reqData); + flagErr = lowByte(reqData); + if (ret) + { + publishData("flagErr", String(flagErr)); + switch (flagErr) + { + case 0: + sendTelegramm("EctoControlAdapter: Необходимо обслуживание!"); + break; + case 1: + sendTelegramm("EctoControlAdapter: Котёл заблокирован!"); + break; + case 2: + sendTelegramm("EctoControlAdapter: Низкое давление в отопительном контуре!"); + break; + case 3: + sendTelegramm("EctoControlAdapter: Ошибка розжига!"); + break; + case 4: + sendTelegramm("EctoControlAdapter: Низкое давления воздуха!"); + break; + case 5: + sendTelegramm("EctoControlAdapter: Перегрев теплоносителя в контуре!"); + break; + default: + break; + } + } + return ret; + } + + bool getFlowRate() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_FlowRate, reqData); + flow = lowByte(reqData) / 10.f; + if (ret) + publishData("flowRate", String(flow)); + return ret; + } + bool getMaxSetCH() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MaxSetCH, reqData); + maxSetCH = (float)lowByte(reqData); + if (ret) + publishData("maxSetCH", String(maxSetCH)); + return ret; + } + bool getMaxSetDHW() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MaxSetDHW, reqData); + maxSetDHW = (float)lowByte(reqData); + if (ret) + publishData("maxSetDHW", String(maxSetDHW)); + return ret; + } + bool getMinSetCH() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MinSetCH, reqData); + minSetCH = (float)lowByte(reqData); + if (ret) + publishData("minSetCH", String(minSetCH)); + return ret; + } + bool getMinSetDHW() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MinSetDHW, reqData); + minSetDHW = (float)lowByte(reqData); + if (ret) + publishData("minSetDHW", String(minSetDHW)); + return ret; + } + bool getModLevel() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_ModLevel, reqData); + modLevel = (float)lowByte(reqData); + if (ret) + publishData("modLevel", String(modLevel)); + return ret; + } + bool getPressure() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_Pressure, reqData); + press = lowByte(reqData) / 10.f; + if (ret) + publishData("press", String(press)); + return ret; + } + bool getTempCH() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempCH, reqData); + tCH = reqData / 10.f; + if (ret) + publishData("tCH", String(tCH)); + return ret; + } + bool getTempDHW() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempDHW, reqData); + tDHW = reqData / 10.f; + if (ret) + publishData("tDHW", String(tDHW)); + return ret; + } + bool getTempOutside() + { + uint16_t reqData; + bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempOutside, reqData); + tOut = (float)lowByte(reqData); + if (ret) + publishData("tOut", String(tOut)); + return ret; + } + + bool setTypeConnect(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_SetTypeConnect, (uint16_t &)data)) + { + // TODO запросить результат записи у адаптера + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setTypeConnect"); + } + return ret; + } + bool setTCH(float &data) + { + bool ret = false; + uint16_t d16 = data * 10; + if (writeFunctionModBus(ecW_TSetCH, d16)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setTCH"); + } + + return ret; + } + bool setTCHFaultConn(float &data) + { + bool ret = false; + uint16_t d16 = data * 10; + if (writeFunctionModBus(ecW_TSetCHFaultConn, d16)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setTCHFaultConn"); + } + return ret; + } + bool setMinCH(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_TSetMinCH, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setMinCH"); + } + return ret; + } + bool setMaxCH(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_TSetMaxCH, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setMaxCH"); + } + return ret; + } + bool setMinDHW(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_TSetMinDHW, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setMinDHW"); + } + return ret; + } + bool setMaxDHW(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_TSetMaxDHW, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setMaxDHW"); + } + return ret; + } + bool setTDHW(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_TSetDHW, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setTDHW"); + } + return ret; + } + bool setMaxModLevel(float &data) + { + bool ret = false; + if (writeFunctionModBus(ecW_SetMaxModLevel, (uint16_t &)data)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setMaxModLevel"); + } + return ret; + } + + bool setStatusCH(bool data) + { + bool ret = false; + enableCH = data; + uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); + if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setStatusCH"); + } + return ret; + } + bool setStatusDHW(bool data) + { + bool ret = false; + enableDHW = data; + uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); + if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setStatusDHW"); + } + return ret; + } + bool setStatusCH2(bool data) + { + bool ret = false; + enableCH2 = data; + uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); + if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, setStatusCH2"); + } + return ret; + } + + bool lockOutReset() + { + bool ret = false; + uint16_t d16 = comm_LockOutReset; + if (writeFunctionModBus(ecW_Command, d16)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, lockOutReset"); + } + return ret; + } + bool rebootAdapter() + { + bool ret = false; + uint16_t d16 = comm_RebootAdapter; + if (writeFunctionModBus(ecW_Command, d16)) + { + ret = true; + } + else + { + if (_debug > 1) + SerialPrint("E", "EctoControlAdapter", "Failed, rebootAdapter"); + } + return ret; + } + + + }; void *getAPI_EctoControlAdapter(String subtype, String param) diff --git a/src/modules/exec/EctoControlAdapter/lib/ModbusEC.cpp b/src/modules/exec/EctoControlAdapter/ModbusEC.cpp similarity index 99% rename from src/modules/exec/EctoControlAdapter/lib/ModbusEC.cpp rename to src/modules/exec/EctoControlAdapter/ModbusEC.cpp index 79af9485..1b74d552 100644 --- a/src/modules/exec/EctoControlAdapter/lib/ModbusEC.cpp +++ b/src/modules/exec/EctoControlAdapter/ModbusEC.cpp @@ -18,11 +18,11 @@ Call once class has been instantiated, typically within setup(). @param &serial reference to serial port object (Serial, Serial1, ... Serial3) @ingroup setup */ -void ModbusMaster::begin(uint8_t slave, Stream &serial) +void ModbusMaster::begin(uint8_t slave, Stream *serial) { // txBuffer = (uint16_t*) calloc(ku8MaxBufferSize, sizeof(uint16_t)); _u8MBSlave = slave; - _serial = &serial; + _serial = serial; _u8TransmitBufferIndex = 0; u16TransmitBufferLength = 0; diff --git a/src/modules/exec/EctoControlAdapter/lib/ModbusEC.h b/src/modules/exec/EctoControlAdapter/ModbusEC.h similarity index 99% rename from src/modules/exec/EctoControlAdapter/lib/ModbusEC.h rename to src/modules/exec/EctoControlAdapter/ModbusEC.h index 64105d60..0f5f1f79 100644 --- a/src/modules/exec/EctoControlAdapter/lib/ModbusEC.h +++ b/src/modules/exec/EctoControlAdapter/ModbusEC.h @@ -20,7 +20,7 @@ class ModbusMaster public: ModbusMaster(); - void begin(uint8_t, Stream &serial); + void begin(uint8_t, Stream *serial); void idle(void (*)()); void preTransmission(void (*)()); void postTransmission(void (*)()); diff --git a/src/modules/exec/EctoControlAdapter/lib/librsEctoControl.a b/src/modules/exec/EctoControlAdapter/lib/librsEctoControl.a deleted file mode 100644 index f1a36c0e..00000000 Binary files a/src/modules/exec/EctoControlAdapter/lib/librsEctoControl.a and /dev/null differ diff --git a/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.cpp b/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.cpp deleted file mode 100644 index 431f6322..00000000 --- a/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.cpp +++ /dev/null @@ -1,633 +0,0 @@ -#include -#include -#ifdef ESP32 -#include -#endif -#include "rsEctoControl.h" - -struct IoTValue -{ - float valD = 0; - String valS = ""; - - bool isDecimal = true; -}; -uint8_t _DIR_PIN_ = 0; - -void modbusPreTransmission() -{ - // delay(500); - if (_DIR_PIN_) - digitalWrite(_DIR_PIN_, HIGH); -} - -// Pin 4 made low for Modbus receive mode -// Контакт 4 установлен на низком уровне для режима приема Modbus -void modbusPostTransmission() -{ - if (_DIR_PIN_) - digitalWrite(_DIR_PIN_, LOW); - // delay(500); -} - -//======================================================================================================= -// setup() -RsEctoControl::RsEctoControl(String parameters) -{ - node.preTransmission(modbusPreTransmission); - node.postTransmission(modbusPostTransmission); - - if (parameters != "") - { - DynamicJsonDocument doc(4096); - DeserializationError error = deserializeJson(doc, parameters); - if (!error) - { - if (doc.containsKey("DIR_PIN")) - _DIR_PIN = doc["DIR_PIN"].as(); - if (doc.containsKey("addr")) - _addr = doc["addr"].as(); - if (doc.containsKey("debug")) - _debug = doc["debug"].as(); - } - } - if (_DIR_PIN) - { - _DIR_PIN_ = _DIR_PIN; - pinMode(_DIR_PIN, OUTPUT); - digitalWrite(_DIR_PIN, LOW); - } - - // 0x14 – адаптер OpenTherm (вторая версия) - // 0x15 – адаптер eBus - // 0x16 – адаптер Navien - uint16_t type; - readFunctionModBus(0x0000, type); - if (0x14 != (uint8_t)type || 0x15 != (uint8_t)type || 0x16 != (uint8_t)type) - { - _SerialPrint("E", "EctoControlAdapter", "Не подходящее устройство, type: " + String(type, HEX)); - } - - uint8_t addr = node.readAddresEctoControl(); - _SerialPrint("I", "EctoControlAdapter", "readAddresEctoControl, addr: " + String(addr, HEX) + " - Enter to configuration"); - - getModelVersion(); - getBoilerInfo(); - getBoilerStatus(); -} - -void RsEctoControl::begin(uint8_t slave, Stream &serial) -{ - _modbusUART = &serial; - node.begin(slave, serial); -} - -void RsEctoControl::initFunction(void (*publishData)(String, String), void (*sendTelegramm)(String), void (*SerialPrint)(const String &, const String &, const String &)) -{ //, const String & - _publishData = publishData; - _sendTelegramm = sendTelegramm; - _SerialPrint = SerialPrint; -}; - -void RsEctoControl::doByInterval() -{ - // readBoilerInfo(); - getBoilerStatus(); - - getCodeError(); - getCodeErrorExt(); - if (info.adapterType == 0) - getFlagErrorOT(); - // getFlowRate(); - // getMaxSetCH(); - // getMaxSetDHW(); - // getMinSetCH(); - // getMinSetDHW(); - getModLevel(); - getPressure(); - getTempCH(); - getTempDHW(); - getTempOutside(); -} - -// Основной цикл программы -void RsEctoControl::loop(bool isNetworkActive, bool mqttIsConnect) -{ - _isNetworkActive = isNetworkActive; - _mqttIsConnect = mqttIsConnect; -} - -// Исполнительные комманды -void RsEctoControl::execute(String command, std::vector ¶m) -{ -} - -bool RsEctoControl::writeFunctionModBus(const uint16_t ®, uint16_t &data) -{ - // set word 0 of TX buffer to least-significant word of counter (bits 15..0) - node.setTransmitBuffer(1, lowWord(data)); - // set word 1 of TX buffer to most-significant word of counter (bits 31..16) - node.setTransmitBuffer(0, highWord(data)); - // slave: write TX buffer to (2) 16-bit registers starting at register 0 - uint8_t result = node.writeMultipleRegisters(0, 2); - if (_debug > 2) - { - _SerialPrint("I", "EctoControlAdapter", "writeSingleRegister, addr: " + String((uint8_t)_addr, HEX) + ", reg: " + String(reg, HEX) + ", state: " + String(data) + " = result: " + String(result, HEX)); - } -} - -bool RsEctoControl::readFunctionModBus(const uint16_t ®, uint16_t &reading) -{ - // float retValue = 0; - if (_modbusUART) - { - // if (!addr) - // addr = _addr; - node.begin(_addr, (Stream &)*_modbusUART); - uint8_t result; - // uint32_t reading; - - if (reg == 0x0000) - result = node.readHoldingRegisters(reg, 4); - else - result = node.readHoldingRegisters(reg, 1); - if (_debug > 2) - _SerialPrint("I", "EctoControlAdapter", "readHoldingRegisters, addr: " + String(_addr, HEX) + ", reg: " + String(reg, HEX) + " = result: " + String(result, HEX)); - // break; - if (result == node.ku8MBSuccess) - { - if (reg == 0x0000) - { - reading = node.getResponseBuffer(0x03); - reading = (uint16_t)((uint8_t)(reading) >> 8); - _SerialPrint("I", "EctoControlAdapter", "read info, addr: " + String(_addr, HEX) + ", type: " + String(reading, HEX)); - } - else - { - reading = node.getResponseBuffer(0x00); - if (_debug > 2) - _SerialPrint("I", "EctoControlAdapter", "Success, Received data, register: " + String(reg) + " = " + String(reading, HEX)); - } - node.clearResponseBuffer(); - } - else - { - if (_debug > 2) - _SerialPrint("E", "EctoControlAdapter", "Failed, Response Code: " + String(result, HEX)); - return false; - } - - if (reading != 0x7FFF) - return true; - else - return false; - } - return false; -} - -bool RsEctoControl::getModelVersion() -{ - uint16_t reqData; - info.boilerMemberCode = readFunctionModBus(ReadDataEctoControl::ecR_MemberCode, info.boilerMemberCode); - info.boilerModelCode = readFunctionModBus(ReadDataEctoControl::ecR_ModelCode, info.boilerModelCode); - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_AdaperVersion, reqData); - info.adapterHardVer = highByte(reqData); - info.adapterSoftVer = lowByte(reqData); - return ret; -} - -bool RsEctoControl::getBoilerInfo() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_AdapterInfo, reqData); - info.adapterType = highByte(reqData) & 0xF8; - info.boilerStatus = (highByte(reqData) >> 3) & 1u; - info.rebootStatus = lowByte(reqData); - if (ret) - { - _publishData("adapterType", String(info.adapterType)); - _publishData("boilerStatus", String(info.boilerStatus)); - _publishData("rebootStatus", String(info.rebootStatus)); - } - return ret; -} -bool RsEctoControl::getBoilerStatus() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_BoilerStatus, reqData); - status.burnStatus = (lowByte(reqData) >> 0) & 1u; - status.CHStatus = (lowByte(reqData) >> 1) & 1u; - status.DHWStatus = (lowByte(reqData) >> 2) & 1u; - if (ret) - { - _publishData("burnStatus", String(status.burnStatus)); - _publishData("CHStatus", String(status.CHStatus)); - _publishData("DHWStatus", String(status.DHWStatus)); - } - return ret; -} -bool RsEctoControl::getCodeError() -{ - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_CodeError, code); - if (ret) - { - _publishData("codeError", String(code)); - if (codeExt) - _sendTelegramm("EctoControlAdapter: код ошибки: " + String((int)codeExt)); - } - return ret; -} -bool RsEctoControl::getCodeErrorExt() -{ - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_CodeErrorExt, codeExt); - if (ret) - { - _publishData("codeErrorExt", String(codeExt)); - if (codeExt) - _sendTelegramm("EctoControlAdapter: код ошибки: " + String((int)codeExt)); - } - return ret; -} -bool RsEctoControl::getFlagErrorOT() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_FlagErrorOT, reqData); - flagErr = lowByte(reqData); - if (ret) - { - _publishData("flagErr", String(flagErr)); - switch (flagErr) - { - case 0: - _sendTelegramm("EctoControlAdapter: Необходимо обслуживание!"); - break; - case 1: - _sendTelegramm("EctoControlAdapter: Котёл заблокирован!"); - break; - case 2: - _sendTelegramm("EctoControlAdapter: Низкое давление в отопительном контуре!"); - break; - case 3: - _sendTelegramm("EctoControlAdapter: Ошибка розжига!"); - break; - case 4: - _sendTelegramm("EctoControlAdapter: Низкое давления воздуха!"); - break; - case 5: - _sendTelegramm("EctoControlAdapter: Перегрев теплоносителя в контуре!"); - break; - default: - break; - } - } - return ret; -} - -bool RsEctoControl::getFlowRate() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_FlowRate, reqData); - flow = lowByte(reqData) / 10.f; - if (ret) - _publishData("flowRate", String(flow)); - return ret; -} -bool RsEctoControl::getMaxSetCH() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MaxSetCH, reqData); - maxSetCH = (float)lowByte(reqData); - if (ret) - _publishData("maxSetCH", String(maxSetCH)); - return ret; -} -bool RsEctoControl::getMaxSetDHW() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MaxSetDHW, reqData); - maxSetDHW = (float)lowByte(reqData); - if (ret) - _publishData("maxSetDHW", String(maxSetDHW)); - return ret; -} -bool RsEctoControl::getMinSetCH() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MinSetCH, reqData); - minSetCH = (float)lowByte(reqData); - if (ret) - _publishData("minSetCH", String(minSetCH)); - return ret; -} -bool RsEctoControl::getMinSetDHW() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_MinSetDHW, reqData); - minSetDHW = (float)lowByte(reqData); - if (ret) - _publishData("minSetDHW", String(minSetDHW)); - return ret; -} -bool RsEctoControl::getModLevel() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_ModLevel, reqData); - modLevel = (float)lowByte(reqData); - if (ret) - _publishData("modLevel", String(modLevel)); - return ret; -} -bool RsEctoControl::getPressure() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_Pressure, reqData); - press = lowByte(reqData) / 10.f; - if (ret) - _publishData("press", String(press)); - return ret; -} -bool RsEctoControl::getTempCH() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempCH, reqData); - tCH = reqData / 10.f; - if (ret) - _publishData("tCH", String(tCH)); - return ret; -} -bool RsEctoControl::getTempDHW() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempDHW, reqData); - tDHW = reqData / 10.f; - if (ret) - _publishData("tDHW", String(tDHW)); - return ret; -} -bool RsEctoControl::getTempOutside() -{ - uint16_t reqData; - bool ret = readFunctionModBus(ReadDataEctoControl::ecR_TempOutside, reqData); - tOut = (float)lowByte(reqData); - if (ret) - _publishData("tOut", String(tOut)); - return ret; -} - -bool RsEctoControl::setTypeConnect(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_SetTypeConnect, (uint16_t &)data)) - { - // TODO запросить результат записи у адаптера - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setTypeConnect"); - } - return ret; -} -bool RsEctoControl::setTCH(float &data) -{ - bool ret = false; - uint16_t d16 = data * 10; - if (writeFunctionModBus(ecW_TSetCH, d16)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setTCH"); - } - - return ret; -} -bool RsEctoControl::setTCHFaultConn(float &data) -{ - bool ret = false; - uint16_t d16 = data * 10; - if (writeFunctionModBus(ecW_TSetCHFaultConn, d16)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setTCHFaultConn"); - } - return ret; -} -bool RsEctoControl::setMinCH(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_TSetMinCH, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setMinCH"); - } - return ret; -} -bool RsEctoControl::setMaxCH(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_TSetMaxCH, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setMaxCH"); - } - return ret; -} -bool RsEctoControl::setMinDHW(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_TSetMinDHW, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setMinDHW"); - } - return ret; -} -bool RsEctoControl::setMaxDHW(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_TSetMaxDHW, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setMaxDHW"); - } -} -bool RsEctoControl::setTDHW(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_TSetDHW, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setTDHW"); - } - return ret; -} -bool RsEctoControl::setMaxModLevel(float &data) -{ - bool ret = false; - if (writeFunctionModBus(ecW_SetMaxModLevel, (uint16_t &)data)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setMaxModLevel"); - } - return ret; -} - -bool RsEctoControl::setStatusCH(bool data) -{ - bool ret = false; - enableCH = data; - uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); - if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setStatusCH"); - } - return ret; -} -bool RsEctoControl::setStatusDHW(bool data) -{ - bool ret = false; - enableDHW = data; - uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); - if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setStatusDHW"); - } - return ret; -} -bool RsEctoControl::setStatusCH2(bool data) -{ - bool ret = false; - enableCH2 = data; - uint16_t stat = enableCH | (enableDHW << 1) | (enableCH2 << 2); - if (writeFunctionModBus(ecW_SetStatusBoiler, stat)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, setStatusCH2"); - } - return ret; -} - -bool RsEctoControl::lockOutReset() -{ - bool ret = false; - uint16_t d16 = comm_LockOutReset; - if (writeFunctionModBus(ecW_Command, d16)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, lockOutReset"); - } - return ret; -} -bool RsEctoControl::rebootAdapter() -{ - bool ret = false; - uint16_t d16 = comm_RebootAdapter; - if (writeFunctionModBus(ecW_Command, d16)) - { - ret = true; - } - else - { - if (_debug > 1) - _SerialPrint("E", "EctoControlAdapter", "Failed, rebootAdapter"); - } - return ret; -} - -const String RsEctoControl::getChipId() -{ - return String(ESP_getChipId()) + "-" + String(getFlashChipIdNew()); // + "v" + String(FIRMWARE_VERSION); -} - -uint32_t RsEctoControl::getFlashChipIdNew() -{ - // Cache since size does not change - static uint32_t flashChipId = 0; - - if (flashChipId == 0) - { -#ifdef ESP32 - uint32_t tmp = g_rom_flashchip.device_id; - - for (int i = 0; i < 3; ++i) - { - flashChipId = flashChipId << 8; - flashChipId |= (tmp & 0xFF); - tmp = tmp >> 8; - } - - // esp_flash_read_id(nullptr, &flashChipId); -#elif defined(ESP8266) - flashChipId = ESP.getFlashChipId(); -#endif // ifdef ESP32 - } - return flashChipId; -} - -uint32_t RsEctoControl::ESP_getChipId(void) -{ -#ifdef ESP32 - uint32_t id = 0; - for (uint32_t i = 0; i < 17; i = i + 8) - { - id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; - } - return id; -#else - return ESP.getChipId(); -#endif -} - -RsEctoControl::~RsEctoControl() -{ -} diff --git a/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.h b/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.h deleted file mode 100644 index edd88518..00000000 --- a/src/modules/exec/EctoControlAdapter/lib/rsEctoControl.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include "ModbusEC.h" -#include "AdapterCommon.h" -// #include "Stream.h" -#include - -struct IoTValue; - -// static void publishData(String widget, String status); -static void (*_publishData)(String, String); - -// static void sendTelegramm(String msg); -static void (*_sendTelegramm)(String); - -static void (*_SerialPrint)(const String &, const String &, const String &); //, const String& itemId = "" - -class RsEctoControl //: public ModbusMaster -{ -private: - ModbusMaster node; - uint8_t _addr; - uint8_t _debug; - Stream *_modbusUART; - - BoilerInfo info; - BoilerStatus status; - - uint16_t code; - uint16_t codeExt; - uint8_t flagErr; - float flow; - float maxSetCH; - float maxSetDHW; - float minSetCH; - float minSetDHW; - float modLevel; - float press; - float tCH; - float tDHW; - float tOut; - bool enableCH; - bool enableDHW; - bool enableCH2; - bool _isNetworkActive; - bool _mqttIsConnect; - - uint32_t getFlashChipIdNew(); - - uint32_t ESP_getChipId(void); - - const String getChipId(); - - bool readFunctionModBus(const uint16_t ®, uint16_t &reading); - - bool writeFunctionModBus(const uint16_t ®, uint16_t &data); - -public: - uint8_t _DIR_PIN; - //======================================================================================================= - // setup() - RsEctoControl(String parameters); //: ModbusMaster(); - - ~RsEctoControl(); - - void begin(uint8_t slave, Stream &serial); - - static void initFunction(void (*_publishData_)(String, String), void (*_sendTelegramm_)(String), void (*_SerialPrint_)(const String &, const String &, const String &)); //, const String& - - void doByInterval(); - - // Основной цикл программы - void loop(bool isNetworkActive, bool mqttIsConnect); - - // Исполнительные комманды - void execute(String command, std::vector ¶m); - - bool getModelVersion(); - bool getBoilerInfo(); - bool getBoilerStatus(); - bool getCodeError(); - bool getCodeErrorExt(); - bool getFlagErrorOT(); - bool getFlowRate(); - bool getMaxSetCH(); - bool getMaxSetDHW(); - bool getMinSetCH(); - bool getMinSetDHW(); - bool getModLevel(); - bool getPressure(); - bool getTempCH(); - bool getTempDHW(); - bool getTempOutside(); - - bool setTypeConnect(float &data); - bool setTCH(float &data); - bool setTCHFaultConn(float &data); - bool setMinCH(float &data); - bool setMaxCH(float &data); - bool setMinDHW(float &data); - bool setMaxDHW(float &data); - bool setTDHW(float &data); - bool setMaxModLevel(float &data); - bool setStatusCH(bool data); - bool setStatusDHW(bool data); - bool setStatusCH2(bool data); - - bool lockOutReset(); - bool rebootAdapter(); -}; diff --git a/src/modules/exec/EctoControlAdapter/lib/util/crc16.h b/src/modules/exec/EctoControlAdapter/util/crc16.h similarity index 100% rename from src/modules/exec/EctoControlAdapter/lib/util/crc16.h rename to src/modules/exec/EctoControlAdapter/util/crc16.h diff --git a/src/modules/exec/EctoControlAdapter/lib/util/word.h b/src/modules/exec/EctoControlAdapter/util/word.h similarity index 100% rename from src/modules/exec/EctoControlAdapter/lib/util/word.h rename to src/modules/exec/EctoControlAdapter/util/word.h