Get modbus coverage back to 100% (#108734)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
jan iversen 2024-01-23 21:50:25 +01:00 committed by GitHub
parent a6807b8a7f
commit d8f16c14ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 26 deletions

View File

@ -133,12 +133,10 @@ from .const import ( # noqa: F401
)
from .modbus import ModbusHub, async_modbus_setup
from .validators import (
duplicate_entity_validator,
check_config,
duplicate_fan_mode_validator,
duplicate_modbus_validator,
nan_validator,
number_validator,
scan_interval_validator,
struct_validator,
)
@ -417,12 +415,10 @@ CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.All(
cv.ensure_list,
scan_interval_validator,
duplicate_entity_validator,
duplicate_modbus_validator,
[
vol.Any(SERIAL_SCHEMA, ETHERNET_SCHEMA),
],
check_config,
),
},
extra=vol.ALLOW_EXTRA,

View File

@ -96,10 +96,6 @@ class BasePlatform(Entity):
"url": "https://www.home-assistant.io/integrations/modbus",
},
)
_LOGGER.warning(
"`close_comm_on_error`: is deprecated and will be removed in version 2024.4"
)
_LOGGER.warning(
"`lazy_error_count`: is deprecated and will be removed in version 2024.7"
)

View File

@ -203,6 +203,23 @@ def nan_validator(value: Any) -> int:
raise vol.Invalid(f"invalid number {value}") from err
def duplicate_fan_mode_validator(config: dict[str, Any]) -> dict:
"""Control modbus climate fan mode values for duplicates."""
fan_modes: set[int] = set()
errors = []
for key, value in config[CONF_FAN_MODE_VALUES].items():
if value in fan_modes:
warn = f"Modbus fan mode {key} has a duplicate value {value}, not loaded, values must be unique!"
_LOGGER.warning(warn)
errors.append(key)
else:
fan_modes.add(value)
for key in reversed(errors):
del config[CONF_FAN_MODE_VALUES][key]
return config
def scan_interval_validator(config: dict) -> dict:
"""Control scan_interval."""
for hub in config:
@ -306,7 +323,7 @@ def duplicate_entity_validator(config: dict) -> dict:
return config
def duplicate_modbus_validator(config: list) -> list:
def duplicate_modbus_validator(config: dict) -> dict:
"""Control modbus connection for duplicates."""
hosts: set[str] = set()
names: set[str] = set()
@ -334,18 +351,9 @@ def duplicate_modbus_validator(config: list) -> list:
return config
def duplicate_fan_mode_validator(config: dict[str, Any]) -> dict:
"""Control modbus climate fan mode values for duplicates."""
fan_modes: set[int] = set()
errors = []
for key, value in config[CONF_FAN_MODE_VALUES].items():
if value in fan_modes:
wrn = f"Modbus fan mode {key} has a duplicate value {value}, not loaded, values must be unique!"
_LOGGER.warning(wrn)
errors.append(key)
else:
fan_modes.add(value)
for key in reversed(errors):
del config[CONF_FAN_MODE_VALUES][key]
return config
def check_config(config: dict) -> dict:
"""Do final config check."""
config2 = duplicate_modbus_validator(config)
config3 = scan_interval_validator(config2)
config4 = duplicate_entity_validator(config3)
return config4

View File

@ -309,6 +309,36 @@ async def test_temperature_climate(
assert hass.states.get(ENTITY_ID).state == expected
@pytest.mark.parametrize(
"do_config",
[
{
CONF_CLIMATES: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_SLAVE: 1,
CONF_TARGET_TEMP: 117,
CONF_ADDRESS: 117,
CONF_DATA_TYPE: DataType.INT32,
},
],
},
],
)
@pytest.mark.parametrize(
("register_words", "expected"),
[
(
None,
"unavailable",
),
],
)
async def test_temperature_error(hass: HomeAssistant, expected, mock_do_cycle) -> None:
"""Run test for given config."""
assert hass.states.get(ENTITY_ID).state == expected
@pytest.mark.parametrize(
("do_config", "result", "register_words"),
[

View File

@ -56,6 +56,7 @@ from homeassistant.components.modbus.const import (
CONF_INPUT_TYPE,
CONF_MSG_WAIT,
CONF_PARITY,
CONF_RETRIES,
CONF_RETRY_ON_EMPTY,
CONF_SLAVE_COUNT,
CONF_STOPBITS,
@ -610,6 +611,12 @@ async def test_duplicate_entity_validator_with_climate(do_config) -> None:
CONF_PORT: TEST_PORT_TCP,
CONF_CLOSE_COMM_ON_ERROR: True,
},
{
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,
CONF_PORT: TEST_PORT_TCP,
CONF_RETRIES: 3,
},
{
CONF_TYPE: TCP,
CONF_HOST: TEST_MODBUS_HOST,

View File

@ -9,6 +9,7 @@ from homeassistant.components.modbus.const import (
CONF_DATA_TYPE,
CONF_DEVICE_ADDRESS,
CONF_INPUT_TYPE,
CONF_LAZY_ERROR,
CONF_MAX_VALUE,
CONF_MIN_VALUE,
CONF_NAN_VALUE,
@ -173,6 +174,17 @@ SLAVE_UNIQUE_ID = "ground_floor_sensor"
}
]
},
{
CONF_SENSORS: [
{
CONF_NAME: TEST_ENTITY_NAME,
CONF_ADDRESS: 51,
CONF_DATA_TYPE: DataType.INT32,
CONF_VIRTUAL_COUNT: 5,
CONF_LAZY_ERROR: 3,
}
]
},
],
)
async def test_config_sensor(hass: HomeAssistant, mock_modbus) -> None: