mirror of
https://github.com/esphome/esphome.git
synced 2026-08-23 06:36:23 +00:00
161 lines
6.7 KiB
YAML
161 lines
6.7 KiB
YAML
esphome:
|
|
name: uart-mock-modbus-shared
|
|
|
|
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:
|
|
responses:
|
|
# Three sensors, one frame. At 0x9001 a U_WORD (1 register) and a U_DWORD (2 registers) share the
|
|
# start address but cannot merge, so the range widens to count 2. A third sensor at 0x9002 falls
|
|
# inside the widened range and must read its slice of the same response rather than splitting into
|
|
# a second overlapping poll. The single expect_tx pins the "one frame on the wire" contract - any
|
|
# duplicate or overlapping range would put an extra frame on the bus and fail to match.
|
|
- expect_tx: [0x01, 0x03, 0x90, 0x01, 0x00, 0x02, 0xB8, 0xCB] # Read holding 0x9001 count 2 on device 1
|
|
inject_rx: [0x01, 0x03, 0x04, 0x03, 0x97, 0x02, 0x91, 0x8B, 0x57] # 0x9001=0x0397, 0x9002=0x0291
|
|
# A force_new_range sensor at a HIGH address (0x30) sorts before the plain sensor at a LOW address
|
|
# (0x10). The two must poll as separate ranges: the covered branch's lower-bound check prevents the
|
|
# 0x10 sensor from being absorbed into the forced 0x30 range with a wrapped byte offset.
|
|
- expect_tx: [0x01, 0x03, 0x00, 0x30, 0x00, 0x01, 0x84, 0x05] # Read holding 0x30 count 1 (forced range)
|
|
inject_rx: [0x01, 0x03, 0x02, 0x01, 0x11, 0x79, 0xD8] # 0x30 = 0x0111 = 273
|
|
- expect_tx: [0x01, 0x03, 0x00, 0x10, 0x00, 0x01, 0x85, 0xCF] # Read holding 0x10 count 1 (own range)
|
|
inject_rx: [0x01, 0x03, 0x02, 0x02, 0x22, 0x39, 0x3D] # 0x10 = 0x0222 = 546
|
|
# A wide sensor (U_QWORD at 0x100, 4 registers) followed by plain sensors at 0x101 and 0x103.
|
|
# None of them merge, so all three poll separately - exactly as before the range refactor. The
|
|
# 0x103 sensor sits at the wide range's tail address, so it must not anchor a re-use join on a
|
|
# mid-range predecessor and inherit its byte offset.
|
|
- expect_tx: [0x01, 0x03, 0x01, 0x00, 0x00, 0x04, 0x45, 0xF5] # Read holding 0x100 count 4
|
|
inject_rx: [0x01, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x94, 0x3C] # = 100
|
|
- expect_tx: [0x01, 0x03, 0x01, 0x01, 0x00, 0x01, 0xD4, 0x36] # Read holding 0x101 count 1
|
|
inject_rx: [0x01, 0x03, 0x02, 0x01, 0x41, 0x79, 0xE4] # 0x101 = 0x0141 = 321
|
|
- expect_tx: [0x01, 0x03, 0x01, 0x03, 0x00, 0x01, 0x75, 0xF6] # Read holding 0x103 count 1
|
|
inject_rx: [0x01, 0x03, 0x02, 0x01, 0xA5, 0x79, 0xAF] # 0x103 = 0x01A5 = 421
|
|
# A widened shared-address range at 0x200 plus a sensor at 0x201 carrying its own skip_updates.
|
|
# The sensor must keep its own range so the polling rates stay independent; if it were folded into
|
|
# the widened range it would decode 0x201 from THAT response (2, not 777) and drag the range's
|
|
# rate down to its own.
|
|
- expect_tx: [0x01, 0x03, 0x02, 0x00, 0x00, 0x02, 0xC5, 0xB3] # Read holding 0x200 count 2
|
|
inject_rx: [0x01, 0x03, 0x04, 0x01, 0x41, 0x00, 0x02, 0x2A, 0x1A] # 0x200=0x0141, 0x201=0x0002
|
|
- expect_tx: [0x01, 0x03, 0x02, 0x01, 0x00, 0x01, 0xD4, 0x72] # Read holding 0x201 count 1
|
|
inject_rx: [0x01, 0x03, 0x02, 0x03, 0x09, 0x78, 0xB2] # 0x201 = 0x0309 = 777
|
|
|
|
modbus:
|
|
uart_id: virtual_uart_dev
|
|
send_wait_time: 200ms
|
|
turnaround_time: 10ms
|
|
|
|
modbus_controller:
|
|
- address: 1
|
|
id: modbus_controller_ok
|
|
max_cmd_retries: 2
|
|
update_interval: never
|
|
|
|
sensor:
|
|
# Word sensor at 0x9001 (1 register)
|
|
- platform: modbus_controller
|
|
name: "shared_word"
|
|
address: 0x9001
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Dword sensor at the SAME address 0x9001 (2 registers) - non-mergeable, shares the range start
|
|
- platform: modbus_controller
|
|
name: "shared_dword"
|
|
address: 0x9001
|
|
register_type: holding
|
|
value_type: U_DWORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Word sensor at 0x9002 - inside the widened range, reads bytes 2-3 of the same response
|
|
- platform: modbus_controller
|
|
name: "covered_word"
|
|
address: 0x9002
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Forced sensor at a high address: sorts first, opens its own isolated range
|
|
- platform: modbus_controller
|
|
name: "forced_high"
|
|
address: 0x30
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
force_new_range: true
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Plain sensor at a lower address: must get its own range, never absorbed into the forced one
|
|
- platform: modbus_controller
|
|
name: "plain_low"
|
|
address: 0x10
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Wide sensor spanning 0x100-0x103; the two sensors below sit inside its span but do not merge
|
|
- platform: modbus_controller
|
|
name: "wide_qword"
|
|
address: 0x100
|
|
register_type: holding
|
|
value_type: U_QWORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
- platform: modbus_controller
|
|
name: "inside_wide"
|
|
address: 0x101
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# At the wide range's tail address: must decode its own poll, not inherit a mid-range byte offset
|
|
- platform: modbus_controller
|
|
name: "tail_of_wide"
|
|
address: 0x103
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Shared address 0x200: the dword widens the range the word opened (or vice versa)
|
|
- platform: modbus_controller
|
|
name: "rate_word"
|
|
address: 0x200
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
- platform: modbus_controller
|
|
name: "rate_dword"
|
|
address: 0x200
|
|
register_type: holding
|
|
value_type: U_DWORD
|
|
modbus_controller_id: modbus_controller_ok
|
|
# Inside the widened range but with its own skip_updates: must NOT be folded in, or the two sensors
|
|
# above would silently drop to this sensor's polling rate
|
|
- platform: modbus_controller
|
|
name: "own_rate"
|
|
address: 0x201
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
skip_updates: 100
|
|
modbus_controller_id: modbus_controller_ok
|
|
|
|
button:
|
|
- platform: template
|
|
name: "Start Scenario"
|
|
id: start_scenario_btn
|
|
on_press:
|
|
- lambda: |-
|
|
id(virtual_uart_dev).start_scenario();
|
|
id(modbus_controller_ok).set_update_interval(1000);
|
|
id(modbus_controller_ok).start_poller();
|