Do not fail MQTT setup if climate's configured via yaml can't be validated (#102303)

Add climate
This commit is contained in:
Jan Bouwhuis 2023-10-19 21:14:45 +02:00 committed by GitHub
parent b57af4e404
commit e26a2596af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 41 deletions

View File

@ -3,7 +3,6 @@ from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections.abc import Callable from collections.abc import Callable
import functools
import logging import logging
from typing import Any from typing import Any
@ -47,7 +46,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.template import Template from homeassistant.helpers.template import Template
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType
from homeassistant.util.unit_conversion import TemperatureConverter from homeassistant.util.unit_conversion import TemperatureConverter
from . import subscription from . import subscription
@ -85,7 +84,7 @@ from .debug_info import log_messages
from .mixins import ( from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA, MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity, MqttEntity,
async_setup_entry_helper, async_mqtt_entry_helper,
write_state_on_attr_change, write_state_on_attr_change,
) )
from .models import ( from .models import (
@ -399,22 +398,16 @@ async def async_setup_entry(
config_entry: ConfigEntry, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up MQTT climate device through YAML and through MQTT discovery.""" """Set up MQTT climate through YAML and through MQTT discovery."""
setup = functools.partial( await async_mqtt_entry_helper(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry hass,
config_entry,
MqttClimate,
climate.DOMAIN,
async_add_entities,
DISCOVERY_SCHEMA,
PLATFORM_SCHEMA_MODERN,
) )
await async_setup_entry_helper(hass, climate.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
hass: HomeAssistant,
async_add_entities: AddEntitiesCallback,
config: ConfigType,
config_entry: ConfigEntry,
discovery_data: DiscoveryInfoType | None = None,
) -> None:
"""Set up the MQTT climate devices."""
async_add_entities([MqttClimate(hass, config, config_entry, discovery_data)])
class MqttTemperatureControlEntity(MqttEntity, ABC): class MqttTemperatureControlEntity(MqttEntity, ABC):

View File

@ -16,7 +16,6 @@ from homeassistant.helpers import config_validation as cv
from . import ( from . import (
button as button_platform, button as button_platform,
climate as climate_platform,
cover as cover_platform, cover as cover_platform,
event as event_platform, event as event_platform,
humidifier as humidifier_platform, humidifier as humidifier_platform,
@ -52,10 +51,7 @@ CONFIG_SCHEMA_BASE = vol.Schema(
[button_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type] [button_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type]
), ),
Platform.CAMERA.value: vol.All(cv.ensure_list, [dict]), Platform.CAMERA.value: vol.All(cv.ensure_list, [dict]),
Platform.CLIMATE.value: vol.All( Platform.CLIMATE.value: vol.All(cv.ensure_list, [dict]),
cv.ensure_list,
[climate_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type]
),
Platform.COVER.value: vol.All( Platform.COVER.value: vol.All(
cv.ensure_list, cv.ensure_list,
[cover_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type] [cover_platform.PLATFORM_SCHEMA_MODERN], # type: ignore[has-type]

View File

@ -138,9 +138,8 @@ async def test_preset_none_in_preset_modes(
mqtt_mock_entry: MqttMockHAClientGenerator, mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None: ) -> None:
"""Test the preset mode payload reset configuration.""" """Test the preset mode payload reset configuration."""
with pytest.raises(AssertionError): assert await mqtt_mock_entry()
await mqtt_mock_entry() assert "not a valid value" in caplog.text
assert "Invalid config for [mqtt]: not a valid value" in caplog.text
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -2448,11 +2447,11 @@ async def test_publishing_with_custom_encoding(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("hass_config", "valid"), ("hass_config", "valid"),
[ [
( ( # test_valid_humidity_min_max
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
climate.DOMAIN: { climate.DOMAIN: {
"name": "test_valid_humidity_min_max", "name": "test",
"min_humidity": 20, "min_humidity": 20,
"max_humidity": 80, "max_humidity": 80,
}, },
@ -2460,11 +2459,11 @@ async def test_publishing_with_custom_encoding(
}, },
True, True,
), ),
( ( # test_invalid_humidity_min_max_1
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
climate.DOMAIN: { climate.DOMAIN: {
"name": "test_invalid_humidity_min_max_1", "name": "test",
"min_humidity": 0, "min_humidity": 0,
"max_humidity": 101, "max_humidity": 101,
}, },
@ -2472,11 +2471,11 @@ async def test_publishing_with_custom_encoding(
}, },
False, False,
), ),
( ( # test_invalid_humidity_min_max_2
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
climate.DOMAIN: { climate.DOMAIN: {
"name": "test_invalid_humidity_min_max_2", "name": "test",
"max_humidity": 20, "max_humidity": 20,
"min_humidity": 40, "min_humidity": 40,
}, },
@ -2484,11 +2483,11 @@ async def test_publishing_with_custom_encoding(
}, },
False, False,
), ),
( ( # test_valid_humidity_state
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
climate.DOMAIN: { climate.DOMAIN: {
"name": "test_valid_humidity_state", "name": "test",
"target_humidity_state_topic": "humidity-state", "target_humidity_state_topic": "humidity-state",
"target_humidity_command_topic": "humidity-command", "target_humidity_command_topic": "humidity-command",
}, },
@ -2496,11 +2495,11 @@ async def test_publishing_with_custom_encoding(
}, },
True, True,
), ),
( ( # test_invalid_humidity_state
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
climate.DOMAIN: { climate.DOMAIN: {
"name": "test_invalid_humidity_state", "name": "test",
"target_humidity_state_topic": "humidity-state", "target_humidity_state_topic": "humidity-state",
}, },
} }
@ -2515,11 +2514,9 @@ async def test_humidity_configuration_validity(
valid: bool, valid: bool,
) -> None: ) -> None:
"""Test the validity of humidity configurations.""" """Test the validity of humidity configurations."""
if valid: assert await mqtt_mock_entry()
await mqtt_mock_entry() state = hass.states.get("climate.test")
return assert (state is not None) == valid
with pytest.raises(AssertionError):
await mqtt_mock_entry()
async def test_reloadable( async def test_reloadable(