Optimize async executor use in ViCare integration (#104645)

* use one async executor

* use list comprehension

* simplify

* simplify

* simplify

* simplify

* simplify

* simplify

* simplify

* simplify

* add type

* Apply suggestions from code review

* fix ruff findings
pull/104694/head
Christopher Fenner 2023-11-29 09:28:56 +01:00 committed by GitHub
parent 2663a4d617
commit c4e3ae84f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 218 additions and 146 deletions

View File

@ -7,6 +7,9 @@ import logging
from PyViCare.PyViCareDevice import Device as PyViCareDevice
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
from PyViCare.PyViCareHeatingDevice import (
HeatingDeviceWithComponent as PyViCareHeatingDeviceWithComponent,
)
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
PyViCareNotSupportedFeatureError,
@ -104,39 +107,67 @@ GLOBAL_SENSORS: tuple[ViCareBinarySensorEntityDescription, ...] = (
)
def _build_entity(
vicare_api: PyViCareDevice,
def _build_entities(
device: PyViCareDevice,
device_config: PyViCareDeviceConfig,
entity_description: ViCareBinarySensorEntityDescription,
):
"""Create a ViCare binary sensor entity."""
if is_supported(entity_description.key, entity_description, vicare_api):
return ViCareBinarySensor(
vicare_api,
device_config,
entity_description,
) -> list[ViCareBinarySensor]:
"""Create ViCare binary sensor entities for a device."""
entities: list[ViCareBinarySensor] = _build_entities_for_device(
device, device_config
)
entities.extend(
_build_entities_for_component(
get_circuits(device), device_config, CIRCUIT_SENSORS
)
return None
)
entities.extend(
_build_entities_for_component(
get_burners(device), device_config, BURNER_SENSORS
)
)
entities.extend(
_build_entities_for_component(
get_compressors(device), device_config, COMPRESSOR_SENSORS
)
)
return entities
async def _entities_from_descriptions(
hass: HomeAssistant,
entities: list[ViCareBinarySensor],
sensor_descriptions: tuple[ViCareBinarySensorEntityDescription, ...],
iterables,
config_entry: ConfigEntry,
) -> None:
"""Create entities from descriptions and list of burners/circuits."""
for description in sensor_descriptions:
for current in iterables:
entity = await hass.async_add_executor_job(
_build_entity,
current,
hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG],
description,
)
if entity:
entities.append(entity)
def _build_entities_for_device(
device: PyViCareDevice,
device_config: PyViCareDeviceConfig,
) -> list[ViCareBinarySensor]:
"""Create device specific ViCare binary sensor entities."""
return [
ViCareBinarySensor(
device,
device_config,
description,
)
for description in GLOBAL_SENSORS
if is_supported(description.key, description, device)
]
def _build_entities_for_component(
components: list[PyViCareHeatingDeviceWithComponent],
device_config: PyViCareDeviceConfig,
entity_descriptions: tuple[ViCareBinarySensorEntityDescription, ...],
) -> list[ViCareBinarySensor]:
"""Create component specific ViCare binary sensor entities."""
return [
ViCareBinarySensor(
component,
device_config,
description,
)
for component in components
for description in entity_descriptions
if is_supported(description.key, description, component)
]
async def async_setup_entry(
@ -146,36 +177,16 @@ async def async_setup_entry(
) -> None:
"""Create the ViCare binary sensor devices."""
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
entities = []
for description in GLOBAL_SENSORS:
entity = await hass.async_add_executor_job(
_build_entity,
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG],
description,
device_config,
)
if entity:
entities.append(entity)
circuits = await hass.async_add_executor_job(get_circuits, api)
await _entities_from_descriptions(
hass, entities, CIRCUIT_SENSORS, circuits, config_entry
)
burners = await hass.async_add_executor_job(get_burners, api)
await _entities_from_descriptions(
hass, entities, BURNER_SENSORS, burners, config_entry
)
compressors = await hass.async_add_executor_job(get_compressors, api)
await _entities_from_descriptions(
hass, entities, COMPRESSOR_SENSORS, compressors, config_entry
)
async_add_entities(entities)
class ViCareBinarySensor(ViCareEntity, BinarySensorEntity):
"""Representation of a ViCare sensor."""

View File

@ -47,19 +47,21 @@ BUTTON_DESCRIPTIONS: tuple[ViCareButtonEntityDescription, ...] = (
)
def _build_entity(
vicare_api: PyViCareDevice,
def _build_entities(
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
entity_description: ViCareButtonEntityDescription,
):
"""Create a ViCare button entity."""
if is_supported(entity_description.key, entity_description, vicare_api):
return ViCareButton(
vicare_api,
) -> list[ViCareButton]:
"""Create ViCare button entities for a device."""
return [
ViCareButton(
api,
device_config,
entity_description,
description,
)
return None
for description in BUTTON_DESCRIPTIONS
if is_supported(description.key, description, api)
]
async def async_setup_entry(
@ -69,20 +71,15 @@ async def async_setup_entry(
) -> None:
"""Create the ViCare button entities."""
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
entities = []
for description in BUTTON_DESCRIPTIONS:
entity = await hass.async_add_executor_job(
_build_entity,
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG],
description,
device_config,
)
if entity:
entities.append(entity)
async_add_entities(entities)
)
class ViCareButton(ViCareEntity, ButtonEntity):

View File

@ -95,25 +95,30 @@ HA_TO_VICARE_PRESET_HEATING = {
}
def _build_entities(
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
) -> list[ViCareClimate]:
"""Create ViCare climate entities for a device."""
return [
ViCareClimate(
api,
circuit,
device_config,
"heating",
)
for circuit in get_circuits(api)
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the ViCare climate platform."""
entities = []
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
circuits = await hass.async_add_executor_job(get_circuits, api)
for circuit in circuits:
entity = ViCareClimate(
api,
circuit,
device_config,
"heating",
)
entities.append(entity)
platform = entity_platform.async_get_current_platform()
@ -123,7 +128,13 @@ async def async_setup_entry(
"set_vicare_mode",
)
async_add_entities(entities)
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
device_config,
)
)
class ViCareClimate(ViCareEntity, ClimateEntity):

View File

@ -80,19 +80,22 @@ CIRCUIT_ENTITY_DESCRIPTIONS: tuple[ViCareNumberEntityDescription, ...] = (
)
def _build_entity(
vicare_api: PyViCareHeatingDeviceComponent,
def _build_entities(
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
entity_description: ViCareNumberEntityDescription,
) -> ViCareNumber | None:
"""Create a ViCare number entity."""
if is_supported(entity_description.key, entity_description, vicare_api):
return ViCareNumber(
vicare_api,
) -> list[ViCareNumber]:
"""Create ViCare number entities for a component."""
return [
ViCareNumber(
circuit,
device_config,
entity_description,
description,
)
return None
for circuit in get_circuits(api)
for description in CIRCUIT_ENTITY_DESCRIPTIONS
if is_supported(description.key, description, circuit)
]
async def async_setup_entry(
@ -101,23 +104,16 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Create the ViCare number devices."""
entities: list[ViCareNumber] = []
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
circuits = await hass.async_add_executor_job(get_circuits, api)
for circuit in circuits:
for description in CIRCUIT_ENTITY_DESCRIPTIONS:
entity = await hass.async_add_executor_job(
_build_entity,
circuit,
device_config,
description,
)
if entity:
entities.append(entity)
async_add_entities(entities)
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
device_config,
)
)
class ViCareNumber(ViCareEntity, NumberEntity):

