Hi, I wanted to share my solution for reading data from a smart meter speaking D0 / OBIS. I have a Hager meter approximately 10 years old, which doesn’t speak EDL21 / SML.
I bought an infrared reader whith USB which is connected to the Raspberry Pi 4 running Home Assistant OS. The reader works perfectly as a Serial sensor:
- platform: serial
serial_port: /dev/ttyUSB0
baudrate: 9600
bytesize: 7
parity: E
stopbits: 1
name: smartmeter_data
The meter outputs its current state every second or so. The raw data accumulates to a useless state history very quickly, so I disabled recording for the sensor:
recorder:
exclude:
entities:
- sensor.smartmeter_data
The D0 format includes carriage return + line feed to deliminate the different parts of each message. Therefore I used the following template sensors which ignore intermediate lines with other data. Moreover, my meter gives out the current consumption per phase, which have to be added up.
-platform: template
sensors:
smartmeter_total:
unit_of_measurement: "kWh"
value_template: >
{% if states('sensor.smartmeter_data')|regex_search("1-0:1\.8\.0\*255") %}
{{ states('sensor.smartmeter_data')|regex_findall_index("\((\d*\.\d*)\)") | float }}
{% else %}
{{ states('sensor.smartmeter_total') | float }}
{% endif %}
smartmeter_consumption_phase1:
unit_of_measurement: "W"
value_template: >
{% if states('sensor.smartmeter_data')|regex_search("1-0:21\.7\.0\*255") %}
{{ states('sensor.smartmeter_data')|regex_findall_index("\(([+-]\d*)") | float }}
{% else %}
{{ states('sensor.smartmeter_consumption_phase1') | float }}
{% endif %}
smartmeter_consumption_phase2:
unit_of_measurement: "W"
value_template: >
{% if states('sensor.smartmeter_data')|regex_search("1-0:41\.7\.0\*255") %}
{{ states('sensor.smartmeter_data')|regex_findall_index("\(([+-]\d*)") | float }}
{% else %}
{{ states('sensor.smartmeter_consumption_phase2') | float }}
{% endif %}
smartmeter_consumption_phase3:
unit_of_measurement: "W"
value_template: >
{% if states('sensor.smartmeter_data')|regex_search("1-0:61\.7\.0\*255") %}
{{ states('sensor.smartmeter_data')|regex_findall_index("\(([+-]\d*)") | float }}
{% else %}
{{ states('sensor.smartmeter_consumption_phase3') | float }}
{% endif %}
smartmeter_consumption_total:
unit_of_measurement: "W"
value_template: >
{{ states('sensor.smartmeter_consumption_phase1') | float + states('sensor.smartmeter_consumption_phase2') | float + states('sensor.smartmeter_consumption_phase3') | float }}
The first regex in every template checks wether the current line contains the data for this sensor. The string searched for is the identifier from OBIS, for example ‘1-0:1.8.0*255’ is the total sum of the consumption.
The second regex reads the value between the parentheses in the line.