Use KNX UI entity platform controller class (#123128)

pull/123161/head^2
Matthias Alphart 2024-08-05 12:34:48 +02:00 committed by GitHub
parent 5b7fd29797
commit f2d99cb059
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 165 additions and 123 deletions

View File

@ -24,7 +24,7 @@ from homeassistant.helpers.typing import ConfigType
from . import KNXModule
from .const import ATTR_COUNTER, ATTR_SOURCE, DATA_KNX_CONFIG, DOMAIN
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import BinarySensorSchema
@ -43,7 +43,7 @@ async def async_setup_entry(
)
class KNXBinarySensor(KnxEntity, BinarySensorEntity, RestoreEntity):
class KNXBinarySensor(KnxYamlEntity, BinarySensorEntity, RestoreEntity):
"""Representation of a KNX binary sensor."""
_device: XknxBinarySensor

View File

@ -13,7 +13,7 @@ from homeassistant.helpers.typing import ConfigType
from . import KNXModule
from .const import CONF_PAYLOAD_LENGTH, DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_setup_entry(
@ -31,7 +31,7 @@ async def async_setup_entry(
)
class KNXButton(KnxEntity, ButtonEntity):
class KNXButton(KnxYamlEntity, ButtonEntity):
"""Representation of a KNX button."""
_device: XknxRawValue

View File

@ -35,7 +35,7 @@ from .const import (
DOMAIN,
PRESET_MODES,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import ClimateSchema
ATTR_COMMAND_VALUE = "command_value"
@ -133,7 +133,7 @@ def _create_climate(xknx: XKNX, config: ConfigType) -> XknxClimate:
)
class KNXClimate(KnxEntity, ClimateEntity):
class KNXClimate(KnxYamlEntity, ClimateEntity):
"""Representation of a KNX climate device."""
_device: XknxClimate

View File

@ -27,7 +27,7 @@ from homeassistant.helpers.typing import ConfigType
from . import KNXModule
from .const import DATA_KNX_CONFIG, DOMAIN
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import CoverSchema
@ -43,7 +43,7 @@ async def async_setup_entry(
async_add_entities(KNXCover(knx_module, entity_config) for entity_config in config)
class KNXCover(KnxEntity, CoverEntity):
class KNXCover(KnxYamlEntity, CoverEntity):
"""Representation of a KNX cover."""
_device: XknxCover

View File

@ -31,7 +31,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_setup_entry(
@ -61,7 +61,7 @@ def _create_xknx_device(xknx: XKNX, config: ConfigType) -> XknxDateDevice:
)
class KNXDateEntity(KnxEntity, DateEntity, RestoreEntity):
class KNXDateEntity(KnxYamlEntity, DateEntity, RestoreEntity):
"""Representation of a KNX date."""
_device: XknxDateDevice

View File

@ -32,7 +32,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_setup_entry(
@ -62,7 +62,7 @@ def _create_xknx_device(xknx: XKNX, config: ConfigType) -> XknxDateTimeDevice:
)
class KNXDateTimeEntity(KnxEntity, DateTimeEntity, RestoreEntity):
class KNXDateTimeEntity(KnxYamlEntity, DateTimeEntity, RestoreEntity):
"""Representation of a KNX datetime."""
_device: XknxDateTimeDevice

View File

@ -21,7 +21,7 @@ from homeassistant.util.scaling import int_states_in_range
from . import KNXModule
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import FanSchema
DEFAULT_PERCENTAGE: Final = 50
@ -39,7 +39,7 @@ async def async_setup_entry(
async_add_entities(KNXFan(knx_module, entity_config) for entity_config in config)
class KNXFan(KnxEntity, FanEntity):
class KNXFan(KnxYamlEntity, FanEntity):
"""Representation of a KNX fan."""
_device: XknxFan

View File

@ -2,30 +2,55 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any
from xknx.devices import Device as XknxDevice
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from .const import DOMAIN
from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.entity_registry import RegistryEntry
if TYPE_CHECKING:
from . import KNXModule
SIGNAL_ENTITY_REMOVE = f"{DOMAIN}_entity_remove_signal.{{}}"
from .storage.config_store import PlatformControllerBase
class KnxEntity(Entity):
class KnxUiEntityPlatformController(PlatformControllerBase):
"""Class to manage dynamic adding and reloading of UI entities."""
def __init__(
self,
knx_module: KNXModule,
entity_platform: EntityPlatform,
entity_class: type[KnxUiEntity],
) -> None:
"""Initialize the UI platform."""
self._knx_module = knx_module
self._entity_platform = entity_platform
self._entity_class = entity_class
async def create_entity(self, unique_id: str, config: dict[str, Any]) -> None:
"""Add a new UI entity."""
await self._entity_platform.async_add_entities(
[self._entity_class(self._knx_module, unique_id, config)]
)
async def update_entity(
self, entity_entry: RegistryEntry, config: dict[str, Any]
) -> None:
"""Update an existing UI entities configuration."""
await self._entity_platform.async_remove_entity(entity_entry.entity_id)
await self.create_entity(unique_id=entity_entry.unique_id, config=config)
class _KnxEntityBase(Entity):
"""Representation of a KNX entity."""
_attr_should_poll = False
def __init__(self, knx_module: KNXModule, device: XknxDevice) -> None:
"""Set up device."""
self._knx_module = knx_module
self._device = device
_knx_module: KNXModule
_device: XknxDevice
@property
def name(self) -> str:
@ -49,7 +74,7 @@ class KnxEntity(Entity):
"""Store register state change callback and start device object."""
self._device.register_device_updated_cb(self.after_update_callback)
self._device.xknx.devices.async_add(self._device)
# super call needed to have methods of mulit-inherited classes called
# super call needed to have methods of multi-inherited classes called
# eg. for restoring state (like _KNXSwitch)
await super().async_added_to_hass()
@ -59,19 +84,22 @@ class KnxEntity(Entity):
self._device.xknx.devices.async_remove(self._device)
class KnxUIEntity(KnxEntity):
class KnxYamlEntity(_KnxEntityBase):
"""Representation of a KNX entity configured from YAML."""
def __init__(self, knx_module: KNXModule, device: XknxDevice) -> None:
"""Initialize the YAML entity."""
self._knx_module = knx_module
self._device = device
class KnxUiEntity(_KnxEntityBase, ABC):
"""Representation of a KNX UI entity."""
_attr_unique_id: str
async def async_added_to_hass(self) -> None:
"""Register callbacks when entity added to hass."""
await super().async_added_to_hass()
self._knx_module.config_store.entities.add(self._attr_unique_id)
self.async_on_remove(
async_dispatcher_connect(
self.hass,
SIGNAL_ENTITY_REMOVE.format(self._attr_unique_id),
self.async_remove,
)
)
@abstractmethod
def __init__(
self, knx_module: KNXModule, unique_id: str, config: dict[str, Any]
) -> None:
"""Initialize the UI entity."""

View File

@ -19,15 +19,18 @@ from homeassistant.components.light import (
LightEntity,
)
from homeassistant.const import CONF_ENTITY_CATEGORY, CONF_NAME, Platform
from homeassistant.core import HomeAssistant, callback
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,
async_get_current_platform,
)
from homeassistant.helpers.typing import ConfigType
import homeassistant.util.color as color_util
from . import KNXModule
from .const import CONF_SYNC_STATE, DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS, ColorTempModes
from .knx_entity import KnxEntity, KnxUIEntity
from .knx_entity import KnxUiEntity, KnxUiEntityPlatformController, KnxYamlEntity
from .schema import LightSchema
from .storage.const import (
CONF_COLOR_TEMP_MAX,
@ -63,8 +66,17 @@ async def async_setup_entry(
) -> None:
"""Set up light(s) for KNX platform."""
knx_module: KNXModule = hass.data[DOMAIN]
platform = async_get_current_platform()
knx_module.config_store.add_platform(
platform=Platform.LIGHT,
controller=KnxUiEntityPlatformController(
knx_module=knx_module,
entity_platform=platform,
entity_class=KnxUiLight,
),
)
entities: list[KnxEntity] = []
entities: list[KnxYamlEntity | KnxUiEntity] = []
if yaml_platform_config := hass.data[DATA_KNX_CONFIG].get(Platform.LIGHT):
entities.extend(
KnxYamlLight(knx_module, entity_config)
@ -78,13 +90,6 @@ async def async_setup_entry(
if entities:
async_add_entities(entities)
@callback
def add_new_ui_light(unique_id: str, config: dict[str, Any]) -> None:
"""Add KNX entity at runtime."""
async_add_entities([KnxUiLight(knx_module, unique_id, config)])
knx_module.config_store.async_add_entity[Platform.LIGHT] = add_new_ui_light
def _create_yaml_light(xknx: XKNX, config: ConfigType) -> XknxLight:
"""Return a KNX Light device to be used within XKNX."""
@ -519,7 +524,7 @@ class _KnxLight(LightEntity):
await self._device.set_off()
class KnxYamlLight(_KnxLight, KnxEntity):
class KnxYamlLight(_KnxLight, KnxYamlEntity):
"""Representation of a KNX light."""
_device: XknxLight
@ -546,7 +551,7 @@ class KnxYamlLight(_KnxLight, KnxEntity):
)
class KnxUiLight(_KnxLight, KnxUIEntity):
class KnxUiLight(_KnxLight, KnxUiEntity):
"""Representation of a KNX light."""
_attr_has_entity_name = True
@ -556,11 +561,9 @@ class KnxUiLight(_KnxLight, KnxUIEntity):
self, knx_module: KNXModule, unique_id: str, config: ConfigType
) -> None:
"""Initialize of KNX light."""
super().__init__(
knx_module=knx_module,
device=_create_ui_light(
knx_module.xknx, config[DOMAIN], config[CONF_ENTITY][CONF_NAME]
),
self._knx_module = knx_module
self._device = _create_ui_light(
knx_module.xknx, config[DOMAIN], config[CONF_ENTITY][CONF_NAME]
)
self._attr_max_color_temp_kelvin: int = config[DOMAIN][CONF_COLOR_TEMP_MAX]
self._attr_min_color_temp_kelvin: int = config[DOMAIN][CONF_COLOR_TEMP_MIN]

View File

@ -20,7 +20,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import KNXModule
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_get_service(
@ -103,7 +103,7 @@ def _create_notification_instance(xknx: XKNX, config: ConfigType) -> XknxNotific
)
class KNXNotify(KnxEntity, NotifyEntity):
class KNXNotify(KnxYamlEntity, NotifyEntity):
"""Representation of a KNX notification entity."""
_device: XknxNotification

View File

@ -30,7 +30,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import NumberSchema
@ -58,7 +58,7 @@ def _create_numeric_value(xknx: XKNX, config: ConfigType) -> NumericValue:
)
class KNXNumber(KnxEntity, RestoreNumber):
class KNXNumber(KnxYamlEntity, RestoreNumber):
"""Representation of a KNX number."""
_device: NumericValue

View File

@ -15,7 +15,7 @@ from homeassistant.helpers.typing import ConfigType
from . import KNXModule
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import SceneSchema
@ -31,7 +31,7 @@ async def async_setup_entry(
async_add_entities(KNXScene(knx_module, entity_config) for entity_config in config)
class KNXScene(KnxEntity, Scene):
class KNXScene(KnxYamlEntity, Scene):
"""Representation of a KNX scene."""
_device: XknxScene

View File

@ -30,7 +30,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import SelectSchema
@ -59,7 +59,7 @@ def _create_raw_value(xknx: XKNX, config: ConfigType) -> RawValue:
)
class KNXSelect(KnxEntity, SelectEntity, RestoreEntity):
class KNXSelect(KnxYamlEntity, SelectEntity, RestoreEntity):
"""Representation of a KNX select."""
_device: RawValue

View File

@ -35,7 +35,7 @@ from homeassistant.util.enum import try_parse_enum
from . import KNXModule
from .const import ATTR_SOURCE, DATA_KNX_CONFIG, DOMAIN
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import SensorSchema
SCAN_INTERVAL = timedelta(seconds=10)
@ -141,7 +141,7 @@ def _create_sensor(xknx: XKNX, config: ConfigType) -> XknxSensor:
)
class KNXSensor(KnxEntity, SensorEntity):
class KNXSensor(KnxYamlEntity, SensorEntity):
"""Representation of a KNX sensor."""
_device: XknxSensor

View File

@ -1,6 +1,6 @@
"""KNX entity configuration store."""
from collections.abc import Callable
from abc import ABC, abstractmethod
import logging
from typing import Any, Final, TypedDict
@ -8,12 +8,10 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PLATFORM, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.storage import Store
from homeassistant.util.ulid import ulid_now
from ..const import DOMAIN
from ..knx_entity import SIGNAL_ENTITY_REMOVE
from .const import CONF_DATA
_LOGGER = logging.getLogger(__name__)
@ -33,6 +31,20 @@ class KNXConfigStoreModel(TypedDict):
entities: KNXEntityStoreModel
class PlatformControllerBase(ABC):
"""Entity platform controller base class."""
@abstractmethod
async def create_entity(self, unique_id: str, config: dict[str, Any]) -> None:
"""Create a new entity."""
@abstractmethod
async def update_entity(
self, entity_entry: er.RegistryEntry, config: dict[str, Any]
) -> None:
"""Update an existing entities configuration."""
class KNXConfigStore:
"""Manage KNX config store data."""
@ -46,12 +58,7 @@ class KNXConfigStore:
self.config_entry = config_entry
self._store = Store[KNXConfigStoreModel](hass, STORAGE_VERSION, STORAGE_KEY)
self.data = KNXConfigStoreModel(entities={})
# entities and async_add_entity are filled by platform / entity setups
self.entities: set[str] = set() # unique_id as values
self.async_add_entity: dict[
Platform, Callable[[str, dict[str, Any]], None]
] = {}
self._platform_controllers: dict[Platform, PlatformControllerBase] = {}
async def load_data(self) -> None:
"""Load config store data from storage."""
@ -62,14 +69,19 @@ class KNXConfigStore:
len(self.data["entities"]),
)
def add_platform(
self, platform: Platform, controller: PlatformControllerBase
) -> None:
"""Add platform controller."""
self._platform_controllers[platform] = controller
async def create_entity(
self, platform: Platform, data: dict[str, Any]
) -> str | None:
"""Create a new entity."""
if platform not in self.async_add_entity:
raise ConfigStoreException(f"Entity platform not ready: {platform}")
platform_controller = self._platform_controllers[platform]
unique_id = f"knx_es_{ulid_now()}"
self.async_add_entity[platform](unique_id, data)
await platform_controller.create_entity(unique_id, data)
# store data after entity was added to be sure config didn't raise exceptions
self.data["entities"].setdefault(platform, {})[unique_id] = data
await self._store.async_save(self.data)
@ -95,8 +107,7 @@ class KNXConfigStore:
self, platform: Platform, entity_id: str, data: dict[str, Any]
) -> None:
"""Update an existing entity."""
if platform not in self.async_add_entity:
raise ConfigStoreException(f"Entity platform not ready: {platform}")
platform_controller = self._platform_controllers[platform]
entity_registry = er.async_get(self.hass)
if (entry := entity_registry.async_get(entity_id)) is None:
raise ConfigStoreException(f"Entity not found: {entity_id}")
@ -108,8 +119,7 @@ class KNXConfigStore:
raise ConfigStoreException(
f"Entity not found in storage: {entity_id} - {unique_id}"
)
async_dispatcher_send(self.hass, SIGNAL_ENTITY_REMOVE.format(unique_id))
self.async_add_entity[platform](unique_id, data)
await platform_controller.update_entity(entry, data)
# store data after entity is added to make sure config doesn't raise exceptions
self.data["entities"][platform][unique_id] = data
await self._store.async_save(self.data)
@ -125,23 +135,21 @@ class KNXConfigStore:
raise ConfigStoreException(
f"Entity not found in {entry.domain}: {entry.unique_id}"
) from err
try:
self.entities.remove(entry.unique_id)
except KeyError:
_LOGGER.warning("Entity not initialized when deleted: %s", entity_id)
entity_registry.async_remove(entity_id)
await self._store.async_save(self.data)
def get_entity_entries(self) -> list[er.RegistryEntry]:
"""Get entity_ids of all configured entities by platform."""
"""Get entity_ids of all UI configured entities."""
entity_registry = er.async_get(self.hass)
unique_ids = {
uid for platform in self.data["entities"].values() for uid in platform
}
return [
registry_entry
for registry_entry in er.async_entries_for_config_entry(
entity_registry, self.config_entry.entry_id
)
if registry_entry.unique_id in self.entities
if registry_entry.unique_id in unique_ids
]

View File

@ -17,9 +17,12 @@ from homeassistant.const import (
STATE_UNKNOWN,
Platform,
)
from homeassistant.core import HomeAssistant, callback
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,
async_get_current_platform,
)
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType
@ -32,7 +35,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity, KnxUIEntity
from .knx_entity import KnxUiEntity, KnxUiEntityPlatformController, KnxYamlEntity
from .schema import SwitchSchema
from .storage.const import (
CONF_DEVICE_INFO,
@ -51,8 +54,17 @@ async def async_setup_entry(
) -> None:
"""Set up switch(es) for KNX platform."""
knx_module: KNXModule = hass.data[DOMAIN]
platform = async_get_current_platform()
knx_module.config_store.add_platform(
platform=Platform.SWITCH,
controller=KnxUiEntityPlatformController(
knx_module=knx_module,
entity_platform=platform,
entity_class=KnxUiSwitch,
),
)
entities: list[KnxEntity] = []
entities: list[KnxYamlEntity | KnxUiEntity] = []
if yaml_platform_config := hass.data[DATA_KNX_CONFIG].get(Platform.SWITCH):
entities.extend(
KnxYamlSwitch(knx_module, entity_config)
@ -66,13 +78,6 @@ async def async_setup_entry(
if entities:
async_add_entities(entities)
@callback
def add_new_ui_switch(unique_id: str, config: dict[str, Any]) -> None:
"""Add KNX entity at runtime."""
async_add_entities([KnxUiSwitch(knx_module, unique_id, config)])
knx_module.config_store.async_add_entity[Platform.SWITCH] = add_new_ui_switch
class _KnxSwitch(SwitchEntity, RestoreEntity):
"""Base class for a KNX switch."""
@ -102,7 +107,7 @@ class _KnxSwitch(SwitchEntity, RestoreEntity):
await self._device.set_off()
class KnxYamlSwitch(_KnxSwitch, KnxEntity):
class KnxYamlSwitch(_KnxSwitch, KnxYamlEntity):
"""Representation of a KNX switch configured from YAML."""
_device: XknxSwitch
@ -125,7 +130,7 @@ class KnxYamlSwitch(_KnxSwitch, KnxEntity):
self._attr_unique_id = str(self._device.switch.group_address)
class KnxUiSwitch(_KnxSwitch, KnxUIEntity):
class KnxUiSwitch(_KnxSwitch, KnxUiEntity):
"""Representation of a KNX switch configured from UI."""
_attr_has_entity_name = True
@ -134,21 +139,19 @@ class KnxUiSwitch(_KnxSwitch, KnxUIEntity):
def __init__(
self, knx_module: KNXModule, unique_id: str, config: dict[str, Any]
) -> None:
"""Initialize of KNX switch."""
super().__init__(
knx_module=knx_module,
device=XknxSwitch(
knx_module.xknx,
name=config[CONF_ENTITY][CONF_NAME],
group_address=config[DOMAIN][CONF_GA_SWITCH][CONF_GA_WRITE],
group_address_state=[
config[DOMAIN][CONF_GA_SWITCH][CONF_GA_STATE],
*config[DOMAIN][CONF_GA_SWITCH][CONF_GA_PASSIVE],
],
respond_to_read=config[DOMAIN][CONF_RESPOND_TO_READ],
sync_state=config[DOMAIN][CONF_SYNC_STATE],
invert=config[DOMAIN][CONF_INVERT],
),
"""Initialize KNX switch."""
self._knx_module = knx_module
self._device = XknxSwitch(
knx_module.xknx,
name=config[CONF_ENTITY][CONF_NAME],
group_address=config[DOMAIN][CONF_GA_SWITCH][CONF_GA_WRITE],
group_address_state=[
config[DOMAIN][CONF_GA_SWITCH][CONF_GA_STATE],
*config[DOMAIN][CONF_GA_SWITCH][CONF_GA_PASSIVE],
],
respond_to_read=config[DOMAIN][CONF_RESPOND_TO_READ],
sync_state=config[DOMAIN][CONF_SYNC_STATE],
invert=config[DOMAIN][CONF_INVERT],
)
self._attr_entity_category = config[CONF_ENTITY][CONF_ENTITY_CATEGORY]
self._attr_unique_id = unique_id

View File

@ -30,7 +30,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_setup_entry(
@ -57,7 +57,7 @@ def _create_notification(xknx: XKNX, config: ConfigType) -> XknxNotification:
)
class KNXText(KnxEntity, TextEntity, RestoreEntity):
class KNXText(KnxYamlEntity, TextEntity, RestoreEntity):
"""Representation of a KNX text."""
_device: XknxNotification

View File

@ -31,7 +31,7 @@ from .const import (
DOMAIN,
KNX_ADDRESS,
)
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
async def async_setup_entry(
@ -61,7 +61,7 @@ def _create_xknx_device(xknx: XKNX, config: ConfigType) -> XknxTimeDevice:
)
class KNXTimeEntity(KnxEntity, TimeEntity, RestoreEntity):
class KNXTimeEntity(KnxYamlEntity, TimeEntity, RestoreEntity):
"""Representation of a KNX time."""
_device: XknxTimeDevice

View File

@ -21,7 +21,7 @@ from homeassistant.helpers.typing import ConfigType
from . import KNXModule
from .const import DATA_KNX_CONFIG, DOMAIN
from .knx_entity import KnxEntity
from .knx_entity import KnxYamlEntity
from .schema import WeatherSchema
@ -75,7 +75,7 @@ def _create_weather(xknx: XKNX, config: ConfigType) -> XknxWeather:
)
class KNXWeather(KnxEntity, WeatherEntity):
class KNXWeather(KnxYamlEntity, WeatherEntity):
"""Representation of a KNX weather device."""
_device: XknxWeather