mirror of
https://github.com/esphome/esphome.git
synced 2025-02-18 01:03:12 +01: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:
parent
103ba4c696
commit
de33cbd7e7
6 changed files with 33 additions and 10 deletions
|
@ -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})")
|
||||||
|
|
||||||
cg.add_define(
|
if text_sensors:
|
||||||
"DSMR_TEXT_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(text_sensors))
|
cg.add_define(
|
||||||
)
|
"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
|
||||||
|
|
Loading…
Add table
Reference in a new issue