mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	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
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							103ba4c696
						
					
				
				
					commit
					de33cbd7e7
				
			| @@ -13,6 +13,8 @@ AUTO_LOAD = ["sensor", "text_sensor"] | |||||||
|  |  | ||||||
| CONF_DSMR_ID = "dsmr_id" | CONF_DSMR_ID = "dsmr_id" | ||||||
| CONF_DECRYPTION_KEY = "decryption_key" | 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 | # Hack to prevent compile error due to ambiguity with lib namespace | ||||||
| dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") | dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") | ||||||
| @@ -41,19 +43,23 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
|     { |     { | ||||||
|         cv.GenerateID(): cv.declare_id(Dsmr), |         cv.GenerateID(): cv.declare_id(Dsmr), | ||||||
|         cv.Optional(CONF_DECRYPTION_KEY): _validate_key, |         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) | ).extend(uart.UART_DEVICE_SCHEMA) | ||||||
|  |  | ||||||
|  |  | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     uart_component = await cg.get_variable(config[CONF_UART_ID]) |     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: |     if CONF_DECRYPTION_KEY in config: | ||||||
|         cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY])) |         cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY])) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|  |  | ||||||
|  |     cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID]) | ||||||
|  |  | ||||||
|     # DSMR Parser |     # DSMR Parser | ||||||
|     cg.add_library("glmnet/Dsmr", "0.3") |     cg.add_library("glmnet/Dsmr", "0.5") | ||||||
|  |  | ||||||
|     # Crypto |     # Crypto | ||||||
|     cg.add_library("rweather/Crypto", "0.2.0") |     cg.add_library("rweather/Crypto", "0.2.0") | ||||||
|   | |||||||
| @@ -37,6 +37,12 @@ void Dsmr::receive_telegram_() { | |||||||
|       return; |       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_[telegram_len_] = c; | ||||||
|     telegram_len_++; |     telegram_len_++; | ||||||
|     if (c == '!') {  // footer: exclamation mark |     if (c == '!') {  // footer: exclamation mark | ||||||
| @@ -130,8 +136,8 @@ bool Dsmr::parse_telegram() { | |||||||
|   MyData data; |   MyData data; | ||||||
|   ESP_LOGV(TAG, "Trying to parse"); |   ESP_LOGV(TAG, "Trying to parse"); | ||||||
|   ::dsmr::ParseResult<void> res = |   ::dsmr::ParseResult<void> res = | ||||||
|       ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, |       ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, false, | ||||||
|                               false);  // Parse telegram according to data definition. Ignore unknown values. |                               this->crc_check_);  // Parse telegram according to data definition. Ignore unknown values. | ||||||
|   if (res.err) { |   if (res.err) { | ||||||
|     // Parsing error, show it |     // Parsing error, show it | ||||||
|     auto err_str = res.fullError(telegram_, telegram_ + telegram_len_); |     auto err_str = res.fullError(telegram_, telegram_ + telegram_len_); | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ using MyData = ::dsmr::ParsedData<DSMR_TEXT_SENSOR_LIST(DSMR_DATA_SENSOR, DSMR_C | |||||||
|  |  | ||||||
| class Dsmr : public Component, public uart::UARTDevice { | class Dsmr : public Component, public uart::UARTDevice { | ||||||
|  public: |  public: | ||||||
|   Dsmr(uart::UARTComponent *uart) : uart::UARTDevice(uart) {} |   Dsmr(uart::UARTComponent *uart, bool crc_check) : uart::UARTDevice(uart), crc_check_(crc_check) {} | ||||||
|  |  | ||||||
|   void loop() override; |   void loop() override; | ||||||
|  |  | ||||||
| @@ -99,6 +99,7 @@ class Dsmr : public Component, public uart::UARTDevice { | |||||||
|   DSMR_TEXT_SENSOR_LIST(DSMR_DECLARE_TEXT_SENSOR, ) |   DSMR_TEXT_SENSOR_LIST(DSMR_DECLARE_TEXT_SENSOR, ) | ||||||
|  |  | ||||||
|   std::vector<uint8_t> decryption_key_{}; |   std::vector<uint8_t> decryption_key_{}; | ||||||
|  |   bool crc_check_; | ||||||
| }; | }; | ||||||
| }  // namespace dsmr | }  // namespace dsmr | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -244,4 +244,7 @@ async def to_code(config): | |||||||
|             cg.add(getattr(hub, f"set_{key}")(s)) |             cg.add(getattr(hub, f"set_{key}")(s)) | ||||||
|             sensors.append(f"F({key})") |             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)) | ||||||
|  |         ) | ||||||
|   | |||||||
| @@ -71,6 +71,11 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
|                 cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), |                 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) | ).extend(cv.COMPONENT_SCHEMA) | ||||||
|  |  | ||||||
| @@ -89,6 +94,8 @@ async def to_code(config): | |||||||
|             cg.add(getattr(hub, f"set_{key}")(var)) |             cg.add(getattr(hub, f"set_{key}")(var)) | ||||||
|             text_sensors.append(f"F({key})") |             text_sensors.append(f"F({key})") | ||||||
|  |  | ||||||
|  |     if text_sensors: | ||||||
|         cg.add_define( |         cg.add_define( | ||||||
|         "DSMR_TEXT_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(text_sensors)) |             "DSMR_TEXT_SENSOR_LIST(F, sep)", | ||||||
|  |             cg.RawExpression(" sep ".join(text_sensors)), | ||||||
|         ) |         ) | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ lib_deps = | |||||||
|     1655@1.0.2  ; TinyGPSPlus (has name conflict) |     1655@1.0.2  ; TinyGPSPlus (has name conflict) | ||||||
|     6865@1.0.0  ; TM1651 Battery Display |     6865@1.0.0  ; TM1651 Battery Display | ||||||
|     6306@1.0.3  ; HM3301 |     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 |     rweather/Crypto@0.2.0  ; used by dsmr | ||||||
|     esphome/noise-c@0.1.1  ; used by api |     esphome/noise-c@0.1.1  ; used by api | ||||||
|     dudanov/MideaUART@1.1.0  ; used by midea |     dudanov/MideaUART@1.1.0  ; used by midea | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user