diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index bdf472e4f76..765ce4d8be3 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -308,7 +308,7 @@ def check_config(config: dict) -> dict: ) -> bool: """Validate entity.""" name = entity[CONF_NAME] - addr = str(entity[CONF_ADDRESS]) + addr = f"{hub_name}{entity[CONF_ADDRESS]}" scan_interval = entity.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) if scan_interval < 5: _LOGGER.warning( @@ -335,11 +335,15 @@ def check_config(config: dict) -> dict: loc_addr: set[str] = {addr} if CONF_TARGET_TEMP in entity: - loc_addr.add(f"{entity[CONF_TARGET_TEMP]}_{inx}") + loc_addr.add(f"{hub_name}{entity[CONF_TARGET_TEMP]}_{inx}") if CONF_HVAC_MODE_REGISTER in entity: - loc_addr.add(f"{entity[CONF_HVAC_MODE_REGISTER][CONF_ADDRESS]}_{inx}") + loc_addr.add( + f"{hub_name}{entity[CONF_HVAC_MODE_REGISTER][CONF_ADDRESS]}_{inx}" + ) if CONF_FAN_MODE_REGISTER in entity: - loc_addr.add(f"{entity[CONF_FAN_MODE_REGISTER][CONF_ADDRESS]}_{inx}") + loc_addr.add( + f"{hub_name}{entity[CONF_FAN_MODE_REGISTER][CONF_ADDRESS]}_{inx}" + ) dup_addrs = ent_addr.intersection(loc_addr) if len(dup_addrs) > 0: diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index 5738268a593..4de9a439a01 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -740,6 +740,133 @@ async def test_duplicate_fan_mode_validator(do_config) -> None: assert len(do_config[CONF_FAN_MODE_VALUES]) == 2 +@pytest.mark.parametrize( + ("do_config", "sensor_cnt"), + [ + ( + [ + { + CONF_NAME: TEST_MODBUS_NAME, + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + CONF_TIMEOUT: 3, + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + { + CONF_NAME: TEST_ENTITY_NAME + "1", + CONF_ADDRESS: 119, + CONF_SLAVE: 0, + }, + ], + }, + ], + 2, + ), + ( + [ + { + CONF_NAME: TEST_MODBUS_NAME, + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + CONF_TIMEOUT: 3, + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + { + CONF_NAME: TEST_ENTITY_NAME + "1", + CONF_ADDRESS: 117, + CONF_SLAVE: 1, + }, + ], + }, + ], + 2, + ), + ( + [ + { + CONF_NAME: TEST_MODBUS_NAME, + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + CONF_TIMEOUT: 3, + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + { + CONF_NAME: TEST_ENTITY_NAME + "1", + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + ], + }, + ], + 1, + ), + ( + [ + { + CONF_NAME: TEST_MODBUS_NAME, + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + CONF_TIMEOUT: 3, + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + { + CONF_NAME: TEST_ENTITY_NAME + "1", + CONF_ADDRESS: 119, + CONF_SLAVE: 0, + }, + ], + }, + { + CONF_NAME: TEST_MODBUS_NAME + "1", + CONF_TYPE: TCP, + CONF_HOST: TEST_MODBUS_HOST, + CONF_PORT: TEST_PORT_TCP, + CONF_TIMEOUT: 3, + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 117, + CONF_SLAVE: 0, + }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 119, + CONF_SLAVE: 0, + }, + ], + }, + ], + 2, + ), + ], +) +async def test_duplicate_addresses(do_config, sensor_cnt) -> None: + """Test duplicate entity validator.""" + check_config(do_config) + use_inx = len(do_config) - 1 + assert len(do_config[use_inx][CONF_SENSORS]) == sensor_cnt + + @pytest.mark.parametrize( "do_config", [