From f70bc8a62f4f755dbfe26928b07bed809ccd11bd Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 19 Aug 2025 10:00:31 +0200 Subject: [PATCH 01/14] Implement checksum validation controlled by boolean option validate_checksum --- components/victron/__init__.py | 1 + components/victron/victron.cpp | 37 ++++++++++++++++++++++++++++++++++ components/victron/victron.h | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/components/victron/__init__.py b/components/victron/__init__.py index baf1774..9dfd202 100644 --- a/components/victron/__init__.py +++ b/components/victron/__init__.py @@ -26,6 +26,7 @@ { cv.GenerateID(): cv.declare_id(VictronComponent), cv.Optional(CONF_THROTTLE, default="1s"): cv.positive_time_period_milliseconds, + cv.Optional("validate_checksum", default="false"): cv.boolean, } ) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index e6a254a..0ca0328 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -101,6 +101,7 @@ void VictronComponent::loop() { while (available()) { uint8_t c; read_byte(&c); + checksum_ = (checksum_ + c) & 0xff; if (state_ == 0) { if (c == '\r' || c == '\n') { continue; @@ -126,18 +127,31 @@ void VictronComponent::loop() { if (label_ == "Checksum") { state_ = 0; // The checksum is used as end of frame indicator + #if 0 + // TOCHECK: move this to actual publishing code if (now - this->last_publish_ >= this->throttle_) { this->last_publish_ = now; this->publishing_ = true; } else { this->publishing_ = false; } + #else + publish_frame_(); + frame_.clear(); + #endif + checksum_ = 0; continue; } if (c == '\r' || c == '\n') { + #if 0 if (this->publishing_) { handle_value_(); } + #else + if (frame_.size() < 50) { + frame_.push_back(label_+"\t"+value_); + } + #endif state_ = 0; } else { value_.push_back(c); @@ -713,6 +727,29 @@ static std::string off_reason_text(uint32_t mask) { return value_list; } +void VictronComponent::publish_frame_() { + if (checksum_ != 0) { + ESP_LOGW(TAG, "Checksum error on frame."); + if (validate_checksum_) { + return; + } + } + + const uint32_t now = millis(); + if (now - this->last_publish_ < this->throttle_) { + return; + } + this->last_publish_ = now; + + for(auto item : frame_) { + size_t dpos = item.find("\t"); + label_ = item.substr(0, dpos); + value_ = item.substr(dpos+1); + ESP_LOGD(TAG, "Handle %s value %s", label_.c_str(), value_.c_str()); + handle_value_(); + } +} + void VictronComponent::handle_value_() { int value; diff --git a/components/victron/victron.h b/components/victron/victron.h index 4f8c8c2..91eed04 100644 --- a/components/victron/victron.h +++ b/components/victron/victron.h @@ -209,6 +209,7 @@ class VictronComponent : public uart::UARTDevice, public Component { float get_setup_priority() const override { return setup_priority::DATA; } protected: + void publish_frame_(); void handle_value_(); void publish_state_(binary_sensor::BinarySensor *binary_sensor, const bool &state); void publish_state_(sensor::Sensor *sensor, float value); @@ -289,11 +290,14 @@ class VictronComponent : public uart::UARTDevice, public Component { bool publishing_{true}; int state_{0}; + u_int16_t checksum_{0}; std::string label_; std::string value_; + std::vector frame_; uint32_t last_transmission_{0}; uint32_t last_publish_{0}; uint32_t throttle_{0}; + bool validate_checksum_{false}; }; } // namespace victron From bb63355bdade4c04dbaab34d07931e57b060ea6f Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 19 Aug 2025 10:26:56 +0200 Subject: [PATCH 02/14] Fix option to enable checksum validation --- components/victron/__init__.py | 5 ++++- components/victron/victron.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/components/victron/__init__.py b/components/victron/__init__.py index 9dfd202..b8043e6 100644 --- a/components/victron/__init__.py +++ b/components/victron/__init__.py @@ -16,6 +16,8 @@ CONF_VICTRON_ID = "victron_id" +CONF_VALIDATE_CHECKSUM = "validate_checksum" + VICTRON_COMPONENT_SCHEMA = cv.Schema( { cv.GenerateID(CONF_VICTRON_ID): cv.use_id(VictronComponent), @@ -26,7 +28,7 @@ { cv.GenerateID(): cv.declare_id(VictronComponent), cv.Optional(CONF_THROTTLE, default="1s"): cv.positive_time_period_milliseconds, - cv.Optional("validate_checksum", default="false"): cv.boolean, + cv.Optional(CONF_VALIDATE_CHECKSUM, default="false"): cv.boolean, } ) @@ -37,3 +39,4 @@ def to_code(config): yield uart.register_uart_device(var, config) cg.add(var.set_throttle(config[CONF_THROTTLE])) + cg.add(var.set_checksum_validation(config[CONF_VALIDATE_CHECKSUM])) diff --git a/components/victron/victron.h b/components/victron/victron.h index 91eed04..206ef70 100644 --- a/components/victron/victron.h +++ b/components/victron/victron.h @@ -12,6 +12,7 @@ namespace victron { class VictronComponent : public uart::UARTDevice, public Component { public: void set_throttle(uint32_t throttle) { this->throttle_ = throttle; } + void set_checksum_validation(bool state) { this->validate_checksum_ = state; } void set_load_state_binary_sensor(binary_sensor::BinarySensor *load_state_binary_sensor) { load_state_binary_sensor_ = load_state_binary_sensor; } From 4b604828f8c1562e2729f032e08e65570314afbe Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 19 Aug 2025 15:33:07 +0200 Subject: [PATCH 03/14] Improve checksum error warning --- components/victron/victron.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index 0ca0328..d9ecb60 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -729,9 +729,11 @@ static std::string off_reason_text(uint32_t mask) { void VictronComponent::publish_frame_() { if (checksum_ != 0) { - ESP_LOGW(TAG, "Checksum error on frame."); if (validate_checksum_) { + ESP_LOGW(TAG, "Dropping frame due to checksum error."); return; + } else { + ESP_LOGW(TAG, "Processing frame with checksum error. Consider enabling option 'validate_checksum'"); } } From 3a5e71803b055594735d533cf8c4c92be957401d Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 20 Aug 2025 14:37:30 +0200 Subject: [PATCH 04/14] Switch buffer implementation from vector to string, add size contraint --- components/victron/victron.cpp | 22 ++++++++++++++++++---- components/victron/victron.h | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index d9ecb60..70b4044 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -3,6 +3,12 @@ #include // std::min #include "esphome/core/helpers.h" +#define MAX_LABEL_LENGTH 9 +#define MAX_VALUE_LENGTH 33 +#define MAX_FIELDS_PER_BLOCK 30 // allow for some headroom over the 22 according to protocol specs + +#define MAX_BUF_SIZE ((2 + MAX_LABEL_LENGTH + 1 + MAX_VALUE_LENGTH) * MAX_FIELDS_PER_BLOCK) + namespace esphome { namespace victron { @@ -137,7 +143,7 @@ void VictronComponent::loop() { } #else publish_frame_(); - frame_.clear(); + block_buffer_.clear(); #endif checksum_ = 0; continue; @@ -148,8 +154,11 @@ void VictronComponent::loop() { handle_value_(); } #else - if (frame_.size() < 50) { - frame_.push_back(label_+"\t"+value_); + if (block_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { + block_buffer_.append(label_.c_str()); + block_buffer_.append("\t"); + block_buffer_.append(value_.c_str()); + block_buffer_.append("\r\n"); } #endif state_ = 0; @@ -743,7 +752,12 @@ void VictronComponent::publish_frame_() { } this->last_publish_ = now; - for(auto item : frame_) { + size_t last = 0; + size_t next = 0; + while ((next = block_buffer_.find("\r\n", last)) != std::string::npos) { + std::string item = block_buffer_.substr(last, next-last); + last = next + 2; + size_t dpos = item.find("\t"); label_ = item.substr(0, dpos); value_ = item.substr(dpos+1); diff --git a/components/victron/victron.h b/components/victron/victron.h index 206ef70..077bebf 100644 --- a/components/victron/victron.h +++ b/components/victron/victron.h @@ -294,7 +294,7 @@ class VictronComponent : public uart::UARTDevice, public Component { u_int16_t checksum_{0}; std::string label_; std::string value_; - std::vector frame_; + std::string block_buffer_; uint32_t last_transmission_{0}; uint32_t last_publish_{0}; uint32_t throttle_{0}; From 38792cfd293211ac12f9623b4e5bfb12ff70edca Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 15:00:13 +0200 Subject: [PATCH 05/14] Switch buffer implementation from vector to string, add size contraint --- components/victron/victron.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index 70b4044..b71b3e1 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -3,9 +3,11 @@ #include // std::min #include "esphome/core/helpers.h" -#define MAX_LABEL_LENGTH 9 -#define MAX_VALUE_LENGTH 33 -#define MAX_FIELDS_PER_BLOCK 30 // allow for some headroom over the 22 according to protocol specs +// size contraints used for overflow checks +static const uint8_t MAX_LABEL_LENGTH = 9; +static const uint8_t MAX_VALUE_LENGTH = 33; +// allow for some headroom over the 22 lines per frame according to protocol specs +static const uint8_t MAX_FIELDS_PER_BLOCK = 30; #define MAX_BUF_SIZE ((2 + MAX_LABEL_LENGTH + 1 + MAX_VALUE_LENGTH) * MAX_FIELDS_PER_BLOCK) @@ -107,7 +109,7 @@ void VictronComponent::loop() { while (available()) { uint8_t c; read_byte(&c); - checksum_ = (checksum_ + c) & 0xff; + checksum_ = (checksum_ + c) & 0xff; if (state_ == 0) { if (c == '\r' || c == '\n') { continue; @@ -132,8 +134,8 @@ void VictronComponent::loop() { if (state_ == 2) { if (label_ == "Checksum") { state_ = 0; - // The checksum is used as end of frame indicator - #if 0 +// The checksum is used as end of frame indicator +#if 0 // TOCHECK: move this to actual publishing code if (now - this->last_publish_ >= this->throttle_) { this->last_publish_ = now; @@ -141,26 +143,26 @@ void VictronComponent::loop() { } else { this->publishing_ = false; } - #else +#else publish_frame_(); block_buffer_.clear(); - #endif +#endif checksum_ = 0; continue; } if (c == '\r' || c == '\n') { - #if 0 +#if 0 if (this->publishing_) { handle_value_(); } - #else +#else if (block_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { block_buffer_.append(label_.c_str()); block_buffer_.append("\t"); block_buffer_.append(value_.c_str()); block_buffer_.append("\r\n"); } - #endif +#endif state_ = 0; } else { value_.push_back(c); @@ -751,16 +753,16 @@ void VictronComponent::publish_frame_() { return; } this->last_publish_ = now; - - size_t last = 0; - size_t next = 0; + + size_t last = 0; + size_t next = 0; while ((next = block_buffer_.find("\r\n", last)) != std::string::npos) { - std::string item = block_buffer_.substr(last, next-last); + std::string item = block_buffer_.substr(last, next - last); last = next + 2; size_t dpos = item.find("\t"); label_ = item.substr(0, dpos); - value_ = item.substr(dpos+1); + value_ = item.substr(dpos + 1); ESP_LOGD(TAG, "Handle %s value %s", label_.c_str(), value_.c_str()); handle_value_(); } From bef7a05562fc9c00b70eb7e9d1091a87fd64cb34 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 20 Aug 2025 14:43:44 +0200 Subject: [PATCH 06/14] Add sanity checks when splitting block buffer --- components/victron/victron.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index b71b3e1..c90fc8c 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -759,8 +759,13 @@ void VictronComponent::publish_frame_() { while ((next = block_buffer_.find("\r\n", last)) != std::string::npos) { std::string item = block_buffer_.substr(last, next - last); last = next + 2; - + if (item.size() == 0) { + continue; + } size_t dpos = item.find("\t"); + if (dpos == std::string::npos) { + continue; + } label_ = item.substr(0, dpos); value_ = item.substr(dpos + 1); ESP_LOGD(TAG, "Handle %s value %s", label_.c_str(), value_.c_str()); From b1a64d6def9e502ea4138bc13eca63438a251b98 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 08:53:07 +0200 Subject: [PATCH 07/14] Cleanup code, add more length checks --- components/victron/victron.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index c90fc8c..c1f292f 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -127,45 +127,37 @@ void VictronComponent::loop() { if (c == '\t') { state_ = 2; } else { - label_.push_back(c); + // transmission errors may impact delimiters, leading to excess label length + if (label_.length() <= MAX_LABEL_LENGTH) { + label_.push_back(c); + } } continue; } if (state_ == 2) { if (label_ == "Checksum") { state_ = 0; -// The checksum is used as end of frame indicator -#if 0 - // TOCHECK: move this to actual publishing code - if (now - this->last_publish_ >= this->throttle_) { - this->last_publish_ = now; - this->publishing_ = true; - } else { - this->publishing_ = false; - } -#else + // The checksum is used as end of frame indicator, checksum_ should now be 0 publish_frame_(); block_buffer_.clear(); -#endif checksum_ = 0; continue; } if (c == '\r' || c == '\n') { -#if 0 - if (this->publishing_) { - handle_value_(); - } -#else + // a block/frame has up to 22 entries + // transmission errors could garble the end of frame indicator, leading to excess buffer length if (block_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { block_buffer_.append(label_.c_str()); block_buffer_.append("\t"); block_buffer_.append(value_.c_str()); block_buffer_.append("\r\n"); } -#endif state_ = 0; } else { - value_.push_back(c); + // transmission errors may impact delimiters, leading to excess value length + if (value_.length() <= MAX_VALUE_LENGTH) { + value_.push_back(c); + } } } // Discard ve.direct hex frame From 9948b8e1cbce31293572e42f2d2ba4cb644ac78d Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 08:53:41 +0200 Subject: [PATCH 08/14] Make checksum validation the default --- components/victron/__init__.py | 2 +- components/victron/victron.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/victron/__init__.py b/components/victron/__init__.py index b8043e6..3c74edf 100644 --- a/components/victron/__init__.py +++ b/components/victron/__init__.py @@ -28,7 +28,7 @@ { cv.GenerateID(): cv.declare_id(VictronComponent), cv.Optional(CONF_THROTTLE, default="1s"): cv.positive_time_period_milliseconds, - cv.Optional(CONF_VALIDATE_CHECKSUM, default="false"): cv.boolean, + cv.Optional(CONF_VALIDATE_CHECKSUM, default="true"): cv.boolean, } ) diff --git a/components/victron/victron.h b/components/victron/victron.h index 077bebf..181a552 100644 --- a/components/victron/victron.h +++ b/components/victron/victron.h @@ -298,7 +298,7 @@ class VictronComponent : public uart::UARTDevice, public Component { uint32_t last_transmission_{0}; uint32_t last_publish_{0}; uint32_t throttle_{0}; - bool validate_checksum_{false}; + bool validate_checksum_{true}; }; } // namespace victron From 67824f30d63d3e7318e17d1627f4ede88744c8fe Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 11:19:41 +0200 Subject: [PATCH 09/14] Add note on checksum validation parameter --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8f09bc9..b7b59ed 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,8 @@ The `uart_id` and `victron_id` is optional if you use a single UART / victron de The victron device pushs one status message per second. To reduce the update interval of the ESPHome entities please use the `throttle` parameter to discard some messages. +Transmission integrity is validated through a checksum. Checksum validation can be switched off with the `validate_checksum` parameter set to `false`. + ## Entities ### Binary sensors From f9d2bf046999343841ec082b1af051c35af1092d Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 21 Aug 2025 12:55:01 +0200 Subject: [PATCH 10/14] Update components/victron/victron.cpp Co-authored-by: Sebastian Muszynski --- components/victron/victron.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index c1f292f..14416fc 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -733,7 +733,7 @@ static std::string off_reason_text(uint32_t mask) { void VictronComponent::publish_frame_() { if (checksum_ != 0) { if (validate_checksum_) { - ESP_LOGW(TAG, "Dropping frame due to checksum error."); + ESP_LOGW(TAG, "Dropping frame due to checksum error"); return; } else { ESP_LOGW(TAG, "Processing frame with checksum error. Consider enabling option 'validate_checksum'"); From 6d408025e8f82f9aa630128d5a589aa1a88e5eb5 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 13:09:51 +0200 Subject: [PATCH 11/14] Choose proper name for frame buffer --- components/victron/victron.cpp | 22 +++++++++++----------- components/victron/victron.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index 14416fc..cabe7a2 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -139,18 +139,18 @@ void VictronComponent::loop() { state_ = 0; // The checksum is used as end of frame indicator, checksum_ should now be 0 publish_frame_(); - block_buffer_.clear(); + frame_buffer_.clear(); checksum_ = 0; continue; } if (c == '\r' || c == '\n') { // a block/frame has up to 22 entries // transmission errors could garble the end of frame indicator, leading to excess buffer length - if (block_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { - block_buffer_.append(label_.c_str()); - block_buffer_.append("\t"); - block_buffer_.append(value_.c_str()); - block_buffer_.append("\r\n"); + if (frame_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { + frame_buffer_.append(label_.c_str()); + frame_buffer_.append("\t"); + frame_buffer_.append(value_.c_str()); + frame_buffer_.append("\r\n"); } state_ = 0; } else { @@ -745,11 +745,11 @@ void VictronComponent::publish_frame_() { return; } this->last_publish_ = now; - - size_t last = 0; - size_t next = 0; - while ((next = block_buffer_.find("\r\n", last)) != std::string::npos) { - std::string item = block_buffer_.substr(last, next - last); + + size_t last = 0; + size_t next = 0; + while ((next = frame_buffer_.find("\r\n", last)) != std::string::npos) { + std::string item = frame_buffer_.substr(last, next-last); last = next + 2; if (item.size() == 0) { continue; diff --git a/components/victron/victron.h b/components/victron/victron.h index 181a552..0002587 100644 --- a/components/victron/victron.h +++ b/components/victron/victron.h @@ -294,7 +294,7 @@ class VictronComponent : public uart::UARTDevice, public Component { u_int16_t checksum_{0}; std::string label_; std::string value_; - std::string block_buffer_; + std::string frame_buffer_; uint32_t last_transmission_{0}; uint32_t last_publish_{0}; uint32_t throttle_{0}; From 4132c43d36446a579c4962c6ec0939a62ce4322e Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 14:28:23 +0200 Subject: [PATCH 12/14] Reset checksum after receiving a hex frame --- components/victron/victron.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index cabe7a2..ba73447 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -163,7 +163,9 @@ void VictronComponent::loop() { // Discard ve.direct hex frame if (state_ == 3) { if (c == '\r' || c == '\n') { + // a hex frame ends with '\n' and has its own checksum; prepare to receive another text frame state_ = 0; + checksum_ = 0; } } } From db768eb0c4f44678f6658fc9f6ed3d243b993b5f Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 14:52:10 +0200 Subject: [PATCH 13/14] Apply linter --- components/victron/victron.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index ba73447..979604e 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -165,7 +165,7 @@ void VictronComponent::loop() { if (c == '\r' || c == '\n') { // a hex frame ends with '\n' and has its own checksum; prepare to receive another text frame state_ = 0; - checksum_ = 0; + checksum_ = 0; } } } @@ -747,11 +747,11 @@ void VictronComponent::publish_frame_() { return; } this->last_publish_ = now; - - size_t last = 0; - size_t next = 0; + + size_t last = 0; + size_t next = 0; while ((next = frame_buffer_.find("\r\n", last)) != std::string::npos) { - std::string item = frame_buffer_.substr(last, next-last); + std::string item = frame_buffer_.substr(last, next - last); last = next + 2; if (item.size() == 0) { continue; From 0eea1159e5605bfb0df06fa378d3baa38ecfe188 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 21 Aug 2025 15:58:35 +0200 Subject: [PATCH 14/14] Satisfy clang-tidy for ESP32 --- components/victron/victron.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/victron/victron.cpp b/components/victron/victron.cpp index 979604e..cf9dc4c 100644 --- a/components/victron/victron.cpp +++ b/components/victron/victron.cpp @@ -147,9 +147,9 @@ void VictronComponent::loop() { // a block/frame has up to 22 entries // transmission errors could garble the end of frame indicator, leading to excess buffer length if (frame_buffer_.size() + label_.size() + value_.size() + 3 < MAX_BUF_SIZE) { - frame_buffer_.append(label_.c_str()); + frame_buffer_.append(label_); frame_buffer_.append("\t"); - frame_buffer_.append(value_.c_str()); + frame_buffer_.append(value_); frame_buffer_.append("\r\n"); } state_ = 0; @@ -753,10 +753,10 @@ void VictronComponent::publish_frame_() { while ((next = frame_buffer_.find("\r\n", last)) != std::string::npos) { std::string item = frame_buffer_.substr(last, next - last); last = next + 2; - if (item.size() == 0) { + if (item.empty()) { continue; } - size_t dpos = item.find("\t"); + size_t dpos = item.find('\t'); if (dpos == std::string::npos) { continue; }