SML (Smart Message Language)¶
The SML
component connects to smart meters which use the Smart Message Language (SML) protocol.
Although the SML protocol is well defined, it gives a lot of freedom to the manufacturers how to store and identify the transmitted data. Within a telegram the physical values are identified by OBIS codes (Object Identification System). If it is known which code the manufacturer assigns to the physical value, the corresponding value can be extracted.
Hardware¶
This component is passive, it does not transmit any data to your equipment. Usually a smart meter transmit a telegram at regular intervals (2-4 seconds) on its own. This component decodes and updates the configured sensors at the pace the data is received.
Most smart meters transmit the telegrams using an infrared optical interface. As a sensor a suitable photo transistor (e.g. BPW40) can be attached to the ESP’s UART (emitter to GND and collector to RX pin). A more mature solution can be found here (in German). There are plenty of other examples and ready to buy solutions on the web.
Component/Hub¶
As the communciation with the sensor is done using UART, you need to have the UART bus in your configuration. The interface parameters should be set to 9600/8N1 or 9600/7E1 depending on your smart meter. If you see checksum errors in the log try changing the interface parameter.
# Example configuration entry
sml:
id: mysml
uart_id: uart_bus
on_data:
- lambda: !lambda |-
if (valid) {
id(mqttclient).publish("gridmeter/sensor/sml/state", format_hex(bytes));
} else {
id(mqttclient).publish("gridmeter/sensor/sml/error", format_hex(bytes));
}
Configuration variables:
id (Optional, ID): Manually specify the ID used for code generation.
uart_id (Optional, ID): Manually specify the ID of the UART Component if you want to use multiple UART buses.
Sensor¶
sensor:
- platform: sml
name: "Total energy"
sml_id: mysml
server_id: "0123456789abcdef"
obis_code: "1-0:1.8.0"
unit_of_measurement: kWh
accuracy_decimals: 1
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.0001
obis_code (Required, string): Specify the OBIS code you want to retrieve data for from the device. The format must be (A-B:C.D.E, e.g. 1-0:1.8.0)
server_id (Optional, string): Specify the device’s server_id to retrieve the OBIS code from. Should be specified if more then one device is connected to the same hardware sensor component.
sml_id (Optional, ID): The ID of the SML platform
All other options from Sensor.
Text Sensor¶
text_sensor:
- platform: sml
name: "Manufacturer"
sml_id: mysml
server_id: "0123456789abcdef"
obis_code: "129-129:199.130.3"
format: text
obis_code (Required, string): Specify the OBIS code you want to retrieve data for from the device. The format must be (A-B:C.D.E, e.g. 1-0:1.8.0)
server_id (Optional, string): Specify the device’s server_id to retrieve the OBIS code from. Should be specified if more then one device is connected to the same hardware sensor component.
sml_id (Optional, ID): The ID of the SML platform
format (Optional, string): Override the automatic interpretation of the transmitted binary data value. Possible values (int, uint, bool, hex, text).
All other options from Text Sensor.
Automations:¶
on_data (Optional, Automation): An automation to perform when a SML message is received. See on_data Trigger.
on_data
Trigger¶
This automation will be triggered when a valid SML message is received. The variable bytes
(of type
std::vector<uint8_t>
) contains the raw sml data including start/end sequence. The variable valid
(of type bool
) contains the result of the checksum verification.
Getting OBIS codes and sensor ids¶
The physical values in the transmitted SML telegram are identified by a server id and OBIS codes. The server id identifies your smart meter. If you have only one hardware component attached to your optical sensor you usually don’t have to care about the server id and you may ommit it in your configuration.
In order to get the server id and the available OBIS codes provided by your smart meter, simply set up the
SML platform and observe the log output (the log level
must be set to at least debug
!).
Your log output will show something like this:
Each line represents a combination of the server id (in brackets), the OBIS code and the transmitted hex value (in square brackets).
Precision errors¶
Many smart meters emit very huge numbers for certain OBIS codes (like the accumulated total active energy). This may lead to precision errors for the values reported by the sensor component to ESPHome. This shows in the fact that slightly wrong numbers may be reported to HomeAssistant. This is a result from internal limitations in ESPHome and has nothing to do with the SML component.
If you cannot live with this, you can use the TextSensor with an appropriate format to transmit the value as a string to HomeAssistant. On the HomeAssistant side you can define a Template Sensor to cast the value into the appropriate format and do some scaling.
For ESPHome we have:
# ESPHome configuration file
text_sensor:
- platform: sml
name: "Total energy text"
obis_code: "1-0:1.8.0"
format: uint
The format parameter is optional. If ommited, the SML component will try to guess the correct datatype from the received SML message.
And in HomeAssistant:
# Home Assistant configuration.yaml
template:
- sensor:
- name: "Total Energy Consumption"
unit_of_measurement: "kWh"
state: >
{% if states('sensor.total_energy_text') == 'unavailable' %}
{{ states('sensor.total_energy_consumption') }}
{% else %}
{{ ((states('sensor.total_energy_text') | float) * 0.0001) | round(2) }}
{% endif %}
Usually the template sensor’s value would turn to 0 if the ESP device is unavailable. This results in problems when using the sensor in combination with the Utility Meter integration. The state template provided above checks for the sensor’s availability and keeps the current state in case of unavailability.
Holley DTZ541 Smart Meters¶
The Holley DTZ541 series of electricity meters have a faulty implementation of the SML protocol.
These meters send multiple conflicting values with the OBIS code 1-0:1.8.0
, the code for the meter’s energy reading.
Because the first value of every package is the correct value, in order to discard the erroneous values a throttle filter of 0.5s can be applied.
sensor:
- platform: sml
name: "Total energy Consumption"
sml_id: mysml
obis_code: "1-0:1.8.0"
unit_of_measurement: kWh
accuracy_decimals: 5
device_class: energy
state_class: total_increasing
filters:
- throttle: 0.5s
- multiply: 0.0001
These meters can also measure the instantaneous power usage.
sensor:
- platform: sml
name: "Instantaneous power"
sml_id: mysml
obis_code: "1-0:16.7.0"
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement