Hi everybody,
I have a smart reader with a P1 port and I connected it to an ESP32-S3-WROOM-1 platform running ESPHome and the DSMR Component. Super cool! But there is a problem… the OBIS codes used in my country (Israel) are not the Dutch standard codes, and I couldn’t get the readings I wanted. So, I created (together with Gemini…) a simple YAML that parses out custom OBIS codes from the raw DSMR output and pushes them out as sensors. No need to use any extra libraries other than the standard DSMR Reader. I hope it will be useful to other people who want to read extra fields out of their DSMR-style P1 sensors.
Enjoy!
esphome:
name: smartmeter
friendly_name: Smart Meter
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
light:
- platform: esp32_rmt_led_strip
id: my_light
rgb_order: GRB
pin: GPIO48
num_leds: 1
chipset: ws2812
name: "RGB LED"
# Enable logging
logger:
level: INFO
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: "xxx"
ota:
- platform: esphome
password: "xxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Fallback Hotspot"
password: "xxx"
captive_portal:
# Serial connection to the meter
uart:
baud_rate: 115200
data_bits: 8
rx_buffer_size: 1500
rx_pin:
number: GPIO14
inverted: true
parity: NONE
stop_bits: 1
# Regex parsing from UART
text_sensor:
- platform: dsmr
telegram:
id: "telegram"
internal: true
name: "Raw DSMR Telegram"
on_value:
then:
- lambda: |-
std::string telegram_content = x;
auto get_value = [&](const std::string& pattern_start, const std::string& pattern_end) -> optional<float> {
size_t start_pos = telegram_content.find(pattern_start);
if (start_pos == std::string::npos) {
return {};
}
start_pos += pattern_start.length();
size_t end_pos = telegram_content.find(pattern_end, start_pos);
if (end_pos == std::string::npos) {
return {};
}
std::string value_str = telegram_content.substr(start_pos, end_pos - start_pos);
return parse_number<float>(value_str);
};
// Active Energy Consumption
if (auto val = get_value("1-0:1.8.11(", "*kWh)")) {
id(energy_consumption_t1).publish_state(*val);
}
if (auto val = get_value("1-0:1.8.13(", "*kWh)")) {
id(energy_consumption_t2).publish_state(*val);
}
// Active Energy Production
if (auto val = get_value("1-0:2.8.13(", "*kWh)")) {
id(total_energy_production).publish_state(*val);
}
// Active Power
if (auto val = get_value("1-0:1.7.0(", "*kW)")) {
id(active_power_consumption).publish_state(*val);
}
if (auto val = get_value("1-0:2.7.0(", "*kW)")) {
id(active_power_production).publish_state(*val);
}
// Active Power Consumption per Phase
if (auto val = get_value("1-0:21.7.0(", "*kW)")) {
id(active_power_consumption_phase1).publish_state(*val);
}
if (auto val = get_value("1-0:41.7.0(", "*kW)")) {
id(active_power_consumption_phase2).publish_state(*val);
}
if (auto val = get_value("1-0:61.7.0(", "*kW)")) {
id(active_power_consumption_phase3).publish_state(*val);
}
// Active Power Production per Phase
if (auto val = get_value("1-0:22.7.0(", "*kW)")) {
id(active_power_production_phase1).publish_state(*val);
}
if (auto val = get_value("1-0:42.7.0(", "*kW)")) {
id(active_power_production_phase2).publish_state(*val);
}
if (auto val = get_value("1-0:62.7.0(", "*kW)")) {
id(active_power_production_phase3).publish_state(*val);
}
// Voltage and Current per Phase
if (auto val = get_value("1-0:32.7.0(", "*V)")) {
id(voltage_phase1).publish_state(*val);
}
if (auto val = get_value("1-0:52.7.0(", "*V)")) {
id(voltage_phase2).publish_state(*val);
}
if (auto val = get_value("1-0:72.7.0(", "*V)")) {
id(voltage_phase3).publish_state(*val);
}
if (auto val = get_value("1-0:31.7.0(", "*A)")) {
id(current_phase1).publish_state(*val);
}
if (auto val = get_value("1-0:51.7.0(", "*A)")) {
id(current_phase2).publish_state(*val);
}
if (auto val = get_value("1-0:71.7.0(", "*A)")) {
id(current_phase3).publish_state(*val);
}
# Individual template sensors that are published by the parser
sensor:
- platform: template
id: energy_consumption_t1
name: "Energy Consumption (Tariff 1)"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
- platform: template
id: energy_consumption_t2
name: "Energy Consumption (Tariff 2)"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
- platform: template
id: total_energy_consumption
unit_of_measurement: "kWh"
name: "Total Energy Consumption"
device_class: energy
state_class: total_increasing
lambda: |-
return id(energy_consumption_t1).state + id(energy_consumption_t2).state;
- platform: template
id: total_energy_production
name: "Total Energy Production"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
- platform: template
id: active_power_consumption
name: "Active Power Consumption"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_production
name: "Active Power Production"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: voltage_phase1
name: "Voltage (Phase 1)"
unit_of_measurement: "V"
device_class: voltage
state_class: measurement
- platform: template
id: voltage_phase2
name: "Voltage (Phase 2)"
unit_of_measurement: "V"
device_class: voltage
state_class: measurement
- platform: template
id: voltage_phase3
name: "Voltage (Phase 3)"
unit_of_measurement: "V"
device_class: voltage
state_class: measurement
- platform: template
id: current_phase1
name: "Current (Phase 1)"
unit_of_measurement: "A"
device_class: current
state_class: measurement
- platform: template
id: current_phase2
name: "Current (Phase 2)"
unit_of_measurement: "A"
device_class: current
state_class: measurement
- platform: template
id: current_phase3
name: "Current (Phase 3)"
unit_of_measurement: "A"
device_class: current
state_class: measurement
- platform: template
id: active_power_consumption_phase1
name: "Active Power Consumption (Phase 1)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_consumption_phase2
name: "Active Power Consumption (Phase 2)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_consumption_phase3
name: "Active Power Consumption (Phase 3)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_production_phase1
name: "Active Power Production (Phase 1)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_production_phase2
name: "Active Power Production (Phase 2)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement
- platform: template
id: active_power_production_phase3
name: "Active Power Production (Phase 3)"
unit_of_measurement: "kW"
device_class: power
state_class: measurement