跳转到内容

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]; // 根据您的数据适当调整大小
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));
}
  • id (可选, ID): 手动指定用于代码生成的 ID。
  • uart_id (可选, ID): 如果要使用多个 UART 总线,请手动指定 UART 组件 的 ID。
sensor:
- platform: sml
name: "总能量"
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 (必填, 字符串): 指定要从设备检索数据的 OBIS 代码。 格式必须为 (A-B:C.D.E,例如 1-0:1.8.0)

  • server_id (可选, 字符串): 指定设备的 server_id 以从中检索 OBIS 代码。如果同一硬件传感器组件连接了多个设备,则应指定此项。

  • sml_id (可选, ID): SML 平台 的 ID

  • 所有其他选项来自 传感器

text_sensor:
- platform: sml
name: "制造商"
sml_id: mysml
server_id: "0123456789abcdef"
obis_code: "129-129:199.130.3"
format: text
  • obis_code (必填, 字符串): 指定要从设备检索数据的 OBIS 代码。 格式必须为 (A-B:C.D.E,例如 1-0:1.8.0)

  • server_id (可选, 字符串): 指定设备的 server_id 以从中检索 OBIS 代码。如果同一硬件传感器组件连接了多个设备,则应指定此项。

  • sml_id (可选, ID): SML 平台 的 ID

  • format (可选, 字符串): 覆盖传输二进制数据值的自动解释。可能的值有 (intuintboolhextext)。

  • 所有其他选项来自 文本传感器

当接收到有效的 SML 消息时,将触发此自动化。变量 bytes(类型为 std::vector<uint8_t>)包含原始 sml 数据,包括起始/结束序列。变量 valid(类型为 bool)包含校验和验证的结果。

传输的 SML 电报中的物理值由 server idOBIS 代码 标识。server id 标识您的智能电表。如果您只有一个硬件组件连接到光学传感器,通常不需要关心 server id,可以在配置中省略它。

为了获取智能电表提供的 server id 和可用的 OBIS 代码,只需设置 SML 平台 并观察日志输出(日志级别必须至少设置为 debug!)。

您的日志输出将显示如下内容:

SML 组件日志中的 OBIS 信息

每行代表 server id(在括号中)、OBIS 代码和传输的十六进制值(在方括号中)的组合。

许多智能电表对某些 OBIS 代码发出非常大的数字(如累计总有功电能)。这可能导致传感器组件向 ESPHome 报告的值出现精度误差。这表现为向 HomeAssistant 报告的数字可能略有错误。这是 ESPHome 内部限制的结果,与 SML 组件无关。

如果您无法接受这种情况,可以使用带有适当格式的 TextSensor 将值作为字符串传输到 HomeAssistant。在 HomeAssistant 端,您可以定义一个 模板传感器 将值转换为适当的格式并进行一些缩放。

对于 ESPHome,我们有:

# ESPHome 配置文件
text_sensor:
- platform: sml
name: "总能量文本"
obis_code: "1-0:1.8.0"
format: uint

format 参数是可选的。如果省略,SML 组件将尝试从接收到的 SML 消息中猜测正确的数据类型。

在 HomeAssistant 中:

# Home Assistant configuration.yaml
template:
- sensor:
- name: "总能耗"
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。 这会导致在将传感器与 公用事业仪表 集成结合使用时出现问题。 上面提供的状态模板会检查传感器的可用性,并在不可用时保持当前状态。

Holley DTZ541 系列电能表的 SML 协议实现存在问题。 这些电表发送多个与 OBIS 代码 1-0:1.8.0 冲突的值,该代码是电表能量读数的代码。 由于每个数据包的第一个值是正确的值,为了丢弃错误的值,可以应用 0.5s 的节流过滤器。

sensor:
- platform: sml
name: "总能耗"
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: "瞬时功率"
sml_id: mysml
obis_code: "1-0:16.7.0"
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement