From 4da385898bbc4c58814d3ce1f2f393abd502de2d Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Fri, 2 Aug 2024 08:50:19 +0200 Subject: [PATCH] Mitigate breaking change for KNX climate schema (#123043) --- homeassistant/components/knx/schema.py | 7 +++-- homeassistant/components/knx/validation.py | 34 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/knx/schema.py b/homeassistant/components/knx/schema.py index 43037ad8188..c31b3d30ad0 100644 --- a/homeassistant/components/knx/schema.py +++ b/homeassistant/components/knx/schema.py @@ -56,6 +56,7 @@ from .const import ( ColorTempModes, ) from .validation import ( + backwards_compatible_xknx_climate_enum_member, dpt_base_type_validator, ga_list_validator, ga_validator, @@ -409,10 +410,12 @@ class ClimateSchema(KNXPlatformSchema): CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT ): cv.boolean, vol.Optional(CONF_OPERATION_MODES): vol.All( - cv.ensure_list, [vol.All(vol.Upper, cv.enum(HVACOperationMode))] + cv.ensure_list, + [backwards_compatible_xknx_climate_enum_member(HVACOperationMode)], ), vol.Optional(CONF_CONTROLLER_MODES): vol.All( - cv.ensure_list, [vol.All(vol.Upper, cv.enum(HVACControllerMode))] + cv.ensure_list, + [backwards_compatible_xknx_climate_enum_member(HVACControllerMode)], ), vol.Optional( CONF_DEFAULT_CONTROLLER_MODE, default=HVACMode.HEAT diff --git a/homeassistant/components/knx/validation.py b/homeassistant/components/knx/validation.py index 422b8474fd9..0283b65f899 100644 --- a/homeassistant/components/knx/validation.py +++ b/homeassistant/components/knx/validation.py @@ -1,6 +1,7 @@ """Validation helpers for KNX config schemas.""" from collections.abc import Callable +from enum import Enum import ipaddress from typing import Any @@ -104,3 +105,36 @@ sync_state_validator = vol.Any( cv.boolean, cv.matches_regex(r"^(init|expire|every)( \d*)?$"), ) + + +def backwards_compatible_xknx_climate_enum_member(enumClass: type[Enum]) -> vol.All: + """Transform a string to an enum member. + + Backwards compatible with member names of xknx 2.x climate DPT Enums + due to unintentional breaking change in HA 2024.8. + """ + + def _string_transform(value: Any) -> str: + """Upper and slugify string and substitute old member names. + + Previously this was checked against Enum values instead of names. These + looked like `FAN_ONLY = "Fan only"`, therefore the upper & replace part. + """ + if not isinstance(value, str): + raise vol.Invalid("value should be a string") + name = value.upper().replace(" ", "_") + match name: + case "NIGHT": + return "ECONOMY" + case "FROST_PROTECTION": + return "BUILDING_PROTECTION" + case "DRY": + return "DEHUMIDIFICATION" + case _: + return name + + return vol.All( + _string_transform, + vol.In(enumClass.__members__), + enumClass.__getitem__, + )