Improve code quality for ViCare integration (#124613)

* move type to module

* set translation key outside of init

* align import alias

* align constructor parameter order/naming

* move static attr init outside init function

* add missing types

* fix test

* revert move of _attributes
This commit is contained in:
Christopher Fenner 2024-08-26 08:30:28 +02:00 committed by GitHub
parent bb6f9ec844
commit 0591b5e47b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 85 additions and 87 deletions

View file

@ -10,7 +10,7 @@ import logging
from PyViCare.PyViCareDevice import Device as PyViCareDevice
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
from PyViCare.PyViCareHeatingDevice import (
HeatingDeviceWithComponent as PyViCareHeatingDeviceWithComponent,
HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent,
)
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
@ -139,8 +139,8 @@ def _build_entities_for_device(
return [
ViCareBinarySensor(
device,
device_config,
device,
description,
)
for description in GLOBAL_SENSORS
@ -149,7 +149,7 @@ def _build_entities_for_device(
def _build_entities_for_component(
components: list[PyViCareHeatingDeviceWithComponent],
components: list[PyViCareHeatingDeviceComponent],
device_config: PyViCareDeviceConfig,
entity_descriptions: tuple[ViCareBinarySensorEntityDescription, ...],
) -> list[ViCareBinarySensor]:
@ -157,8 +157,8 @@ def _build_entities_for_component(
return [
ViCareBinarySensor(
component,
device_config,
component,
description,
)
for component in components
@ -190,8 +190,8 @@ class ViCareBinarySensor(ViCareEntity, BinarySensorEntity):
def __init__(
self,
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
api: PyViCareDevice | PyViCareHeatingDeviceComponent,
description: ViCareBinarySensorEntityDescription,
) -> None:
"""Initialize the sensor."""

View file

@ -54,8 +54,8 @@ def _build_entities(
return [
ViCareButton(
device.api,
device.config,
device.api,
description,
)
for device in device_list
@ -87,12 +87,12 @@ class ViCareButton(ViCareEntity, ButtonEntity):
def __init__(
self,
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
device: PyViCareDevice,
description: ViCareButtonEntityDescription,
) -> None:
"""Initialize the button."""
super().__init__(device_config, api, description.key)
super().__init__(device_config, device, description.key)
self.entity_description = description
def press(self) -> None:

View file

@ -87,10 +87,9 @@ def _build_entities(
"""Create ViCare climate entities for a device."""
return [
ViCareClimate(
device.config,
device.api,
circuit,
device.config,
"heating",
)
for device in device_list
for circuit in get_circuits(device.api)
@ -136,24 +135,22 @@ class ViCareClimate(ViCareEntity, ClimateEntity):
_attr_min_temp = VICARE_TEMP_HEATING_MIN
_attr_max_temp = VICARE_TEMP_HEATING_MAX
_attr_target_temperature_step = PRECISION_WHOLE
_attr_translation_key = "heating"
_current_action: bool | None = None
_current_mode: str | None = None
_current_program: str | None = None
_enable_turn_on_off_backwards_compatibility = False
def __init__(
self,
api: PyViCareDevice,
circuit: PyViCareHeatingCircuit,
device_config: PyViCareDeviceConfig,
translation_key: str,
device: PyViCareDevice,
circuit: PyViCareHeatingCircuit,
) -> None:
"""Initialize the climate device."""
super().__init__(device_config, api, circuit.id)
super().__init__(device_config, device, circuit.id)
self._circuit = circuit
self._attributes: dict[str, Any] = {}
self._current_program = None
self._attr_translation_key = translation_key
self._attributes["vicare_programs"] = self._circuit.getPrograms()
self._attr_preset_modes = [
preset
@ -340,7 +337,7 @@ class ViCareClimate(ViCareEntity, ClimateEntity):
) from err
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Show Device Attributes."""
return self._attributes

View file

@ -3,6 +3,7 @@
from __future__ import annotations
from contextlib import suppress
import enum
import logging
from PyViCare.PyViCareDevice import Device as PyViCareDevice
@ -28,10 +29,58 @@ from homeassistant.util.percentage import (
from .const import DEVICE_LIST, DOMAIN
from .entity import ViCareEntity
from .types import VentilationMode, VentilationProgram
_LOGGER = logging.getLogger(__name__)
class VentilationProgram(enum.StrEnum):
"""ViCare preset ventilation programs.
As listed in https://github.com/somm15/PyViCare/blob/6c5b023ca6c8bb2d38141dd1746dc1705ec84ce8/PyViCare/PyViCareVentilationDevice.py#L37
"""
LEVEL_ONE = "levelOne"
LEVEL_TWO = "levelTwo"
LEVEL_THREE = "levelThree"
LEVEL_FOUR = "levelFour"
class VentilationMode(enum.StrEnum):
"""ViCare ventilation modes."""
PERMANENT = "permanent" # on, speed controlled by program (levelOne-levelFour)
VENTILATION = "ventilation" # activated by schedule
SENSOR_DRIVEN = "sensor_driven" # activated by schedule, override by sensor
SENSOR_OVERRIDE = "sensor_override" # activated by sensor
@staticmethod
def to_vicare_mode(mode: str | None) -> str | None:
"""Return the mapped ViCare ventilation mode for the Home Assistant mode."""
if mode:
try:
ventilation_mode = VentilationMode(mode)
except ValueError:
# ignore unsupported / unmapped modes
return None
return HA_TO_VICARE_MODE_VENTILATION.get(ventilation_mode) if mode else None
return None
@staticmethod
def from_vicare_mode(vicare_mode: str | None) -> str | None:
"""Return the mapped Home Assistant mode for the ViCare ventilation mode."""
for mode in VentilationMode:
if HA_TO_VICARE_MODE_VENTILATION.get(VentilationMode(mode)) == vicare_mode:
return mode
return None
HA_TO_VICARE_MODE_VENTILATION = {
VentilationMode.PERMANENT: "permanent",
VentilationMode.VENTILATION: "ventilation",
VentilationMode.SENSOR_DRIVEN: "sensorDriven",
VentilationMode.SENSOR_OVERRIDE: "sensorOverride",
}
ORDERED_NAMED_FAN_SPEEDS = [
VentilationProgram.LEVEL_ONE,
VentilationProgram.LEVEL_TWO,

View file

@ -235,8 +235,8 @@ def _build_entities(
entities: list[ViCareNumber] = [
ViCareNumber(
device.api,
device.config,
device.api,
description,
)
for device in device_list
@ -247,8 +247,8 @@ def _build_entities(
entities.extend(
[
ViCareNumber(
circuit,
device.config,
circuit,
description,
)
for device in device_list
@ -283,8 +283,8 @@ class ViCareNumber(ViCareEntity, NumberEntity):
def __init__(
self,
api: PyViCareHeatingDeviceComponent,
device_config: PyViCareDeviceConfig,
api: PyViCareDevice | PyViCareHeatingDeviceComponent,
description: ViCareNumberEntityDescription,
) -> None:
"""Initialize the number."""

View file

@ -10,7 +10,7 @@ import logging
from PyViCare.PyViCareDevice import Device as PyViCareDevice
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
from PyViCare.PyViCareHeatingDevice import (
HeatingDeviceWithComponent as PyViCareHeatingDeviceWithComponent,
HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent,
)
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
@ -892,8 +892,8 @@ def _build_entities_for_device(
return [
ViCareSensor(
device,
device_config,
device,
description,
)
for description in GLOBAL_SENSORS
@ -902,7 +902,7 @@ def _build_entities_for_device(
def _build_entities_for_component(
components: list[PyViCareHeatingDeviceWithComponent],
components: list[PyViCareHeatingDeviceComponent],
device_config: PyViCareDeviceConfig,
entity_descriptions: tuple[ViCareSensorEntityDescription, ...],
) -> list[ViCareSensor]:
@ -910,8 +910,8 @@ def _build_entities_for_component(
return [
ViCareSensor(
component,
device_config,
component,
description,
)
for component in components
@ -943,8 +943,8 @@ class ViCareSensor(ViCareEntity, SensorEntity):
def __init__(
self,
api,
device_config: PyViCareDeviceConfig,
api: PyViCareDevice | PyViCareHeatingDeviceComponent,
description: ViCareSensorEntityDescription,
) -> None:
"""Initialize the sensor."""

View file

@ -64,55 +64,6 @@ VICARE_TO_HA_PRESET_HEATING = {
}
class VentilationMode(enum.StrEnum):
"""ViCare ventilation modes."""
PERMANENT = "permanent" # on, speed controlled by program (levelOne-levelFour)
VENTILATION = "ventilation" # activated by schedule
SENSOR_DRIVEN = "sensor_driven" # activated by schedule, override by sensor
SENSOR_OVERRIDE = "sensor_override" # activated by sensor
@staticmethod
def to_vicare_mode(mode: str | None) -> str | None:
"""Return the mapped ViCare ventilation mode for the Home Assistant mode."""
if mode:
try:
ventilation_mode = VentilationMode(mode)
except ValueError:
# ignore unsupported / unmapped modes
return None
return HA_TO_VICARE_MODE_VENTILATION.get(ventilation_mode) if mode else None
return None
@staticmethod
def from_vicare_mode(vicare_mode: str | None) -> str | None:
"""Return the mapped Home Assistant mode for the ViCare ventilation mode."""
for mode in VentilationMode:
if HA_TO_VICARE_MODE_VENTILATION.get(VentilationMode(mode)) == vicare_mode:
return mode
return None
HA_TO_VICARE_MODE_VENTILATION = {
VentilationMode.PERMANENT: "permanent",
VentilationMode.VENTILATION: "ventilation",
VentilationMode.SENSOR_DRIVEN: "sensorDriven",
VentilationMode.SENSOR_OVERRIDE: "sensorOverride",
}
class VentilationProgram(enum.StrEnum):
"""ViCare preset ventilation programs.
As listed in https://github.com/somm15/PyViCare/blob/6c5b023ca6c8bb2d38141dd1746dc1705ec84ce8/PyViCare/PyViCareVentilationDevice.py#L37
"""
LEVEL_ONE = "levelOne"
LEVEL_TWO = "levelTwo"
LEVEL_THREE = "levelThree"
LEVEL_FOUR = "levelFour"
@dataclass(frozen=True)
class ViCareDevice:
"""Dataclass holding the device api and config."""

View file

@ -69,10 +69,9 @@ def _build_entities(
return [
ViCareWater(
device.config,
device.api,
circuit,
device.config,
"domestic_hot_water",
)
for device in device_list
for circuit in get_circuits(device.api)
@ -104,20 +103,19 @@ class ViCareWater(ViCareEntity, WaterHeaterEntity):
_attr_min_temp = VICARE_TEMP_WATER_MIN
_attr_max_temp = VICARE_TEMP_WATER_MAX
_attr_operation_list = list(HA_TO_VICARE_HVAC_DHW)
_attr_translation_key = "domestic_hot_water"
_current_mode: str | None = None
def __init__(
self,
api: PyViCareDevice,
circuit: PyViCareHeatingCircuit,
device_config: PyViCareDeviceConfig,
translation_key: str,
device: PyViCareDevice,
circuit: PyViCareHeatingCircuit,
) -> None:
"""Initialize the DHW water_heater device."""
super().__init__(device_config, api, circuit.id)
super().__init__(device_config, device, circuit.id)
self._circuit = circuit
self._attributes: dict[str, Any] = {}
self._current_mode = None
self._attr_translation_key = translation_key
def update(self) -> None:
"""Let HA know there has been an update from the ViCare API."""
@ -151,6 +149,8 @@ class ViCareWater(ViCareEntity, WaterHeaterEntity):
self._attr_target_temperature = temp
@property
def current_operation(self):
def current_operation(self) -> str | None:
"""Return current operation ie. heat, cool, idle."""
return VICARE_TO_HA_HVAC_DHW.get(self._current_mode)
if self._current_mode is None:
return None
return VICARE_TO_HA_HVAC_DHW.get(self._current_mode, None)

View file

@ -3,7 +3,8 @@
import pytest
from homeassistant.components.climate import PRESET_COMFORT, PRESET_SLEEP
from homeassistant.components.vicare.types import HeatingProgram, VentilationMode
from homeassistant.components.vicare.fan import VentilationMode
from homeassistant.components.vicare.types import HeatingProgram
@pytest.mark.parametrize(