mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +00:00
Use a common base entity for Idasen Desk (#132496)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
413a578fdb
commit
5fb5e933e2
@ -4,53 +4,31 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from attr import dataclass
|
|
||||||
from bleak.exc import BleakError
|
from bleak.exc import BleakError
|
||||||
from idasen_ha.errors import AuthFailedError
|
from idasen_ha.errors import AuthFailedError
|
||||||
|
|
||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth.match import ADDRESS, BluetoothCallbackMatcher
|
from homeassistant.components.bluetooth.match import ADDRESS, BluetoothCallbackMatcher
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_ADDRESS, EVENT_HOMEASSISTANT_STOP, Platform
|
||||||
ATTR_NAME,
|
|
||||||
CONF_ADDRESS,
|
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
|
||||||
Platform,
|
|
||||||
)
|
|
||||||
from homeassistant.core import Event, HomeAssistant, callback
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers import device_registry as dr
|
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
|
||||||
|
|
||||||
from .const import DOMAIN
|
|
||||||
from .coordinator import IdasenDeskCoordinator
|
from .coordinator import IdasenDeskCoordinator
|
||||||
|
|
||||||
PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.COVER, Platform.SENSOR]
|
PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.COVER, Platform.SENSOR]
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
type IdasenDeskConfigEntry = ConfigEntry[IdasenDeskCoordinator]
|
||||||
@dataclass
|
|
||||||
class DeskData:
|
|
||||||
"""Data for the Idasen Desk integration."""
|
|
||||||
|
|
||||||
address: str
|
|
||||||
device_info: DeviceInfo
|
|
||||||
coordinator: IdasenDeskCoordinator
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: IdasenDeskConfigEntry) -> bool:
|
||||||
"""Set up IKEA Idasen from a config entry."""
|
"""Set up IKEA Idasen from a config entry."""
|
||||||
address: str = entry.data[CONF_ADDRESS].upper()
|
address: str = entry.data[CONF_ADDRESS].upper()
|
||||||
|
|
||||||
coordinator = IdasenDeskCoordinator(hass, _LOGGER, entry.title, address)
|
coordinator = IdasenDeskCoordinator(hass, _LOGGER, entry.title, address)
|
||||||
device_info = DeviceInfo(
|
entry.runtime_data = coordinator
|
||||||
name=entry.title,
|
|
||||||
connections={(dr.CONNECTION_BLUETOOTH, address)},
|
|
||||||
)
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = DeskData(
|
|
||||||
address, device_info, coordinator
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not await coordinator.async_connect():
|
if not await coordinator.async_connect():
|
||||||
@ -89,18 +67,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
async def _async_update_listener(
|
||||||
|
hass: HomeAssistant, entry: IdasenDeskConfigEntry
|
||||||
|
) -> None:
|
||||||
"""Handle options update."""
|
"""Handle options update."""
|
||||||
data: DeskData = hass.data[DOMAIN][entry.entry_id]
|
|
||||||
if entry.title != data.device_info[ATTR_NAME]:
|
|
||||||
await hass.config_entries.async_reload(entry.entry_id)
|
await hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: IdasenDeskConfigEntry) -> bool:
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||||
data: DeskData = hass.data[DOMAIN].pop(entry.entry_id)
|
coordinator = entry.runtime_data
|
||||||
await data.coordinator.async_disconnect()
|
await coordinator.async_disconnect()
|
||||||
bluetooth.async_rediscover_address(hass, data.address)
|
bluetooth.async_rediscover_address(hass, coordinator.address)
|
||||||
|
|
||||||
return unload_ok
|
return unload_ok
|
||||||
|
@ -6,14 +6,12 @@ import logging
|
|||||||
from typing import Any, Final
|
from typing import Any, Final
|
||||||
|
|
||||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DeskData, IdasenDeskCoordinator
|
from . import IdasenDeskConfigEntry, IdasenDeskCoordinator
|
||||||
from .const import DOMAIN
|
from .entity import IdasenDeskEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -45,43 +43,38 @@ BUTTONS: Final = [
|
|||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: IdasenDeskConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set buttons for device."""
|
"""Set buttons for device."""
|
||||||
data: DeskData = hass.data[DOMAIN][entry.entry_id]
|
coordinator = entry.runtime_data
|
||||||
async_add_entities(
|
async_add_entities(IdasenDeskButton(coordinator, button) for button in BUTTONS)
|
||||||
IdasenDeskButton(data.address, data.device_info, data.coordinator, button)
|
|
||||||
for button in BUTTONS
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class IdasenDeskButton(ButtonEntity):
|
class IdasenDeskButton(IdasenDeskEntity, ButtonEntity):
|
||||||
"""Defines a IdasenDesk button."""
|
"""Defines a IdasenDesk button."""
|
||||||
|
|
||||||
entity_description: IdasenDeskButtonDescription
|
entity_description: IdasenDeskButtonDescription
|
||||||
_attr_has_entity_name = True
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
address: str,
|
|
||||||
device_info: DeviceInfo,
|
|
||||||
coordinator: IdasenDeskCoordinator,
|
coordinator: IdasenDeskCoordinator,
|
||||||
description: IdasenDeskButtonDescription,
|
description: IdasenDeskButtonDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the IdasenDesk button entity."""
|
"""Initialize the IdasenDesk button entity."""
|
||||||
|
super().__init__(f"{description.key}-{coordinator.address}", coordinator)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
|
||||||
self._attr_unique_id = f"{description.key}-{address}"
|
|
||||||
self._attr_device_info = device_info
|
|
||||||
self._address = address
|
|
||||||
self._coordinator = coordinator
|
|
||||||
|
|
||||||
async def async_press(self) -> None:
|
async def async_press(self) -> None:
|
||||||
"""Triggers the IdasenDesk button press service."""
|
"""Triggers the IdasenDesk button press service."""
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Trigger %s for %s",
|
"Trigger %s for %s",
|
||||||
self.entity_description.key,
|
self.entity_description.key,
|
||||||
self._address,
|
self.coordinator.address,
|
||||||
)
|
)
|
||||||
await self.entity_description.press_action(self._coordinator)()
|
await self.entity_description.press_action(self.coordinator)()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Connect/disconnect buttons should always be available."""
|
||||||
|
return True
|
||||||
|
@ -26,20 +26,20 @@ class IdasenDeskCoordinator(DataUpdateCoordinator[int | None]):
|
|||||||
"""Init IdasenDeskCoordinator."""
|
"""Init IdasenDeskCoordinator."""
|
||||||
|
|
||||||
super().__init__(hass, logger, name=name)
|
super().__init__(hass, logger, name=name)
|
||||||
self._address = address
|
self.address = address
|
||||||
self._expected_connected = False
|
self._expected_connected = False
|
||||||
|
|
||||||
self.desk = Desk(self.async_set_updated_data)
|
self.desk = Desk(self.async_set_updated_data)
|
||||||
|
|
||||||
async def async_connect(self) -> bool:
|
async def async_connect(self) -> bool:
|
||||||
"""Connect to desk."""
|
"""Connect to desk."""
|
||||||
_LOGGER.debug("Trying to connect %s", self._address)
|
_LOGGER.debug("Trying to connect %s", self.address)
|
||||||
self._expected_connected = True
|
self._expected_connected = True
|
||||||
ble_device = bluetooth.async_ble_device_from_address(
|
ble_device = bluetooth.async_ble_device_from_address(
|
||||||
self.hass, self._address, connectable=True
|
self.hass, self.address, connectable=True
|
||||||
)
|
)
|
||||||
if ble_device is None:
|
if ble_device is None:
|
||||||
_LOGGER.debug("No BLEDevice for %s", self._address)
|
_LOGGER.debug("No BLEDevice for %s", self.address)
|
||||||
return False
|
return False
|
||||||
await self.desk.connect(ble_device)
|
await self.desk.connect(ble_device)
|
||||||
return True
|
return True
|
||||||
@ -47,7 +47,7 @@ class IdasenDeskCoordinator(DataUpdateCoordinator[int | None]):
|
|||||||
async def async_disconnect(self) -> None:
|
async def async_disconnect(self) -> None:
|
||||||
"""Disconnect from desk."""
|
"""Disconnect from desk."""
|
||||||
self._expected_connected = False
|
self._expected_connected = False
|
||||||
_LOGGER.debug("Disconnecting from %s", self._address)
|
_LOGGER.debug("Disconnecting from %s", self.address)
|
||||||
await self.desk.disconnect()
|
await self.desk.disconnect()
|
||||||
|
|
||||||
async def async_connect_if_expected(self) -> None:
|
async def async_connect_if_expected(self) -> None:
|
||||||
|
@ -12,30 +12,25 @@ from homeassistant.components.cover import (
|
|||||||
CoverEntity,
|
CoverEntity,
|
||||||
CoverEntityFeature,
|
CoverEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
|
|
||||||
from . import DeskData, IdasenDeskCoordinator
|
from . import IdasenDeskConfigEntry, IdasenDeskCoordinator
|
||||||
from .const import DOMAIN
|
from .entity import IdasenDeskEntity
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: IdasenDeskConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the cover platform for Idasen Desk."""
|
"""Set up the cover platform for Idasen Desk."""
|
||||||
data: DeskData = hass.data[DOMAIN][entry.entry_id]
|
coordinator = entry.runtime_data
|
||||||
async_add_entities(
|
async_add_entities([IdasenDeskCover(coordinator)])
|
||||||
[IdasenDeskCover(data.address, data.device_info, data.coordinator)]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class IdasenDeskCover(CoordinatorEntity[IdasenDeskCoordinator], CoverEntity):
|
class IdasenDeskCover(IdasenDeskEntity, CoverEntity):
|
||||||
"""Representation of Idasen Desk device."""
|
"""Representation of Idasen Desk device."""
|
||||||
|
|
||||||
_attr_device_class = CoverDeviceClass.DAMPER
|
_attr_device_class = CoverDeviceClass.DAMPER
|
||||||
@ -45,29 +40,14 @@ class IdasenDeskCover(CoordinatorEntity[IdasenDeskCoordinator], CoverEntity):
|
|||||||
| CoverEntityFeature.STOP
|
| CoverEntityFeature.STOP
|
||||||
| CoverEntityFeature.SET_POSITION
|
| CoverEntityFeature.SET_POSITION
|
||||||
)
|
)
|
||||||
_attr_has_entity_name = True
|
|
||||||
_attr_name = None
|
_attr_name = None
|
||||||
_attr_translation_key = "desk"
|
_attr_translation_key = "desk"
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, coordinator: IdasenDeskCoordinator) -> None:
|
||||||
self,
|
|
||||||
address: str,
|
|
||||||
device_info: DeviceInfo,
|
|
||||||
coordinator: IdasenDeskCoordinator,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize an Idasen Desk cover."""
|
"""Initialize an Idasen Desk cover."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator.address, coordinator)
|
||||||
self._desk = coordinator.desk
|
|
||||||
self._attr_unique_id = address
|
|
||||||
self._attr_device_info = device_info
|
|
||||||
|
|
||||||
self._attr_current_cover_position = self._desk.height_percent
|
self._attr_current_cover_position = self._desk.height_percent
|
||||||
|
|
||||||
@property
|
|
||||||
def available(self) -> bool:
|
|
||||||
"""Return True if entity is available."""
|
|
||||||
return super().available and self._desk.is_connected is True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> bool:
|
def is_closed(self) -> bool:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
|
34
homeassistant/components/idasen_desk/entity.py
Normal file
34
homeassistant/components/idasen_desk/entity.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"""Base entity for Idasen Desk."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from . import IdasenDeskCoordinator
|
||||||
|
|
||||||
|
|
||||||
|
class IdasenDeskEntity(CoordinatorEntity[IdasenDeskCoordinator]):
|
||||||
|
"""IdasenDesk sensor."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
unique_id: str,
|
||||||
|
coordinator: IdasenDeskCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the IdasenDesk sensor entity."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
|
||||||
|
self._attr_unique_id = unique_id
|
||||||
|
self._attr_device_info = dr.DeviceInfo(
|
||||||
|
manufacturer="LINAK",
|
||||||
|
connections={(dr.CONNECTION_BLUETOOTH, coordinator.address)},
|
||||||
|
)
|
||||||
|
self._desk = coordinator.desk
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return True if entity is available."""
|
||||||
|
return super().available and self._desk.is_connected is True
|
@ -9,10 +9,7 @@ rules:
|
|||||||
comment: |
|
comment: |
|
||||||
This integration does not use polling.
|
This integration does not use polling.
|
||||||
brands: done
|
brands: done
|
||||||
common-modules:
|
common-modules: done
|
||||||
status: todo
|
|
||||||
comment: |
|
|
||||||
The cover and sensor entities could move common initialization to a base entity class.
|
|
||||||
config-flow-test-coverage:
|
config-flow-test-coverage:
|
||||||
status: todo
|
status: todo
|
||||||
comment: |
|
comment: |
|
||||||
@ -33,7 +30,7 @@ rules:
|
|||||||
entity-event-setup: done
|
entity-event-setup: done
|
||||||
entity-unique-id: done
|
entity-unique-id: done
|
||||||
has-entity-name: done
|
has-entity-name: done
|
||||||
runtime-data: todo
|
runtime-data: done
|
||||||
test-before-configure: done
|
test-before-configure: done
|
||||||
test-before-setup: done
|
test-before-setup: done
|
||||||
unique-config-entry: done
|
unique-config-entry: done
|
||||||
|
@ -6,7 +6,6 @@ from collections.abc import Callable
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant import config_entries
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
@ -15,12 +14,10 @@ from homeassistant.components.sensor import (
|
|||||||
)
|
)
|
||||||
from homeassistant.const import UnitOfLength
|
from homeassistant.const import UnitOfLength
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
|
|
||||||
from . import DeskData, IdasenDeskCoordinator
|
from . import IdasenDeskConfigEntry, IdasenDeskCoordinator
|
||||||
from .const import DOMAIN
|
from .entity import IdasenDeskEntity
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
@ -46,51 +43,36 @@ SENSORS = (
|
|||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: config_entries.ConfigEntry,
|
entry: IdasenDeskConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Idasen Desk sensors."""
|
"""Set up Idasen Desk sensors."""
|
||||||
data: DeskData = hass.data[DOMAIN][entry.entry_id]
|
coordinator = entry.runtime_data
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
IdasenDeskSensor(
|
IdasenDeskSensor(coordinator, sensor_description)
|
||||||
data.address, data.device_info, data.coordinator, sensor_description
|
|
||||||
)
|
|
||||||
for sensor_description in SENSORS
|
for sensor_description in SENSORS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class IdasenDeskSensor(CoordinatorEntity[IdasenDeskCoordinator], SensorEntity):
|
class IdasenDeskSensor(IdasenDeskEntity, SensorEntity):
|
||||||
"""IdasenDesk sensor."""
|
"""IdasenDesk sensor."""
|
||||||
|
|
||||||
entity_description: IdasenDeskSensorDescription
|
entity_description: IdasenDeskSensorDescription
|
||||||
_attr_has_entity_name = True
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
address: str,
|
|
||||||
device_info: DeviceInfo,
|
|
||||||
coordinator: IdasenDeskCoordinator,
|
coordinator: IdasenDeskCoordinator,
|
||||||
description: IdasenDeskSensorDescription,
|
description: IdasenDeskSensorDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the IdasenDesk sensor entity."""
|
"""Initialize the IdasenDesk sensor entity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(f"{description.key}-{coordinator.address}", coordinator)
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
|
||||||
self._attr_unique_id = f"{description.key}-{address}"
|
|
||||||
self._attr_device_info = device_info
|
|
||||||
self._address = address
|
|
||||||
self._desk = coordinator.desk
|
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""When entity is added to hass."""
|
"""When entity is added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
self._update_native_value()
|
self._update_native_value()
|
||||||
|
|
||||||
@property
|
|
||||||
def available(self) -> bool:
|
|
||||||
"""Return True if entity is available."""
|
|
||||||
return super().available and self._desk.is_connected is True
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _handle_coordinator_update(self, *args: Any) -> None:
|
def _handle_coordinator_update(self, *args: Any) -> None:
|
||||||
"""Handle data update."""
|
"""Handle data update."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user