View File

@ -6,8 +6,11 @@ from contextlib import suppress
from dataclasses import dataclass
import logging
from PyViCare.PyViCareDevice import Device
from PyViCare.PyViCareDevice import Device as PyViCareDevice
from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
from PyViCare.PyViCareHeatingDevice import (
HeatingDeviceWithComponent as PyViCareHeatingDeviceWithComponent,
)
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
PyViCareNotSupportedFeatureError,
@ -59,7 +62,7 @@ VICARE_UNIT_TO_DEVICE_CLASS = {
class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysMixin):
"""Describes ViCare sensor entity."""
unit_getter: Callable[[Device], str | None] | None = None
unit_getter: Callable[[PyViCareDevice], str | None] | None = None
GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
@ -628,45 +631,86 @@ async def _entities_from_descriptions(
entities.append(entity)
def _build_entities(
device: PyViCareDevice,
device_config: PyViCareDeviceConfig,
) -> list[ViCareSensor]:
"""Create ViCare sensor entities for a device."""
entities: list[ViCareSensor] = _build_entities_for_device(device, device_config)
entities.extend(
_build_entities_for_component(
get_circuits(device), device_config, CIRCUIT_SENSORS
)
)
entities.extend(
_build_entities_for_component(
get_burners(device), device_config, BURNER_SENSORS
)
)
entities.extend(
_build_entities_for_component(
get_compressors(device), device_config, COMPRESSOR_SENSORS
)
)
return entities
def _build_entities_for_device(
device: PyViCareDevice,
device_config: PyViCareDeviceConfig,
) -> list[ViCareSensor]:
"""Create device specific ViCare sensor entities."""
return [
ViCareSensor(
device,
device_config,
description,
)
for description in GLOBAL_SENSORS
if is_supported(description.key, description, device)
]
def _build_entities_for_component(
components: list[PyViCareHeatingDeviceWithComponent],
device_config: PyViCareDeviceConfig,
entity_descriptions: tuple[ViCareSensorEntityDescription, ...],
) -> list[ViCareSensor]:
"""Create component specific ViCare sensor entities."""
return [
ViCareSensor(
component,
device_config,
description,
)
for component in components
for description in entity_descriptions
if is_supported(description.key, description, component)
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Create the ViCare sensor devices."""
api: Device = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
api: PyViCareDevice = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config: PyViCareDeviceConfig = hass.data[DOMAIN][config_entry.entry_id][
VICARE_DEVICE_CONFIG
]
entities = []
for description in GLOBAL_SENSORS:
entity = await hass.async_add_executor_job(
_build_entity,
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
device_config,
description,
)
if entity:
entities.append(entity)
circuits = await hass.async_add_executor_job(get_circuits, api)
await _entities_from_descriptions(
hass, entities, CIRCUIT_SENSORS, circuits, config_entry
)
burners = await hass.async_add_executor_job(get_burners, api)
await _entities_from_descriptions(
hass, entities, BURNER_SENSORS, burners, config_entry
)
compressors = await hass.async_add_executor_job(get_compressors, api)
await _entities_from_descriptions(
hass, entities, COMPRESSOR_SENSORS, compressors, config_entry
)
async_add_entities(entities)
class ViCareSensor(ViCareEntity, SensorEntity):
"""Representation of a ViCare sensor."""

View File

@ -1,4 +1,6 @@
"""Viessmann ViCare water_heater device."""
from __future__ import annotations
from contextlib import suppress
import logging
from typing import Any
@ -58,27 +60,38 @@ HA_TO_VICARE_HVAC_DHW = {
}
def _build_entities(
api: PyViCareDevice,
device_config: PyViCareDeviceConfig,
) -> list[ViCareWater]:
"""Create ViCare water entities for a device."""
return [
ViCareWater(
api,
circuit,
device_config,
"water",
)
for circuit in get_circuits(api)
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the ViCare climate platform."""
entities = []
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
device_config = hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG]
circuits = await hass.async_add_executor_job(get_circuits, api)
for circuit in circuits:
entity = ViCareWater(
async_add_entities(
await hass.async_add_executor_job(
_build_entities,
api,
circuit,
device_config,
"water",
)
entities.append(entity)
async_add_entities(entities)
)
class ViCareWater(ViCareEntity, WaterHeaterEntity):