Mitigate breaking change for KNX climate schema (#123043)

pull/121786/head^2
Matthias Alphart 2024-08-02 08:50:19 +02:00 committed by GitHub
parent 8ec8aef02e
commit 4da385898b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 2 deletions

View File

@ -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

View File

@ -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__,
)