open src EctoControl

This commit is contained in:
Mit4el
2025-02-17 22:32:08 +03:00
parent 9cbf5f0b38
commit 33d19bea97
5 changed files with 1165 additions and 24 deletions

View File

@@ -3,7 +3,7 @@
#include <map>
#include <HardwareSerial.h>
#include "rsEctoControl.h"
#include "lib/rsEctoControl.h"
// class ModbusUart;
Stream *_mbUART = nullptr;

View File

@@ -0,0 +1,517 @@
#include "ModbusEC.h"
ModbusMaster::ModbusMaster(void)
{
_idle = 0;
_preTransmission = 0;
_postTransmission = 0;
}
/**
Initialize class object.
Assigns the Modbus slave ID and serial port.
Call once class has been instantiated, typically within setup().
@param slave Modbus slave ID (1..255)
@param &serial reference to serial port object (Serial, Serial1, ... Serial3)
@ingroup setup
*/
void ModbusMaster::begin(uint8_t slave, Stream &serial)
{
// txBuffer = (uint16_t*) calloc(ku8MaxBufferSize, sizeof(uint16_t));
_u8MBSlave = slave;
_serial = &serial;
_u8TransmitBufferIndex = 0;
u16TransmitBufferLength = 0;
#if __MODBUSMASTER_DEBUG__
pinMode(__MODBUSMASTER_DEBUG_PIN_A__, OUTPUT);
pinMode(__MODBUSMASTER_DEBUG_PIN_B__, OUTPUT);
#endif
}
void ModbusMaster::beginTransmission(uint16_t u16Address)
{
_u16WriteAddress = u16Address;
_u8TransmitBufferIndex = 0;
u16TransmitBufferLength = 0;
}
// eliminate this function in favor of using existing MB request functions
uint8_t ModbusMaster::requestFrom(uint16_t address, uint16_t quantity)
{
uint8_t read;
// clamp to buffer length
if (quantity > ku8MaxBufferSize)
{
quantity = ku8MaxBufferSize;
}
// set rx buffer iterator vars
_u8ResponseBufferIndex = 0;
_u8ResponseBufferLength = read;
return read;
}
void ModbusMaster::sendBit(bool data)
{
uint8_t txBitIndex = u16TransmitBufferLength % 16;
if ((u16TransmitBufferLength >> 4) < ku8MaxBufferSize)
{
if (0 == txBitIndex)
{
_u16TransmitBuffer[_u8TransmitBufferIndex] = 0;
}
bitWrite(_u16TransmitBuffer[_u8TransmitBufferIndex], txBitIndex, data);
u16TransmitBufferLength++;
_u8TransmitBufferIndex = u16TransmitBufferLength >> 4;
}
}
void ModbusMaster::send(uint16_t data)
{
if (_u8TransmitBufferIndex < ku8MaxBufferSize)
{
_u16TransmitBuffer[_u8TransmitBufferIndex++] = data;
u16TransmitBufferLength = _u8TransmitBufferIndex << 4;
}
}
void ModbusMaster::send(uint32_t data)
{
send(lowWord(data));
send(highWord(data));
}
void ModbusMaster::send(uint8_t data)
{
send(word(data));
}
uint8_t ModbusMaster::available(void)
{
return _u8ResponseBufferLength - _u8ResponseBufferIndex;
}
uint16_t ModbusMaster::receive(void)
{
if (_u8ResponseBufferIndex < _u8ResponseBufferLength)
{
return _u16ResponseBuffer[_u8ResponseBufferIndex++];
}
else
{
return 0xFFFF;
}
}
/**
Set idle time callback function (cooperative multitasking).
This function gets called in the idle time between transmission of data
and response from slave. Do not call functions that read from the serial
buffer that is used by ModbusMaster. Use of i2c/TWI, 1-Wire, other
serial ports, etc. is permitted within callback function.
@see ModbusMaster::ModbusMasterTransaction()
*/
void ModbusMaster::idle(void (*idle)())
{
_idle = idle;
}
/**
Set pre-transmission callback function.
This function gets called just before a Modbus message is sent over serial.
Typical usage of this callback is to enable an RS485 transceiver's
Driver Enable pin, and optionally disable its Receiver Enable pin.
@see ModbusMaster::ModbusMasterTransaction()
@see ModbusMaster::postTransmission()
*/
void ModbusMaster::preTransmission(void (*preTransmission)())
{
_preTransmission = preTransmission;
}
/**
Set post-transmission callback function.
This function gets called after a Modbus message has finished sending
(i.e. after all data has been physically transmitted onto the serial
bus).
Typical usage of this callback is to enable an RS485 transceiver's
Receiver Enable pin, and disable its Driver Enable pin.
@see ModbusMaster::ModbusMasterTransaction()
@see ModbusMaster::preTransmission()
*/
void ModbusMaster::postTransmission(void (*postTransmission)())
{
_postTransmission = postTransmission;
}
/**
Retrieve data from response buffer.
@see ModbusMaster::clearResponseBuffer()
@param u8Index index of response buffer array (0x00..0x3F)
@return value in position u8Index of response buffer (0x0000..0xFFFF)
@ingroup buffer
*/
uint16_t ModbusMaster::getResponseBuffer(uint8_t u8Index)
{
if (u8Index < ku8MaxBufferSize)
{
return _u16ResponseBuffer[u8Index];
}
else
{
return 0xFFFF;
}
}
/**
Clear Modbus response buffer.
@see ModbusMaster::getResponseBuffer(uint8_t u8Index)
@ingroup buffer
*/
void ModbusMaster::clearResponseBuffer()
{
uint8_t i;
for (i = 0; i < ku8MaxBufferSize; i++)
{
_u16ResponseBuffer[i] = 0;
}
}
/**
Place data in transmit buffer.
@see ModbusMaster::clearTransmitBuffer()
@param u8Index index of transmit buffer array (0x00..0x3F)
@param u16Value value to place in position u8Index of transmit buffer (0x0000..0xFFFF)
@return 0 on success; exception number on failure
@ingroup buffer
*/
uint8_t ModbusMaster::setTransmitBuffer(uint8_t u8Index, uint16_t u16Value)
{
if (u8Index < ku8MaxBufferSize)
{
_u16TransmitBuffer[u8Index] = u16Value;
return ku8MBSuccess;
}
else
{
return ku8MBIllegalDataAddress;
}
}
/**
Clear Modbus transmit buffer.
@see ModbusMaster::setTransmitBuffer(uint8_t u8Index, uint16_t u16Value)
@ingroup buffer
*/
void ModbusMaster::clearTransmitBuffer()
{
uint8_t i;
for (i = 0; i < ku8MaxBufferSize; i++)
{
_u16TransmitBuffer[i] = 0;
}
}
/**
Modbus function 0x03 Read Holding Registers.
This function code is used to read the contents of a contiguous block of
holding registers in a remote device. The request specifies the starting
register address and the number of registers. Registers are addressed
starting at zero.
The register data in the response buffer is packed as one word per
register.
@param u16ReadAddress address of the first holding register (0x0000..0xFFFF)
@param u16ReadQty quantity of holding registers to read (1..125, enforced by remote device)
@return 0 on success; exception number on failure
@ingroup register
*/
uint8_t ModbusMaster::readHoldingRegisters(uint16_t u16ReadAddress,
uint16_t u16ReadQty)
{
_u16ReadAddress = u16ReadAddress;
_u16ReadQty = u16ReadQty;
return ModbusMasterTransaction(ku8MBReadHoldingRegisters);
}
/**
Modbus function 0x10 Write Multiple Registers.
This function code is used to write a block of contiguous registers (1
to 123 registers) in a remote device.
The requested written values are specified in the transmit buffer. Data
is packed as one word per register.
@param u16WriteAddress address of the holding register (0x0000..0xFFFF)
@param u16WriteQty quantity of holding registers to write (1..123, enforced by remote device)
@return 0 on success; exception number on failure
@ingroup register
*/
uint8_t ModbusMaster::writeMultipleRegisters(uint16_t u16WriteAddress,
uint16_t u16WriteQty)
{
_u16WriteAddress = u16WriteAddress;
_u16WriteQty = u16WriteQty;
return ModbusMasterTransaction(ku8MBWriteMultipleRegisters);
}
// new version based on Wire.h
uint8_t ModbusMaster::writeMultipleRegisters()
{
_u16WriteQty = _u8TransmitBufferIndex;
return ModbusMasterTransaction(ku8MBWriteMultipleRegisters);
}
uint8_t ModbusMaster::readAddresEctoControl()
{
_u16ReadAddress = 0x00;
_u16ReadQty = 1;
return ModbusMasterTransaction(ku8MBProgRead46);
}
uint8_t ModbusMaster::writeAddresEctoControl(uint8_t addr)
{
_u16WriteAddress = 0x00;
_u16WriteQty = 1;
_u16TransmitBuffer[0] = (uint16_t)addr;
return ModbusMasterTransaction(ku8MBProgWrite47);
}
/* _____PRIVATE FUNCTIONS____________________________________________________ */
/**
Modbus transaction engine.
Sequence:
- assemble Modbus Request Application Data Unit (ADU),
based on particular function called
- transmit request over selected serial port
- wait for/retrieve response
- evaluate/disassemble response
- return status (success/exception)
@param u8MBFunction Modbus function (0x01..0xFF)
@return 0 on success; exception number on failure
*/
uint8_t ModbusMaster::ModbusMasterTransaction(uint8_t u8MBFunction)
{
uint8_t u8ModbusADU[24];
uint8_t u8ModbusADUSize = 0;
uint8_t i, u8Qty;
uint16_t u16CRC;
uint32_t u32StartTime;
uint8_t u8BytesLeft = 8;
uint8_t u8MBStatus = ku8MBSuccess;
// assemble Modbus Request Application Data Unit
if (u8MBFunction == ku8MBProgRead46 || u8MBFunction == ku8MBProgWrite47)
{
u8ModbusADU[u8ModbusADUSize++] = 0x00;
u8ModbusADU[u8ModbusADUSize++] = u8MBFunction;
}
else
{
u8ModbusADU[u8ModbusADUSize++] = _u8MBSlave;
u8ModbusADU[u8ModbusADUSize++] = u8MBFunction;
}
switch (u8MBFunction)
{
case ku8MBReadHoldingRegisters:
u8ModbusADU[u8ModbusADUSize++] = highByte(_u16ReadAddress);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16ReadAddress);
u8ModbusADU[u8ModbusADUSize++] = highByte(_u16ReadQty);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16ReadQty);
break;
}
switch (u8MBFunction)
{
case ku8MBWriteMultipleRegisters:
u8ModbusADU[u8ModbusADUSize++] = highByte(_u16WriteAddress);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16WriteAddress);
break;
}
switch (u8MBFunction)
{
case ku8MBWriteMultipleRegisters:
u8ModbusADU[u8ModbusADUSize++] = highByte(_u16WriteQty);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16WriteQty);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16WriteQty << 1);
for (i = 0; i < lowByte(_u16WriteQty); i++)
{
u8ModbusADU[u8ModbusADUSize++] = highByte(_u16TransmitBuffer[i]);
u8ModbusADU[u8ModbusADUSize++] = lowByte(_u16TransmitBuffer[i]);
}
break;
}
// append CRC
u16CRC = 0xFFFF;
for (i = 0; i < u8ModbusADUSize; i++)
{
u16CRC = crc16_update(u16CRC, u8ModbusADU[i]);
}
u8ModbusADU[u8ModbusADUSize++] = lowByte(u16CRC);
u8ModbusADU[u8ModbusADUSize++] = highByte(u16CRC);
u8ModbusADU[u8ModbusADUSize] = 0;
// flush receive buffer before transmitting request
while (_serial->read() != -1)
;
// transmit request
if (_preTransmission)
{
_preTransmission();
}
for (i = 0; i < u8ModbusADUSize; i++)
{
_serial->write(u8ModbusADU[i]);
}
u8ModbusADUSize = 0;
_serial->flush(); // flush transmit buffer
if (_postTransmission)
{
_postTransmission();
}
// loop until we run out of time or bytes, or an error occurs
u32StartTime = millis();
while (u8BytesLeft && !u8MBStatus)
{
if (_serial->available())
{
#if __MODBUSMASTER_DEBUG__
digitalWrite(__MODBUSMASTER_DEBUG_PIN_A__, true);
#endif
u8ModbusADU[u8ModbusADUSize++] = _serial->read();
u8BytesLeft--;
#if __MODBUSMASTER_DEBUG__
digitalWrite(__MODBUSMASTER_DEBUG_PIN_A__, false);
#endif
}
else
{
#if __MODBUSMASTER_DEBUG__
digitalWrite(__MODBUSMASTER_DEBUG_PIN_B__, true);
#endif
if (_idle)
{
_idle();
}
#if __MODBUSMASTER_DEBUG__
digitalWrite(__MODBUSMASTER_DEBUG_PIN_B__, false);
#endif
}
// evaluate slave ID, function code once enough bytes have been read
if (u8ModbusADUSize == 5)
{
// verify response is for correct Modbus slave
if (u8ModbusADU[0] != _u8MBSlave || u8ModbusADU[0] != 0x00)
{
u8MBStatus = ku8MBInvalidSlaveID;
break;
}
// verify response is for correct Modbus function code (mask exception bit 7)
if ((u8ModbusADU[1] & 0x7F) != u8MBFunction)
{
u8MBStatus = ku8MBInvalidFunction;
break;
}
// check whether Modbus exception occurred; return Modbus Exception Code
if (bitRead(u8ModbusADU[1], 7))
{
u8MBStatus = u8ModbusADU[2];
break;
}
// evaluate returned Modbus function code
switch (u8ModbusADU[1])
{
case ku8MBReadHoldingRegisters:
u8BytesLeft = u8ModbusADU[2];
break;
case ku8MBWriteMultipleRegisters:
u8BytesLeft = 3;
break;
}
}
if ((millis() - u32StartTime) > ku16MBResponseTimeout)
{
u8MBStatus = ku8MBResponseTimedOut;
}
}
// verify response is large enough to inspect further
if (!u8MBStatus && u8ModbusADUSize >= 5)
{
// calculate CRC
u16CRC = 0xFFFF;
for (i = 0; i < (u8ModbusADUSize - 2); i++)
{
u16CRC = crc16_update(u16CRC, u8ModbusADU[i]);
}
// verify CRC
if (!u8MBStatus && (lowByte(u16CRC) != u8ModbusADU[u8ModbusADUSize - 2] ||
highByte(u16CRC) != u8ModbusADU[u8ModbusADUSize - 1]))
{
u8MBStatus = ku8MBInvalidCRC;
}
}
// disassemble ADU into words
if (!u8MBStatus)
{
// evaluate returned Modbus function code
switch (u8ModbusADU[1])
{
case ku8MBReadHoldingRegisters:
// load bytes into word; response bytes are ordered H, L, H, L, ...
for (i = 0; i < (u8ModbusADU[2] >> 1); i++)
{
if (i < ku8MaxBufferSize)
{
_u16ResponseBuffer[i] = word(u8ModbusADU[2 * i + 3], u8ModbusADU[2 * i + 4]);
}
_u8ResponseBufferLength = i;
}
break;
case ku8MBProgRead46:
_u16ResponseBuffer[0] = (uint16_t)u8ModbusADU[2];
_u8ResponseBufferLength = 1;
break;
}
}
_u8TransmitBufferIndex = 0;
u16TransmitBufferLength = 0;
_u8ResponseBufferIndex = 0;
return u8MBStatus;
}

View File

@@ -0,0 +1,633 @@
#include <Arduino.h>
#include <ArduinoJson.h>
#ifdef ESP32
#include <rom/spi_flash.h>
#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<int>();
if (doc.containsKey("addr"))
_addr = doc["addr"].as<int>();
if (doc.containsKey("debug"))
_debug = doc["debug"].as<int>();
}
}
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<IoTValue> &param)
{
}
bool RsEctoControl::writeFunctionModBus(const uint16_t &reg, 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 &reg, 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()
{
}

View File

@@ -19,7 +19,6 @@ class RsEctoControl //: public ModbusMaster
{
private:
ModbusMaster node;
String _license;
uint8_t _addr;
uint8_t _debug;
Stream *_modbusUART;
@@ -45,8 +44,6 @@ private:
bool enableCH2;
bool _isNetworkActive;
bool _mqttIsConnect;
int md = 0;
int md2 = 0;
uint32_t getFlashChipIdNew();