Type check KNX integration climate (#48054)
parent
21c72fa559
commit
6b2a2740f1
|
@ -1,6 +1,8 @@
|
|||
"""Support for KNX/IP climate devices."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable, Iterable
|
||||
|
||||
from xknx.devices import Climate as XknxClimate
|
||||
from xknx.dpt.dpt_hvac_mode import HVACControllerMode, HVACOperationMode
|
||||
|
||||
|
@ -13,6 +15,12 @@ from homeassistant.components.climate.const import (
|
|||
SUPPORT_TARGET_TEMPERATURE,
|
||||
)
|
||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.typing import (
|
||||
ConfigType,
|
||||
DiscoveryInfoType,
|
||||
HomeAssistantType,
|
||||
)
|
||||
|
||||
from .const import CONTROLLER_MODES, DOMAIN, PRESET_MODES
|
||||
from .knx_entity import KnxEntity
|
||||
|
@ -21,7 +29,12 @@ CONTROLLER_MODES_INV = {value: key for key, value in CONTROLLER_MODES.items()}
|
|||
PRESET_MODES_INV = {value: key for key, value in PRESET_MODES.items()}
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistantType,
|
||||
config: ConfigType,
|
||||
async_add_entities: Callable[[Iterable[Entity]], None],
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up climate(s) for KNX platform."""
|
||||
entities = []
|
||||
for device in hass.data[DOMAIN].xknx.devices:
|
||||
|
@ -33,8 +46,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
class KNXClimate(KnxEntity, ClimateEntity):
|
||||
"""Representation of a KNX climate device."""
|
||||
|
||||
def __init__(self, device: XknxClimate):
|
||||
def __init__(self, device: XknxClimate) -> None:
|
||||
"""Initialize of a KNX climate device."""
|
||||
self._device: XknxClimate
|
||||
super().__init__(device)
|
||||
|
||||
self._unit_of_measurement = TEMP_CELSIUS
|
||||
|
@ -44,42 +58,45 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
"""Return the list of supported features."""
|
||||
return SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
|
||||
|
||||
async def async_update(self):
|
||||
async def async_update(self) -> None:
|
||||
"""Request a state update from KNX bus."""
|
||||
await self._device.sync()
|
||||
await self._device.mode.sync()
|
||||
if self._device.mode is not None:
|
||||
await self._device.mode.sync()
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
def temperature_unit(self) -> str:
|
||||
"""Return the unit of measurement."""
|
||||
return self._unit_of_measurement
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
return self._device.temperature.value
|
||||
return self._device.temperature.value # type: ignore[no-any-return]
|
||||
|
||||
@property
|
||||
def target_temperature_step(self):
|
||||
def target_temperature_step(self) -> float:
|
||||
"""Return the supported step of target temperature."""
|
||||
return self._device.temperature_step
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._device.target_temperature.value
|
||||
return self._device.target_temperature.value # type: ignore[no-any-return]
|
||||
|
||||
@property
|
||||
def min_temp(self):
|
||||
def min_temp(self) -> float:
|
||||
"""Return the minimum temperature."""
|
||||
return self._device.target_temperature_min
|
||||
temp = self._device.target_temperature_min
|
||||
return temp if temp is not None else super().min_temp
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
def max_temp(self) -> float:
|
||||
"""Return the maximum temperature."""
|
||||
return self._device.target_temperature_max
|
||||
temp = self._device.target_temperature_max
|
||||
return temp if temp is not None else super().max_temp
|
||||
|
||||
async def async_set_temperature(self, **kwargs) -> None:
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
temperature = kwargs.get(ATTR_TEMPERATURE)
|
||||
if temperature is None:
|
||||
|
@ -88,11 +105,11 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def hvac_mode(self) -> str | None:
|
||||
def hvac_mode(self) -> str:
|
||||
"""Return current operation ie. heat, cool, idle."""
|
||||
if self._device.supports_on_off and not self._device.is_on:
|
||||
return HVAC_MODE_OFF
|
||||
if self._device.mode.supports_controller_mode:
|
||||
if self._device.mode is not None and self._device.mode.supports_controller_mode:
|
||||
return CONTROLLER_MODES.get(
|
||||
self._device.mode.controller_mode.value, HVAC_MODE_HEAT
|
||||
)
|
||||
|
@ -100,21 +117,23 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
return HVAC_MODE_HEAT
|
||||
|
||||
@property
|
||||
def hvac_modes(self) -> list[str] | None:
|
||||
def hvac_modes(self) -> list[str]:
|
||||
"""Return the list of available operation/controller modes."""
|
||||
_controller_modes = [
|
||||
CONTROLLER_MODES.get(controller_mode.value)
|
||||
for controller_mode in self._device.mode.controller_modes
|
||||
]
|
||||
ha_controller_modes: list[str | None] = []
|
||||
if self._device.mode is not None:
|
||||
for knx_controller_mode in self._device.mode.controller_modes:
|
||||
ha_controller_modes.append(
|
||||
CONTROLLER_MODES.get(knx_controller_mode.value)
|
||||
)
|
||||
|
||||
if self._device.supports_on_off:
|
||||
if not _controller_modes:
|
||||
_controller_modes.append(HVAC_MODE_HEAT)
|
||||
_controller_modes.append(HVAC_MODE_OFF)
|
||||
if not ha_controller_modes:
|
||||
ha_controller_modes.append(HVAC_MODE_HEAT)
|
||||
ha_controller_modes.append(HVAC_MODE_OFF)
|
||||
|
||||
_modes = list(set(filter(None, _controller_modes)))
|
||||
hvac_modes = list(set(filter(None, ha_controller_modes)))
|
||||
# default to ["heat"]
|
||||
return _modes if _modes else [HVAC_MODE_HEAT]
|
||||
return hvac_modes if hvac_modes else [HVAC_MODE_HEAT]
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||
"""Set operation mode."""
|
||||
|
@ -123,7 +142,10 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
else:
|
||||
if self._device.supports_on_off and not self._device.is_on:
|
||||
await self._device.turn_on()
|
||||
if self._device.mode.supports_controller_mode:
|
||||
if (
|
||||
self._device.mode is not None
|
||||
and self._device.mode.supports_controller_mode
|
||||
):
|
||||
knx_controller_mode = HVACControllerMode(
|
||||
CONTROLLER_MODES_INV.get(hvac_mode)
|
||||
)
|
||||
|
@ -136,7 +158,7 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
|
||||
Requires SUPPORT_PRESET_MODE.
|
||||
"""
|
||||
if self._device.mode.supports_operation_mode:
|
||||
if self._device.mode is not None and self._device.mode.supports_operation_mode:
|
||||
return PRESET_MODES.get(self._device.mode.operation_mode.value, PRESET_AWAY)
|
||||
return None
|
||||
|
||||
|
@ -146,16 +168,18 @@ class KNXClimate(KnxEntity, ClimateEntity):
|
|||
|
||||
Requires SUPPORT_PRESET_MODE.
|
||||
"""
|
||||
_presets = [
|
||||
if self._device.mode is None:
|
||||
return None
|
||||
|
||||
presets = [
|
||||
PRESET_MODES.get(operation_mode.value)
|
||||
for operation_mode in self._device.mode.operation_modes
|
||||
]
|
||||
|
||||
return list(filter(None, _presets))
|
||||
return list(filter(None, presets))
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set new preset mode."""
|
||||
if self._device.mode.supports_operation_mode:
|
||||
if self._device.mode is not None and self._device.mode.supports_operation_mode:
|
||||
knx_operation_mode = HVACOperationMode(PRESET_MODES_INV.get(preset_mode))
|
||||
await self._device.mode.set_operation_mode(knx_operation_mode)
|
||||
self.async_write_ha_state()
|
||||
|
|
Loading…
Reference in New Issue