Type check KNX integration climate (#48054)

pull/48317/head
Matthias Alphart 2021-03-25 09:47:49 +01:00 committed by GitHub
parent 21c72fa559
commit 6b2a2740f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 57 additions and 33 deletions

View File

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