Skip to content

Commit

Permalink
fix modbus multiple devices (mixer) emsesp#2229
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelDvP committed Nov 20, 2024
1 parent 9f3d3c7 commit aea9a44
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 36 deletions.
7 changes: 4 additions & 3 deletions src/emsdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1928,7 +1928,7 @@ const char * EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> teleg
bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
for (auto & tf : telegram_functions_) {
if (tf.telegram_type_id_ == telegram->type_id) {
// for telegram desitnation only read telegram
// for telegram destination only read telegram
if (telegram->dest == device_id_ && telegram->message_length > 0) {
tf.process_function_(telegram);
return true;
Expand Down Expand Up @@ -1996,8 +1996,9 @@ int EMSdevice::get_modbus_value(uint8_t tag, const std::string & shortname, std:
// find device value by shortname
// TODO replace linear search which is inefficient
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() && (it->short_name != shortname || it->tag != tag)) {
return -1;
}

auto & dv = *it;

Expand Down Expand Up @@ -2082,7 +2083,7 @@ int EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & 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; });
if (it == devicevalues_.end()) {
if (it == devicevalues_.end() && (it->short_name != shortname || it->tag != tag)) {
return -1;
}

Expand Down
56 changes: 23 additions & 33 deletions src/modbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,8 @@ ModbusMessage Modbus::handleRead(const ModbusMessage & request) {

auto register_offset = start_address - tag * REGISTER_BLOCK_SIZE;

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; });

if (dev_it == EMSESP::emsdevices.end()) {
// device not found => invalid server ID
LOG_ERROR("device with type %d not found => invalid server ID", device_type);
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
return response;
}

const auto & dev = *dev_it;

// binary search in modbus infos
auto key = EntityModbusInfoKey(dev->device_type(), tag_type, register_offset);
auto key = EntityModbusInfoKey(device_type, tag_type, register_offset);

const auto & modbusInfo = std::lower_bound(std::begin(modbus_register_mappings),
std::end(modbus_register_mappings),
Expand All @@ -312,7 +300,15 @@ ModbusMessage Modbus::handleRead(const ModbusMessage & request) {
}

auto buf = std::vector<uint16_t>(num_words);
auto error_code = dev->get_modbus_value(tag, modbusInfo->short_name, buf);
int error_code = -1;
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->device_type() == device_type) {
error_code = emsdevice->get_modbus_value(tag, modbusInfo->short_name, buf);
if (!error_code) {
break;
}
}
}
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);
Expand Down Expand Up @@ -370,22 +366,9 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {

LOG_DEBUG("Tag %d, offset %d", tag, register_offset);

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; });

if (dev_it == EMSESP::emsdevices.end()) {
// device not found => invalid server ID
LOG_ERROR("device_type (%d) not found => invalid server ID", device_type);
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
return response;
}

const auto & dev = *dev_it;

LOG_DEBUG("found device '%s' of type %d", dev->name().c_str(), dev->device_type());

// binary search in modbus infos
auto key = EntityModbusInfoKey(dev->device_type(), tag_type, register_offset);
auto key = EntityModbusInfoKey(device_type, tag_type, register_offset);
auto modbusInfo = std::lower_bound(std::begin(modbus_register_mappings),
std::end(modbus_register_mappings),
key,
Expand All @@ -412,9 +395,16 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {
}

JsonDocument input_doc;
JsonObject input = input_doc.to<JsonObject>();

auto error_code = dev->modbus_value_to_json(tag, modbusInfo->short_name, data, input);
JsonObject input = input_doc.to<JsonObject>();
int error_code = -1;
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->device_type() == device_type) {
error_code = emsdevice->modbus_value_to_json(tag, modbusInfo->short_name, data, input);
if (!error_code) {
break;
}
}
}
if (error_code) {
// error getting modbus value as json
LOG_ERROR("error getting modbus value as json, error code = %d", error_code);
Expand All @@ -424,9 +414,9 @@ ModbusMessage Modbus::handleWrite(const ModbusMessage & request) {

std::string path;
if (tag < DeviceValueTAG::TAG_HC1) {
path = std::string("ems-esp/") + std::string(EMSdevice::device_type_2_device_name(dev->device_type())) + "/" + modbusInfo->short_name;
path = std::string("ems-esp/") + std::string(EMSdevice::device_type_2_device_name(device_type)) + "/" + modbusInfo->short_name;
} else {
path = std::string("ems-esp/") + std::string(EMSdevice::device_type_2_device_name(dev->device_type())) + "/" + EMSdevice::tag_to_mqtt(tag) + "/"
path = std::string("ems-esp/") + std::string(EMSdevice::device_type_2_device_name(device_type)) + "/" + EMSdevice::tag_to_mqtt(tag) + "/"
+ modbusInfo->short_name;
}

Expand Down

0 comments on commit aea9a44

Please sign in to comment.