Modbus, Remove duplicate address check (#121579)

This commit is contained in:
jan iversen 2024-07-09 21:16:47 +02:00 committed by GitHub
parent 9d2cf70ba5
commit 5e56c27703
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 0 additions and 571 deletions

View File

@ -139,7 +139,6 @@ from .const import (
) )
from .modbus import ModbusHub, async_modbus_setup from .modbus import ModbusHub, async_modbus_setup
from .validators import ( from .validators import (
check_hvac_target_temp_registers,
duplicate_fan_mode_validator, duplicate_fan_mode_validator,
duplicate_swing_mode_validator, duplicate_swing_mode_validator,
hvac_fixedsize_reglist_validator, hvac_fixedsize_reglist_validator,
@ -321,7 +320,6 @@ CLIMATE_SCHEMA = vol.All(
), ),
}, },
), ),
check_hvac_target_temp_registers,
) )
COVERS_SCHEMA = BASE_COMPONENT_SCHEMA.extend( COVERS_SCHEMA = BASE_COMPONENT_SCHEMA.extend(

View File

@ -12,14 +12,11 @@ import voluptuous as vol
from homeassistant.components.climate import HVACMode from homeassistant.components.climate import HVACMode
from homeassistant.const import ( from homeassistant.const import (
CONF_ADDRESS, CONF_ADDRESS,
CONF_COMMAND_OFF,
CONF_COMMAND_ON,
CONF_COUNT, CONF_COUNT,
CONF_HOST, CONF_HOST,
CONF_NAME, CONF_NAME,
CONF_PORT, CONF_PORT,
CONF_SCAN_INTERVAL, CONF_SCAN_INTERVAL,
CONF_SLAVE,
CONF_STRUCTURE, CONF_STRUCTURE,
CONF_TIMEOUT, CONF_TIMEOUT,
CONF_TYPE, CONF_TYPE,
@ -29,12 +26,7 @@ from homeassistant.helpers.issue_registry import IssueSeverity, async_create_iss
from .const import ( from .const import (
CONF_DATA_TYPE, CONF_DATA_TYPE,
CONF_DEVICE_ADDRESS,
CONF_FAN_MODE_REGISTER,
CONF_FAN_MODE_VALUES, CONF_FAN_MODE_VALUES,
CONF_HVAC_MODE_REGISTER,
CONF_HVAC_ONOFF_REGISTER,
CONF_INPUT_TYPE,
CONF_LAZY_ERROR, CONF_LAZY_ERROR,
CONF_RETRIES, CONF_RETRIES,
CONF_SLAVE_COUNT, CONF_SLAVE_COUNT,
@ -42,11 +34,8 @@ from .const import (
CONF_SWAP_BYTE, CONF_SWAP_BYTE,
CONF_SWAP_WORD, CONF_SWAP_WORD,
CONF_SWAP_WORD_BYTE, CONF_SWAP_WORD_BYTE,
CONF_SWING_MODE_REGISTER,
CONF_SWING_MODE_VALUES, CONF_SWING_MODE_VALUES,
CONF_TARGET_TEMP,
CONF_VIRTUAL_COUNT, CONF_VIRTUAL_COUNT,
CONF_WRITE_TYPE,
DEFAULT_HUB, DEFAULT_HUB,
DEFAULT_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL,
MODBUS_DOMAIN as DOMAIN, MODBUS_DOMAIN as DOMAIN,
@ -273,45 +262,6 @@ def duplicate_swing_mode_validator(config: dict[str, Any]) -> dict:
return config return config
def check_hvac_target_temp_registers(config: dict) -> dict:
"""Check conflicts among HVAC target temperature registers and HVAC ON/OFF, HVAC register, Fan Modes, Swing Modes."""
if (
CONF_HVAC_MODE_REGISTER in config
and config[CONF_HVAC_MODE_REGISTER][CONF_ADDRESS] in config[CONF_TARGET_TEMP]
):
wrn = f"{CONF_HVAC_MODE_REGISTER} overlaps CONF_TARGET_TEMP register(s). {CONF_HVAC_MODE_REGISTER} is not loaded!"
_LOGGER.warning(wrn)
del config[CONF_HVAC_MODE_REGISTER]
if (
CONF_HVAC_ONOFF_REGISTER in config
and config[CONF_HVAC_ONOFF_REGISTER] in config[CONF_TARGET_TEMP]
):
wrn = f"{CONF_HVAC_ONOFF_REGISTER} overlaps CONF_TARGET_TEMP register(s). {CONF_HVAC_ONOFF_REGISTER} is not loaded!"
_LOGGER.warning(wrn)
del config[CONF_HVAC_ONOFF_REGISTER]
if (
CONF_FAN_MODE_REGISTER in config
and config[CONF_FAN_MODE_REGISTER][CONF_ADDRESS] in config[CONF_TARGET_TEMP]
):
wrn = f"{CONF_FAN_MODE_REGISTER} overlaps CONF_TARGET_TEMP register(s). {CONF_FAN_MODE_REGISTER} is not loaded!"
_LOGGER.warning(wrn)
del config[CONF_FAN_MODE_REGISTER]
if CONF_SWING_MODE_REGISTER in config:
regToTest = (
config[CONF_SWING_MODE_REGISTER][CONF_ADDRESS]
if isinstance(config[CONF_SWING_MODE_REGISTER][CONF_ADDRESS], int)
else config[CONF_SWING_MODE_REGISTER][CONF_ADDRESS][0]
)
if regToTest in config[CONF_TARGET_TEMP]:
wrn = f"{CONF_SWING_MODE_REGISTER} overlaps CONF_TARGET_TEMP register(s). {CONF_SWING_MODE_REGISTER} is not loaded!"
_LOGGER.warning(wrn)
del config[CONF_SWING_MODE_REGISTER]
return config
def register_int_list_validator(value: Any) -> Any: def register_int_list_validator(value: Any) -> Any:
"""Check if a register (CONF_ADRESS) is an int or a list having only 1 register.""" """Check if a register (CONF_ADRESS) is an int or a list having only 1 register."""
if isinstance(value, int) and value >= 0: if isinstance(value, int) and value >= 0:
@ -422,7 +372,6 @@ def validate_entity(
"`lazy_error_count`: is deprecated and will be removed in version 2024.7" "`lazy_error_count`: is deprecated and will be removed in version 2024.7"
) )
name = f"{component}.{entity[CONF_NAME]}" name = f"{component}.{entity[CONF_NAME]}"
addr = f"{hub_name}{entity[CONF_ADDRESS]}"
scan_interval = entity.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) scan_interval = entity.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
if 0 < scan_interval < 5: if 0 < scan_interval < 5:
err = ( err = (
@ -432,44 +381,6 @@ def validate_entity(
_LOGGER.warning(err) _LOGGER.warning(err)
entity[CONF_SCAN_INTERVAL] = scan_interval entity[CONF_SCAN_INTERVAL] = scan_interval
minimum_scan_interval = min(scan_interval, minimum_scan_interval) minimum_scan_interval = min(scan_interval, minimum_scan_interval)
for conf_type in (
CONF_INPUT_TYPE,
CONF_WRITE_TYPE,
CONF_COMMAND_ON,
CONF_COMMAND_OFF,
):
if conf_type in entity:
addr += f"_{entity[conf_type]}"
inx = entity.get(CONF_SLAVE) or entity.get(CONF_DEVICE_ADDRESS, 0)
addr += f"_{inx}"
loc_addr: set[str] = {addr}
if CONF_TARGET_TEMP in entity:
loc_addr.add(f"{hub_name}{entity[CONF_TARGET_TEMP]}_{inx}")
if CONF_HVAC_MODE_REGISTER in entity:
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"{hub_name}{entity[CONF_FAN_MODE_REGISTER][CONF_ADDRESS]}_{inx}")
if CONF_SWING_MODE_REGISTER in entity:
loc_addr.add(
f"{hub_name}{entity[CONF_SWING_MODE_REGISTER][CONF_ADDRESS]
if isinstance(entity[CONF_SWING_MODE_REGISTER][CONF_ADDRESS],int)
else entity[CONF_SWING_MODE_REGISTER][CONF_ADDRESS][0]}_{inx}"
)
dup_addrs = ent_addr.intersection(loc_addr)
if len(dup_addrs) > 0:
for addr in dup_addrs:
modbus_create_issue(
hass,
"duplicate_entity_entry",
[
f"{hub_name}/{name}",
addr,
"",
],
f"Modbus {hub_name}/{name} address {addr} is duplicate, second entry not loaded!",
)
return False
if name in ent_names: if name in ent_names:
modbus_create_issue( modbus_create_issue(
hass, hass,
@ -483,7 +394,6 @@ def validate_entity(
) )
return False return False
ent_names.add(name) ent_names.add(name)
ent_addr.update(loc_addr)
return True return True

View File

@ -48,15 +48,7 @@ from homeassistant.components.modbus.const import (
CONF_FAN_MODE_HIGH, CONF_FAN_MODE_HIGH,
CONF_FAN_MODE_OFF, CONF_FAN_MODE_OFF,
CONF_FAN_MODE_ON, CONF_FAN_MODE_ON,
CONF_FAN_MODE_REGISTER,
CONF_FAN_MODE_VALUES, CONF_FAN_MODE_VALUES,
CONF_HVAC_MODE_COOL,
CONF_HVAC_MODE_DRY,
CONF_HVAC_MODE_HEAT,
CONF_HVAC_MODE_HEAT_COOL,
CONF_HVAC_MODE_REGISTER,
CONF_HVAC_MODE_VALUES,
CONF_HVAC_ONOFF_REGISTER,
CONF_INPUT_TYPE, CONF_INPUT_TYPE,
CONF_MSG_WAIT, CONF_MSG_WAIT,
CONF_PARITY, CONF_PARITY,
@ -67,12 +59,10 @@ from homeassistant.components.modbus.const import (
CONF_SWAP_BYTE, CONF_SWAP_BYTE,
CONF_SWAP_WORD, CONF_SWAP_WORD,
CONF_SWAP_WORD_BYTE, CONF_SWAP_WORD_BYTE,
CONF_SWING_MODE_REGISTER,
CONF_SWING_MODE_SWING_BOTH, CONF_SWING_MODE_SWING_BOTH,
CONF_SWING_MODE_SWING_OFF, CONF_SWING_MODE_SWING_OFF,
CONF_SWING_MODE_SWING_ON, CONF_SWING_MODE_SWING_ON,
CONF_SWING_MODE_VALUES, CONF_SWING_MODE_VALUES,
CONF_TARGET_TEMP,
CONF_VIRTUAL_COUNT, CONF_VIRTUAL_COUNT,
DEFAULT_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL,
MODBUS_DOMAIN as DOMAIN, MODBUS_DOMAIN as DOMAIN,
@ -88,7 +78,6 @@ from homeassistant.components.modbus.const import (
) )
from homeassistant.components.modbus.validators import ( from homeassistant.components.modbus.validators import (
check_config, check_config,
check_hvac_target_temp_registers,
duplicate_fan_mode_validator, duplicate_fan_mode_validator,
duplicate_swing_mode_validator, duplicate_swing_mode_validator,
hvac_fixedsize_reglist_validator, hvac_fixedsize_reglist_validator,
@ -457,27 +446,6 @@ async def test_check_config(hass: HomeAssistant, do_config) -> None:
], ],
} }
], ],
[
{
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 + " 2",
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
},
],
}
],
], ],
) )
async def test_check_config_sensor(hass: HomeAssistant, do_config) -> None: async def test_check_config_sensor(hass: HomeAssistant, do_config) -> None:
@ -510,225 +478,6 @@ async def test_check_config_sensor(hass: HomeAssistant, do_config) -> None:
], ],
} }
], ],
[
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
},
],
}
],
[
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 118,
CONF_SLAVE: 0,
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 119,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 1,
},
},
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 1,
},
},
},
],
}
],
[
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 118,
CONF_SLAVE: 0,
CONF_TARGET_TEMP: [99],
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
],
}
],
[
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
CONF_TARGET_TEMP: [117],
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: [121],
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
],
}
],
[ # Testing Swing modes
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 117,
CONF_SLAVE: 0,
CONF_SWING_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_SWING_MODE_VALUES: {
CONF_SWING_MODE_SWING_ON: 0,
CONF_SWING_MODE_SWING_BOTH: 1,
},
},
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 119,
CONF_SLAVE: 0,
CONF_TARGET_TEMP: 118,
CONF_SWING_MODE_REGISTER: {
CONF_ADDRESS: [120],
CONF_SWING_MODE_VALUES: {
CONF_SWING_MODE_SWING_ON: 0,
CONF_SWING_MODE_SWING_BOTH: 1,
},
},
},
],
}
],
[
{
CONF_NAME: TEST_MODBUS_NAME,
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_TIMEOUT: 3,
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 117,
CONF_TARGET_TEMP: [130, 131, 132, 133, 134, 135, 136],
CONF_SLAVE: 0,
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 118,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 2,
CONF_HVAC_MODE_DRY: 3,
},
},
CONF_HVAC_ONOFF_REGISTER: 122,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
{
CONF_NAME: TEST_ENTITY_NAME + " 2",
CONF_ADDRESS: 118,
CONF_TARGET_TEMP: [130, 131, 132, 133, 134, 135, 136],
CONF_SLAVE: 0,
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 130,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 2,
CONF_HVAC_MODE_DRY: 3,
},
},
CONF_HVAC_ONOFF_REGISTER: 122,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 120,
CONF_FAN_MODE_VALUES: {
CONF_FAN_MODE_ON: 0,
CONF_FAN_MODE_HIGH: 1,
},
},
},
],
}
],
], ],
) )
async def test_check_config_climate(hass: HomeAssistant, do_config) -> None: async def test_check_config_climate(hass: HomeAssistant, do_config) -> None:
@ -737,83 +486,6 @@ async def test_check_config_climate(hass: HomeAssistant, do_config) -> None:
assert len(do_config[0][CONF_CLIMATES]) == 1 assert len(do_config[0][CONF_CLIMATES]) == 1
@pytest.mark.parametrize(
"do_config",
[
[
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1,
CONF_TARGET_TEMP: [117, 121, 119, 150, 151, 152, 156],
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 119,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 1,
CONF_HVAC_MODE_HEAT_COOL: 2,
CONF_HVAC_MODE_DRY: 3,
},
},
CONF_HVAC_ONOFF_REGISTER: 117,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 121,
},
},
],
[
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1,
CONF_TARGET_TEMP: [117],
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 117,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 1,
CONF_HVAC_MODE_HEAT_COOL: 2,
CONF_HVAC_MODE_DRY: 3,
},
},
CONF_HVAC_ONOFF_REGISTER: 117,
CONF_FAN_MODE_REGISTER: {
CONF_ADDRESS: 117,
},
CONF_SWING_MODE_REGISTER: {
CONF_ADDRESS: 117,
},
},
],
[
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 1,
CONF_TARGET_TEMP: [117],
CONF_HVAC_MODE_REGISTER: {
CONF_ADDRESS: 117,
CONF_HVAC_MODE_VALUES: {
CONF_HVAC_MODE_COOL: 0,
CONF_HVAC_MODE_HEAT: 1,
CONF_HVAC_MODE_HEAT_COOL: 2,
CONF_HVAC_MODE_DRY: 3,
},
},
CONF_HVAC_ONOFF_REGISTER: 117,
CONF_SWING_MODE_REGISTER: {
CONF_ADDRESS: [117],
},
},
],
],
)
async def test_climate_conflict_addresses(do_config) -> None:
"""Test conflicts among the addresses of target temp and other climate addresses."""
check_hvac_target_temp_registers(do_config[0])
assert CONF_HVAC_MODE_REGISTER not in do_config[0]
assert CONF_HVAC_ONOFF_REGISTER not in do_config[0]
assert CONF_FAN_MODE_REGISTER not in do_config[0]
assert CONF_SWING_MODE_REGISTER not in do_config[0]
@pytest.mark.parametrize( @pytest.mark.parametrize(
"do_config", "do_config",
[ [
@ -852,157 +524,6 @@ async def test_duplicate_swing_mode_validator(do_config) -> None:
assert len(do_config[CONF_SWING_MODE_VALUES]) == 2 assert len(do_config[CONF_SWING_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,
),
(
[
{
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,
CONF_ADDRESS: 1179,
CONF_SLAVE: 0,
},
],
},
],
1,
),
],
)
async def test_duplicate_addresses(hass: HomeAssistant, do_config, sensor_cnt) -> None:
"""Test duplicate entity validator."""
check_config(hass, do_config)
use_inx = len(do_config) - 1
assert len(do_config[use_inx][CONF_SENSORS]) == sensor_cnt
@pytest.mark.parametrize( @pytest.mark.parametrize(
"do_config", "do_config",
[ [