Add type hints to LCN (#52509)
* Add type hints to LCN * Fix requested review changes
This commit is contained in:
parent
b496469a2f
commit
e16ef10af5
13 changed files with 333 additions and 172 deletions
|
@ -48,6 +48,7 @@ homeassistant.components.image_processing.*
|
||||||
homeassistant.components.integration.*
|
homeassistant.components.integration.*
|
||||||
homeassistant.components.knx.*
|
homeassistant.components.knx.*
|
||||||
homeassistant.components.kraken.*
|
homeassistant.components.kraken.*
|
||||||
|
homeassistant.components.lcn.*
|
||||||
homeassistant.components.light.*
|
homeassistant.components.light.*
|
||||||
homeassistant.components.local_ip.*
|
homeassistant.components.local_ip.*
|
||||||
homeassistant.components.lock.*
|
homeassistant.components.lock.*
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
"""Support for LCN devices."""
|
"""Support for LCN devices."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
|
@ -14,16 +17,22 @@ from homeassistant.const import (
|
||||||
)
|
)
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from .const import CONF_DIM_MODE, CONF_SK_NUM_TRIES, CONNECTION, DOMAIN, PLATFORMS
|
from .const import CONF_DIM_MODE, CONF_SK_NUM_TRIES, CONNECTION, DOMAIN, PLATFORMS
|
||||||
from .helpers import generate_unique_id, import_lcn_config
|
from .helpers import (
|
||||||
|
DeviceConnectionType,
|
||||||
|
InputType,
|
||||||
|
generate_unique_id,
|
||||||
|
import_lcn_config,
|
||||||
|
)
|
||||||
from .schemas import CONFIG_SCHEMA # noqa: F401
|
from .schemas import CONFIG_SCHEMA # noqa: F401
|
||||||
from .services import SERVICES
|
from .services import SERVICES
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||||
"""Set up the LCN component."""
|
"""Set up the LCN component."""
|
||||||
if DOMAIN not in config:
|
if DOMAIN not in config:
|
||||||
return True
|
return True
|
||||||
|
@ -43,7 +52,9 @@ async def async_setup(hass, config):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType, config_entry: config_entries.ConfigEntry
|
||||||
|
) -> bool:
|
||||||
"""Set up a connection to PCHK host from a config entry."""
|
"""Set up a connection to PCHK host from a config entry."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
if config_entry.entry_id in hass.data[DOMAIN]:
|
if config_entry.entry_id in hass.data[DOMAIN]:
|
||||||
|
@ -104,7 +115,9 @@ async def async_setup_entry(hass, config_entry):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass, config_entry):
|
async def async_unload_entry(
|
||||||
|
hass: HomeAssistantType, config_entry: config_entries.ConfigEntry
|
||||||
|
) -> bool:
|
||||||
"""Close connection to PCHK host represented by config_entry."""
|
"""Close connection to PCHK host represented by config_entry."""
|
||||||
# forward unloading to platforms
|
# forward unloading to platforms
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(
|
unload_ok = await hass.config_entries.async_unload_platforms(
|
||||||
|
@ -126,16 +139,18 @@ async def async_unload_entry(hass, config_entry):
|
||||||
class LcnEntity(Entity):
|
class LcnEntity(Entity):
|
||||||
"""Parent class for all entities associated with the LCN component."""
|
"""Parent class for all entities associated with the LCN component."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN device."""
|
"""Initialize the LCN device."""
|
||||||
self.config = config
|
self.config = config
|
||||||
self.entry_id = entry_id
|
self.entry_id = entry_id
|
||||||
self.device_connection = device_connection
|
self.device_connection = device_connection
|
||||||
self._unregister_for_inputs = None
|
self._unregister_for_inputs: Callable | None = None
|
||||||
self._name = config[CONF_NAME]
|
self._name: str = config[CONF_NAME]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self) -> str:
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
unique_device_id = generate_unique_id(
|
unique_device_id = generate_unique_id(
|
||||||
(
|
(
|
||||||
|
@ -147,26 +162,26 @@ class LcnEntity(Entity):
|
||||||
return f"{self.entry_id}-{unique_device_id}-{self.config[CONF_RESOURCE]}"
|
return f"{self.entry_id}-{unique_device_id}-{self.config[CONF_RESOURCE]}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self) -> bool:
|
||||||
"""Lcn device entity pushes its state to HA."""
|
"""Lcn device entity pushes its state to HA."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
self._unregister_for_inputs = self.device_connection.register_for_inputs(
|
self._unregister_for_inputs = self.device_connection.register_for_inputs(
|
||||||
self.input_received
|
self.input_received
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
if self._unregister_for_inputs is not None:
|
if self._unregister_for_inputs is not None:
|
||||||
self._unregister_for_inputs()
|
self._unregister_for_inputs()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str:
|
||||||
"""Return the name of the device."""
|
"""Return the name of the device."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set state/value when LCN input object (command) is received."""
|
"""Set state/value when LCN input object (command) is received."""
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
"""Support for LCN binary sensors."""
|
"""Support for LCN binary sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
DOMAIN as DOMAIN_BINARY_SENSOR,
|
DOMAIN as DOMAIN_BINARY_SENSOR,
|
||||||
BinarySensorEntity,
|
BinarySensorEntity,
|
||||||
)
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES, CONF_SOURCE
|
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES, CONF_SOURCE
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import BINSENSOR_PORTS, CONF_DOMAIN_DATA, SETPOINTS
|
from .const import BINSENSOR_PORTS, CONF_DOMAIN_DATA, SETPOINTS
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_binary_sensor_entity(hass, entity_config, config_entry):
|
def create_lcn_binary_sensor_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
if entity_config[CONF_DOMAIN_DATA][CONF_SOURCE] in SETPOINTS:
|
if entity_config[CONF_DOMAIN_DATA][CONF_SOURCE] in SETPOINTS:
|
||||||
|
@ -28,7 +35,11 @@ def create_lcn_binary_sensor_entity(hass, entity_config, config_entry):
|
||||||
return LcnLockKeysSensor(entity_config, config_entry.entry_id, device_connection)
|
return LcnLockKeysSensor(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN switch entities from a config entry."""
|
"""Set up LCN switch entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -44,7 +55,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
||||||
"""Representation of a LCN binary sensor for regulator locks."""
|
"""Representation of a LCN binary sensor for regulator locks."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN binary sensor."""
|
"""Initialize the LCN binary sensor."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -54,7 +67,7 @@ class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
||||||
|
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -62,7 +75,7 @@ class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
||||||
self.setpoint_variable
|
self.setpoint_variable
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -71,11 +84,11 @@ class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set sensor value when LCN input object (command) is received."""
|
"""Set sensor value when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusVar)
|
not isinstance(input_obj, pypck.inputs.ModStatusVar)
|
||||||
|
@ -90,7 +103,9 @@ class LcnRegulatorLockSensor(LcnEntity, BinarySensorEntity):
|
||||||
class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
||||||
"""Representation of a LCN binary sensor for binary sensor ports."""
|
"""Representation of a LCN binary sensor for binary sensor ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN binary sensor."""
|
"""Initialize the LCN binary sensor."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -100,7 +115,7 @@ class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
||||||
|
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -108,7 +123,7 @@ class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
||||||
self.bin_sensor_port
|
self.bin_sensor_port
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -117,11 +132,11 @@ class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set sensor value when LCN input object (command) is received."""
|
"""Set sensor value when LCN input object (command) is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusBinSensors):
|
if not isinstance(input_obj, pypck.inputs.ModStatusBinSensors):
|
||||||
return
|
return
|
||||||
|
@ -133,31 +148,33 @@ class LcnBinarySensor(LcnEntity, BinarySensorEntity):
|
||||||
class LcnLockKeysSensor(LcnEntity, BinarySensorEntity):
|
class LcnLockKeysSensor(LcnEntity, BinarySensorEntity):
|
||||||
"""Representation of a LCN sensor for key locks."""
|
"""Representation of a LCN sensor for key locks."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN sensor."""
|
"""Initialize the LCN sensor."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
self.source = pypck.lcn_defs.Key[config[CONF_DOMAIN_DATA][CONF_SOURCE]]
|
self.source = pypck.lcn_defs.Key[config[CONF_DOMAIN_DATA][CONF_SOURCE]]
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.source)
|
await self.device_connection.activate_status_request_handler(self.source)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.source)
|
await self.device_connection.cancel_status_request_handler(self.source)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set sensor value when LCN input object (command) is received."""
|
"""Set sensor value when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusKeyLocks)
|
not isinstance(input_obj, pypck.inputs.ModStatusKeyLocks)
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
"""Support for LCN climate control."""
|
"""Support for LCN climate control."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
|
@ -6,6 +10,7 @@ from homeassistant.components.climate import (
|
||||||
ClimateEntity,
|
ClimateEntity,
|
||||||
const,
|
const,
|
||||||
)
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
|
@ -14,6 +19,8 @@ from homeassistant.const import (
|
||||||
CONF_SOURCE,
|
CONF_SOURCE,
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import (
|
from .const import (
|
||||||
|
@ -23,21 +30,27 @@ from .const import (
|
||||||
CONF_MIN_TEMP,
|
CONF_MIN_TEMP,
|
||||||
CONF_SETPOINT,
|
CONF_SETPOINT,
|
||||||
)
|
)
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_climate_entity(hass, entity_config, config_entry):
|
def create_lcn_climate_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
return LcnClimate(entity_config, config_entry.entry_id, device_connection)
|
return LcnClimate(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN switch entities from a config entry."""
|
"""Set up LCN switch entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -53,7 +66,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnClimate(LcnEntity, ClimateEntity):
|
class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
"""Representation of a LCN climate device."""
|
"""Representation of a LCN climate device."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize of a LCN climate device."""
|
"""Initialize of a LCN climate device."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -72,14 +87,14 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
self._target_temperature = None
|
self._target_temperature = None
|
||||||
self._is_on = True
|
self._is_on = True
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.variable)
|
await self.device_connection.activate_status_request_handler(self.variable)
|
||||||
await self.device_connection.activate_status_request_handler(self.setpoint)
|
await self.device_connection.activate_status_request_handler(self.setpoint)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -87,27 +102,27 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
await self.device_connection.cancel_status_request_handler(self.setpoint)
|
await self.device_connection.cancel_status_request_handler(self.setpoint)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self) -> int:
|
||||||
"""Return the list of supported features."""
|
"""Return the list of supported features."""
|
||||||
return const.SUPPORT_TARGET_TEMPERATURE
|
return const.SUPPORT_TARGET_TEMPERATURE
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def temperature_unit(self):
|
def temperature_unit(self) -> str:
|
||||||
"""Return the unit of measurement."""
|
"""Return the unit of measurement."""
|
||||||
return self.unit.value
|
return cast(str, self.unit.value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_temperature(self):
|
def current_temperature(self) -> float | None:
|
||||||
"""Return the current temperature."""
|
"""Return the current temperature."""
|
||||||
return self._current_temperature
|
return self._current_temperature
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature(self):
|
def target_temperature(self) -> float | None:
|
||||||
"""Return the temperature we try to reach."""
|
"""Return the temperature we try to reach."""
|
||||||
return self._target_temperature
|
return self._target_temperature
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self):
|
def hvac_mode(self) -> str:
|
||||||
"""Return hvac operation ie. heat, cool mode.
|
"""Return hvac operation ie. heat, cool mode.
|
||||||
|
|
||||||
Need to be one of HVAC_MODE_*.
|
Need to be one of HVAC_MODE_*.
|
||||||
|
@ -117,7 +132,7 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
return const.HVAC_MODE_OFF
|
return const.HVAC_MODE_OFF
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self):
|
def hvac_modes(self) -> list[str]:
|
||||||
"""Return the list of available hvac operation modes.
|
"""Return the list of available hvac operation modes.
|
||||||
|
|
||||||
Need to be a subset of HVAC_MODES.
|
Need to be a subset of HVAC_MODES.
|
||||||
|
@ -128,16 +143,16 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
return modes
|
return modes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_temp(self):
|
def max_temp(self) -> float:
|
||||||
"""Return the maximum temperature."""
|
"""Return the maximum temperature."""
|
||||||
return self._max_temp
|
return cast(float, self._max_temp)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self) -> float:
|
||||||
"""Return the minimum temperature."""
|
"""Return the minimum temperature."""
|
||||||
return self._min_temp
|
return cast(float, self._min_temp)
|
||||||
|
|
||||||
async def async_set_hvac_mode(self, hvac_mode):
|
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||||
"""Set new target hvac mode."""
|
"""Set new target hvac mode."""
|
||||||
if hvac_mode == const.HVAC_MODE_HEAT:
|
if hvac_mode == const.HVAC_MODE_HEAT:
|
||||||
if not await self.device_connection.lock_regulator(
|
if not await self.device_connection.lock_regulator(
|
||||||
|
@ -153,7 +168,7 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
self._target_temperature = None
|
self._target_temperature = None
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_set_temperature(self, **kwargs):
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||||
"""Set new target temperature."""
|
"""Set new target temperature."""
|
||||||
temperature = kwargs.get(ATTR_TEMPERATURE)
|
temperature = kwargs.get(ATTR_TEMPERATURE)
|
||||||
if temperature is None:
|
if temperature is None:
|
||||||
|
@ -166,7 +181,7 @@ class LcnClimate(LcnEntity, ClimateEntity):
|
||||||
self._target_temperature = temperature
|
self._target_temperature = temperature
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set temperature value when LCN input object is received."""
|
"""Set temperature value when LCN input object is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusVar):
|
if not isinstance(input_obj, pypck.inputs.ModStatusVar):
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""Config flow to configure the LCN integration."""
|
"""Config flow to configure the LCN integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
@ -11,13 +13,17 @@ from homeassistant.const import (
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
)
|
)
|
||||||
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from .const import CONF_DIM_MODE, CONF_SK_NUM_TRIES, DOMAIN
|
from .const import CONF_DIM_MODE, CONF_SK_NUM_TRIES, DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_config_entry(hass, data):
|
def get_config_entry(
|
||||||
|
hass: HomeAssistantType, data: ConfigType
|
||||||
|
) -> config_entries.ConfigEntry | None:
|
||||||
"""Check config entries for already configured entries based on the ip address/port."""
|
"""Check config entries for already configured entries based on the ip address/port."""
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
|
@ -30,7 +36,7 @@ def get_config_entry(hass, data):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def validate_connection(host_name, data):
|
async def validate_connection(host_name: str, data: ConfigType) -> ConfigType:
|
||||||
"""Validate if a connection to LCN can be established."""
|
"""Validate if a connection to LCN can be established."""
|
||||||
host = data[CONF_IP_ADDRESS]
|
host = data[CONF_IP_ADDRESS]
|
||||||
port = data[CONF_PORT]
|
port = data[CONF_PORT]
|
||||||
|
@ -62,7 +68,7 @@ class LcnFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 1
|
||||||
|
|
||||||
async def async_step_import(self, data):
|
async def async_step_import(self, data: ConfigType) -> FlowResult:
|
||||||
"""Import existing configuration from LCN."""
|
"""Import existing configuration from LCN."""
|
||||||
host_name = data[CONF_HOST]
|
host_name = data[CONF_HOST]
|
||||||
# validate the imported connection parameters
|
# validate the imported connection parameters
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
"""Support for LCN covers."""
|
"""Support for LCN covers."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.cover import DOMAIN as DOMAIN_COVER, CoverEntity
|
from homeassistant.components.cover import DOMAIN as DOMAIN_COVER, CoverEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import CONF_DOMAIN_DATA, CONF_MOTOR, CONF_REVERSE_TIME
|
from .const import CONF_DOMAIN_DATA, CONF_MOTOR, CONF_REVERSE_TIME
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_cover_entity(hass, entity_config, config_entry):
|
def create_lcn_cover_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
if entity_config[CONF_DOMAIN_DATA][CONF_MOTOR] in "OUTPUTS":
|
if entity_config[CONF_DOMAIN_DATA][CONF_MOTOR] in "OUTPUTS":
|
||||||
|
@ -24,7 +32,11 @@ def create_lcn_cover_entity(hass, entity_config, config_entry):
|
||||||
return LcnRelayCover(entity_config, config_entry.entry_id, device_connection)
|
return LcnRelayCover(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN cover entities from a config entry."""
|
"""Set up LCN cover entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -38,7 +50,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnOutputsCover(LcnEntity, CoverEntity):
|
class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
"""Representation of a LCN cover connected to output ports."""
|
"""Representation of a LCN cover connected to output ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN cover."""
|
"""Initialize the LCN cover."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -57,7 +71,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = False
|
self._is_closing = False
|
||||||
self._is_opening = False
|
self._is_opening = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -68,7 +82,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
pypck.lcn_defs.OutputPort["OUTPUTDOWN"]
|
pypck.lcn_defs.OutputPort["OUTPUTDOWN"]
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
|
@ -80,26 +94,26 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self) -> bool:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
return self._is_closed
|
return self._is_closed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_opening(self):
|
def is_opening(self) -> bool:
|
||||||
"""Return if the cover is opening or not."""
|
"""Return if the cover is opening or not."""
|
||||||
return self._is_opening
|
return self._is_opening
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closing(self):
|
def is_closing(self) -> bool:
|
||||||
"""Return if the cover is closing or not."""
|
"""Return if the cover is closing or not."""
|
||||||
return self._is_closing
|
return self._is_closing
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def assumed_state(self):
|
def assumed_state(self) -> bool:
|
||||||
"""Return True if unable to access real state of the entity."""
|
"""Return True if unable to access real state of the entity."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_close_cover(self, **kwargs):
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close the cover."""
|
"""Close the cover."""
|
||||||
state = pypck.lcn_defs.MotorStateModifier.DOWN
|
state = pypck.lcn_defs.MotorStateModifier.DOWN
|
||||||
if not await self.device_connection.control_motors_outputs(
|
if not await self.device_connection.control_motors_outputs(
|
||||||
|
@ -110,7 +124,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = True
|
self._is_closing = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_open_cover(self, **kwargs):
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open the cover."""
|
"""Open the cover."""
|
||||||
state = pypck.lcn_defs.MotorStateModifier.UP
|
state = pypck.lcn_defs.MotorStateModifier.UP
|
||||||
if not await self.device_connection.control_motors_outputs(
|
if not await self.device_connection.control_motors_outputs(
|
||||||
|
@ -122,7 +136,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = False
|
self._is_closing = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_stop_cover(self, **kwargs):
|
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||||
"""Stop the cover."""
|
"""Stop the cover."""
|
||||||
state = pypck.lcn_defs.MotorStateModifier.STOP
|
state = pypck.lcn_defs.MotorStateModifier.STOP
|
||||||
if not await self.device_connection.control_motors_outputs(state):
|
if not await self.device_connection.control_motors_outputs(state):
|
||||||
|
@ -131,7 +145,7 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
self._is_opening = False
|
self._is_opening = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set cover states when LCN input object (command) is received."""
|
"""Set cover states when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
||||||
|
@ -159,7 +173,9 @@ class LcnOutputsCover(LcnEntity, CoverEntity):
|
||||||
class LcnRelayCover(LcnEntity, CoverEntity):
|
class LcnRelayCover(LcnEntity, CoverEntity):
|
||||||
"""Representation of a LCN cover connected to relays."""
|
"""Representation of a LCN cover connected to relays."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN cover."""
|
"""Initialize the LCN cover."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -171,39 +187,39 @@ class LcnRelayCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = False
|
self._is_closing = False
|
||||||
self._is_opening = False
|
self._is_opening = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.motor)
|
await self.device_connection.activate_status_request_handler(self.motor)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.motor)
|
await self.device_connection.cancel_status_request_handler(self.motor)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self) -> bool:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
return self._is_closed
|
return self._is_closed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_opening(self):
|
def is_opening(self) -> bool:
|
||||||
"""Return if the cover is opening or not."""
|
"""Return if the cover is opening or not."""
|
||||||
return self._is_opening
|
return self._is_opening
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closing(self):
|
def is_closing(self) -> bool:
|
||||||
"""Return if the cover is closing or not."""
|
"""Return if the cover is closing or not."""
|
||||||
return self._is_closing
|
return self._is_closing
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def assumed_state(self):
|
def assumed_state(self) -> bool:
|
||||||
"""Return True if unable to access real state of the entity."""
|
"""Return True if unable to access real state of the entity."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_close_cover(self, **kwargs):
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close the cover."""
|
"""Close the cover."""
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.DOWN
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.DOWN
|
||||||
|
@ -213,7 +229,7 @@ class LcnRelayCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = True
|
self._is_closing = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_open_cover(self, **kwargs):
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open the cover."""
|
"""Open the cover."""
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.UP
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.UP
|
||||||
|
@ -224,7 +240,7 @@ class LcnRelayCover(LcnEntity, CoverEntity):
|
||||||
self._is_closing = False
|
self._is_closing = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_stop_cover(self, **kwargs):
|
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||||
"""Stop the cover."""
|
"""Stop the cover."""
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.STOP
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.STOP
|
||||||
|
@ -234,7 +250,7 @@ class LcnRelayCover(LcnEntity, CoverEntity):
|
||||||
self._is_opening = False
|
self._is_opening = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set cover states when LCN input object (command) is received."""
|
"""Set cover states when LCN input object (command) is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
"""Helpers for LCN component."""
|
"""Helpers for LCN component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from typing import Tuple, Type, Union, cast
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
CONF_BINARY_SENSORS,
|
CONF_BINARY_SENSORS,
|
||||||
|
@ -21,6 +25,7 @@ from homeassistant.const import (
|
||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_CLIMATES,
|
CONF_CLIMATES,
|
||||||
|
@ -38,6 +43,13 @@ from .const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# typing
|
||||||
|
AddressType = Tuple[int, int, bool]
|
||||||
|
DeviceConnectionType = Union[
|
||||||
|
pypck.module.ModuleConnection, pypck.module.GroupConnection
|
||||||
|
]
|
||||||
|
InputType = Type[pypck.inputs.Input]
|
||||||
|
|
||||||
# Regex for address validation
|
# Regex for address validation
|
||||||
PATTERN_ADDRESS = re.compile(
|
PATTERN_ADDRESS = re.compile(
|
||||||
"^((?P<conn_id>\\w+)\\.)?s?(?P<seg_id>\\d+)\\.(?P<type>m|g)?(?P<id>\\d+)$"
|
"^((?P<conn_id>\\w+)\\.)?s?(?P<seg_id>\\d+)\\.(?P<type>m|g)?(?P<id>\\d+)$"
|
||||||
|
@ -55,21 +67,23 @@ DOMAIN_LOOKUP = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_device_connection(hass, address, config_entry):
|
def get_device_connection(
|
||||||
|
hass: HomeAssistantType, address: AddressType, config_entry: ConfigEntry
|
||||||
|
) -> DeviceConnectionType | None:
|
||||||
"""Return a lcn device_connection."""
|
"""Return a lcn device_connection."""
|
||||||
host_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
|
host_connection = hass.data[DOMAIN][config_entry.entry_id][CONNECTION]
|
||||||
addr = pypck.lcn_addr.LcnAddr(*address)
|
addr = pypck.lcn_addr.LcnAddr(*address)
|
||||||
return host_connection.get_address_conn(addr)
|
return host_connection.get_address_conn(addr)
|
||||||
|
|
||||||
|
|
||||||
def get_resource(domain_name, domain_data):
|
def get_resource(domain_name: str, domain_data: ConfigType) -> str:
|
||||||
"""Return the resource for the specified domain_data."""
|
"""Return the resource for the specified domain_data."""
|
||||||
if domain_name in ["switch", "light"]:
|
if domain_name in ["switch", "light"]:
|
||||||
return domain_data["output"]
|
return cast(str, domain_data["output"])
|
||||||
if domain_name in ["binary_sensor", "sensor"]:
|
if domain_name in ["binary_sensor", "sensor"]:
|
||||||
return domain_data["source"]
|
return cast(str, domain_data["source"])
|
||||||
if domain_name == "cover":
|
if domain_name == "cover":
|
||||||
return domain_data["motor"]
|
return cast(str, domain_data["motor"])
|
||||||
if domain_name == "climate":
|
if domain_name == "climate":
|
||||||
return f'{domain_data["source"]}.{domain_data["setpoint"]}'
|
return f'{domain_data["source"]}.{domain_data["setpoint"]}'
|
||||||
if domain_name == "scene":
|
if domain_name == "scene":
|
||||||
|
@ -77,13 +91,13 @@ def get_resource(domain_name, domain_data):
|
||||||
raise ValueError("Unknown domain")
|
raise ValueError("Unknown domain")
|
||||||
|
|
||||||
|
|
||||||
def generate_unique_id(address):
|
def generate_unique_id(address: AddressType) -> str:
|
||||||
"""Generate a unique_id from the given parameters."""
|
"""Generate a unique_id from the given parameters."""
|
||||||
is_group = "g" if address[2] else "m"
|
is_group = "g" if address[2] else "m"
|
||||||
return f"{is_group}{address[0]:03d}{address[1]:03d}"
|
return f"{is_group}{address[0]:03d}{address[1]:03d}"
|
||||||
|
|
||||||
|
|
||||||
def import_lcn_config(lcn_config):
|
def import_lcn_config(lcn_config: ConfigType) -> list[ConfigType]:
|
||||||
"""Convert lcn settings from configuration.yaml to config_entries data.
|
"""Convert lcn settings from configuration.yaml to config_entries data.
|
||||||
|
|
||||||
Create a list of config_entry data structures like:
|
Create a list of config_entry data structures like:
|
||||||
|
@ -185,7 +199,7 @@ def import_lcn_config(lcn_config):
|
||||||
return list(data.values())
|
return list(data.values())
|
||||||
|
|
||||||
|
|
||||||
def has_unique_host_names(hosts):
|
def has_unique_host_names(hosts: list[ConfigType]) -> list[ConfigType]:
|
||||||
"""Validate that all connection names are unique.
|
"""Validate that all connection names are unique.
|
||||||
|
|
||||||
Use 'pchk' as default connection_name (or add a numeric suffix if
|
Use 'pchk' as default connection_name (or add a numeric suffix if
|
||||||
|
@ -206,7 +220,7 @@ def has_unique_host_names(hosts):
|
||||||
return hosts
|
return hosts
|
||||||
|
|
||||||
|
|
||||||
def is_address(value):
|
def is_address(value: str) -> tuple[AddressType, str]:
|
||||||
"""Validate the given address string.
|
"""Validate the given address string.
|
||||||
|
|
||||||
Examples for S000M005 at myhome:
|
Examples for S000M005 at myhome:
|
||||||
|
@ -227,7 +241,7 @@ def is_address(value):
|
||||||
raise ValueError(f"{value} is not a valid address string")
|
raise ValueError(f"{value} is not a valid address string")
|
||||||
|
|
||||||
|
|
||||||
def is_states_string(states_string):
|
def is_states_string(states_string: str) -> list[str]:
|
||||||
"""Validate the given states string and return states list."""
|
"""Validate the given states string and return states list."""
|
||||||
if len(states_string) != 8:
|
if len(states_string) != 8:
|
||||||
raise ValueError("Invalid length of states string")
|
raise ValueError("Invalid length of states string")
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
"""Support for LCN lights."""
|
"""Support for LCN lights."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
|
@ -10,7 +13,10 @@ from homeassistant.components.light import (
|
||||||
SUPPORT_TRANSITION,
|
SUPPORT_TRANSITION,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import (
|
from .const import (
|
||||||
|
@ -20,15 +26,17 @@ from .const import (
|
||||||
CONF_TRANSITION,
|
CONF_TRANSITION,
|
||||||
OUTPUT_PORTS,
|
OUTPUT_PORTS,
|
||||||
)
|
)
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_light_entity(hass, entity_config, config_entry):
|
def create_lcn_light_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
if entity_config[CONF_DOMAIN_DATA][CONF_OUTPUT] in OUTPUT_PORTS:
|
if entity_config[CONF_DOMAIN_DATA][CONF_OUTPUT] in OUTPUT_PORTS:
|
||||||
|
@ -37,7 +45,11 @@ def create_lcn_light_entity(hass, entity_config, config_entry):
|
||||||
return LcnRelayLight(entity_config, config_entry.entry_id, device_connection)
|
return LcnRelayLight(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN light entities from a config entry."""
|
"""Set up LCN light entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -51,7 +63,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnOutputLight(LcnEntity, LightEntity):
|
class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
"""Representation of a LCN light for output ports."""
|
"""Representation of a LCN light for output ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN light."""
|
"""Initialize the LCN light."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -66,36 +80,36 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
self._is_dimming_to_zero = False
|
self._is_dimming_to_zero = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.output)
|
await self.device_connection.activate_status_request_handler(self.output)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.output)
|
await self.device_connection.cancel_status_request_handler(self.output)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self) -> int:
|
||||||
"""Flag supported features."""
|
"""Flag supported features."""
|
||||||
if self.dimmable:
|
if self.dimmable:
|
||||||
return SUPPORT_TRANSITION | SUPPORT_BRIGHTNESS
|
return SUPPORT_TRANSITION | SUPPORT_BRIGHTNESS
|
||||||
return SUPPORT_TRANSITION
|
return SUPPORT_TRANSITION
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self) -> int | None:
|
||||||
"""Return the brightness of this light between 0..255."""
|
"""Return the brightness of this light between 0..255."""
|
||||||
return self._brightness
|
return self._brightness
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool:
|
||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self._is_on
|
return self._is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
if ATTR_BRIGHTNESS in kwargs:
|
if ATTR_BRIGHTNESS in kwargs:
|
||||||
percent = int(kwargs[ATTR_BRIGHTNESS] / 255.0 * 100)
|
percent = int(kwargs[ATTR_BRIGHTNESS] / 255.0 * 100)
|
||||||
|
@ -116,7 +130,7 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
self._is_dimming_to_zero = False
|
self._is_dimming_to_zero = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity off."""
|
"""Turn the entity off."""
|
||||||
if ATTR_TRANSITION in kwargs:
|
if ATTR_TRANSITION in kwargs:
|
||||||
transition = pypck.lcn_defs.time_to_ramp_value(
|
transition = pypck.lcn_defs.time_to_ramp_value(
|
||||||
|
@ -133,7 +147,7 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set light state when LCN input object (command) is received."""
|
"""Set light state when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
||||||
|
@ -144,7 +158,7 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
self._brightness = int(input_obj.get_percent() / 100.0 * 255)
|
self._brightness = int(input_obj.get_percent() / 100.0 * 255)
|
||||||
if self.brightness == 0:
|
if self.brightness == 0:
|
||||||
self._is_dimming_to_zero = False
|
self._is_dimming_to_zero = False
|
||||||
if not self._is_dimming_to_zero:
|
if not self._is_dimming_to_zero and self.brightness is not None:
|
||||||
self._is_on = self.brightness > 0
|
self._is_on = self.brightness > 0
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
@ -152,7 +166,9 @@ class LcnOutputLight(LcnEntity, LightEntity):
|
||||||
class LcnRelayLight(LcnEntity, LightEntity):
|
class LcnRelayLight(LcnEntity, LightEntity):
|
||||||
"""Representation of a LCN light for relay ports."""
|
"""Representation of a LCN light for relay ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN light."""
|
"""Initialize the LCN light."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -160,24 +176,24 @@ class LcnRelayLight(LcnEntity, LightEntity):
|
||||||
|
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.output)
|
await self.device_connection.activate_status_request_handler(self.output)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.output)
|
await self.device_connection.cancel_status_request_handler(self.output)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool:
|
||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self._is_on
|
return self._is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
||||||
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.ON
|
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.ON
|
||||||
|
@ -186,7 +202,7 @@ class LcnRelayLight(LcnEntity, LightEntity):
|
||||||
self._is_on = True
|
self._is_on = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity off."""
|
"""Turn the entity off."""
|
||||||
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
||||||
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.OFF
|
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.OFF
|
||||||
|
@ -195,7 +211,7 @@ class LcnRelayLight(LcnEntity, LightEntity):
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set light state when LCN input object (command) is received."""
|
"""Set light state when LCN input object (command) is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
"""Support for LCN scenes."""
|
"""Support for LCN scenes."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.scene import DOMAIN as DOMAIN_SCENE, Scene
|
from homeassistant.components.scene import DOMAIN as DOMAIN_SCENE, Scene
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES, CONF_SCENE
|
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES, CONF_SCENE
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import (
|
from .const import (
|
||||||
|
@ -13,21 +19,27 @@ from .const import (
|
||||||
CONF_TRANSITION,
|
CONF_TRANSITION,
|
||||||
OUTPUT_PORTS,
|
OUTPUT_PORTS,
|
||||||
)
|
)
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, get_device_connection
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_scene_entity(hass, entity_config, config_entry):
|
def create_lcn_scene_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
return LcnScene(entity_config, config_entry.entry_id, device_connection)
|
return LcnScene(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN switch entities from a config entry."""
|
"""Set up LCN switch entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -41,7 +53,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnScene(LcnEntity, Scene):
|
class LcnScene(LcnEntity, Scene):
|
||||||
"""Representation of a LCN scene."""
|
"""Representation of a LCN scene."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN scene."""
|
"""Initialize the LCN scene."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -63,7 +77,7 @@ class LcnScene(LcnEntity, Scene):
|
||||||
config[CONF_DOMAIN_DATA][CONF_TRANSITION]
|
config[CONF_DOMAIN_DATA][CONF_TRANSITION]
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_activate(self, **kwargs):
|
async def async_activate(self, **kwargs: Any) -> None:
|
||||||
"""Activate scene."""
|
"""Activate scene."""
|
||||||
await self.device_connection.activate_scene(
|
await self.device_connection.activate_scene(
|
||||||
self.register_id,
|
self.register_id,
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""Support for LCN sensors."""
|
"""Support for LCN sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.sensor import DOMAIN as DOMAIN_SENSOR, SensorEntity
|
from homeassistant.components.sensor import DOMAIN as DOMAIN_SENSOR, SensorEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
CONF_DOMAIN,
|
CONF_DOMAIN,
|
||||||
|
@ -10,6 +12,8 @@ from homeassistant.const import (
|
||||||
CONF_SOURCE,
|
CONF_SOURCE,
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import (
|
from .const import (
|
||||||
|
@ -20,13 +24,15 @@ from .const import (
|
||||||
THRESHOLDS,
|
THRESHOLDS,
|
||||||
VARIABLES,
|
VARIABLES,
|
||||||
)
|
)
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_sensor_entity(hass, entity_config, config_entry):
|
def create_lcn_sensor_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -40,7 +46,11 @@ def create_lcn_sensor_entity(hass, entity_config, config_entry):
|
||||||
return LcnLedLogicSensor(entity_config, config_entry.entry_id, device_connection)
|
return LcnLedLogicSensor(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN switch entities from a config entry."""
|
"""Set up LCN switch entities from a config entry."""
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
@ -54,7 +64,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnVariableSensor(LcnEntity, SensorEntity):
|
class LcnVariableSensor(LcnEntity, SensorEntity):
|
||||||
"""Representation of a LCN sensor for variables."""
|
"""Representation of a LCN sensor for variables."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN sensor."""
|
"""Initialize the LCN sensor."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -65,29 +77,29 @@ class LcnVariableSensor(LcnEntity, SensorEntity):
|
||||||
|
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.variable)
|
await self.device_connection.activate_status_request_handler(self.variable)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.variable)
|
await self.device_connection.cancel_status_request_handler(self.variable)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self) -> str | None:
|
||||||
"""Return the state of the entity."""
|
"""Return the state of the entity."""
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self) -> str:
|
||||||
"""Return the unit of measurement of this entity, if any."""
|
"""Return the unit of measurement of this entity, if any."""
|
||||||
return self.unit.value
|
return str(self.unit.value)
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set sensor value when LCN input object (command) is received."""
|
"""Set sensor value when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusVar)
|
not isinstance(input_obj, pypck.inputs.ModStatusVar)
|
||||||
|
@ -102,7 +114,9 @@ class LcnVariableSensor(LcnEntity, SensorEntity):
|
||||||
class LcnLedLogicSensor(LcnEntity, SensorEntity):
|
class LcnLedLogicSensor(LcnEntity, SensorEntity):
|
||||||
"""Representation of a LCN sensor for leds and logicops."""
|
"""Representation of a LCN sensor for leds and logicops."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN sensor."""
|
"""Initialize the LCN sensor."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
|
@ -115,24 +129,24 @@ class LcnLedLogicSensor(LcnEntity, SensorEntity):
|
||||||
|
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.source)
|
await self.device_connection.activate_status_request_handler(self.source)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.source)
|
await self.device_connection.cancel_status_request_handler(self.source)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self) -> str | None:
|
||||||
"""Return the state of the entity."""
|
"""Return the state of the entity."""
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set sensor value when LCN input object (command) is received."""
|
"""Set sensor value when LCN input object (command) is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusLedsAndLogicOps):
|
if not isinstance(input_obj, pypck.inputs.ModStatusLedsAndLogicOps):
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,6 +12,7 @@ from homeassistant.const import (
|
||||||
TIME_SECONDS,
|
TIME_SECONDS,
|
||||||
)
|
)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType, ServiceCallType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_KEYS,
|
CONF_KEYS,
|
||||||
|
@ -40,7 +41,12 @@ from .const import (
|
||||||
VAR_UNITS,
|
VAR_UNITS,
|
||||||
VARIABLES,
|
VARIABLES,
|
||||||
)
|
)
|
||||||
from .helpers import get_device_connection, is_address, is_states_string
|
from .helpers import (
|
||||||
|
DeviceConnectionType,
|
||||||
|
get_device_connection,
|
||||||
|
is_address,
|
||||||
|
is_states_string,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LcnServiceCall:
|
class LcnServiceCall:
|
||||||
|
@ -48,11 +54,11 @@ class LcnServiceCall:
|
||||||
|
|
||||||
schema = vol.Schema({vol.Required(CONF_ADDRESS): is_address})
|
schema = vol.Schema({vol.Required(CONF_ADDRESS): is_address})
|
||||||
|
|
||||||
def __init__(self, hass):
|
def __init__(self, hass: HomeAssistantType) -> None:
|
||||||
"""Initialize service call."""
|
"""Initialize service call."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
|
||||||
def get_device_connection(self, service):
|
def get_device_connection(self, service: ServiceCallType) -> DeviceConnectionType:
|
||||||
"""Get address connection object."""
|
"""Get address connection object."""
|
||||||
address, host_name = service.data[CONF_ADDRESS]
|
address, host_name = service.data[CONF_ADDRESS]
|
||||||
|
|
||||||
|
@ -66,7 +72,7 @@ class LcnServiceCall:
|
||||||
return device_connection
|
return device_connection
|
||||||
raise ValueError("Invalid host name.")
|
raise ValueError("Invalid host name.")
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -86,7 +92,7 @@ class OutputAbs(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
||||||
brightness = service.data[CONF_BRIGHTNESS]
|
brightness = service.data[CONF_BRIGHTNESS]
|
||||||
|
@ -110,7 +116,7 @@ class OutputRel(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
||||||
brightness = service.data[CONF_BRIGHTNESS]
|
brightness = service.data[CONF_BRIGHTNESS]
|
||||||
|
@ -131,7 +137,7 @@ class OutputToggle(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
output = pypck.lcn_defs.OutputPort[service.data[CONF_OUTPUT]]
|
||||||
transition = pypck.lcn_defs.time_to_ramp_value(
|
transition = pypck.lcn_defs.time_to_ramp_value(
|
||||||
|
@ -147,7 +153,7 @@ class Relays(LcnServiceCall):
|
||||||
|
|
||||||
schema = LcnServiceCall.schema.extend({vol.Required(CONF_STATE): is_states_string})
|
schema = LcnServiceCall.schema.extend({vol.Required(CONF_STATE): is_states_string})
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
states = [
|
states = [
|
||||||
pypck.lcn_defs.RelayStateModifier[state]
|
pypck.lcn_defs.RelayStateModifier[state]
|
||||||
|
@ -168,7 +174,7 @@ class Led(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
led = pypck.lcn_defs.LedPort[service.data[CONF_LED]]
|
led = pypck.lcn_defs.LedPort[service.data[CONF_LED]]
|
||||||
led_state = pypck.lcn_defs.LedStatus[service.data[CONF_STATE]]
|
led_state = pypck.lcn_defs.LedStatus[service.data[CONF_STATE]]
|
||||||
|
@ -196,7 +202,7 @@ class VarAbs(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
||||||
value = service.data[CONF_VALUE]
|
value = service.data[CONF_VALUE]
|
||||||
|
@ -213,7 +219,7 @@ class VarReset(LcnServiceCall):
|
||||||
{vol.Required(CONF_VARIABLE): vol.All(vol.Upper, vol.In(VARIABLES + SETPOINTS))}
|
{vol.Required(CONF_VARIABLE): vol.All(vol.Upper, vol.In(VARIABLES + SETPOINTS))}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
||||||
|
|
||||||
|
@ -239,7 +245,7 @@ class VarRel(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
var = pypck.lcn_defs.Var[service.data[CONF_VARIABLE]]
|
||||||
value = service.data[CONF_VALUE]
|
value = service.data[CONF_VALUE]
|
||||||
|
@ -260,7 +266,7 @@ class LockRegulator(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
setpoint = pypck.lcn_defs.Var[service.data[CONF_SETPOINT]]
|
setpoint = pypck.lcn_defs.Var[service.data[CONF_SETPOINT]]
|
||||||
state = service.data[CONF_STATE]
|
state = service.data[CONF_STATE]
|
||||||
|
@ -288,7 +294,7 @@ class SendKeys(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
device_connection = self.get_device_connection(service)
|
device_connection = self.get_device_connection(service)
|
||||||
|
|
||||||
|
@ -331,7 +337,7 @@ class LockKeys(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
device_connection = self.get_device_connection(service)
|
device_connection = self.get_device_connection(service)
|
||||||
|
|
||||||
|
@ -368,7 +374,7 @@ class DynText(LcnServiceCall):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
row_id = service.data[CONF_ROW] - 1
|
row_id = service.data[CONF_ROW] - 1
|
||||||
text = service.data[CONF_TEXT]
|
text = service.data[CONF_TEXT]
|
||||||
|
@ -382,7 +388,7 @@ class Pck(LcnServiceCall):
|
||||||
|
|
||||||
schema = LcnServiceCall.schema.extend({vol.Required(CONF_PCK): str})
|
schema = LcnServiceCall.schema.extend({vol.Required(CONF_PCK): str})
|
||||||
|
|
||||||
async def async_call_service(self, service):
|
async def async_call_service(self, service: ServiceCallType) -> None:
|
||||||
"""Execute service call."""
|
"""Execute service call."""
|
||||||
pck = service.data[CONF_PCK]
|
pck = service.data[CONF_PCK]
|
||||||
device_connection = self.get_device_connection(service)
|
device_connection = self.get_device_connection(service)
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
"""Support for LCN switches."""
|
"""Support for LCN switches."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import pypck
|
import pypck
|
||||||
|
|
||||||
from homeassistant.components.switch import DOMAIN as DOMAIN_SWITCH, SwitchEntity
|
from homeassistant.components.switch import DOMAIN as DOMAIN_SWITCH, SwitchEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
from homeassistant.const import CONF_ADDRESS, CONF_DOMAIN, CONF_ENTITIES
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
|
||||||
from . import LcnEntity
|
from . import LcnEntity
|
||||||
from .const import CONF_DOMAIN_DATA, CONF_OUTPUT, OUTPUT_PORTS
|
from .const import CONF_DOMAIN_DATA, CONF_OUTPUT, OUTPUT_PORTS
|
||||||
from .helpers import get_device_connection
|
from .helpers import DeviceConnectionType, InputType, get_device_connection
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
def create_lcn_switch_entity(hass, entity_config, config_entry):
|
def create_lcn_switch_entity(
|
||||||
|
hass: HomeAssistantType, entity_config: ConfigType, config_entry: ConfigEntry
|
||||||
|
) -> LcnEntity:
|
||||||
"""Set up an entity for this domain."""
|
"""Set up an entity for this domain."""
|
||||||
device_connection = get_device_connection(
|
device_connection = get_device_connection(
|
||||||
hass, tuple(entity_config[CONF_ADDRESS]), config_entry
|
hass, entity_config[CONF_ADDRESS], config_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
if entity_config[CONF_DOMAIN_DATA][CONF_OUTPUT] in OUTPUT_PORTS:
|
if entity_config[CONF_DOMAIN_DATA][CONF_OUTPUT] in OUTPUT_PORTS:
|
||||||
|
@ -24,7 +32,11 @@ def create_lcn_switch_entity(hass, entity_config, config_entry):
|
||||||
return LcnRelaySwitch(entity_config, config_entry.entry_id, device_connection)
|
return LcnRelaySwitch(entity_config, config_entry.entry_id, device_connection)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
"""Set up LCN switch entities from a config entry."""
|
"""Set up LCN switch entities from a config entry."""
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
@ -39,46 +51,48 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
class LcnOutputSwitch(LcnEntity, SwitchEntity):
|
class LcnOutputSwitch(LcnEntity, SwitchEntity):
|
||||||
"""Representation of a LCN switch for output ports."""
|
"""Representation of a LCN switch for output ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN switch."""
|
"""Initialize the LCN switch."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
self.output = pypck.lcn_defs.OutputPort[config[CONF_DOMAIN_DATA][CONF_OUTPUT]]
|
self.output = pypck.lcn_defs.OutputPort[config[CONF_DOMAIN_DATA][CONF_OUTPUT]]
|
||||||
|
|
||||||
self._is_on = None
|
self._is_on = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.output)
|
await self.device_connection.activate_status_request_handler(self.output)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.output)
|
await self.device_connection.cancel_status_request_handler(self.output)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool:
|
||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self._is_on
|
return self._is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
if not await self.device_connection.dim_output(self.output.value, 100, 0):
|
if not await self.device_connection.dim_output(self.output.value, 100, 0):
|
||||||
return
|
return
|
||||||
self._is_on = True
|
self._is_on = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity off."""
|
"""Turn the entity off."""
|
||||||
if not await self.device_connection.dim_output(self.output.value, 0, 0):
|
if not await self.device_connection.dim_output(self.output.value, 0, 0):
|
||||||
return
|
return
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set switch state when LCN input object (command) is received."""
|
"""Set switch state when LCN input object (command) is received."""
|
||||||
if (
|
if (
|
||||||
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
not isinstance(input_obj, pypck.inputs.ModStatusOutput)
|
||||||
|
@ -93,32 +107,34 @@ class LcnOutputSwitch(LcnEntity, SwitchEntity):
|
||||||
class LcnRelaySwitch(LcnEntity, SwitchEntity):
|
class LcnRelaySwitch(LcnEntity, SwitchEntity):
|
||||||
"""Representation of a LCN switch for relay ports."""
|
"""Representation of a LCN switch for relay ports."""
|
||||||
|
|
||||||
def __init__(self, config, entry_id, device_connection):
|
def __init__(
|
||||||
|
self, config: ConfigType, entry_id: str, device_connection: DeviceConnectionType
|
||||||
|
) -> None:
|
||||||
"""Initialize the LCN switch."""
|
"""Initialize the LCN switch."""
|
||||||
super().__init__(config, entry_id, device_connection)
|
super().__init__(config, entry_id, device_connection)
|
||||||
|
|
||||||
self.output = pypck.lcn_defs.RelayPort[config[CONF_DOMAIN_DATA][CONF_OUTPUT]]
|
self.output = pypck.lcn_defs.RelayPort[config[CONF_DOMAIN_DATA][CONF_OUTPUT]]
|
||||||
|
|
||||||
self._is_on = None
|
self._is_on = False
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.activate_status_request_handler(self.output)
|
await self.device_connection.activate_status_request_handler(self.output)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""Run when entity will be removed from hass."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
if not self.device_connection.is_group:
|
if not self.device_connection.is_group:
|
||||||
await self.device_connection.cancel_status_request_handler(self.output)
|
await self.device_connection.cancel_status_request_handler(self.output)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool:
|
||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self._is_on
|
return self._is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity on."""
|
"""Turn the entity on."""
|
||||||
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
||||||
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.ON
|
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.ON
|
||||||
|
@ -127,7 +143,7 @@ class LcnRelaySwitch(LcnEntity, SwitchEntity):
|
||||||
self._is_on = True
|
self._is_on = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the entity off."""
|
"""Turn the entity off."""
|
||||||
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
states = [pypck.lcn_defs.RelayStateModifier.NOCHANGE] * 8
|
||||||
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.OFF
|
states[self.output.value] = pypck.lcn_defs.RelayStateModifier.OFF
|
||||||
|
@ -136,7 +152,7 @@ class LcnRelaySwitch(LcnEntity, SwitchEntity):
|
||||||
self._is_on = False
|
self._is_on = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj: InputType) -> None:
|
||||||
"""Set switch state when LCN input object (command) is received."""
|
"""Set switch state when LCN input object (command) is received."""
|
||||||
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
if not isinstance(input_obj, pypck.inputs.ModStatusRelays):
|
||||||
return
|
return
|
||||||
|
|
11
mypy.ini
11
mypy.ini
|
@ -539,6 +539,17 @@ no_implicit_optional = true
|
||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
|
[mypy-homeassistant.components.lcn.*]
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unreachable = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.light.*]
|
[mypy-homeassistant.components.light.*]
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
disallow_incomplete_defs = true
|
disallow_incomplete_defs = true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue