mirror of
https://github.com/esphome/esphome.git
synced 2026-09-13 00:07:32 +00:00
234 lines
6.5 KiB
YAML
234 lines
6.5 KiB
YAML
esphome:
|
|
name: uart-mock-modbus-loopback
|
|
|
|
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
|
|
|
|
# Shared loopback fixture (see the shared_yaml markers in the test file);
|
|
# register spaces are disjoint so each test only observes its own entities.
|
|
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;
|
|
|
|
globals:
|
|
- id: reg10
|
|
type: uint16_t
|
|
initial_value: "100"
|
|
- id: reg11
|
|
type: uint16_t
|
|
initial_value: "200"
|
|
- id: reg12
|
|
type: uint16_t
|
|
initial_value: "300"
|
|
- id: reg13
|
|
type: uint16_t
|
|
initial_value: "0xABCD"
|
|
- id: reg30
|
|
type: uint16_t
|
|
initial_value: "0"
|
|
- id: reg40
|
|
type: uint16_t
|
|
initial_value: "5"
|
|
- id: reg50
|
|
type: uint16_t
|
|
initial_value: "0"
|
|
|
|
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
|
|
registers:
|
|
- address: 0x01
|
|
value_type: U_WORD
|
|
read_lambda: return 259;
|
|
- address: 0x10
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg10);
|
|
write_lambda: id(reg10) = x; return true;
|
|
- address: 0x11
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg11);
|
|
write_lambda: id(reg11) = x; return true;
|
|
- address: 0x12
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg12);
|
|
write_lambda: id(reg12) = x; return true;
|
|
- address: 0x13
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg13);
|
|
- address: 0x30
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg30);
|
|
write_lambda: id(reg30) = x; return true;
|
|
- address: 0x40
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg40);
|
|
write_lambda: id(reg40) = x; return true;
|
|
- address: 0x50
|
|
value_type: U_WORD
|
|
read_lambda: return id(reg50);
|
|
write_lambda: id(reg50) = x; return true;
|
|
|
|
# Byte-based offset: 2 bytes -> register 0x11 (the old code folded it in as a
|
|
# register count, hitting 0x12). assumed_state keeps the switch write-only.
|
|
switch:
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "offset_switch"
|
|
register_type: holding
|
|
address: 0x10
|
|
offset: 2
|
|
assumed_state: true
|
|
# Reading switch, byte offset 6 -> register 0x13; the pre-fix resolution (0x16)
|
|
# would draw ILLEGAL_DATA_ADDRESS and never publish.
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "read_offset_switch"
|
|
register_type: holding
|
|
address: 0x10
|
|
offset: 6
|
|
bitmask: 0x1
|
|
# Coil switch whose write_lambda dispatches a holding-register write via `item`;
|
|
# returning an empty optional suppresses the default coil write.
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "cross_switch"
|
|
register_type: coil
|
|
address: 0x00
|
|
assumed_state: true
|
|
write_lambda: |-
|
|
item->write_single_register(0x30, x ? 1234 : 0);
|
|
return {};
|
|
# Active-low: the write_lambda inverts the wire value but the entity must still
|
|
# report the requested state (assumed_state keeps the register unpolled).
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "invert_switch"
|
|
register_type: holding
|
|
address: 0x40
|
|
assumed_state: true
|
|
write_lambda: |-
|
|
return !x;
|
|
|
|
# Uses the deprecated buffer parameter (legacy raw frame as words); the write
|
|
# must land and the deprecation warning must fire only once per entity.
|
|
number:
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "buf_number"
|
|
id: buf_number
|
|
address: 0x50
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
min_value: 0
|
|
max_value: 1000
|
|
step: 1
|
|
write_lambda: |-
|
|
// Legacy raw frame as words: [addr 0x01 | fc 0x06], register 0x0050, value.
|
|
payload.push_back(0x0106);
|
|
payload.push_back(0x0050);
|
|
payload.push_back((uint16_t) x);
|
|
return {};
|
|
|
|
sensor:
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "plain_read"
|
|
address: 0x01
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
# Custom PDU: read holding register 0x0001; device address and CRC are added
|
|
# by the hub. The lambda parses the big-endian register value.
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "custom_read"
|
|
custom_pdu: [0x03, 0x00, 0x01, 0x00, 0x01]
|
|
lambda: |-
|
|
if (data.size() < 2) return {};
|
|
return (float) ((data[0] << 8) | data[1]);
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "reg_10"
|
|
address: 0x10
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "reg_11"
|
|
address: 0x11
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "reg_12"
|
|
address: 0x12
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "reg_30"
|
|
address: 0x30
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
- platform: modbus_controller
|
|
modbus_controller_id: modbus_controller_1
|
|
name: "reg_40"
|
|
address: 0x40
|
|
register_type: holding
|
|
value_type: U_WORD
|
|
# Reports the server-side register so the test can observe that the deprecated buffer write landed.
|
|
- platform: template
|
|
name: "written_value"
|
|
id: written_value
|
|
update_interval: 0.5s
|
|
lambda: "return id(reg50);"
|
|
|
|
button:
|
|
- platform: template
|
|
name: "Start Scenario"
|
|
id: start_scenario_btn
|
|
# Nothing to start (mock is autostart); tests drive entities directly
|