mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Merge pull request #1970 from mheyse/modbus-write-cmd
Modbus: Handle writes to CMD entities, extend tests
This commit is contained in:
@@ -2027,13 +2027,13 @@ int EMSdevice::get_modbus_value(uint8_t tag, const std::string & shortname, std:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname, const std::vector<uint8_t> & modbus_data, JsonObject jsonValue) {
|
int EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname, const std::vector<uint8_t> & modbus_data, JsonObject jsonValue) {
|
||||||
//Serial.printf("modbus_value_to_json(%d,%s,[%d bytes])\n", tag, shortname.c_str(), modbus_data.size());
|
// LOG_DEBUG("modbus_value_to_json(%d,%s,[%d bytes])\n", tag, shortname.c_str(), modbus_data.size());
|
||||||
|
|
||||||
// find device value by shortname
|
// find device value by shortname
|
||||||
const auto & it = std::find_if(devicevalues_.begin(), devicevalues_.end(), [&](const DeviceValue & x) { return x.tag == tag && x.short_name == shortname; });
|
const auto & it = std::find_if(devicevalues_.begin(), devicevalues_.end(), [&](const DeviceValue & x) { return x.tag == tag && x.short_name == shortname; });
|
||||||
if (it == devicevalues_.end()) {
|
if (it == devicevalues_.end()) {
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto & dv = *it;
|
auto & dv = *it;
|
||||||
@@ -2042,7 +2042,7 @@ bool EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname,
|
|||||||
if (dv.type == DeviceValueType::BOOL) {
|
if (dv.type == DeviceValueType::BOOL) {
|
||||||
// bools are 1 16 bit register
|
// bools are 1 16 bit register
|
||||||
if (modbus_data.size() != 2) {
|
if (modbus_data.size() != 2) {
|
||||||
return false;
|
return -2;
|
||||||
}
|
}
|
||||||
jsonValue["value"] = modbus_data[0] || modbus_data[1];
|
jsonValue["value"] = modbus_data[0] || modbus_data[1];
|
||||||
}
|
}
|
||||||
@@ -2059,7 +2059,7 @@ bool EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname,
|
|||||||
else if (dv.type == DeviceValueType::ENUM) {
|
else if (dv.type == DeviceValueType::ENUM) {
|
||||||
// these data types are 1 16 bit register
|
// these data types are 1 16 bit register
|
||||||
if (modbus_data.size() != 2) {
|
if (modbus_data.size() != 2) {
|
||||||
return false;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonValue["value"] = (uint16_t)modbus_data[0] << 8 | (uint16_t)modbus_data[1];
|
jsonValue["value"] = (uint16_t)modbus_data[0] << 8 | (uint16_t)modbus_data[1];
|
||||||
@@ -2069,14 +2069,14 @@ bool EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname,
|
|||||||
else if (dv.type == DeviceValueType::INT8 || dv.type == DeviceValueType::UINT8 || dv.type == DeviceValueType::INT16 || dv.type == DeviceValueType::UINT16) {
|
else if (dv.type == DeviceValueType::INT8 || dv.type == DeviceValueType::UINT8 || dv.type == DeviceValueType::INT16 || dv.type == DeviceValueType::UINT16) {
|
||||||
// these data types are 1 16 bit register
|
// these data types are 1 16 bit register
|
||||||
if (modbus_data.size() != 2) {
|
if (modbus_data.size() != 2) {
|
||||||
return false;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonValue["value"] = Helpers::numericoperator2scalefactor(dv.numeric_operator) * (float)((uint16_t)modbus_data[0] << 8 | (uint16_t)modbus_data[1]);
|
jsonValue["value"] = Helpers::numericoperator2scalefactor(dv.numeric_operator) * (float)((uint16_t)modbus_data[0] << 8 | (uint16_t)modbus_data[1]);
|
||||||
} else if (dv.type == DeviceValueType::UINT24 || dv.type == DeviceValueType::UINT32 || dv.type == DeviceValueType::TIME) {
|
} else if (dv.type == DeviceValueType::UINT24 || dv.type == DeviceValueType::UINT32 || dv.type == DeviceValueType::TIME) {
|
||||||
// these data types are 2 16 bit register
|
// these data types are 2 16 bit register
|
||||||
if (modbus_data.size() != 4) {
|
if (modbus_data.size() != 4) {
|
||||||
return false;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonValue["value"] =
|
jsonValue["value"] =
|
||||||
@@ -2084,11 +2084,25 @@ bool EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname,
|
|||||||
* (float)((uint32_t)modbus_data[0] << 24 | (uint32_t)modbus_data[1] << 16 | (uint32_t)modbus_data[2] << 8 | (uint32_t)modbus_data[3]);
|
* (float)((uint32_t)modbus_data[0] << 24 | (uint32_t)modbus_data[1] << 16 | (uint32_t)modbus_data[2] << 8 | (uint32_t)modbus_data[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
// handle CMD
|
||||||
return false;
|
else if (dv.type == DeviceValueType::CMD) {
|
||||||
|
if (modbus_data.size() > 4) {
|
||||||
|
return -7;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
uint32_t value = 0;
|
||||||
|
for(auto i = 0; i < modbus_data.size(); i++) {
|
||||||
|
value += (uint32_t)modbus_data[modbus_data.size() - i - 1] << (i * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonValue["value"] = Helpers::numericoperator2scalefactor(dv.numeric_operator) * (float)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ class EMSdevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get_modbus_value(uint8_t tag, const std::string & shortname, std::vector<uint16_t> & result);
|
int get_modbus_value(uint8_t tag, const std::string & shortname, std::vector<uint16_t> & result);
|
||||||
bool modbus_value_to_json(uint8_t tag, const std::string & shortname, const std::vector<uint8_t> & modbus_data, JsonObject jsonValue);
|
int modbus_value_to_json(uint8_t tag, const std::string & shortname, const std::vector<uint8_t> & modbus_data, JsonObject jsonValue);
|
||||||
|
|
||||||
const char * brand_to_char();
|
const char * brand_to_char();
|
||||||
const std::string to_string();
|
const std::string to_string();
|
||||||
|
|||||||
@@ -313,16 +313,17 @@ ModbusMessage Modbus::handleRead(const ModbusMessage & request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto buf = std::vector<uint16_t>(num_words);
|
auto buf = std::vector<uint16_t>(num_words);
|
||||||
if (dev->get_modbus_value(tag, modbusInfo->short_name, buf) == 0) {
|
auto error_code = dev->get_modbus_value(tag, modbusInfo->short_name, buf);
|
||||||
|
if (error_code) {
|
||||||
|
LOG_ERROR("Unable to read raw device value %s for tag=%d - error_code = %d", modbusInfo->short_name, (int)tag, error_code);
|
||||||
|
response.setError(request.getServerID(), request.getFunctionCode(), SERVER_DEVICE_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
response.add(request.getServerID());
|
response.add(request.getServerID());
|
||||||
response.add(request.getFunctionCode());
|
response.add(request.getFunctionCode());
|
||||||
response.add((uint8_t)(num_words * 2));
|
response.add((uint8_t)(num_words * 2));
|
||||||
for (auto & value : buf)
|
for (auto & value : buf)
|
||||||
response.add(value);
|
response.add(value);
|
||||||
} else {
|
|
||||||
LOG_ERROR("Unable to read raw device value %s for tag=%d", modbusInfo->short_name, (int)tag);
|
|
||||||
response.setError(request.getServerID(), request.getFunctionCode(), SERVER_DEVICE_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -368,6 +369,8 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
|
|||||||
|
|
||||||
auto register_offset = start_address - tag * REGISTER_BLOCK_SIZE;
|
auto register_offset = start_address - tag * REGISTER_BLOCK_SIZE;
|
||||||
|
|
||||||
|
LOG_DEBUG("Tag %d, offset %d", tag, register_offset);
|
||||||
|
|
||||||
const auto & dev_it =
|
const auto & dev_it =
|
||||||
std::find_if(EMSESP::emsdevices.begin(), EMSESP::emsdevices.end(), [&](const std::unique_ptr<EMSdevice> & x) { return x->device_type() == device_type; });
|
std::find_if(EMSESP::emsdevices.begin(), EMSESP::emsdevices.end(), [&](const std::unique_ptr<EMSdevice> & x) { return x->device_type() == device_type; });
|
||||||
|
|
||||||
@@ -380,6 +383,8 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
|
|||||||
|
|
||||||
const auto & dev = *dev_it;
|
const auto & dev = *dev_it;
|
||||||
|
|
||||||
|
LOG_DEBUG("found device '%s' of type %d", dev->name(), dev->device_type());
|
||||||
|
|
||||||
// binary search in modbus infos
|
// binary search in modbus infos
|
||||||
auto key = EntityModbusInfoKey(dev->device_type(), tag_type, register_offset);
|
auto key = EntityModbusInfoKey(dev->device_type(), tag_type, register_offset);
|
||||||
auto modbusInfo = std::lower_bound(std::begin(modbus_register_mappings),
|
auto modbusInfo = std::lower_bound(std::begin(modbus_register_mappings),
|
||||||
@@ -397,6 +402,8 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("Writing to entity %s", modbusInfo->short_name);
|
||||||
|
|
||||||
// only writing a single value at a time is supported for now
|
// only writing a single value at a time is supported for now
|
||||||
if (num_words != modbusInfo->registerCount) {
|
if (num_words != modbusInfo->registerCount) {
|
||||||
// number of registers requested does not match actual register count for entity
|
// number of registers requested does not match actual register count for entity
|
||||||
@@ -408,9 +415,10 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
|
|||||||
JsonDocument input_doc;
|
JsonDocument input_doc;
|
||||||
JsonObject input = input_doc.to<JsonObject>();
|
JsonObject input = input_doc.to<JsonObject>();
|
||||||
|
|
||||||
if (!dev->modbus_value_to_json(tag, modbusInfo->short_name, data, input)) {
|
auto error_code = dev->modbus_value_to_json(tag, modbusInfo->short_name, data, input);
|
||||||
|
if (error_code) {
|
||||||
// error getting modbus value as json
|
// error getting modbus value as json
|
||||||
LOG_ERROR("error getting modbus value as json");
|
LOG_ERROR("error getting modbus value as json, error code = %d", error_code);
|
||||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -488,7 +496,6 @@ int Modbus::getRegisterCount(const DeviceValue & dv) {
|
|||||||
case DeviceValue::INT16:
|
case DeviceValue::INT16:
|
||||||
case DeviceValue::UINT16:
|
case DeviceValue::UINT16:
|
||||||
case DeviceValue::ENUM: // 8 bit
|
case DeviceValue::ENUM: // 8 bit
|
||||||
case DeviceValue::CMD:
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case DeviceValue::UINT24:
|
case DeviceValue::UINT24:
|
||||||
@@ -496,6 +503,21 @@ int Modbus::getRegisterCount(const DeviceValue & dv) {
|
|||||||
case DeviceValue::TIME: // 32 bit
|
case DeviceValue::TIME: // 32 bit
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
case DeviceValue::CMD: {
|
||||||
|
// calculate a sensible register size from min, max and numeric_operator
|
||||||
|
uint32_t num_values = std::max(dv.max, (uint32_t)abs(dv.min));
|
||||||
|
int num_registers = 0;
|
||||||
|
|
||||||
|
if (num_values <= (1L << 8)) num_registers = 1;
|
||||||
|
else if(num_values <= (1L << 16)) num_registers = 2;
|
||||||
|
else if(num_values <= (1L << 32)) num_registers = 4;
|
||||||
|
else LOG_ERROR("num_registers is too big to be encoded with modbus registers");
|
||||||
|
|
||||||
|
LOG_DEBUG("Value for CMD '%s' can take on %ld values and is encoded in %d registers", dv.short_name, num_values, num_registers);
|
||||||
|
|
||||||
|
return num_registers;
|
||||||
|
}
|
||||||
|
|
||||||
case DeviceValue::STRING:
|
case DeviceValue::STRING:
|
||||||
break; // impossible to guess, needs to be hardcoded
|
break; // impossible to guess, needs to be hardcoded
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1844,17 +1844,28 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
|
|
||||||
System::test_set_all_active(true);
|
System::test_set_all_active(true);
|
||||||
add_device(0x08, 172); // boiler: Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i
|
add_device(0x08, 172); // boiler: Enviline/Compress 6000AW/Hybrid 3000-7000iAW/SupraEco/Geo 5xx/WLW196i
|
||||||
|
add_device(0x10, 158); // thermostat: RC310
|
||||||
|
|
||||||
const auto & it = std::find_if(EMSESP::emsdevices.begin(), EMSESP::emsdevices.end(), [&](const std::unique_ptr<EMSdevice> & dev) {
|
const auto & boiler_it = std::find_if(EMSESP::emsdevices.begin(), EMSESP::emsdevices.end(), [&](const std::unique_ptr<EMSdevice> & dev) {
|
||||||
return dev && dev->device_id() == 0x08;
|
return dev && dev->device_id() == 0x08;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (it == EMSESP::emsdevices.end()) {
|
if (boiler_it == EMSESP::emsdevices.end()) {
|
||||||
EMSESP::logger().err("ERROR - can not find mocked heatpump device");
|
EMSESP::logger().err("ERROR - can not find mocked boiler device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto & device = *it;
|
const auto & thermostat_it = std::find_if(EMSESP::emsdevices.begin(), EMSESP::emsdevices.end(), [&](const std::unique_ptr<EMSdevice> & dev) {
|
||||||
|
return dev && dev->device_id() == 0x10;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (thermostat_it == EMSESP::emsdevices.end()) {
|
||||||
|
EMSESP::logger().err("ERROR - can not find mocked thermostat device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto & boiler_dev = *boiler_it;
|
||||||
|
const auto & thermostat_dev = *thermostat_it;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto test_int8 = [&](const std::unique_ptr<EMSdevice> & device, uint8_t tag, const std::string & shortname) {
|
auto test_int8 = [&](const std::unique_ptr<EMSdevice> & device, uint8_t tag, const std::string & shortname) {
|
||||||
@@ -1967,14 +1978,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printfln("Testing device->get_modbus_value():");
|
shell.printfln("Testing device->get_modbus_value():");
|
||||||
test_int8(device, DeviceValueTAG::TAG_DEVICE_DATA, "mintempsilent");
|
test_int8(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "mintempsilent");
|
||||||
test_uint8(device, DeviceValueTAG::TAG_DEVICE_DATA, "selflowtemp");
|
test_uint8(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "selflowtemp");
|
||||||
test_int16(device, DeviceValueTAG::TAG_DEVICE_DATA, "outdoortemp");
|
test_int16(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "outdoortemp");
|
||||||
test_uint16(device, DeviceValueTAG::TAG_DEVICE_DATA, "rettemp");
|
test_uint16(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "rettemp");
|
||||||
// test_uint32(device, DeviceValueTAG::TAG_DEVICE_DATA, "heatstarts"); // apparently there are no uint32 entities?
|
// test_uint32(device, DeviceValueTAG::TAG_DEVICE_DATA, "heatstarts"); // apparently there are no uint32 entities?
|
||||||
test_uint24(device, DeviceValueTAG::TAG_DEVICE_DATA, "heatstarts");
|
test_uint24(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "heatstarts");
|
||||||
test_bool(device, DeviceValueTAG::TAG_DEVICE_DATA, "heatingactivated");
|
test_bool(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "heatingactivated");
|
||||||
test_enum(device, DeviceValueTAG::TAG_DEVICE_DATA, "pumpmode");
|
test_enum(boiler_dev, DeviceValueTAG::TAG_DEVICE_DATA, "pumpmode");
|
||||||
}
|
}
|
||||||
|
|
||||||
// modbus_value_to_json
|
// modbus_value_to_json
|
||||||
@@ -1987,7 +1998,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
JsonObject inputObject = input.to<JsonObject>();
|
JsonObject inputObject = input.to<JsonObject>();
|
||||||
modbus_bytes[0] = 0;
|
modbus_bytes[0] = 0;
|
||||||
modbus_bytes[1] = EMS_VALUE_DEFAULT_UINT8_DUMMY;
|
modbus_bytes[1] = EMS_VALUE_DEFAULT_UINT8_DUMMY;
|
||||||
device->modbus_value_to_json(DeviceValueTAG::TAG_DEVICE_DATA, "selflowtemp", modbus_bytes, inputObject);
|
boiler_dev->modbus_value_to_json(DeviceValueTAG::TAG_DEVICE_DATA, "selflowtemp", modbus_bytes, inputObject);
|
||||||
|
|
||||||
std::string jsonString;
|
std::string jsonString;
|
||||||
serializeJson(inputObject, jsonString);
|
serializeJson(inputObject, jsonString);
|
||||||
@@ -2004,9 +2015,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
shell.println();
|
shell.println();
|
||||||
shell.printfln("Testing modbus->handleRead():");
|
shell.printfln("Testing modbus->handleRead():");
|
||||||
|
|
||||||
uint16_t reg = Modbus::REGISTER_BLOCK_SIZE * DeviceValueTAG::TAG_DEVICE_DATA + 209; // mintempsilent is tag 2 (TAG_DEVICE_DATA), offset 209
|
uint16_t reg = Modbus::REGISTER_BLOCK_SIZE * DeviceValueTAG::TAG_DEVICE_DATA + 214; // mintempsilent is tag 2 (TAG_DEVICE_DATA), offset 214
|
||||||
|
|
||||||
ModbusMessage request({device->device_type(), 0x03, static_cast<unsigned char>(reg >> 8), static_cast<unsigned char>(reg & 0xff), 0, 1});
|
ModbusMessage request({boiler_dev->device_type(), 0x03, static_cast<unsigned char>(reg >> 8), static_cast<unsigned char>(reg & 0xff), 0, 1});
|
||||||
auto response = EMSESP::modbus_->handleRead(request);
|
auto response = EMSESP::modbus_->handleRead(request);
|
||||||
|
|
||||||
if (response.getError() == SUCCESS) {
|
if (response.getError() == SUCCESS) {
|
||||||
@@ -2025,13 +2036,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleWrite
|
// handleWrite boiler
|
||||||
{
|
{
|
||||||
shell.println();
|
shell.println();
|
||||||
shell.printfln("Testing modbus->handleWrite():");
|
shell.printfln("Testing modbus->handleWrite() for boiler:");
|
||||||
|
|
||||||
uint16_t reg = Modbus::REGISTER_BLOCK_SIZE * DeviceValueTAG::TAG_DEVICE_DATA + 4; // selflowtemp is tag 2 (TAG_DEVICE_DATA), offset 4
|
uint16_t reg = Modbus::REGISTER_BLOCK_SIZE * DeviceValueTAG::TAG_DEVICE_DATA + 4; // selflowtemp
|
||||||
ModbusMessage request({device->device_type(), 0x06, static_cast<unsigned char>(reg >> 8), static_cast<unsigned char>(reg & 0xff), 0, 1, 2, 0, 45});
|
ModbusMessage request({boiler_dev->device_type(), 0x06, static_cast<unsigned char>(reg >> 8), static_cast<unsigned char>(reg & 0xff), 0, 1, 2, 0, 45});
|
||||||
auto response = EMSESP::modbus_->handleWrite(request);
|
auto response = EMSESP::modbus_->handleWrite(request);
|
||||||
|
|
||||||
if (response.getError() == SUCCESS) {
|
if (response.getError() == SUCCESS) {
|
||||||
@@ -2045,6 +2056,26 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleWrite thermostat
|
||||||
|
{
|
||||||
|
shell.println();
|
||||||
|
shell.printfln("Testing modbus->handleWrite() for thermostat:");
|
||||||
|
|
||||||
|
uint16_t reg = Modbus::REGISTER_BLOCK_SIZE * DeviceValueTAG::TAG_HC1 + 41; // remotetemp
|
||||||
|
ModbusMessage request({thermostat_dev->device_type(), 0x06, static_cast<unsigned char>(reg >> 8), static_cast<unsigned char>(reg & 0xff), 0, 1, 2, 0, 45});
|
||||||
|
auto response = EMSESP::modbus_->handleWrite(request);
|
||||||
|
|
||||||
|
if (response.getError() == SUCCESS) {
|
||||||
|
shell.print("remotetemp MODBUS response:");
|
||||||
|
for (const auto & d : response._data) {
|
||||||
|
shell.printf(" %d", d);
|
||||||
|
}
|
||||||
|
shell.println(" [OK]");
|
||||||
|
} else {
|
||||||
|
shell.printf("remotetemp [MODBUS ERROR %d]\n", response.getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user