mirror of
https://github.com/home-assistant/core.git
synced 2025-08-05 05:35:11 +02:00
Add support for multiple devices linked to a Viessmann account (#96044)
* care about all devices
* use first device for diagnostics
* update constants
* handle multiple devices
* handle multiple devices
* handle multiple devices
* handle multiple devices
* handle multiple devices
* code style
* code style
* code style
* code style
* code style
* remove unused import
* remove unused import
* use has_entity_name and add serial to device name
* use has_entity_name and add serial to device name
* use has_entity_name and add serial to device name
* use has_entity_name and add serial to device name
* use has_entity_name and add serial to device name
* remove unused constant
* Update const.py
* Update binary_sensor.py
* change format
* change format
* fix line duplication
* fix line duplication
* change format
* fix typo
* use serial in device name if multiple devices are found
* add common base class
* use base class
* Update __init__.py
* Update __init__.py
* Update __init__.py
* Update sensor.py
* Update binary_sensor.py
* correct import
* use base class
* fix cdestyle findings
* fix pylint findings
* fix mypy findings
* fix codestyle finidings
* move has_entity_name to base class
* Revert "fix mypy findings"
This reverts commit 2d78801a69
.
* fix type issue
* move multiple device handling
* fix import
* remove special handling for device name
* extract api getter
* Update __init__.py
* Update __init__.py
* Update entity.py
* Update button.py
* Update binary_sensor.py
* Update climate.py
* Update sensor.py
* Update water_heater.py
* Apply suggestions from code review
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
* Update __init__.py
* fix mypy & black
* move get_device to utils
* rename const
* Apply suggestions from code review
Co-authored-by: Robert Resch <robert@resch.dev>
* store device in config entry
* extract types
* fix diagnostics
* handle new platform
* handle api rate limit
* add types
* add types
* rename
* add types
* ignore gateways for now
* Update .coveragerc
* adjust types
* fix merge issues
* rename
* Update types.py
* fix type
* add test method
* simplify
* ignore unused devices
* Apply suggestions from code review
Co-authored-by: Robert Resch <robert@resch.dev>
* fix findings
* handle unsupported devices
* Apply suggestions from code review
Co-authored-by: Robert Resch <robert@resch.dev>
* Update types.py
* fix format
* adjust variable naming
* Update conftest.py
* Update conftest.py
* remove kw_only
* Apply suggestions from code review
* Update __init__.py
* Update binary_sensor.py
* Update button.py
* Update climate.py
* Update const.py
* Update diagnostics.py
* Update number.py
* Update sensor.py
* Update types.py
* Update water_heater.py
* fix comment
* Apply suggestions from code review
Co-authored-by: Erik Montnemery <erik@montnemery.com>
---------
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
committed by
GitHub
parent
fd0f093299
commit
47cbe8f00c
@@ -1535,6 +1535,7 @@ omit =
|
|||||||
homeassistant/components/vicare/entity.py
|
homeassistant/components/vicare/entity.py
|
||||||
homeassistant/components/vicare/number.py
|
homeassistant/components/vicare/number.py
|
||||||
homeassistant/components/vicare/sensor.py
|
homeassistant/components/vicare/sensor.py
|
||||||
|
homeassistant/components/vicare/types.py
|
||||||
homeassistant/components/vicare/utils.py
|
homeassistant/components/vicare/utils.py
|
||||||
homeassistant/components/vicare/water_heater.py
|
homeassistant/components/vicare/water_heater.py
|
||||||
homeassistant/components/vilfo/__init__.py
|
homeassistant/components/vilfo/__init__.py
|
||||||
|
@@ -1,15 +1,13 @@
|
|||||||
"""The ViCare integration."""
|
"""The ViCare integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable, Mapping
|
from collections.abc import Mapping
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from dataclasses import dataclass
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from PyViCare.PyViCare import PyViCare
|
from PyViCare.PyViCare import PyViCare
|
||||||
from PyViCare.PyViCareDevice import Device
|
|
||||||
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
|
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
|
||||||
from PyViCare.PyViCareUtils import (
|
from PyViCare.PyViCareUtils import (
|
||||||
PyViCareInvalidConfigurationError,
|
PyViCareInvalidConfigurationError,
|
||||||
@@ -22,36 +20,14 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||||
from homeassistant.helpers.storage import STORAGE_DIR
|
from homeassistant.helpers.storage import STORAGE_DIR
|
||||||
|
|
||||||
from .const import (
|
from .const import DEFAULT_CACHE_DURATION, DEVICE_LIST, DOMAIN, PLATFORMS
|
||||||
CONF_HEATING_TYPE,
|
from .types import ViCareDevice
|
||||||
DEFAULT_SCAN_INTERVAL,
|
from .utils import get_device
|
||||||
DOMAIN,
|
|
||||||
HEATING_TYPE_TO_CREATOR_METHOD,
|
|
||||||
PLATFORMS,
|
|
||||||
VICARE_API,
|
|
||||||
VICARE_DEVICE_CONFIG,
|
|
||||||
VICARE_DEVICE_CONFIG_LIST,
|
|
||||||
HeatingType,
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_TOKEN_FILENAME = "vicare_token.save"
|
_TOKEN_FILENAME = "vicare_token.save"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class ViCareRequiredKeysMixin:
|
|
||||||
"""Mixin for required keys."""
|
|
||||||
|
|
||||||
value_getter: Callable[[Device], Any]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class ViCareRequiredKeysMixinWithSet(ViCareRequiredKeysMixin):
|
|
||||||
"""Mixin for required keys with setter."""
|
|
||||||
|
|
||||||
value_setter: Callable[[Device], bool]
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up from config entry."""
|
"""Set up from config entry."""
|
||||||
_LOGGER.debug("Setting up ViCare component")
|
_LOGGER.debug("Setting up ViCare component")
|
||||||
@@ -69,10 +45,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def vicare_login(hass: HomeAssistant, entry_data: Mapping[str, Any]) -> PyViCare:
|
def vicare_login(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry_data: Mapping[str, Any],
|
||||||
|
cache_duration=DEFAULT_CACHE_DURATION,
|
||||||
|
) -> PyViCare:
|
||||||
"""Login via PyVicare API."""
|
"""Login via PyVicare API."""
|
||||||
vicare_api = PyViCare()
|
vicare_api = PyViCare()
|
||||||
vicare_api.setCacheDuration(DEFAULT_SCAN_INTERVAL)
|
vicare_api.setCacheDuration(cache_duration)
|
||||||
vicare_api.initWithCredentials(
|
vicare_api.initWithCredentials(
|
||||||
entry_data[CONF_USERNAME],
|
entry_data[CONF_USERNAME],
|
||||||
entry_data[CONF_PASSWORD],
|
entry_data[CONF_PASSWORD],
|
||||||
@@ -87,20 +67,25 @@ def setup_vicare_api(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|||||||
vicare_api = vicare_login(hass, entry.data)
|
vicare_api = vicare_login(hass, entry.data)
|
||||||
|
|
||||||
device_config_list = get_supported_devices(vicare_api.devices)
|
device_config_list = get_supported_devices(vicare_api.devices)
|
||||||
|
if (number_of_devices := len(device_config_list)) > 1:
|
||||||
|
cache_duration = DEFAULT_CACHE_DURATION * number_of_devices
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Found %s devices, adjusting cache duration to %s",
|
||||||
|
number_of_devices,
|
||||||
|
cache_duration,
|
||||||
|
)
|
||||||
|
vicare_api = vicare_login(hass, entry.data, cache_duration)
|
||||||
|
device_config_list = get_supported_devices(vicare_api.devices)
|
||||||
|
|
||||||
for device in device_config_list:
|
for device in device_config_list:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Found device: %s (online: %s)", device.getModel(), str(device.isOnline())
|
"Found device: %s (online: %s)", device.getModel(), str(device.isOnline())
|
||||||
)
|
)
|
||||||
|
|
||||||
# Currently we only support a single device
|
hass.data[DOMAIN][entry.entry_id][DEVICE_LIST] = [
|
||||||
device = device_config_list[0]
|
ViCareDevice(config=device_config, api=get_device(entry, device_config))
|
||||||
hass.data[DOMAIN][entry.entry_id][VICARE_DEVICE_CONFIG_LIST] = device_config_list
|
for device_config in device_config_list
|
||||||
hass.data[DOMAIN][entry.entry_id][VICARE_DEVICE_CONFIG] = device
|
]
|
||||||
hass.data[DOMAIN][entry.entry_id][VICARE_API] = getattr(
|
|
||||||
device,
|
|
||||||
HEATING_TYPE_TO_CREATOR_METHOD[HeatingType(entry.data[CONF_HEATING_TYPE])],
|
|
||||||
)()
|
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@@ -27,9 +27,9 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import ViCareRequiredKeysMixin
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG
|
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice, ViCareRequiredKeysMixin
|
||||||
from .utils import get_burners, get_circuits, get_compressors, is_supported
|
from .utils import get_burners, get_circuits, get_compressors, is_supported
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -111,29 +111,28 @@ GLOBAL_SENSORS: tuple[ViCareBinarySensorEntityDescription, ...] = (
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
device: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareBinarySensor]:
|
) -> list[ViCareBinarySensor]:
|
||||||
"""Create ViCare binary sensor entities for a device."""
|
"""Create ViCare binary sensor entities for a device."""
|
||||||
|
|
||||||
entities: list[ViCareBinarySensor] = _build_entities_for_device(
|
entities: list[ViCareBinarySensor] = []
|
||||||
device, device_config
|
for device in device_list:
|
||||||
)
|
entities.extend(_build_entities_for_device(device.api, device.config))
|
||||||
entities.extend(
|
entities.extend(
|
||||||
_build_entities_for_component(
|
_build_entities_for_component(
|
||||||
get_circuits(device), device_config, CIRCUIT_SENSORS
|
get_circuits(device.api), device.config, CIRCUIT_SENSORS
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
entities.extend(
|
||||||
entities.extend(
|
_build_entities_for_component(
|
||||||
_build_entities_for_component(
|
get_burners(device.api), device.config, BURNER_SENSORS
|
||||||
get_burners(device), device_config, BURNER_SENSORS
|
)
|
||||||
)
|
)
|
||||||
)
|
entities.extend(
|
||||||
entities.extend(
|
_build_entities_for_component(
|
||||||
_build_entities_for_component(
|
get_compressors(device.api), device.config, COMPRESSOR_SENSORS
|
||||||
get_compressors(device), device_config, COMPRESSOR_SENSORS
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
|
|
||||||
@@ -179,14 +178,12 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create the ViCare binary sensor devices."""
|
"""Create the ViCare binary sensor devices."""
|
||||||
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
|
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -20,9 +20,9 @@ from homeassistant.const import EntityCategory
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import ViCareRequiredKeysMixinWithSet
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG
|
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice, ViCareRequiredKeysMixinWithSet
|
||||||
from .utils import is_supported
|
from .utils import is_supported
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -48,19 +48,19 @@ BUTTON_DESCRIPTIONS: tuple[ViCareButtonEntityDescription, ...] = (
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
api: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareButton]:
|
) -> list[ViCareButton]:
|
||||||
"""Create ViCare button entities for a device."""
|
"""Create ViCare button entities for a device."""
|
||||||
|
|
||||||
return [
|
return [
|
||||||
ViCareButton(
|
ViCareButton(
|
||||||
api,
|
device.api,
|
||||||
device_config,
|
device.config,
|
||||||
description,
|
description,
|
||||||
)
|
)
|
||||||
|
for device in device_list
|
||||||
for description in BUTTON_DESCRIPTIONS
|
for description in BUTTON_DESCRIPTIONS
|
||||||
if is_supported(description.key, description, api)
|
if is_supported(description.key, description, device.api)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -70,14 +70,12 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create the ViCare button entities."""
|
"""Create the ViCare button entities."""
|
||||||
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
|
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -40,8 +40,9 @@ from homeassistant.helpers import entity_platform
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice
|
||||||
from .utils import get_burners, get_circuits, get_compressors
|
from .utils import get_burners, get_circuits, get_compressors
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -99,18 +100,18 @@ HA_TO_VICARE_PRESET_HEATING = {
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
api: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareClimate]:
|
) -> list[ViCareClimate]:
|
||||||
"""Create ViCare climate entities for a device."""
|
"""Create ViCare climate entities for a device."""
|
||||||
return [
|
return [
|
||||||
ViCareClimate(
|
ViCareClimate(
|
||||||
api,
|
device.api,
|
||||||
circuit,
|
circuit,
|
||||||
device_config,
|
device.config,
|
||||||
"heating",
|
"heating",
|
||||||
)
|
)
|
||||||
for circuit in get_circuits(api)
|
for device in device_list
|
||||||
|
for circuit in get_circuits(device.api)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -120,8 +121,6 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the ViCare climate platform."""
|
"""Set up the ViCare climate platform."""
|
||||||
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
|
||||||
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
|
|
||||||
|
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
|
||||||
@@ -131,11 +130,12 @@ async def async_setup_entry(
|
|||||||
"set_vicare_mode",
|
"set_vicare_mode",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -14,15 +14,13 @@ PLATFORMS = [
|
|||||||
Platform.WATER_HEATER,
|
Platform.WATER_HEATER,
|
||||||
]
|
]
|
||||||
|
|
||||||
VICARE_DEVICE_CONFIG = "device_conf"
|
DEVICE_LIST = "device_list"
|
||||||
VICARE_DEVICE_CONFIG_LIST = "device_config_list"
|
|
||||||
VICARE_API = "api"
|
|
||||||
VICARE_NAME = "ViCare"
|
VICARE_NAME = "ViCare"
|
||||||
|
|
||||||
CONF_CIRCUIT = "circuit"
|
CONF_CIRCUIT = "circuit"
|
||||||
CONF_HEATING_TYPE = "heating_type"
|
CONF_HEATING_TYPE = "heating_type"
|
||||||
|
|
||||||
DEFAULT_SCAN_INTERVAL = 60
|
DEFAULT_CACHE_DURATION = 60
|
||||||
|
|
||||||
VICARE_CUBIC_METER = "cubicMeter"
|
VICARE_CUBIC_METER = "cubicMeter"
|
||||||
VICARE_KWH = "kilowattHour"
|
VICARE_KWH = "kilowattHour"
|
||||||
|
@@ -9,7 +9,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_CLIENT_ID, CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .const import DOMAIN, VICARE_DEVICE_CONFIG_LIST
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
|
|
||||||
TO_REDACT = {CONF_CLIENT_ID, CONF_PASSWORD, CONF_USERNAME}
|
TO_REDACT = {CONF_CLIENT_ID, CONF_PASSWORD, CONF_USERNAME}
|
||||||
|
|
||||||
@@ -18,10 +18,11 @@ async def async_get_config_entry_diagnostics(
|
|||||||
hass: HomeAssistant, entry: ConfigEntry
|
hass: HomeAssistant, entry: ConfigEntry
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Return diagnostics for a config entry."""
|
"""Return diagnostics for a config entry."""
|
||||||
# Currently we only support a single device
|
|
||||||
data = []
|
data = []
|
||||||
for device in hass.data[DOMAIN][entry.entry_id][VICARE_DEVICE_CONFIG_LIST]:
|
for device in hass.data[DOMAIN][entry.entry_id][DEVICE_LIST]:
|
||||||
data.append(json.loads(await hass.async_add_executor_job(device.dump_secure)))
|
data.append(
|
||||||
|
json.loads(await hass.async_add_executor_job(device.config.dump_secure))
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
|
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
|
||||||
"data": data,
|
"data": data,
|
||||||
|
@@ -29,9 +29,9 @@ from homeassistant.const import EntityCategory, UnitOfTemperature
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import ViCareRequiredKeysMixin
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG
|
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice, ViCareRequiredKeysMixin
|
||||||
from .utils import get_circuits, is_supported
|
from .utils import get_circuits, is_supported
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -123,18 +123,18 @@ CIRCUIT_ENTITY_DESCRIPTIONS: tuple[ViCareNumberEntityDescription, ...] = (
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
api: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareNumber]:
|
) -> list[ViCareNumber]:
|
||||||
"""Create ViCare number entities for a component."""
|
"""Create ViCare number entities for a device."""
|
||||||
|
|
||||||
return [
|
return [
|
||||||
ViCareNumber(
|
ViCareNumber(
|
||||||
circuit,
|
circuit,
|
||||||
device_config,
|
device.config,
|
||||||
description,
|
description,
|
||||||
)
|
)
|
||||||
for circuit in get_circuits(api)
|
for device in device_list
|
||||||
|
for circuit in get_circuits(device.api)
|
||||||
for description in CIRCUIT_ENTITY_DESCRIPTIONS
|
for description in CIRCUIT_ENTITY_DESCRIPTIONS
|
||||||
if is_supported(description.key, description, circuit)
|
if is_supported(description.key, description, circuit)
|
||||||
]
|
]
|
||||||
@@ -146,14 +146,12 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create the ViCare number devices."""
|
"""Create the ViCare number devices."""
|
||||||
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
|
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -38,16 +38,15 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import ViCareRequiredKeysMixin
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
DEVICE_LIST,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
VICARE_API,
|
|
||||||
VICARE_CUBIC_METER,
|
VICARE_CUBIC_METER,
|
||||||
VICARE_DEVICE_CONFIG,
|
|
||||||
VICARE_KWH,
|
VICARE_KWH,
|
||||||
VICARE_UNIT_TO_UNIT_OF_MEASUREMENT,
|
VICARE_UNIT_TO_UNIT_OF_MEASUREMENT,
|
||||||
)
|
)
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice, ViCareRequiredKeysMixin
|
||||||
from .utils import get_burners, get_circuits, get_compressors, is_supported
|
from .utils import get_burners, get_circuits, get_compressors, is_supported
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -693,27 +692,28 @@ COMPRESSOR_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
device: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareSensor]:
|
) -> list[ViCareSensor]:
|
||||||
"""Create ViCare sensor entities for a device."""
|
"""Create ViCare sensor entities for a device."""
|
||||||
|
|
||||||
entities: list[ViCareSensor] = _build_entities_for_device(device, device_config)
|
entities: list[ViCareSensor] = []
|
||||||
entities.extend(
|
for device in device_list:
|
||||||
_build_entities_for_component(
|
entities.extend(_build_entities_for_device(device.api, device.config))
|
||||||
get_circuits(device), device_config, CIRCUIT_SENSORS
|
entities.extend(
|
||||||
|
_build_entities_for_component(
|
||||||
|
get_circuits(device.api), device.config, CIRCUIT_SENSORS
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
entities.extend(
|
||||||
entities.extend(
|
_build_entities_for_component(
|
||||||
_build_entities_for_component(
|
get_burners(device.api), device.config, BURNER_SENSORS
|
||||||
get_burners(device), device_config, BURNER_SENSORS
|
)
|
||||||
)
|
)
|
||||||
)
|
entities.extend(
|
||||||
entities.extend(
|
_build_entities_for_component(
|
||||||
_build_entities_for_component(
|
get_compressors(device.api), device.config, COMPRESSOR_SENSORS
|
||||||
get_compressors(device), device_config, COMPRESSOR_SENSORS
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
|
|
||||||
@@ -759,16 +759,12 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create the ViCare sensor devices."""
|
"""Create the ViCare sensor devices."""
|
||||||
api: PyViCareDevice = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
device_config: PyViCareDeviceConfig = hass.data[DOMAIN][config_entry.entry_id][
|
|
||||||
VICARE_DEVICE_CONFIG
|
|
||||||
]
|
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
29
homeassistant/components/vicare/types.py
Normal file
29
homeassistant/components/vicare/types.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
"""Types for the ViCare integration."""
|
||||||
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from PyViCare.PyViCareDevice import Device as PyViCareDevice
|
||||||
|
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ViCareDevice:
|
||||||
|
"""Dataclass holding the device api and config."""
|
||||||
|
|
||||||
|
config: PyViCareDeviceConfig
|
||||||
|
api: PyViCareDevice
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ViCareRequiredKeysMixin:
|
||||||
|
"""Mixin for required keys."""
|
||||||
|
|
||||||
|
value_getter: Callable[[PyViCareDevice], Any]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ViCareRequiredKeysMixinWithSet(ViCareRequiredKeysMixin):
|
||||||
|
"""Mixin for required keys with setter."""
|
||||||
|
|
||||||
|
value_setter: Callable[[PyViCareDevice], bool]
|
@@ -2,16 +2,30 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyViCare.PyViCareDevice import Device as PyViCareDevice
|
from PyViCare.PyViCareDevice import Device as PyViCareDevice
|
||||||
|
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
|
||||||
from PyViCare.PyViCareHeatingDevice import (
|
from PyViCare.PyViCareHeatingDevice import (
|
||||||
HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent,
|
HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent,
|
||||||
)
|
)
|
||||||
from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError
|
from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError
|
||||||
|
|
||||||
from . import ViCareRequiredKeysMixin
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
|
||||||
|
from .const import CONF_HEATING_TYPE, HEATING_TYPE_TO_CREATOR_METHOD, HeatingType
|
||||||
|
from .types import ViCareRequiredKeysMixin
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_device(
|
||||||
|
entry: ConfigEntry, device_config: PyViCareDeviceConfig
|
||||||
|
) -> PyViCareDevice:
|
||||||
|
"""Get device for device config."""
|
||||||
|
return getattr(
|
||||||
|
device_config,
|
||||||
|
HEATING_TYPE_TO_CREATOR_METHOD[HeatingType(entry.data[CONF_HEATING_TYPE])],
|
||||||
|
)()
|
||||||
|
|
||||||
|
|
||||||
def is_supported(
|
def is_supported(
|
||||||
name: str,
|
name: str,
|
||||||
entity_description: ViCareRequiredKeysMixin,
|
entity_description: ViCareRequiredKeysMixin,
|
||||||
|
@@ -24,8 +24,9 @@ from homeassistant.const import ATTR_TEMPERATURE, PRECISION_TENTHS, UnitOfTemper
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG
|
from .const import DEVICE_LIST, DOMAIN
|
||||||
from .entity import ViCareEntity
|
from .entity import ViCareEntity
|
||||||
|
from .types import ViCareDevice
|
||||||
from .utils import get_circuits
|
from .utils import get_circuits
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@@ -61,18 +62,19 @@ HA_TO_VICARE_HVAC_DHW = {
|
|||||||
|
|
||||||
|
|
||||||
def _build_entities(
|
def _build_entities(
|
||||||
api: PyViCareDevice,
|
device_list: list[ViCareDevice],
|
||||||
device_config: PyViCareDeviceConfig,
|
|
||||||
) -> list[ViCareWater]:
|
) -> list[ViCareWater]:
|
||||||
"""Create ViCare domestic hot water entities for a device."""
|
"""Create ViCare domestic hot water entities for a device."""
|
||||||
|
|
||||||
return [
|
return [
|
||||||
ViCareWater(
|
ViCareWater(
|
||||||
api,
|
device.api,
|
||||||
circuit,
|
circuit,
|
||||||
device_config,
|
device.config,
|
||||||
"domestic_hot_water",
|
"domestic_hot_water",
|
||||||
)
|
)
|
||||||
for circuit in get_circuits(api)
|
for device in device_list
|
||||||
|
for circuit in get_circuits(device.api)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -82,14 +84,12 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the ViCare water heater platform."""
|
"""Set up the ViCare water heater platform."""
|
||||||
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
|
device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
|
||||||
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
|
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
_build_entities,
|
_build_entities,
|
||||||
api,
|
device_list,
|
||||||
device_config,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user