Migrate lcn to use runtime_data (#147333)

This commit is contained in:
epenet 2025-06-23 13:41:53 +02:00 committed by GitHub
parent 2bfb09cb11
commit d06da8c2da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 127 additions and 143 deletions

View File

@ -16,7 +16,6 @@ from pypck.connection import (
)
from pypck.lcn_defs import LcnEvent
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_DOMAIN,
@ -38,21 +37,20 @@ from homeassistant.helpers import (
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_ACKNOWLEDGE,
CONF_DIM_MODE,
CONF_DOMAIN_DATA,
CONF_SK_NUM_TRIES,
CONF_TARGET_VALUE_LOCKED,
CONF_TRANSITION,
CONNECTION,
DEVICE_CONNECTIONS,
DOMAIN,
PLATFORMS,
)
from .helpers import (
AddressType,
InputType,
LcnConfigEntry,
LcnRuntimeData,
async_update_config_entry,
generate_unique_id,
purge_device_registry,
@ -69,18 +67,14 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the LCN component."""
hass.data.setdefault(DOMAIN, {})
async_setup_services(hass)
await register_panel_and_ws_api(hass)
return True
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, config_entry: LcnConfigEntry) -> bool:
"""Set up a connection to PCHK host from a config entry."""
if config_entry.entry_id in hass.data[DOMAIN]:
return False
settings = {
"SK_NUM_TRIES": config_entry.data[CONF_SK_NUM_TRIES],
@ -114,11 +108,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
) from ex
_LOGGER.debug('LCN connected to "%s"', config_entry.title)
hass.data[DOMAIN][config_entry.entry_id] = {
CONNECTION: lcn_connection,
DEVICE_CONNECTIONS: {},
ADD_ENTITIES_CALLBACKS: {},
}
config_entry.runtime_data = LcnRuntimeData(
connection=lcn_connection,
device_connections={},
add_entities_callbacks={},
)
# Update config_entry with LCN device serials
await async_update_config_entry(hass, config_entry)
@ -146,7 +140,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
return True
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
async def async_migrate_entry(
hass: HomeAssistant, config_entry: LcnConfigEntry
) -> bool:
"""Migrate old entry."""
_LOGGER.debug(
"Migrating configuration from version %s.%s",
@ -195,7 +191,7 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
async def async_migrate_entities(
hass: HomeAssistant, config_entry: ConfigEntry
hass: HomeAssistant, config_entry: LcnConfigEntry
) -> None:
"""Migrate entity registry."""
@ -217,25 +213,24 @@ async def async_migrate_entities(
await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id)
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, config_entry: LcnConfigEntry) -> bool:
"""Close connection to PCHK host represented by config_entry."""
# forward unloading to platforms
unload_ok = await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS
)
if unload_ok and config_entry.entry_id in hass.data[DOMAIN]:
host = hass.data[DOMAIN].pop(config_entry.entry_id)
await host[CONNECTION].async_close()
if unload_ok:
await config_entry.runtime_data.connection.async_close()
return unload_ok
def async_host_event_received(
hass: HomeAssistant, config_entry: ConfigEntry, event: pypck.lcn_defs.LcnEvent
hass: HomeAssistant, config_entry: LcnConfigEntry, event: pypck.lcn_defs.LcnEvent
) -> None:
"""Process received event from LCN."""
lcn_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
lcn_connection = config_entry.runtime_data.connection
async def reload_config_entry() -> None:
"""Close connection and schedule config entry for reload."""
@ -258,7 +253,7 @@ def async_host_event_received(
def async_host_input_received(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
device_registry: dr.DeviceRegistry,
inp: pypck.inputs.Input,
) -> None:
@ -266,7 +261,7 @@ def async_host_input_received(
if not isinstance(inp, pypck.inputs.ModInput):
return
lcn_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
lcn_connection = config_entry.runtime_data.connection
logical_address = lcn_connection.physical_to_logical(inp.physical_source_addr)
address = (
logical_address.seg_id,

View File

@ -11,7 +11,6 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntity,
)
from homeassistant.components.script import scripts_with_entity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DOMAIN, CONF_ENTITIES, CONF_SOURCE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@ -22,19 +21,13 @@ from homeassistant.helpers.issue_registry import (
)
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
BINSENSOR_PORTS,
CONF_DOMAIN_DATA,
DOMAIN,
SETPOINTS,
)
from .const import BINSENSOR_PORTS, CONF_DOMAIN_DATA, DOMAIN, SETPOINTS
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -53,7 +46,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN switch entities from a config entry."""
@ -63,7 +56,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_BINARY_SENSOR: add_entities}
)
@ -79,7 +72,7 @@ async def async_setup_entry(
class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
"""Representation of a LCN binary sensor for regulator locks."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN binary sensor."""
super().__init__(config, config_entry)
@ -138,7 +131,7 @@ class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
class LcnBinarySensor(LcnEntity, BinarySensorEntity):
"""Representation of a LCN binary sensor for binary sensor ports."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN binary sensor."""
super().__init__(config, config_entry)
@ -174,7 +167,7 @@ class LcnBinarySensor(LcnEntity, BinarySensorEntity):
class LcnLockKeysSensor(LcnEntity, BinarySensorEntity):
"""Representation of a LCN sensor for key locks."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN sensor."""
super().__init__(config, config_entry)

View File

@ -12,7 +12,6 @@ from homeassistant.components.climate import (
ClimateEntityFeature,
HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_TEMPERATURE,
CONF_DOMAIN,
@ -26,23 +25,21 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
CONF_LOCKABLE,
CONF_MAX_TEMP,
CONF_MIN_TEMP,
CONF_SETPOINT,
CONF_TARGET_VALUE_LOCKED,
DOMAIN,
)
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
PARALLEL_UPDATES = 0
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -56,7 +53,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN switch entities from a config entry."""
@ -66,7 +63,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_CLIMATE: add_entities}
)
@ -82,7 +79,7 @@ async def async_setup_entry(
class LcnClimate(LcnEntity, ClimateEntity):
"""Representation of a LCN climate device."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize of a LCN climate device."""
super().__init__(config, config_entry)

View File

@ -15,12 +15,8 @@ PLATFORMS = [
]
DOMAIN = "lcn"
DATA_LCN = "lcn"
DEFAULT_NAME = "pchk"
ADD_ENTITIES_CALLBACKS = "add_entities_callbacks"
CONNECTION = "connection"
DEVICE_CONNECTIONS = "device_connections"
CONF_HARDWARE_SERIAL = "hardware_serial"
CONF_SOFTWARE_SERIAL = "software_serial"
CONF_HARDWARE_TYPE = "hardware_type"

View File

@ -12,28 +12,25 @@ from homeassistant.components.cover import (
CoverEntity,
CoverEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DOMAIN, CONF_ENTITIES
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
CONF_MOTOR,
CONF_POSITIONING_MODE,
CONF_REVERSE_TIME,
DOMAIN,
)
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
PARALLEL_UPDATES = 0
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -50,7 +47,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN cover entities from a config entry."""
@ -60,7 +57,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_COVER: add_entities}
)
@ -81,7 +78,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
_attr_is_opening = False
_attr_assumed_state = True
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN cover."""
super().__init__(config, config_entry)
@ -188,7 +185,7 @@ class LcnRelayCover(LcnEntity, CoverEntity):
positioning_mode: pypck.lcn_defs.MotorPositioningMode
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN cover."""
super().__init__(config, config_entry)

View File

@ -2,7 +2,6 @@
from collections.abc import Callable
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_NAME
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity
@ -13,6 +12,7 @@ from .helpers import (
AddressType,
DeviceConnectionType,
InputType,
LcnConfigEntry,
generate_unique_id,
get_device_connection,
get_resource,
@ -29,7 +29,7 @@ class LcnEntity(Entity):
def __init__(
self,
config: ConfigType,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Initialize the LCN device."""
self.config = config

View File

@ -3,11 +3,14 @@
from __future__ import annotations
import asyncio
from collections.abc import Callable, Iterable
from copy import deepcopy
from dataclasses import dataclass
import re
from typing import cast
import pypck
from pypck.connection import PchkConnectionManager
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
@ -33,12 +36,27 @@ from .const import (
CONF_HARDWARE_TYPE,
CONF_SCENES,
CONF_SOFTWARE_SERIAL,
CONNECTION,
DEVICE_CONNECTIONS,
DOMAIN,
)
@dataclass
class LcnRuntimeData:
"""Data for LCN config entry."""
connection: PchkConnectionManager
"""Connection to PCHK host."""
device_connections: dict[str, DeviceConnectionType]
"""Logical addresses of devices connected to the host."""
add_entities_callbacks: dict[str, Callable[[Iterable[ConfigType]], None]]
"""Callbacks to add entities for platforms."""
# typing
type LcnConfigEntry = ConfigEntry[LcnRuntimeData]
type AddressType = tuple[int, int, bool]
type DeviceConnectionType = pypck.module.ModuleConnection | pypck.module.GroupConnection
@ -62,10 +80,10 @@ DOMAIN_LOOKUP = {
def get_device_connection(
hass: HomeAssistant, address: AddressType, config_entry: ConfigEntry
hass: HomeAssistant, address: AddressType, config_entry: LcnConfigEntry
) -> DeviceConnectionType:
"""Return a lcn device_connection."""
host_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
host_connection = config_entry.runtime_data.connection
addr = pypck.lcn_addr.LcnAddr(*address)
return host_connection.get_address_conn(addr)
@ -165,7 +183,7 @@ def purge_device_registry(
device_registry.async_remove_device(device_id)
def register_lcn_host_device(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
def register_lcn_host_device(hass: HomeAssistant, config_entry: LcnConfigEntry) -> None:
"""Register LCN host for given config_entry in device registry."""
device_registry = dr.async_get(hass)
@ -179,7 +197,7 @@ def register_lcn_host_device(hass: HomeAssistant, config_entry: ConfigEntry) ->
def register_lcn_address_devices(
hass: HomeAssistant, config_entry: ConfigEntry
hass: HomeAssistant, config_entry: LcnConfigEntry
) -> None:
"""Register LCN modules and groups defined in config_entry as devices in device registry.
@ -217,9 +235,9 @@ def register_lcn_address_devices(
model=device_model,
)
hass.data[DOMAIN][config_entry.entry_id][DEVICE_CONNECTIONS][
device_entry.id
] = get_device_connection(hass, address, config_entry)
config_entry.runtime_data.device_connections[device_entry.id] = (
get_device_connection(hass, address, config_entry)
)
async def async_update_device_config(
@ -254,7 +272,7 @@ async def async_update_device_config(
async def async_update_config_entry(
hass: HomeAssistant, config_entry: ConfigEntry
hass: HomeAssistant, config_entry: LcnConfigEntry
) -> None:
"""Fill missing values in config_entry with infos from LCN bus."""
device_configs = deepcopy(config_entry.data[CONF_DEVICES])

View File

@ -14,29 +14,26 @@ from homeassistant.components.light import (
LightEntity,
LightEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DOMAIN, CONF_ENTITIES
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DIMMABLE,
CONF_DOMAIN_DATA,
CONF_OUTPUT,
CONF_TRANSITION,
DOMAIN,
OUTPUT_PORTS,
)
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
PARALLEL_UPDATES = 0
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -53,7 +50,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN light entities from a config entry."""
@ -63,7 +60,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_LIGHT: add_entities}
)
@ -83,7 +80,7 @@ class LcnOutputLight(LcnEntity, LightEntity):
_attr_is_on = False
_attr_brightness = 255
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN light."""
super().__init__(config, config_entry)
@ -175,7 +172,7 @@ class LcnRelayLight(LcnEntity, LightEntity):
_attr_supported_color_modes = {ColorMode.ONOFF}
_attr_is_on = False
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN light."""
super().__init__(config, config_entry)

View File

@ -7,28 +7,26 @@ from typing import Any
import pypck
from homeassistant.components.scene import DOMAIN as DOMAIN_SCENE, Scene
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DOMAIN, CONF_ENTITIES, CONF_SCENE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
CONF_OUTPUTS,
CONF_REGISTER,
CONF_TRANSITION,
DOMAIN,
OUTPUT_PORTS,
)
from .entity import LcnEntity
from .helpers import LcnConfigEntry
PARALLEL_UPDATES = 0
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -42,7 +40,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN switch entities from a config entry."""
@ -52,7 +50,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_SCENE: add_entities}
)
@ -68,7 +66,7 @@ async def async_setup_entry(
class LcnScene(LcnEntity, Scene):
"""Representation of a LCN scene."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN scene."""
super().__init__(config, config_entry)

View File

@ -11,7 +11,6 @@ from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
CONF_DOMAIN,
@ -29,9 +28,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
DOMAIN,
LED_PORTS,
S0_INPUTS,
SETPOINTS,
@ -39,7 +36,7 @@ from .const import (
VARIABLES,
)
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
DEVICE_CLASS_MAPPING = {
pypck.lcn_defs.VarUnit.CELSIUS: SensorDeviceClass.TEMPERATURE,
@ -67,7 +64,7 @@ UNIT_OF_MEASUREMENT_MAPPING = {
def add_lcn_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -86,7 +83,7 @@ def add_lcn_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN switch entities from a config entry."""
@ -96,7 +93,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_SENSOR: add_entities}
)
@ -112,7 +109,7 @@ async def async_setup_entry(
class LcnVariableSensor(LcnEntity, SensorEntity):
"""Representation of a LCN sensor for variables."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN sensor."""
super().__init__(config, config_entry)
@ -157,7 +154,7 @@ class LcnVariableSensor(LcnEntity, SensorEntity):
class LcnLedLogicSensor(LcnEntity, SensorEntity):
"""Representation of a LCN sensor for leds and logicops."""
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN sensor."""
super().__init__(config, config_entry)

View File

@ -36,7 +36,6 @@ from .const import (
CONF_TRANSITION,
CONF_VALUE,
CONF_VARIABLE,
DEVICE_CONNECTIONS,
DOMAIN,
LED_PORTS,
LED_STATUS,
@ -49,7 +48,7 @@ from .const import (
VAR_UNITS,
VARIABLES,
)
from .helpers import DeviceConnectionType, is_states_string
from .helpers import DeviceConnectionType, LcnConfigEntry, is_states_string
class LcnServiceCall:
@ -68,18 +67,28 @@ class LcnServiceCall:
def get_device_connection(self, service: ServiceCall) -> DeviceConnectionType:
"""Get address connection object."""
entries: list[LcnConfigEntry] = self.hass.config_entries.async_loaded_entries(
DOMAIN
)
device_id = service.data[CONF_DEVICE_ID]
device_registry = dr.async_get(self.hass)
if not (device := device_registry.async_get(device_id)):
if not (device := device_registry.async_get(device_id)) or not (
entry := next(
(
entry
for entry in entries
if entry.entry_id == device.primary_config_entry
),
None,
)
):
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_device_id",
translation_placeholders={"device_id": device_id},
)
return self.hass.data[DOMAIN][device.primary_config_entry][DEVICE_CONNECTIONS][
device_id
]
return entry.runtime_data.device_connections[device_id]
async def async_call_service(self, service: ServiceCall) -> ServiceResponse:
"""Execute service call."""

View File

@ -7,29 +7,20 @@ from typing import Any
import pypck
from homeassistant.components.switch import DOMAIN as DOMAIN_SWITCH, SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DOMAIN, CONF_ENTITIES
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
CONF_OUTPUT,
DOMAIN,
OUTPUT_PORTS,
RELAY_PORTS,
SETPOINTS,
)
from .const import CONF_DOMAIN_DATA, CONF_OUTPUT, OUTPUT_PORTS, RELAY_PORTS, SETPOINTS
from .entity import LcnEntity
from .helpers import InputType
from .helpers import InputType, LcnConfigEntry
PARALLEL_UPDATES = 0
def add_lcn_switch_entities(
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
entity_configs: Iterable[ConfigType],
) -> None:
@ -52,7 +43,7 @@ def add_lcn_switch_entities(
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up LCN switch entities from a config entry."""
@ -62,7 +53,7 @@ async def async_setup_entry(
async_add_entities,
)
hass.data[DOMAIN][config_entry.entry_id][ADD_ENTITIES_CALLBACKS].update(
config_entry.runtime_data.add_entities_callbacks.update(
{DOMAIN_SWITCH: add_entities}
)
@ -80,7 +71,7 @@ class LcnOutputSwitch(LcnEntity, SwitchEntity):
_attr_is_on = False
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN switch."""
super().__init__(config, config_entry)
@ -129,7 +120,7 @@ class LcnRelaySwitch(LcnEntity, SwitchEntity):
_attr_is_on = False
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN switch."""
super().__init__(config, config_entry)
@ -179,7 +170,7 @@ class LcnRegulatorLockSwitch(LcnEntity, SwitchEntity):
_attr_is_on = False
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN switch."""
super().__init__(config, config_entry)
@ -235,7 +226,7 @@ class LcnKeyLockSwitch(LcnEntity, SwitchEntity):
_attr_is_on = False
def __init__(self, config: ConfigType, config_entry: ConfigEntry) -> None:
def __init__(self, config: ConfigType, config_entry: LcnConfigEntry) -> None:
"""Initialize the LCN switch."""
super().__init__(config, config_entry)

View File

@ -4,15 +4,17 @@ from __future__ import annotations
from collections.abc import Awaitable, Callable
from functools import wraps
from typing import TYPE_CHECKING, Any, Final
from typing import Any, Final
import lcn_frontend as lcn_panel
import voluptuous as vol
from homeassistant.components import panel_custom, websocket_api
from homeassistant.components.http import StaticPathConfig
from homeassistant.components.websocket_api import AsyncWebSocketCommandHandler
from homeassistant.config_entries import ConfigEntry
from homeassistant.components.websocket_api import (
ActiveConnection,
AsyncWebSocketCommandHandler,
)
from homeassistant.const import (
CONF_ADDRESS,
CONF_DEVICES,
@ -28,16 +30,15 @@ from homeassistant.helpers import (
)
from .const import (
ADD_ENTITIES_CALLBACKS,
CONF_DOMAIN_DATA,
CONF_HARDWARE_SERIAL,
CONF_HARDWARE_TYPE,
CONF_SOFTWARE_SERIAL,
CONNECTION,
DOMAIN,
)
from .helpers import (
DeviceConnectionType,
LcnConfigEntry,
async_update_device_config,
generate_unique_id,
get_device_config,
@ -58,11 +59,8 @@ from .schemas import (
DOMAIN_DATA_SWITCH,
)
if TYPE_CHECKING:
from homeassistant.components.websocket_api import ActiveConnection
type AsyncLcnWebSocketCommandHandler = Callable[
[HomeAssistant, ActiveConnection, dict[str, Any], ConfigEntry], Awaitable[None]
[HomeAssistant, ActiveConnection, dict[str, Any], LcnConfigEntry], Awaitable[None]
]
URL_BASE: Final = "/lcn_static"
@ -127,7 +125,7 @@ async def websocket_get_device_configs(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Get device configs."""
connection.send_result(msg["id"], config_entry.data[CONF_DEVICES])
@ -147,7 +145,7 @@ async def websocket_get_entity_configs(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Get entities configs."""
if CONF_ADDRESS in msg:
@ -178,10 +176,10 @@ async def websocket_scan_devices(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Scan for new devices."""
host_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
host_connection = config_entry.runtime_data.connection
await host_connection.scan_modules()
for device_connection in host_connection.address_conns.values():
@ -210,7 +208,7 @@ async def websocket_add_device(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Add a device."""
if get_device_config(msg[CONF_ADDRESS], config_entry):
@ -256,7 +254,7 @@ async def websocket_delete_device(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Delete a device."""
device_config = get_device_config(msg[CONF_ADDRESS], config_entry)
@ -318,7 +316,7 @@ async def websocket_add_entity(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Add an entity."""
if not (device_config := get_device_config(msg[CONF_ADDRESS], config_entry)):
@ -347,9 +345,7 @@ async def websocket_add_entity(
}
# Create new entity and add to corresponding component
add_entities = hass.data[DOMAIN][msg["entry_id"]][ADD_ENTITIES_CALLBACKS][
msg[CONF_DOMAIN]
]
add_entities = config_entry.runtime_data.add_entities_callbacks[msg[CONF_DOMAIN]]
add_entities([entity_config])
# Add entity config to config_entry
@ -386,7 +382,7 @@ async def websocket_delete_entity(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Delete an entity."""
entity_config = next(
@ -426,7 +422,7 @@ async def websocket_delete_entity(
async def async_create_or_update_device_in_config_entry(
hass: HomeAssistant,
device_connection: DeviceConnectionType,
config_entry: ConfigEntry,
config_entry: LcnConfigEntry,
) -> None:
"""Create or update device in config_entry according to given device_connection."""
address = (
@ -455,7 +451,7 @@ async def async_create_or_update_device_in_config_entry(
def get_entity_entry(
hass: HomeAssistant, entity_config: dict, config_entry: ConfigEntry
hass: HomeAssistant, entity_config: dict, config_entry: LcnConfigEntry
) -> er.RegistryEntry | None:
"""Get entity RegistryEntry from entity_config."""
entity_registry = er.async_get(hass)