diff --git a/esphome/components/sml/sml.cpp b/esphome/components/sml/sml.cpp index bac13be923..7ae9044c72 100644 --- a/esphome/components/sml/sml.cpp +++ b/esphome/components/sml/sml.cpp @@ -52,9 +52,8 @@ void Sml::loop() { break; // remove start/end sequence - this->sml_data_.erase(this->sml_data_.begin(), this->sml_data_.begin() + START_SEQ.size()); - this->sml_data_.resize(this->sml_data_.size() - 8); - this->process_sml_file_(this->sml_data_); + this->process_sml_file_( + BytesView(this->sml_data_).subview(START_SEQ.size(), this->sml_data_.size() - START_SEQ.size() - 8)); } break; }; @@ -66,8 +65,8 @@ void Sml::add_on_data_callback(std::function, bool)> & this->data_callbacks_.add(std::move(callback)); } -void Sml::process_sml_file_(const bytes &sml_data) { - SmlFile sml_file = SmlFile(sml_data); +void Sml::process_sml_file_(const BytesView &sml_data) { + SmlFile sml_file(sml_data); std::vector obis_info = sml_file.get_obis_info(); this->publish_obis_info_(obis_info); @@ -75,6 +74,7 @@ void Sml::process_sml_file_(const bytes &sml_data) { } void Sml::log_obis_info_(const std::vector &obis_info_vec) { +#ifdef ESPHOME_LOG_HAS_DEBUG ESP_LOGD(TAG, "OBIS info:"); for (auto const &obis_info : obis_info_vec) { std::string info; @@ -83,6 +83,7 @@ void Sml::log_obis_info_(const std::vector &obis_info_vec) { info += " [0x" + bytes_repr(obis_info.value) + "]"; ESP_LOGD(TAG, "%s", info.c_str()); } +#endif } void Sml::publish_obis_info_(const std::vector &obis_info_vec) { @@ -92,10 +93,11 @@ void Sml::publish_obis_info_(const std::vector &obis_info_vec) { } void Sml::publish_value_(const ObisInfo &obis_info) { + const auto obis_code = obis_info.code_repr(); for (auto const &sml_listener : sml_listeners_) { if ((!sml_listener->server_id.empty()) && (bytes_repr(obis_info.server_id) != sml_listener->server_id)) continue; - if (obis_info.code_repr() != sml_listener->obis_code) + if (obis_code != sml_listener->obis_code) continue; sml_listener->publish_val(obis_info); } diff --git a/esphome/components/sml/sml.h b/esphome/components/sml/sml.h index b0c932ca95..15ca43944c 100644 --- a/esphome/components/sml/sml.h +++ b/esphome/components/sml/sml.h @@ -27,7 +27,7 @@ class Sml : public Component, public uart::UARTDevice { void add_on_data_callback(std::function, bool)> &&callback); protected: - void process_sml_file_(const bytes &sml_data); + void process_sml_file_(const BytesView &sml_data); void log_obis_info_(const std::vector &obis_info_vec); void publish_obis_info_(const std::vector &obis_info_vec); char check_start_end_bytes_(uint8_t byte); diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 2cc71e87fa..85e5a2da03 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -5,17 +5,17 @@ namespace esphome { namespace sml { -SmlFile::SmlFile(bytes buffer) : buffer_(std::move(buffer)) { +SmlFile::SmlFile(const BytesView &buffer) : buffer_(buffer) { // extract messages this->pos_ = 0; while (this->pos_ < this->buffer_.size()) { if (this->buffer_[this->pos_] == 0x00) break; // EndOfSmlMsg - SmlNode message = SmlNode(); + SmlNode message; if (!this->setup_node(&message)) break; - this->messages.emplace_back(message); + this->messages.emplace_back(std::move(message)); } } @@ -62,22 +62,20 @@ bool SmlFile::setup_node(SmlNode *node) { return false; node->type = type; - node->nodes.clear(); - node->value_bytes.clear(); if (type == SML_LIST) { node->nodes.reserve(length); for (size_t i = 0; i != length; i++) { - SmlNode child_node = SmlNode(); + SmlNode child_node; if (!this->setup_node(&child_node)) return false; - node->nodes.emplace_back(child_node); + node->nodes.emplace_back(std::move(child_node)); } } else { // Value starts at the current position // Value ends "length" bytes later, // (since the TL field is counted but already subtracted from length) - node->value_bytes = bytes(this->buffer_.begin() + this->pos_, this->buffer_.begin() + this->pos_ + length); + node->value_bytes = buffer_.subview(this->pos_, length); // Increment the pointer past all consumed bytes this->pos_ += length; } @@ -87,14 +85,14 @@ bool SmlFile::setup_node(SmlNode *node) { std::vector SmlFile::get_obis_info() { std::vector obis_info; for (auto const &message : messages) { - SmlNode message_body = message.nodes[3]; + const auto &message_body = message.nodes[3]; uint16_t message_type = bytes_to_uint(message_body.nodes[0].value_bytes); if (message_type != SML_GET_LIST_RES) continue; - SmlNode get_list_response = message_body.nodes[1]; - bytes server_id = get_list_response.nodes[1].value_bytes; - SmlNode val_list = get_list_response.nodes[4]; + const auto &get_list_response = message_body.nodes[1]; + const auto &server_id = get_list_response.nodes[1].value_bytes; + const auto &val_list = get_list_response.nodes[4]; for (auto const &val_list_entry : val_list.nodes) { obis_info.emplace_back(server_id, val_list_entry); @@ -103,7 +101,7 @@ std::vector SmlFile::get_obis_info() { return obis_info; } -std::string bytes_repr(const bytes &buffer) { +std::string bytes_repr(const BytesView &buffer) { std::string repr; for (auto const value : buffer) { repr += str_sprintf("%02x", value & 0xff); @@ -111,7 +109,7 @@ std::string bytes_repr(const bytes &buffer) { return repr; } -uint64_t bytes_to_uint(const bytes &buffer) { +uint64_t bytes_to_uint(const BytesView &buffer) { uint64_t val = 0; for (auto const value : buffer) { val = (val << 8) + value; @@ -119,7 +117,7 @@ uint64_t bytes_to_uint(const bytes &buffer) { return val; } -int64_t bytes_to_int(const bytes &buffer) { +int64_t bytes_to_int(const BytesView &buffer) { uint64_t tmp = bytes_to_uint(buffer); int64_t val; @@ -135,14 +133,14 @@ int64_t bytes_to_int(const bytes &buffer) { return val; } -std::string bytes_to_string(const bytes &buffer) { return std::string(buffer.begin(), buffer.end()); } +std::string bytes_to_string(const BytesView &buffer) { return std::string(buffer.begin(), buffer.end()); } -ObisInfo::ObisInfo(bytes server_id, SmlNode val_list_entry) : server_id(std::move(server_id)) { +ObisInfo::ObisInfo(const BytesView &server_id, const SmlNode &val_list_entry) : server_id(server_id) { this->code = val_list_entry.nodes[0].value_bytes; this->status = val_list_entry.nodes[1].value_bytes; this->unit = bytes_to_uint(val_list_entry.nodes[3].value_bytes); this->scaler = bytes_to_int(val_list_entry.nodes[4].value_bytes); - SmlNode value_node = val_list_entry.nodes[5]; + const auto &value_node = val_list_entry.nodes[5]; this->value = value_node.value_bytes; this->value_type = value_node.type; } diff --git a/esphome/components/sml/sml_parser.h b/esphome/components/sml/sml_parser.h index fca859d4b8..bee0c8965b 100644 --- a/esphome/components/sml/sml_parser.h +++ b/esphome/components/sml/sml_parser.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -11,44 +12,73 @@ namespace sml { using bytes = std::vector; +class BytesView { + public: + BytesView() noexcept = default; + + explicit BytesView(const uint8_t *first, size_t count) noexcept : data_{first}, count_{count} {} + + explicit BytesView(const bytes &bytes) noexcept : data_{bytes.data()}, count_{bytes.size()} {} + + size_t size() const noexcept { return count_; } + + uint8_t operator[](size_t index) const noexcept { + assert(index < count_); + return data_[index]; + } + + BytesView subview(size_t offset, size_t count) const noexcept { + assert(offset + count <= count_); + return BytesView{data_ + offset, count}; + } + + const uint8_t *begin() const noexcept { return data_; } + + const uint8_t *end() const noexcept { return data_ + count_; } + + private: + const uint8_t *data_ = nullptr; + size_t count_ = 0; +}; + class SmlNode { public: uint8_t type; - bytes value_bytes; + BytesView value_bytes; std::vector nodes; }; class ObisInfo { public: - ObisInfo(bytes server_id, SmlNode val_list_entry); - bytes server_id; - bytes code; - bytes status; + ObisInfo(const BytesView &server_id, const SmlNode &val_list_entry); + BytesView server_id; + BytesView code; + BytesView status; char unit; char scaler; - bytes value; + BytesView value; uint16_t value_type; std::string code_repr() const; }; class SmlFile { public: - SmlFile(bytes buffer); + SmlFile(const BytesView &buffer); bool setup_node(SmlNode *node); std::vector messages; std::vector get_obis_info(); protected: - const bytes buffer_; + const BytesView buffer_; size_t pos_; }; -std::string bytes_repr(const bytes &buffer); +std::string bytes_repr(const BytesView &buffer); -uint64_t bytes_to_uint(const bytes &buffer); +uint64_t bytes_to_uint(const BytesView &buffer); -int64_t bytes_to_int(const bytes &buffer); +int64_t bytes_to_int(const BytesView &buffer); -std::string bytes_to_string(const bytes &buffer); +std::string bytes_to_string(const BytesView &buffer); } // namespace sml } // namespace esphome