Modbus 控制器
modbus_controller 组件创建一个 RS485 连接,用于:
- 控制 Modbus 服务器(从机)设备,让您的 ESPHome 节点充当 Modbus 客户端(主机)。您可以将设备上的线圈、输入、保持寄存器、只读寄存器作为传感器、开关、选择器、数值或各种其他 ESPHome 组件来访问,并将它们呈现给您最喜欢的家庭自动化系统。您甚至可以将它们作为二进制或浮点输出来写入。
- 让您的 ESPHome 节点充当 Modbus 服务器,允许 Modbus 客户端从您的 ESPHome 节点读取数据(如传感器值)。
要选择角色,请设置此 modbus_controller 组件所依赖的 Modbus 的 role 属性。默认值为 client。
您需要一个 RS485 收发器模块:
有关更多详细信息,请参阅 Stack Exchange 上的 How is this RS485 module working?。
收发器连接到 MCU 的 UART。对于 ESP32,引脚 16 连接到 TXD,引脚 17 连接到 RXD 是默认引脚,但也可以使用任何其他引脚。3.3V 连接到 VCC,当然 GND 连接到 GND。
在总线侧,根据 Modbus 标准,您需要在总线电缆的末端添加 120 欧姆的终端电阻。一些收发器已经在板上焊接了电阻,而一些从机设备可能通过跳线或 DIP 开关提供电阻。
NOTE
如果您使用的是 ESP8266,串行日志可能会导致从 UART 读取时出现问题。为了获得最佳结果,建议使用硬件串口。如果其他组件在 loop() 中花费大量时间,软件串口可能无法读取所有接收到的数据。
对于硬件串口,只能使用有限的引脚集。要么使用 tx_pin: GPIO1 和 rx_pin: GPIO3,要么使用 tx_pin: GPIO15 和 rx_pin: GPIO13。
使用硬件 UART 的缺点是您不能使用串行日志,因为串行日志会发送到 Modbus 设备,从而导致错误。
可以通过设置 baud_rate: 0 来禁用串行日志。
有关更多详细信息,请参阅 日志记录器
logger: level: <level> baud_rate: 0-
modbus_id (可选, ID): 手动指定
modbus集线器的 ID。 -
address (必需, ID): 从机设备的 Modbus 地址。
-
allow_duplicate_commands (可选, 布尔值): 是否允许队列中有重复命令。默认为
false。 -
command_throttle (可选, 时间): 向设备发送请求之间的最小时间间隔。默认为
0ms。 一些 Modbus 从机设备限制了主机的请求速率,因此这允许更改请求之间的间隔。 -
update_interval (可选, 时间): 检查传感器的时间间隔。 默认为 60 秒。
-
offline_skip_updates (可选, 整数): 当从机没有响应命令时,它会被 标记为离线,您可以指定在它离线时要跳过的更新次数。如果使用有多个从机的总线,这可以避免等待超时,从而允许在同一条总线上读取其他从机。当从机 响应命令时,它会再次被标记为在线。
-
max_cmd_retries (可选, 整数): 如果没有收到响应,命令将重试多少次。不包括初始传输。默认为 4。
-
server_courtesy_response (可选): 配置块,用于在设备充当 Modbus 服务器时启用礼貌响应功能。
- enabled (可选, 布尔值): 是否启用礼貌响应功能。
默认为
false。 - register_last_address (可选, 整数): 最高 Modbus 寄存器地址(包含),在此范围内允许读取未定义的寄存器并将使用默认值填充。
任何包含此范围内未定义寄存器的读取请求都将返回
register_value指定的值,而不是触发异常。 默认为65535 - register_value (可选, 整数): 为
register_last_address定义的地址范围内的未定义寄存器返回的 16 位值(范围:0–65535)。 默认为0。
- enabled (可选, 布尔值): 是否启用礼貌响应功能。
默认为
-
server_registers (可选): 充当服务器时响应的寄存器列表。
-
address (必需, 整数): 范围内第一个寄存器的起始地址
-
value_type (可选): mod_bus 寄存器数据的数据类型。ModBUS 的默认数据类型是 大端序 格式的 16 位整数(网络字节顺序,MSB 在前)
U_WORD: 无符号 16 位整数,1 个寄存器,uint16_tS_WORD: 有符号 16 位整数,1 个寄存器,int16_tU_DWORD: 无符号 32 位整数,2 个寄存器,uint32_tS_DWORD: 有符号 32 位整数,2 个寄存器,int32_tU_DWORD_R: 小端序 无符号 32 位整数,2 个寄存器,uint32_tS_DWORD_R: 小端序 有符号 32 位整数,2 个寄存器,int32_tU_QWORD: 无符号 64 位整数,4 个寄存器,uint64_tS_QWORD: 有符号 64 位整数,4 个寄存器int64_tU_QWORD_R: 小端序 无符号 64 位整数,4 个寄存器,uint64_tS_QWORD_R: 小端序 有符号 64 位整数,4 个寄存器int64_tFP32: 32 位 IEEE 754 浮点数,2 个寄存器,floatFP32_R: 小端序 32 位 IEEE 754 浮点数,2 个寄存器,float
默认为
U_WORD。 -
read_lambda (必需, lambda): 返回此寄存器值的 Lambda。
-
write_lambda (可选, lambda): 设置此寄存器值的 Lambda。提供了一个适当类型的变量
x(uint16_t、int32_t等,见上文),其值为要写入的值, 以及包含此寄存器地址的address。如果操作成功,您必须返回true,否则返回false,在这种情况下 将向客户端发送 ModBUS 异常代码4。
-
自动化:
- on_command_sent (可选, 自动化): 当 modbus 命令发送后执行的自动化。请参阅
on_command_sent - on_online (可选, 自动化): 当 modbus 控制器上线时执行的自动化。请参阅
on_online - on_offline (可选, 自动化): 当 modbus 控制器离线时执行的自动化。请参阅
on_offline
以下代码创建一个 modbus_controller 集线器,与地址为 1、波特率为 115200 的 ModBUS 设备通信
ModBUS 传感器可以直接定义(内联)在 modbus_controller 集线器下,也可以作为独立组件
从技术上讲,“内联”和标准定义方法之间没有区别。
# 示例配置条目uart: ...
modbus: flow_control_pin: GPIOXX id: modbus1
modbus_controller:- id: modbus_device address: 0x1 ## 总线上 Modbus 从机设备的地址 modbus_id: modbus1 setup_priority: -10
sensor:- platform: modbus_controller modbus_controller_id: modbus_device name: "Battery Capacity" register_type: holding address: 0x9001 ## Modbus 从机设备内部的寄存器地址 unit_of_measurement: "AH" value_type: U_WORD
switch:- platform: modbus_controller modbus_controller_id: modbus_device name: "Reset to Factory Default" register_type: coil address: 0x15 bitmask: 1
text_sensor:- name: "rtc_clock" platform: modbus_controller modbus_controller_id: modbus_device id: rtc_clock internal: true register_type: holding address: 0x9013 register_count: 3 raw_encode: HEXBYTES response_size: 6上面的配置示例创建了一个 modbus_controller 集线器,与地址为 1、波特率为 115200 的 Modbus 设备通信,实现了一个传感器、一个开关和一个文本传感器。
以下代码允许 ModBUS 客户端从您的 ESPHome 节点读取传感器值,该值是节点本身从 ModBUS 服务器读取的。
uart: - id: uart_modbus_client tx_pin: 32 rx_pin: 34 - id: uart_modbus_server tx_pin: 25 rx_pin: 35
modbus: - uart_id: uart_modbus_client id: modbus_client - uart_id: uart_modbus_server id: modbus_server role: server
modbus_controller: - id: modbus_evse modbus_id: modbus_client address: 0x2 update_interval: 5s - modbus_id: modbus_server address: 0x4 server_registers: - address: 0x0002 value_type: S_DWORD_R read_lambda: |- return id(evse_voltage_l1).state;
sensor: - platform: modbus_controller id: evse_voltage_l1 modbus_controller_id: modbus_evse name: "EVSE voltage L1" register_type: holding address: 0x0000 device_class: voltage value_type: S_DWORD_R accuracy_decimals: 1 unit_of_measurement: V filters: - multiply: 0.1查看文档底部 .. _modbus_controller-automations: 部分中可用的各种 Modbus 组件。它们可以直接定义*(内联)*在 modbus_controller 集线器下,也可以作为独立组件。从技术上讲,内联和标准定义方法之间没有区别。
下面是关于在更高级场景中使用 Modbus 的一些一般提示。适用的组件功能有链接指向这里:
某些设备在只读寄存器中使用十进制值来显示仅占用一个寄存器地址的多个二进制状态。要解码它们,您可以根据下表使用位掩码。对应于某位的十进制值始终是行中前一个值的两倍。通过将对应于位的所有值相加,可以在单个寄存器中表示多个位。
| 报警位 | 描述 | 十进制值 | 十六进制值 |
|---|---|---|---|
| bit 0 | 二进制传感器 0 | 1 | 1 |
| bit 1 | 二进制传感器 1 | 2 | 2 |
| bit 2 | 二进制传感器 2 | 4 | 4 |
| bit 3 | 二进制传感器 3 | 8 | 8 |
| bit 4 | 二进制传感器 4 | 16 | 10 |
| bit 5 | 二进制传感器 5 | 32 | 20 |
| bit 6 | 二进制传感器 6 | 64 | 40 |
| bit 7 | 二进制传感器 7 | 128 | 80 |
| bit 8 | 二进制传感器 8 | 256 | 100 |
| bit 9 | 二进制传感器 9 | 512 | 200 |
| bit 10 | 二进制传感器 10 | 1024 | 400 |
| bit 11 | 二进制传感器 11 | 2048 | 800 |
| bit 12 | 二进制传感器 12 | 4096 | 1000 |
| bit 13 | 二进制传感器 13 | 8192 | 2000 |
| bit 14 | 二进制传感器 14 | 16384 | 4000 |
| bit 15 | 二进制传感器 15 | 32768 | 8000 |
在下面的示例中,寄存器 15 保存了几个二进制值。它存储的十进制值为 12288,即 4096 + 8192 的和,意味着对应的位 12 和 13 为 1,其他位为 0。
要在 ESPHome 中将这些位作为二进制传感器收集,请使用 bitmask:
binary_sensor:- platform: modbus_controller modbus_controller_id: modbus1 name: Alarm bit0 register_type: read address: 15 bitmask: 0x1- platform: modbus_controller modbus_controller_id: modbus1 name: Alarm bit1 register_type: read address: 15 bitmask: 0x2- platform: modbus_controller modbus_controller_id: modbus1 name: Alarm bit10 register_type: read address: 15 bitmask: 0x400- platform: modbus_controller modbus_controller_id: modbus1 name: Alarm bit15 register_type: read address: 15 bitmask: 0x8000使用 custom_command
Section titled “使用 custom_command”custom_command 可用于创建任意 modbus 命令。结合 lambda,可以处理任何响应。
此示例重新实现了从 SDM-120 读取寄存器 0x156(总有功电能)和 0x158(总无功电能)的命令。
SDM-120 以浮点数形式返回值,在 2 个寄存器中使用 32 位。
uart: id: mod_uart ...
modbus: send_wait_time: 200ms uart_id: mod_uart id: mod_bus
modbus_controller:- id: sdm address: 2 modbus_id: mod_bus command_throttle: 100ms setup_priority: -10 update_interval: 30s
sensors:- platform: modbus_controller modbus_controller_id: sdm name: "Total active energy" id: total_energy # address: 0x156 # register_type: "read" ## 使用 custom_command 重新实现 # 0x2 : modbus 设备地址 # 0x4 : modbus 功能码 # 0x1 : modbus 寄存器地址高字节 # 0x56: modbus 寄存器地址低字节 # 0x00: 请求的寄存器总数高字节 # 0x02: 请求的寄存器总数低字节 custom_command: [ 0x2, 0x4, 0x1, 0x56,0x00, 0x02] value_type: FP32 unit_of_measurement: kWh accuracy_decimals: 1
- platform: modbus_controller modbus_controller_id: sdm name: "Total reactive energy" # address: 0x158 # register_type: "read" custom_command: [0x2, 0x4, 0x1, 0x58, 0x00, 0x02] ## 命令返回一个使用 4 字节的浮点值 lambda: |- ESP_LOGD("Modbus Sensor Lambda","Got new data" ); union { float float_value; uint32_t raw; } raw_to_float; if (data.size() < 4 ) { ESP_LOGE("Modbus Sensor Lambda", "invalid data size %d",data.size()); return NAN; } raw_to_float.raw = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; ESP_LOGD("Modbus Sensor Lambda", "FP32 = 0x%08X => %f", raw_to_float.raw, raw_to_float.float_value); return raw_to_float.float_value; unit_of_measurement: kVArh accuracy_decimals: 1优化 modbus 通信
Section titled “优化 modbus 通信”register_count 是一个仅用于不常见响应编码或优化 modbus 通信的选项。
它描述此数据点跨越的寄存器数量,覆盖由 value_type 确定的默认值。如果没有提供 register_count 的值,则会根据寄存器类型计算。一个寄存器的默认大小是 16 位(一个字)。某些设备不遵守此约定,寄存器大于 16 位。在这种情况下,必须设置 register_count 和 response_size。例如,如果您的 Modbus 设备使用一个寄存器存储 FP32 值(而不是默认的两个),请设置 register_count: 1 和 response_size: 4。
register_count 也可用于跳过连续范围内的一定数量的寄存器。
一个例子是 SDM 电表,在寄存器地址 0、2、4 和 6 中有感兴趣的数据:
- platform: modbus_controller name: "Voltage Phase 1" address: 0 register_type: "read" value_type: FP32
- platform: modbus_controller name: "Voltage Phase 2" address: 2 register_type: "read" value_type: FP32
- platform: modbus_controller name: "Voltage Phase 3" address: 4 register_type: "read" value_type: FP32
- platform: modbus_controller name: "Current Phase 1" address: 6 register_type: "read" value_type: FP32 accuracy_decimals: 1上面的配置将生成一个 modbus 命令——从 0 到 6 读取多个寄存器。
也许您不关心寄存器地址 2 和 4 中的数据,它们是 Phase 2 和 Phase 3 的电压值(或者您使用的是 SDM-120)。
当然,您可以删除不关心的传感器,但这样地址中就会有间隙。如果删除地址 2 和 4 处的寄存器,将生成两个命令——读取寄存器 0 和读取寄存器 6。为了避免生成多个命令从而减少总线上的活动,可以使用 register_count 来填补间隙:
- platform: modbus_controller name: "Voltage Phase 1" address: 0 unit_of_measurement: "V" register_type: "read" value_type: FP32 register_count: 6
- platform: modbus_controller name: "Current Phase 1" address: 6 register_type: "read" value_type: FP32因为第一个传感器使用了选项 register_count: 6,将使用一个命令——从 0 到 6 读取多个寄存器,但中间的值将被忽略。
NOTE
计算: FP32 是一个 32 位值,使用 2 个寄存器。因此,要跳过 2 个 FP32 寄存器,必须将这些 2 个寄存器的大小加到第一个寄存器的默认大小上。所以地址 0 占用 2 个,地址 2 占用 2 个,地址 4 占用 2 个,因此 register_count 必须为 6。
协议解码示例
Section titled “协议解码示例”sensors:- platform: modbus_controller modbus_controller_id: epever id: array_rated_voltage name: "array_rated_voltage" address: 0x3000 unit_of_measurement: "V" register_type: read value_type: U_WORD accuracy_decimals: 1 skip_updates: 60 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: array_rated_current name: "array_rated_current" address: 0x3001 unit_of_measurement: "V" register_type: read value_type: U_WORD accuracy_decimals: 2 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: array_rated_power name: "array_rated_power" address: 0x3002 unit_of_measurement: "W" register_type: read value_type: U_DWORD_R accuracy_decimals: 1 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: battery_rated_voltage name: "battery_rated_voltage" address: 0x3004 unit_of_measurement: "V" register_type: read value_type: U_WORD accuracy_decimals: 1 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: battery_rated_current name: "battery_rated_current" address: 0x3005 unit_of_measurement: "A" register_type: read value_type: U_WORD accuracy_decimals: 1 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: battery_rated_power name: "battery_rated_power" address: 0x3006 unit_of_measurement: "W" register_type: read value_type: U_DWORD_R accuracy_decimals: 1 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: charging_mode name: "charging_mode" address: 0x3008 unit_of_measurement: "" register_type: read value_type: U_WORD accuracy_decimals: 0为了最大限度地减少所需的事务,所有具有相同基地址的寄存器都在一个请求中读取。
响应根据 register_count 和字节偏移量映射到传感器。例如:
请求:
| 数据 | 描述 |
|---|---|
| 0x1 (01) | 设备地址 |
| 0x4 (04) | 功能码 4(读输入寄存器) |
| 0x30 (48) | 起始地址高字节 |
| 0x0 (00) | 起始地址低字节 |
| 0x0 (00) | 要读取的寄存器数量高字节 |
| 0x9 (09) | 要读取的寄存器数量低字节 |
| 0x3f (63) | crc |
| 0xc (12) | crc |
响应:
| 偏移量 | 数据 | 值(类型) | 描述 |
|---|---|---|---|
| H | 0x1 (01) | 设备地址 | |
| H | 0x4 (04) | 功能码 | |
| H | 0x12 (18) | 字节数 | |
| 0 | 0x27 (39) | U_WORD | array_rated_voltage 高字节 |
| 1 | 0x10 (16) | 0x2710 (100000) | array_rated_voltage 低字节 |
| 2 | 0x7 (7) | U_WORD | array_rated_current 高字节 |
| 3 | 0xd0 (208) | 0x7d0 (2000) | array_rated_current 低字节 |
| 4 | 0xcb (203) | U_DWORD_R | array_rated_power 低位字的高字节 |
| 5 | 0x20 (32) | 跨越 2 个寄存器 | array_rated_power 低位字的低字节 |
| 6 | 0x0 (0) | array_rated_power 高位字的高字节 | |
| 7 | 0x0 (0) | 0x0000CB20 (52000) | array_rated_power 高位字的低字节 |
| 8 | 0x9 (09) | U_WORD | battery_rated_voltage 高字节 |
| 9 | 0x60 (96) | 0x960 (2400) | battery_rated_voltage 低字节 |
| 10 | 0x7 (07) | U_WORD | battery_rated_current 高字 |
| 11 | 0xd0 (208) | 0x7d0 (2000) | battery_rated_current 高字 |
| 12 | 0xcb (203) | U_DWORD_R | battery_rated_power 低位字的高字节 |
| 13 | 0x20 (32) | 跨越 2 个寄存器 | battery_rated_power 低位字的低字节 |
| 14 | 0x0 (0) | battery_rated_power 高位字的高字节 | |
| 15 | 0x0 (0) | 0x0000CB20 (52000) | battery_rated_power 高位字的低字节 |
| 16 | 0x0 (0) | U_WORD | charging_mode 高字节 |
| 17 | 0x2 (02) | 0x2 (MPPT) | charging_mode 低字节 |
| C | 0x2f (47) | crc | |
| C | 0x31 (49) | crc |
NOTE
写入支持仅针对开关和选择器实现;但是,C++ 代码提供了写入 Modbus 设备所需的 API。
这些方法可以从 lambda 中调用。
这是一个如何为 EPEVER Trace AN 控制器设置配置值的示例。 该代码将 MCU 的本地时间同步到 epever 控制器 时间是通过向寄存器 0x9013 写入 12 字节来设置的。 然后发送电池充电设置。
esphome: on_boot: ## 在设置时配置控制器设置 ## 确保优先级低于 modbus_controller 的 setup_priority priority: -100 then: - lambda: |- // 获取本地时间并同步到控制器 time_t now = ::time(nullptr); struct tm *time_info = ::localtime(&now); int seconds = time_info->tm_sec; int minutes = time_info->tm_min; int hour = time_info->tm_hour; int day = time_info->tm_mday; int month = time_info->tm_mon + 1; int year = time_info->tm_year % 100; esphome::modbus_controller::ModbusController *controller = id(epever); // 如果没有互联网连接,本地时间返回年份 70 if (year != 70) { // 创建负载 std::vector<uint16_t> rtc_data = {uint16_t((minutes << 8) | seconds), uint16_t((day << 8) | hour), uint16_t((year << 8) | month)}; // 使用时间信息作为负载创建 Modbus 命令项 esphome::modbus_controller::ModbusCommandItem set_rtc_command = esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9013, 3, rtc_data); // 将命令提交到发送队列 epever->queue_command(set_rtc_command); ESP_LOGI("ModbusLambda", "EPSOLAR RTC set to %02d:%02d:%02d %02d.%02d.%04d", hour, minutes, seconds, day, month, year + 2000); } // 电池设置 // 注意:这些值仅作为示例,适用于我的 AGM 电池 std::vector<uint16_t> battery_settings1 = { 0, // 9000 电池类型 0 = 用户 0x0073, // 9001 电池容量 0x55 == 115AH 0x012C, // 9002 温度补偿 -3V /°C/2V 0x05DC, // 9003 0x5DC == 1500 过压断开电压 15.0 0x058C, // 9004 0x58C == 1480 充电限制电压 14.8 0x058C, // 9005 过压恢复电压 14.8 0x05BF, // 9006 均衡充电电压 14.6 0x05BE, // 9007 提升充电电压 14.7 0x0550, // 9008 浮充电压 13.6 0x0528, // 9009 提升恢复充电电压 13.2 0x04C4, // 900A 低压恢复电压 12.2 0x04B0, // 900B 欠压警告恢复电压 12.0 0x04BA, // 900c 欠压警告电压 12.1 0x04BA, // 900d 低压断开电压 11.8 0x04BA // 900E 放电限制电压 11.8 };
// 提升和均衡时间 std::vector<uint16_t> battery_settings2 = { 0x0000, // 906B 均衡时间(分钟) 0 0x0075 // 906C 提升时间(即吸收)117 分钟 }; esphome::modbus_controller::ModbusCommandItem set_battery1_command = esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9000, battery_settings1.size() , battery_settings1);
esphome::modbus_controller::ModbusCommandItem set_battery2_command = esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x906B, battery_settings3.size(), battery_settings2); delay(200) ; controller->queue_command(set_battery1_command); delay(200) ; controller->queue_command(set_battery2_command); ESP_LOGI("ModbusLambda", "EPSOLAR Battery set");
uart: id: mod_bus tx_pin: GPIOXX rx_pin: GPIOXX baud_rate: 115200 stop_bits: 1
modbus: #flow_control_pin: GPIOXX send_wait_time: 200ms id: mod_bus_epever
modbus_controller: - id: epever ## Modbus 设备地址 address: 0x1 modbus_id: mod_bus_epever command_throttle: 0ms setup_priority: -10 update_interval: ${updates}
sensor: - platform: modbus_controller modbus_controller_id: epever id: array_rated_voltage name: "array_rated_voltage" address: 0x3000 unit_of_measurement: "V" register_type: read value_type: U_WORD accuracy_decimals: 1 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: array_rated_current name: "array_rated_current" address: 0x3001 unit_of_measurement: "A" register_type: read value_type: U_WORD accuracy_decimals: 2 filters: - multiply: 0.01
- platform: modbus_controller modbus_controller_id: epever id: array_rated_power name: "array_rated_power" address: 0x3002 unit_of_measurement: "W" register_type: read value_type: U_DWORD_R accuracy_decimals: 1 filters: - multiply: 0.01on_command_sent
Section titled “on_command_sent”此自动化将在 modbus_controller 发送命令后触发。在 Lambdas
中,您可以在 function_code 中获取功能码,在 address 中获取寄存器地址。
modbus_controller: - id: modbus_con # ... on_command_sent: then: - number.increment: modbus_commandson_online
Section titled “on_online”此自动化将在 modbus_controller 从 offline 变为 online 时触发。在 Lambdas
中,您可以在 function_code 中获取功能码,在 address 中获取寄存器地址。
modbus_controller: - id: modbus_con # ... on_online: then: - logger.log: "Controller back online!"on_offline
Section titled “on_offline”此自动化将在 modbus_controller 变为 offline 时触发(请参阅 offline_skip_updates)。在 Lambdas
中,您可以在 function_code 中获取功能码,在 address 中获取寄存器地址。
modbus_controller: - id: modbus_con # ... on_offline: then: - logger.log: "Controller goes offline!"