mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Check for duplicate entity name/address in modbus entities (#54669)
* Check for duplicate entity name/address.
This commit is contained in:
parent
faec82ae8f
commit
0688aaa2b6
@ -116,7 +116,12 @@ from .const import (
|
||||
UDP,
|
||||
)
|
||||
from .modbus import ModbusHub, async_modbus_setup
|
||||
from .validators import number_validator, scan_interval_validator, struct_validator
|
||||
from .validators import (
|
||||
duplicate_entity_validator,
|
||||
number_validator,
|
||||
scan_interval_validator,
|
||||
struct_validator,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -327,6 +332,7 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
DOMAIN: vol.All(
|
||||
cv.ensure_list,
|
||||
scan_interval_validator,
|
||||
duplicate_entity_validator,
|
||||
[
|
||||
vol.Any(SERIAL_SCHEMA, ETHERNET_SCHEMA),
|
||||
],
|
||||
|
@ -9,9 +9,11 @@ from typing import Any
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_ADDRESS,
|
||||
CONF_COUNT,
|
||||
CONF_NAME,
|
||||
CONF_SCAN_INTERVAL,
|
||||
CONF_SLAVE,
|
||||
CONF_STRUCTURE,
|
||||
CONF_TIMEOUT,
|
||||
)
|
||||
@ -189,3 +191,35 @@ def scan_interval_validator(config: dict) -> dict:
|
||||
)
|
||||
hub[CONF_TIMEOUT] = minimum_scan_interval - 1
|
||||
return config
|
||||
|
||||
|
||||
def duplicate_entity_validator(config: dict) -> dict:
|
||||
"""Control scan_interval."""
|
||||
for hub_index, hub in enumerate(config):
|
||||
addresses: set[str] = set()
|
||||
for component, conf_key in PLATFORMS:
|
||||
if conf_key not in hub:
|
||||
continue
|
||||
names: set[str] = set()
|
||||
errors: list[int] = []
|
||||
for index, entry in enumerate(hub[conf_key]):
|
||||
name = entry[CONF_NAME]
|
||||
addr = str(entry[CONF_ADDRESS])
|
||||
if CONF_SLAVE in entry:
|
||||
addr += "_" + str(entry[CONF_SLAVE])
|
||||
if addr in addresses:
|
||||
err = f"Modbus {component}/{name} address {addr} is duplicate, second entry not loaded!"
|
||||
_LOGGER.warning(err)
|
||||
errors.append(index)
|
||||
elif name in names:
|
||||
err = f"Modbus {component}/{name} is duplicate, second entry not loaded!"
|
||||
_LOGGER.warning(err)
|
||||
errors.append(index)
|
||||
else:
|
||||
names.add(name)
|
||||
addresses.add(addr)
|
||||
|
||||
for i in reversed(errors):
|
||||
del config[hub_index][conf_key][i]
|
||||
|
||||
return config
|
||||
|
@ -235,7 +235,7 @@ async def test_restore_state_cover(hass, mock_test_state, mock_modbus):
|
||||
{
|
||||
CONF_NAME: f"{TEST_ENTITY_NAME}2",
|
||||
CONF_INPUT_TYPE: CALL_TYPE_COIL,
|
||||
CONF_ADDRESS: 1234,
|
||||
CONF_ADDRESS: 1235,
|
||||
CONF_SCAN_INTERVAL: 0,
|
||||
},
|
||||
]
|
||||
|
@ -231,7 +231,7 @@ async def test_fan_service_turn(hass, caplog, mock_pymodbus):
|
||||
},
|
||||
{
|
||||
CONF_NAME: f"{TEST_ENTITY_NAME}2",
|
||||
CONF_ADDRESS: 17,
|
||||
CONF_ADDRESS: 18,
|
||||
CONF_WRITE_TYPE: CALL_TYPE_REGISTER_HOLDING,
|
||||
CONF_SCAN_INTERVAL: 0,
|
||||
CONF_VERIFY: {},
|
||||
|
@ -231,7 +231,7 @@ async def test_light_service_turn(hass, caplog, mock_pymodbus):
|
||||
},
|
||||
{
|
||||
CONF_NAME: f"{TEST_ENTITY_NAME}2",
|
||||
CONF_ADDRESS: 17,
|
||||
CONF_ADDRESS: 18,
|
||||
CONF_WRITE_TYPE: CALL_TYPE_REGISTER_HOLDING,
|
||||
CONF_SCAN_INTERVAL: 0,
|
||||
CONF_VERIFY: {},
|
||||
|
@ -245,7 +245,7 @@ async def test_switch_service_turn(hass, caplog, mock_pymodbus):
|
||||
},
|
||||
{
|
||||
CONF_NAME: f"{TEST_ENTITY_NAME}2",
|
||||
CONF_ADDRESS: 17,
|
||||
CONF_ADDRESS: 18,
|
||||
CONF_WRITE_TYPE: CALL_TYPE_REGISTER_HOLDING,
|
||||
CONF_SCAN_INTERVAL: 0,
|
||||
CONF_VERIFY: {},
|
||||
|
Loading…
x
Reference in New Issue
Block a user