diff --git a/homeassistant/components/modbus/__init__.py b/homeassistant/components/modbus/__init__.py index cc1b3c74356..734546a34bc 100644 --- a/homeassistant/components/modbus/__init__.py +++ b/homeassistant/components/modbus/__init__.py @@ -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, diff --git a/homeassistant/components/modbus/base_platform.py b/homeassistant/components/modbus/base_platform.py index d3ec06bbdd7..af9b83f8b85 100644 --- a/homeassistant/components/modbus/base_platform.py +++ b/homeassistant/components/modbus/base_platform.py @@ -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" ) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index 5e2129bd90a..e108231c5e6 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -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 diff --git a/tests/components/modbus/test_climate.py b/tests/components/modbus/test_climate.py index 325b68869e0..b6855d7be18 100644 --- a/tests/components/modbus/test_climate.py +++ b/tests/components/modbus/test_climate.py @@ -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"), [ diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index df415807119..da46979526f 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -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, diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index 8fb7f9fd951..c9e943b06a7 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -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: