Optimize DlmsParser allocations and types
Use stack buffers and C-strings to avoid heap allocations, and modernize token handling and ownership. - Replace heap-allocated std::string temporaries in dlms_parser.cpp with stack buffers and pass const char* to callbacks/logs to reduce allocations and copying. - Change DlmsDataCallback signature to accept const char* for obis and string values; update DlmsPushComponent to match. - Switch DlmsParser ownership to std::unique_ptr in DlmsPushComponent and add <memory> include. - Replace std::list with std::vector for DSL token parsing, update iteration/insertion logic accordingly. - Remove unused <list> include and adjust related function signatures/whitespace. These changes improve performance and memory usage; note the callback/API signature change may require updating any external callers.main
parent
789611a611
commit
a9e13b6e8c
|
|
@ -399,10 +399,9 @@ bool DlmsParser::match_pattern_(uint8_t elem_idx, const AxdrDescriptorPattern &p
|
|||
void DlmsParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptures &c) {
|
||||
if (!c.obis || !this->callback_) return;
|
||||
|
||||
// Use stack-allocated buffer for OBIS to avoid string allocation
|
||||
// Use stack-allocated buffer for OBIS to avoid heap allocation
|
||||
char obis_str_buf[32];
|
||||
this->obis_to_string_(c.obis, obis_str_buf, sizeof(obis_str_buf));
|
||||
std::string obis_str(obis_str_buf);
|
||||
|
||||
float raw_val_f = this->data_as_float_(c.value_type, c.value_ptr, c.value_len);
|
||||
float val_f = raw_val_f;
|
||||
|
|
@ -410,7 +409,6 @@ void DlmsParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptur
|
|||
// Use stack-allocated buffer for formatting data
|
||||
char val_s_buf[128];
|
||||
this->data_to_string_(c.value_type, c.value_ptr, c.value_len, val_s_buf, sizeof(val_s_buf));
|
||||
std::string val_s(val_s_buf);
|
||||
|
||||
bool is_numeric = (c.value_type != DLMS_DATA_TYPE_OCTET_STRING &&
|
||||
c.value_type != DLMS_DATA_TYPE_STRING &&
|
||||
|
|
@ -424,7 +422,7 @@ void DlmsParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptur
|
|||
ESP_LOGD(TAG, "Pattern match '%s' at idx %u ===============", pat.name.c_str(), c.elem_idx);
|
||||
uint16_t cid = c.class_id ? c.class_id : pat.default_class_id;
|
||||
|
||||
ESP_LOGI(TAG, "Found attribute descriptor: class_id=%d, obis=%s", cid, obis_str.c_str());
|
||||
ESP_LOGI(TAG, "Found attribute descriptor: class_id=%d, obis=%s", cid, obis_str_buf);
|
||||
|
||||
if (c.has_scaler_unit) {
|
||||
ESP_LOGI(TAG, "Value type: %s, len %d, scaler %d, unit %d",
|
||||
|
|
@ -438,7 +436,7 @@ void DlmsParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptur
|
|||
esphome::format_hex_pretty_to(hex_buf, sizeof(hex_buf), c.value_ptr, c.value_len);
|
||||
ESP_LOGI(TAG, " as hex dump : %s", hex_buf);
|
||||
}
|
||||
ESP_LOGI(TAG, " as string :'%s'", val_s.c_str());
|
||||
ESP_LOGI(TAG, " as string :'%s'", val_s_buf);
|
||||
ESP_LOGI(TAG, " as number : %f", raw_val_f);
|
||||
|
||||
if (c.has_scaler_unit && is_numeric) {
|
||||
|
|
@ -446,7 +444,7 @@ void DlmsParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptur
|
|||
}
|
||||
}
|
||||
|
||||
this->callback_(obis_str, val_f, val_s, is_numeric);
|
||||
this->callback_(obis_str_buf, val_f, val_s_buf, is_numeric);
|
||||
this->objects_found_++;
|
||||
}
|
||||
|
||||
|
|
@ -620,7 +618,7 @@ void DlmsParser::register_pattern_dsl_(const std::string &name, const std::strin
|
|||
return s.substr(b, e - b + 1);
|
||||
};
|
||||
|
||||
std::list<std::string> tokens;
|
||||
std::vector<std::string> tokens;
|
||||
std::string current;
|
||||
int paren = 0;
|
||||
for (char c : dsl) {
|
||||
|
|
@ -639,8 +637,8 @@ void DlmsParser::register_pattern_dsl_(const std::string &name, const std::strin
|
|||
}
|
||||
if (!current.empty()) tokens.push_back(trim(current));
|
||||
|
||||
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
|
||||
std::string tok = *it;
|
||||
for (size_t i = 0; i < tokens.size(); i++) {
|
||||
std::string tok = tokens[i];
|
||||
if (tok.empty()) continue;
|
||||
|
||||
if (tok == "F") pat.steps.push_back({AxdrTokenType::EXPECT_TO_BE_FIRST});
|
||||
|
|
@ -671,7 +669,7 @@ void DlmsParser::register_pattern_dsl_(const std::string &name, const std::strin
|
|||
size_t r = tok.rfind(')');
|
||||
if (l != std::string::npos && r != std::string::npos && r > l + 1) {
|
||||
std::string inner = tok.substr(l + 1, r - l - 1);
|
||||
std::list<std::string> inner_tokens;
|
||||
std::vector<std::string> inner_tokens;
|
||||
std::string cur;
|
||||
for (char c2 : inner) {
|
||||
if (c2 == ',') {
|
||||
|
|
@ -685,9 +683,9 @@ void DlmsParser::register_pattern_dsl_(const std::string &name, const std::strin
|
|||
|
||||
if (!inner_tokens.empty()) {
|
||||
pat.steps.push_back({AxdrTokenType::EXPECT_STRUCTURE_N, static_cast<uint8_t>(inner_tokens.size())});
|
||||
inner_tokens.push_front("DN");
|
||||
inner_tokens.insert(inner_tokens.begin(), "DN");
|
||||
inner_tokens.push_back("UP");
|
||||
tokens.insert(std::next(it), inner_tokens.begin(), inner_tokens.end());
|
||||
tokens.insert(tokens.begin() + i + 1, inner_tokens.begin(), inner_tokens.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace esphome {
|
||||
namespace dlms_push {
|
||||
|
|
@ -37,7 +36,7 @@ enum DlmsDataType : uint8_t {
|
|||
};
|
||||
|
||||
// Callback for the hub: OBIS code (e.g. "1.0.1.8.0.255"), numeric value, string value, is_numeric flag
|
||||
using DlmsDataCallback = std::function<void(const std::string &obis_code, float float_val, const std::string &str_val, bool is_numeric)>;
|
||||
using DlmsDataCallback = std::function<void(const char *obis_code, float float_val, const char *str_val, bool is_numeric)>;
|
||||
|
||||
// --- Pattern Matching Enums & Structs ---
|
||||
enum class AxdrTokenType : uint8_t {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace dlms_push {
|
|||
static const char *const TAG = "dlms_push";
|
||||
|
||||
DlmsPushComponent::DlmsPushComponent() {
|
||||
this->parser_ = new DlmsParser();
|
||||
this->parser_ = std::make_unique<DlmsParser>();
|
||||
}
|
||||
|
||||
void DlmsPushComponent::setup() {
|
||||
|
|
@ -96,7 +96,7 @@ void DlmsPushComponent::process_frame_() {
|
|||
ESP_LOGD(TAG, "PUSH frame size: %zu bytes", this->rx_buffer_len_);
|
||||
}
|
||||
|
||||
auto callback = [this](const std::string &obis_code, float float_val, const std::string &str_val, bool is_numeric) {
|
||||
auto callback = [this](const char *obis_code, float float_val, const char *str_val, bool is_numeric) {
|
||||
this->on_data_parsed_(obis_code, float_val, str_val, is_numeric);
|
||||
};
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ void DlmsPushComponent::process_frame_() {
|
|||
this->rx_buffer_len_ = 0;
|
||||
}
|
||||
|
||||
void DlmsPushComponent::on_data_parsed_(const std::string &obis_code, float float_val, const std::string &str_val, bool is_numeric) {
|
||||
void DlmsPushComponent::on_data_parsed_(const char *obis_code, float float_val, const char *str_val, bool is_numeric) {
|
||||
int updated_count = 0;
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
|
|
@ -117,7 +117,7 @@ void DlmsPushComponent::on_data_parsed_(const std::string &obis_code, float floa
|
|||
for (const auto &entry : this->sensors_) {
|
||||
if (entry.obis == obis_code) {
|
||||
if (this->show_log_) {
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code.c_str(), entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code, entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Publishing data");
|
||||
}
|
||||
entry.sensor->publish_state(float_val);
|
||||
|
|
@ -131,7 +131,7 @@ void DlmsPushComponent::on_data_parsed_(const std::string &obis_code, float floa
|
|||
for (const auto &entry : this->text_sensors_) {
|
||||
if (entry.obis == obis_code) {
|
||||
if (this->show_log_) {
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code.c_str(), entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code, entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Publishing data");
|
||||
}
|
||||
entry.sensor->publish_state(str_val);
|
||||
|
|
@ -146,7 +146,7 @@ void DlmsPushComponent::on_data_parsed_(const std::string &obis_code, float floa
|
|||
for (const auto &entry : this->binary_sensors_) {
|
||||
if (entry.obis == obis_code) {
|
||||
if (this->show_log_) {
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code.c_str(), entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s'", obis_code, entry.sensor->get_name().c_str());
|
||||
ESP_LOGD(TAG, "Publishing data");
|
||||
}
|
||||
entry.sensor->publish_state(state);
|
||||
|
|
@ -157,7 +157,7 @@ void DlmsPushComponent::on_data_parsed_(const std::string &obis_code, float floa
|
|||
#endif
|
||||
|
||||
if (this->show_log_ && updated_count == 0) {
|
||||
ESP_LOGV(TAG, "Received OBIS %s, but no sensors are registered for it.", obis_code.c_str());
|
||||
ESP_LOGV(TAG, "Received OBIS %s, but no sensors are registered for it.", obis_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace esphome {
|
||||
namespace dlms_push {
|
||||
|
|
@ -49,7 +50,7 @@ class DlmsPushComponent : public Component, public uart::UARTDevice {
|
|||
void read_rx_buffer_();
|
||||
void process_frame_();
|
||||
|
||||
void on_data_parsed_(const std::string &obis_code, float float_val, const std::string &str_val, bool is_numeric);
|
||||
void on_data_parsed_(const char *obis_code, float float_val, const char *str_val, bool is_numeric);
|
||||
|
||||
uint32_t receive_timeout_ms_{50};
|
||||
bool show_log_{false};
|
||||
|
|
@ -61,7 +62,7 @@ class DlmsPushComponent : public Component, public uart::UARTDevice {
|
|||
uint32_t last_rx_char_time_{0};
|
||||
bool receiving_{false};
|
||||
|
||||
DlmsParser *parser_{nullptr};
|
||||
std::unique_ptr<DlmsParser> parser_;
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
struct NumericSensorEntry {
|
||||
|
|
|
|||
Loading…
Reference in New Issue