SML (智能消息语言)
SML 组件连接到使用 智能消息语言 (SML) 协议的智能电表。
尽管 SML 协议有明确定义,但它为制造商在存储和标识传输数据方面提供了很大的自由度。在一个报文中,物理值由 OBIS 代码(对象标识系统)来识别。如果已知制造商为某物理值分配的代码,就可以提取出对应的值。
该组件是被动的,它不会向你的设备传输任何数据。通常智能电表会自行按固定间隔(2-4 秒)发送报文。 该组件以接收数据的速度进行解码并更新已配置的传感器。
大多数智能电表使用红外光学接口发送报文。可以搭配合适的光电晶体管(例如 BPW40)连接到 ESP 的 UART(发射极到 GND,集电极到 RX 引脚)。更完善的解决方案(德语)可以在 Volkszaehler Wiki 上找到。网络上还有很多其他示例和可购买的现成方案。
由于与传感器的通信是通过 UART 进行的,你需要在配置中包含 UART 总线。接口参数应根据你的智能电表设置为 9600/8N1 或 9600/7E1。如果你在日志中看到校验和错误,可以尝试更改接口参数。
# 示例配置条目sml: id: mysml uart_id: uart_bus on_data: - lambda: !lambda |- char hex[512]; // Size appropriately for your data if (valid) { id(mqttclient).publish("gridmeter/sensor/sml/state", format_hex_to(hex, bytes)); } else { id(mqttclient).publish("gridmeter/sensor/sml/error", format_hex_to(hex, bytes)); }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 (必选, string): 指定你想从设备获取数据的 OBIS 代码。格式必须为 (A-B:C.D.E,例如 1-0:1.8.0)
-
server_id (可选, string): 指定设备的 server_id 以从中提取 OBIS 代码。如果多个设备连接到同一个硬件传感器组件,则应指定此项。
-
其他所有选项来自 Sensor。
text_sensor: - platform: sml name: "Manufacturer" sml_id: mysml server_id: "0123456789abcdef" obis_code: "129-129:199.130.3" format: text-
obis_code (必选, string): 指定你想从设备获取数据的 OBIS 代码。格式必须为 (A-B:C.D.E,例如 1-0:1.8.0)
-
server_id (可选, string): 指定设备的 server_id 以从中提取 OBIS 代码。如果多个设备连接到同一个硬件传感器组件,则应指定此项。
-
format (可选, string): 覆盖对传输的二进制数据值的自动解释。可选值有 (
int、uint、bool、hex、text)。 -
其他所有选项来自 Text Sensor。
- on_data (可选, Automation): 收到 SML 消息时要执行的自动化。参见
on_data触发器。
on_data 触发器
Section titled “on_data 触发器”收到有效的 SML 消息时将触发该自动化。变量 bytes(类型为 std::vector<uint8_t>)包含包含起始/结束序列的原始 SML 数据。变量 valid(类型为 bool)包含校验和验证的结果。
获取 OBIS 代码和传感器 ID
Section titled “获取 OBIS 代码和传感器 ID”传输的 SML 报文中的物理值由 server id 和 OBIS 代码 标识。server id 标识你的智能电表。如果你的光学传感器只连接了一个硬件组件,通常不需要关心 server id,可以在配置中省略它。
为了获取 server id 以及智能电表提供的可用 OBIS 代码,只需设置好 SML 平台 并观察日志输出(日志级别 必须至少设为 debug!)。
你的日志输出会显示如下类似的内容:

SML 组件日志中的 OBIS 信息每一行代表 server id(方括号内)、OBIS 代码和传输的十六进制值(方括号内)的组合。
许多智能电表对某些 OBIS 代码(如累积的总有功电量)输出非常大的数字。这可能导致传感器组件上报给 ESPHome 的值存在精度误差。这表现为向 HomeAssistant 报告了略微错误的数值。这是 ESPHome 内部限制导致的结果,与 SML 组件本身无关。
如果你无法接受这种情况,可以使用 TextSensor 配合适当的格式,将值以字符串形式传输到 HomeAssistant。在 HomeAssistant 端可以定义一个 Template Sensor 将值转换为合适的格式并进行一定的缩放。
在 ESPHome 中配置如下:
# ESPHome 配置文件text_sensor: - platform: sml name: "Total energy text" obis_code: "1-0:1.8.0" format: uintformat 参数是可选的。如果省略,SML 组件会尝试从收到的 SML 消息中猜测正确的数据类型。
在 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 %}通常,当 ESP 设备不可用时,模板传感器的值会变为 0。这会导致在配合 Utility Meter 集成使用传感器时出现问题。上面提供的状态模板会检查传感器的可用性,并在不可用时保持当前状态。
Holley DTZ541 智能电表
Section titled “Holley DTZ541 智能电表”Holley DTZ541 系列电能表存在 SML 协议的有缺陷实现。这些电表使用 OBIS 代码 1-0:1.8.0(即电表电量读数对应的代码)发送多个相互冲突的值。由于每个包中的第一个值是正确值,为了丢弃错误值,可以应用 0.5s 的节流过滤器。
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这些电表也可以测量瞬时功率。
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