esphome: name: uart-mock-modbus-test 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 must be false to avoid races: the test presses the # "Start Scenario" button only after subscribing to states. auto_start: false debug: on_tx: - then: - if: condition: #Read 80 input registers on device 2, starting at address 0 (SDM meter request) lambda: "return data == std::vector({0x02,0x04,0x00,0x00,0x00,0x50,0xF0,0x05});" then: - uart_mock.inject_rx: # Good response from SDM meter with CRC. Voltage is 243V !lambda return {0x02,0x04,0xA0,0x43,0x73,0x19,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - delay: 120ms # Simulate some delay for UART buffer to fill before next part of response (1ms = 1 byte at 9600 baud) - uart_mock.inject_rx: # Rest of response (including CRC) !lambda return{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6F,0xCC,0xCD,0x43,0x7C,0xB8,0x10,0x3D,0x38,0x51,0xEC, 0x43,0x81,0x1B,0xE7,0x3B,0x03,0x12,0x6F,0x50,0x1B}; modbus: uart_id: virtual_uart_dev turnaround_time: 10ms sensor: - platform: sdm_meter address: 2 id: sdm_meter_1 # update_interval is set to never to avoid automatic polling before the test starts the scenario. # The test will manually start the poller after subscribing to states, to ensure no state changes are missed. # This also allows us to assert there are no modbus errors/warnings during the initial request/response. update_interval: never phase_a: voltage: name: sdm_voltage button: - platform: template name: "Start Scenario" id: start_scenario_btn on_press: - lambda: |- id(virtual_uart_dev).start_scenario(); id(sdm_meter_1).set_update_interval(1000); id(sdm_meter_1).start_poller();