[modbus_server] Add coil/discrete-input support (#17464)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bonne Eggleston
2026-08-10 18:13:12 -05:00
committed by GitHub
co-authored by Claude Fable 5
parent c8d2c3691a
commit 2a0f2d59f0
11 changed files with 632 additions and 22 deletions
@@ -7,8 +7,13 @@ from esphome.components.modbus_server import (
SERVER_SENSOR_VALUE_TYPE,
_validate_no_overlapping_registers,
_validate_register_ranges,
_validate_unique_bit_addresses,
)
from esphome.components.modbus_server.const import (
CONF_BITS,
CONF_REGISTERS,
CONF_VALUE_TYPE,
)
from esphome.components.modbus_server.const import CONF_REGISTERS, CONF_VALUE_TYPE
from esphome.const import CONF_ADDRESS
@@ -21,6 +26,10 @@ def _config(registers: list[tuple[int, str]]) -> dict:
}
def _bits_config(addresses: list[int]) -> dict:
return {CONF_BITS: [{CONF_ADDRESS: address} for address in addresses]}
def test_non_overlapping_registers_pass() -> None:
# Values that tile the address space without gaps or overlaps are accepted.
config = _config([(0x00, "U_WORD"), (0x01, "U_DWORD"), (0x03, "U_WORD")])
@@ -42,6 +51,18 @@ def test_duplicate_address_rejected() -> None:
_validate_no_overlapping_registers(config)
def test_unique_bit_addresses_pass() -> None:
config = _bits_config([0x00, 0x01, 0x02])
assert _validate_unique_bit_addresses(config) is config
def test_duplicate_bit_address_rejected() -> None:
# Coils and discrete inputs share one bit address space, so a repeated address is rejected.
config = _bits_config([0x05, 0x05])
with pytest.raises(cv.Invalid, match="more than once"):
_validate_unique_bit_addresses(config)
def test_multi_register_value_overlapping_neighbour_rejected() -> None:
# U_DWORD at 0x10 occupies 0x10 and 0x11; a U_WORD at 0x11 collides with its low word.
config = _config([(0x10, "U_DWORD"), (0x11, "U_WORD")])