mirror of
https://github.com/esphome/esphome.git
synced 2026-08-23 06:36:23 +00:00
126 lines
3.9 KiB
YAML
126 lines
3.9 KiB
YAML
esphome:
|
|
name: uart-mock-modbus-fairness
|
|
|
|
host:
|
|
api:
|
|
logger:
|
|
# DEBUG (not VERBOSE) keeps the log volume manageable while both controllers
|
|
# hammer the bus at a high rate.
|
|
level: DEBUG
|
|
|
|
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
|
|
|
|
# Counters for the number of requests seen on the bus for each device address.
|
|
globals:
|
|
- id: req_count_1
|
|
type: int
|
|
initial_value: "0"
|
|
- id: req_count_2
|
|
type: int
|
|
initial_value: "0"
|
|
|
|
uart_mock:
|
|
- id: virtual_uart
|
|
baud_rate: 9600
|
|
# auto_start so the mock is ready to deliver injected responses. Polling
|
|
# itself is gated by the Start button below.
|
|
auto_start: true
|
|
debug:
|
|
on_tx:
|
|
- then:
|
|
# Count each outgoing request by device address (byte 0 of the frame).
|
|
- lambda: |-
|
|
if (data.empty())
|
|
return;
|
|
if (data[0] == 0x01) {
|
|
id(req_count_1) += 1;
|
|
id(requests_1).publish_state(id(req_count_1));
|
|
} else if (data[0] == 0x02) {
|
|
id(req_count_2) += 1;
|
|
id(requests_2).publish_state(id(req_count_2));
|
|
}
|
|
# Reply directly with a canned, CRC-correct "read holding register"
|
|
# response for whichever device was addressed (both controllers only
|
|
# ever issue this one fixed request, so the responses are constant).
|
|
- uart_mock.inject_rx:
|
|
id: virtual_uart
|
|
data: !lambda |-
|
|
if (!data.empty() && data[0] == 0x01)
|
|
return {0x01, 0x03, 0x02, 0x00, 0x6F, 0xF8, 0x68}; // value 111
|
|
if (!data.empty() && data[0] == 0x02)
|
|
return {0x02, 0x03, 0x02, 0x00, 0xDE, 0x7C, 0x1C}; // value 222
|
|
return {};
|
|
|
|
modbus:
|
|
- uart_id: virtual_uart
|
|
id: virtual_modbus_client
|
|
role: client
|
|
turnaround_time: 15ms #This is longer than the polling interval to cause contention
|
|
|
|
# Two controllers sharing one client bus, each polling a different device.
|
|
# Polling is started by the test (update_interval: never until then) so counting
|
|
# only begins once the API client has subscribed.
|
|
modbus_controller:
|
|
- address: 1
|
|
modbus_id: virtual_modbus_client
|
|
id: modbus_controller_1
|
|
update_interval: never
|
|
- address: 2
|
|
modbus_id: virtual_modbus_client
|
|
id: modbus_controller_2
|
|
update_interval: never
|
|
|
|
sensor:
|
|
# These sensors define the register range each controller polls (and so drive
|
|
# the requests). Their values are not checked by the test.
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: reg_1
|
|
address: 0x01
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_2
|
|
name: reg_2
|
|
address: 0x01
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
# Request counters exposed to the test. Updated manually from the on_tx hook.
|
|
- platform: template
|
|
name: requests_1
|
|
id: requests_1
|
|
update_interval: never
|
|
- platform: template
|
|
name: requests_2
|
|
id: requests_2
|
|
update_interval: never
|
|
|
|
button:
|
|
- platform: template
|
|
name: "Start Scenario"
|
|
id: start_scenario_btn
|
|
on_press:
|
|
- lambda: |-
|
|
// Poll much faster than the bus can service so both controllers always
|
|
// have a request pending and must contend for the bus.
|
|
id(modbus_controller_1).set_update_interval(10);
|
|
id(modbus_controller_1).start_poller();
|
|
id(modbus_controller_2).set_update_interval(10);
|
|
id(modbus_controller_2).start_poller();
|
|
- platform: template
|
|
name: "Stop Scenario"
|
|
id: stop_scenario_btn
|
|
on_press:
|
|
- lambda: |-
|
|
id(modbus_controller_1).stop_poller();
|
|
id(modbus_controller_2).stop_poller();
|