From de33cbd7e7c37670d5a3c4262af024ea222b986e Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Tue, 14 Sep 2021 22:14:49 -0300 Subject: [PATCH] Dsmr updates (#2157) * add option to use check_crc * ignore newline before ( in parsing * add gas delivered text for raw sensor * fix compile issue when not listing any sensor * make gas_mbus_id configurable * update dsmr lib for clang --- esphome/components/dsmr/__init__.py | 10 ++++++++-- esphome/components/dsmr/dsmr.cpp | 10 ++++++++-- esphome/components/dsmr/dsmr.h | 3 ++- esphome/components/dsmr/sensor.py | 5 ++++- esphome/components/dsmr/text_sensor.py | 13 ++++++++++--- platformio.ini | 2 +- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index df11a14ee8..1f1a2f980e 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -13,6 +13,8 @@ AUTO_LOAD = ["sensor", "text_sensor"] CONF_DSMR_ID = "dsmr_id" CONF_DECRYPTION_KEY = "decryption_key" +CONF_CRC_CHECK = "crc_check" +CONF_GAS_MBUS_ID = "gas_mbus_id" # Hack to prevent compile error due to ambiguity with lib namespace dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") @@ -41,19 +43,23 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(Dsmr), cv.Optional(CONF_DECRYPTION_KEY): _validate_key, + cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean, + cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, } ).extend(uart.UART_DEVICE_SCHEMA) async def to_code(config): uart_component = await cg.get_variable(config[CONF_UART_ID]) - var = cg.new_Pvariable(config[CONF_ID], uart_component) + var = cg.new_Pvariable(config[CONF_ID], uart_component, config[CONF_CRC_CHECK]) if CONF_DECRYPTION_KEY in config: cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY])) await cg.register_component(var, config) + cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID]) + # DSMR Parser - cg.add_library("glmnet/Dsmr", "0.3") + cg.add_library("glmnet/Dsmr", "0.5") # Crypto cg.add_library("rweather/Crypto", "0.2.0") diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index 39f05a28d1..7c1b406d42 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -37,6 +37,12 @@ void Dsmr::receive_telegram_() { return; } + // Some v2.2 or v3 meters will send a new value which starts with '(' + // in a new line while the value belongs to the previous ObisId. For + // proper parsing remove these new line characters + while (c == '(' && (telegram_[telegram_len_ - 1] == '\n' || telegram_[telegram_len_ - 1] == '\r')) + telegram_len_--; + telegram_[telegram_len_] = c; telegram_len_++; if (c == '!') { // footer: exclamation mark @@ -130,8 +136,8 @@ bool Dsmr::parse_telegram() { MyData data; ESP_LOGV(TAG, "Trying to parse"); ::dsmr::ParseResult res = - ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, - false); // Parse telegram according to data definition. Ignore unknown values. + ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, false, + this->crc_check_); // Parse telegram according to data definition. Ignore unknown values. if (res.err) { // Parsing error, show it auto err_str = res.fullError(telegram_, telegram_ + telegram_len_); diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index 984f2596db..dcb8f5f73d 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -48,7 +48,7 @@ using MyData = ::dsmr::ParsedData decryption_key_{}; + bool crc_check_; }; } // namespace dsmr } // namespace esphome diff --git a/esphome/components/dsmr/sensor.py b/esphome/components/dsmr/sensor.py index 9d531293e9..761009c766 100644 --- a/esphome/components/dsmr/sensor.py +++ b/esphome/components/dsmr/sensor.py @@ -244,4 +244,7 @@ async def to_code(config): cg.add(getattr(hub, f"set_{key}")(s)) sensors.append(f"F({key})") - cg.add_define("DSMR_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(sensors))) + if sensors: + cg.add_define( + "DSMR_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(sensors)) + ) diff --git a/esphome/components/dsmr/text_sensor.py b/esphome/components/dsmr/text_sensor.py index 821b07dc6b..339eea711f 100644 --- a/esphome/components/dsmr/text_sensor.py +++ b/esphome/components/dsmr/text_sensor.py @@ -71,6 +71,11 @@ CONFIG_SCHEMA = cv.Schema( cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), } ), + cv.Optional("gas_delivered_text"): text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), + } + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -89,6 +94,8 @@ async def to_code(config): cg.add(getattr(hub, f"set_{key}")(var)) text_sensors.append(f"F({key})") - cg.add_define( - "DSMR_TEXT_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(text_sensors)) - ) + if text_sensors: + cg.add_define( + "DSMR_TEXT_SENSOR_LIST(F, sep)", + cg.RawExpression(" sep ".join(text_sensors)), + ) diff --git a/platformio.ini b/platformio.ini index 3b1241f282..174832b067 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,7 @@ lib_deps = 1655@1.0.2 ; TinyGPSPlus (has name conflict) 6865@1.0.0 ; TM1651 Battery Display 6306@1.0.3 ; HM3301 - glmnet/Dsmr@0.3 ; used by dsmr + glmnet/Dsmr@0.5 ; used by dsmr rweather/Crypto@0.2.0 ; used by dsmr esphome/noise-c@0.1.1 ; used by api dudanov/MideaUART@1.1.0 ; used by midea