optimize modbus

This commit is contained in:
proddy
2025-11-24 23:25:53 +01:00
parent 3113a4be2b
commit 2e343ce0c3
2 changed files with 33 additions and 9 deletions

View File

@@ -632,6 +632,9 @@ void EMSdevice::add_device_value(int8_t tag, // to b
devicevalues_.emplace_back(
device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state);
// add to index for fast lookup by (tag, short_name)
devicevalue_index_[{static_cast<uint8_t>(tag), short_name}] = devicevalues_.size() - 1;
// add a new command if it has a function attached
if (has_cmd) {
uint8_t flags = CommandFlag::ADMIN_ONLY; // executing commands require admin privileges
@@ -2032,14 +2035,13 @@ std::string EMSdevice::name() {
// copy a raw value (i.e. without applying the numeric_operator) to the output buffer.
// returns true on success.
int EMSdevice::get_modbus_value(uint8_t tag, const std::string & shortname, std::vector<uint16_t> & result) {
// 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() && (it->short_name != shortname || it->tag != tag)) {
// find device value by shortname using hash map index
auto index_it = devicevalue_index_.find({tag, shortname});
if (index_it == devicevalue_index_.end()) {
return -1;
}
auto & dv = *it;
auto & dv = devicevalues_[index_it->second];
// check if it exists, there is a value for the entity. Set the flag to ACTIVE
// not that this will override any previously removed states
@@ -2120,13 +2122,13 @@ int EMSdevice::get_modbus_value(uint8_t tag, const std::string & shortname, std:
int EMSdevice::modbus_value_to_json(uint8_t tag, const std::string & shortname, const std::vector<uint8_t> & modbus_data, JsonObject jsonValue) {
// LOG_DEBUG("modbus_value_to_json(%d,%s,[%d bytes])\n", tag, shortname.c_str(), modbus_data.size());
// 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() && (it->short_name != shortname || it->tag != tag)) {
// find device value by shortname using hash map index
auto index_it = devicevalue_index_.find({tag, shortname});
if (index_it == devicevalue_index_.end()) {
return -1;
}
auto & dv = *it;
auto & dv = devicevalues_[index_it->second];
// handle Booleans
if (dv.type == DeviceValueType::BOOL) {

View File

@@ -25,6 +25,8 @@
#include "helpers.h"
#include "emsdevicevalue.h"
#include <unordered_map>
namespace emsesp {
class EMSdevice {
@@ -553,6 +555,26 @@ class EMSdevice {
#endif
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
std::vector<DeviceValue> devicevalues_; // all the device values
// added for modbus
// Hash map for O(1) lookup of device values by (tag, short_name) key
struct DeviceValueKey {
uint8_t tag;
std::string short_name;
bool operator==(const DeviceValueKey & other) const {
return tag == other.tag && short_name == other.short_name;
}
};
struct DeviceValueKeyHash {
std::size_t operator()(const DeviceValueKey & key) const {
// Combine hash of tag and short_name
return std::hash<uint8_t>()(key.tag) ^ (std::hash<std::string>()(key.short_name) << 1);
}
};
std::unordered_map<DeviceValueKey, size_t, DeviceValueKeyHash> devicevalue_index_; // index: key -> devicevalues_ position
};
} // namespace emsesp