esphome: name: uart-mock-modbus-custom-command 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_server baud_rate: 9600 auto_start: true debug: on_tx: - then: - uart_mock.inject_rx: id: virtual_uart_controller data: !lambda return data; - id: virtual_uart_controller baud_rate: 9600 auto_start: true debug: on_tx: - then: - uart_mock.inject_rx: id: virtual_uart_server data: !lambda return data; modbus: - uart_id: virtual_uart_server id: virtual_modbus_server role: server - uart_id: virtual_uart_controller id: virtual_modbus_controller role: client turnaround_time: 10ms modbus_controller: - address: 1 modbus_id: virtual_modbus_controller id: modbus_controller_1 update_interval: 1s modbus_server: - address: 1 modbus_id: virtual_modbus_server id: modbus_server_1 registers: - address: 0x01 value_type: U_WORD read_lambda: return 259; sensor: # Plain read to confirm the controller <-> server link is up. - platform: modbus_controller modbus_controller_id: modbus_controller_1 name: "plain_read" address: 0x01 register_type: holding value_type: U_WORD # Custom command: a raw frame {device address, function code, address hi, address lo, # count hi, count lo}; the CRC is appended by the hub. Reads holding register 0x0001, # count 1; the lambda parses the response payload (the register value, big-endian). - platform: modbus_controller modbus_controller_id: modbus_controller_1 name: "custom_read" custom_command: [0x01, 0x03, 0x00, 0x01, 0x00, 0x01] lambda: |- if (data.size() < 2) return {}; return (float) ((data[0] << 8) | data[1]); button: - platform: template name: "Start Scenario" id: start_scenario_btn # This test does not have anything to start (mock is autostart)