esphome: name: uart-mock-modbus-srv-rw host: api: logger: level: VERBOSE external_components: - source: type: local path: EXTERNAL_COMPONENT_PATH # Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] # The actual UART bus used is the uart_mock component below uart: baud_rate: 115200 port: /dev/null uart_mock: - id: virtual_uart_dev baud_rate: 9600 rx_full_threshold: 120 rx_timeout: 2 auto_start: false debug: injections: # FC 0x17 Read/Write Multiple Registers on device 1: # write reg 0x0001 = 0x1234 (qty 1), then read regs 0x0001..0x0002 (qty 2). # Per Modbus 6.17 the write is performed before the read, so reg 0x0001 must # read back the just-written 0x1234 in the same request. - delay: 100ms inject_rx: [0x01, 0x17, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x02, 0x12, 0x34, 0x49, 0xD8] # FC 0x17: write reg 0x0003 = 0x5678 (qty 1), then read reg 0x0003 (qty 1) - # a write and read targeting a different register block. - delay: 100ms inject_rx: [0x01, 0x17, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x02, 0x56, 0x78, 0x9B, 0x10] globals: - id: stored_1 type: uint16_t initial_value: "0" - id: stored_3 type: uint16_t initial_value: "0" modbus: uart_id: virtual_uart_dev role: server modbus_server: - address: 1 registers: # Writable + readable register backed by a global. The read publishes what it # returns so the test can confirm the write half ran before the read half. - address: 0x01 value_type: U_WORD read_lambda: |- id(rw_read_1).publish_state(id(stored_1)); return id(stored_1); write_lambda: |- id(stored_1) = x; id(rw_write_1).publish_state(x); return true; # Read-only register, read together with 0x01 by the first request's 2-register read. - address: 0x02 value_type: U_WORD read_lambda: |- id(rw_read_2).publish_state(0x00AA); return 0x00AA; # Second writable + readable register, targeted by the second request. - address: 0x03 value_type: U_WORD read_lambda: |- id(rw_read_3).publish_state(id(stored_3)); return id(stored_3); write_lambda: |- id(stored_3) = x; id(rw_write_3).publish_state(x); return true; sensor: - platform: template name: "rw_write_1" id: rw_write_1 - platform: template name: "rw_read_1" id: rw_read_1 - platform: template name: "rw_read_2" id: rw_read_2 - platform: template name: "rw_write_3" id: rw_write_3 - platform: template name: "rw_read_3" id: rw_read_3 button: - platform: template name: "Start Scenario" id: start_scenario_btn on_press: - lambda: "id(virtual_uart_dev).start_scenario();"