mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Add KNX notify entity UI configuration (#177256)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2e99a5e2aa
commit
12b85bbf3f
@@ -201,6 +201,7 @@ SUPPORTED_PLATFORMS_UI: Final = {
|
||||
Platform.FAN,
|
||||
Platform.DATETIME,
|
||||
Platform.LIGHT,
|
||||
Platform.NOTIFY,
|
||||
Platform.NUMBER,
|
||||
Platform.SCENE,
|
||||
Platform.SENSOR,
|
||||
|
||||
@@ -2,19 +2,23 @@
|
||||
|
||||
from typing import override
|
||||
|
||||
from xknx import XKNX
|
||||
from xknx.devices import Notification as XknxNotification
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.notify import NotifyEntity
|
||||
from homeassistant.const import CONF_NAME, CONF_TYPE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
async_get_current_platform,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import KNX_ADDRESS, KNX_MODULE_KEY
|
||||
from .entity import KnxYamlEntity
|
||||
from .const import DOMAIN, KNX_ADDRESS, KNX_MODULE_KEY
|
||||
from .entity import KnxUiEntity, KnxUiEntityPlatformController, KnxYamlEntity
|
||||
from .knx_module import KNXModule
|
||||
from .storage.const import CONF_ENTITY, CONF_GA_SEND
|
||||
from .storage.util import ConfigExtractor
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@@ -24,36 +28,80 @@ async def async_setup_entry(
|
||||
) -> None:
|
||||
"""Set up notify(s) for KNX platform."""
|
||||
knx_module = hass.data[KNX_MODULE_KEY]
|
||||
config: list[ConfigType] = knx_module.config_yaml[Platform.NOTIFY]
|
||||
|
||||
async_add_entities(KNXNotify(knx_module, entity_config) for entity_config in config)
|
||||
|
||||
|
||||
def _create_notification_instance(xknx: XKNX, config: ConfigType) -> XknxNotification:
|
||||
"""Return a KNX Notification to be used within XKNX."""
|
||||
return XknxNotification(
|
||||
xknx,
|
||||
name=config[CONF_NAME],
|
||||
group_address=config[KNX_ADDRESS],
|
||||
value_type=config[CONF_TYPE],
|
||||
platform = async_get_current_platform()
|
||||
knx_module.config_store.add_platform(
|
||||
platform=Platform.NOTIFY,
|
||||
controller=KnxUiEntityPlatformController(
|
||||
knx_module=knx_module,
|
||||
entity_platform=platform,
|
||||
entity_class=KnxUiNotify,
|
||||
),
|
||||
)
|
||||
|
||||
entities: list[KnxYamlEntity | KnxUiEntity] = []
|
||||
if yaml_platform_config := knx_module.config_yaml.get(Platform.NOTIFY):
|
||||
entities.extend(
|
||||
KnxYamlNotify(knx_module, entity_config)
|
||||
for entity_config in yaml_platform_config
|
||||
)
|
||||
if ui_config := knx_module.config_store.data["entities"].get(Platform.NOTIFY):
|
||||
entities.extend(
|
||||
KnxUiNotify(knx_module, unique_id, config)
|
||||
for unique_id, config in ui_config.items()
|
||||
)
|
||||
if entities:
|
||||
async_add_entities(entities)
|
||||
|
||||
class KNXNotify(KnxYamlEntity, NotifyEntity):
|
||||
|
||||
class _KnxNotify(NotifyEntity):
|
||||
"""Representation of a KNX notification entity."""
|
||||
|
||||
_device: XknxNotification
|
||||
|
||||
@override
|
||||
async def async_send_message(self, message: str, title: str | None = None) -> None:
|
||||
"""Send a notification to knx bus."""
|
||||
await self._device.set(message)
|
||||
|
||||
|
||||
class KnxYamlNotify(_KnxNotify, KnxYamlEntity):
|
||||
"""Representation of a KNX notification entity configured from YAML."""
|
||||
|
||||
_device: XknxNotification
|
||||
|
||||
def __init__(self, knx_module: KNXModule, config: ConfigType) -> None:
|
||||
"""Initialize a KNX notification."""
|
||||
self._device = _create_notification_instance(knx_module.xknx, config)
|
||||
self._device = XknxNotification(
|
||||
knx_module.xknx,
|
||||
name=config[CONF_NAME],
|
||||
group_address=config[KNX_ADDRESS],
|
||||
value_type=config[CONF_TYPE],
|
||||
)
|
||||
super().__init__(
|
||||
knx_module=knx_module,
|
||||
unique_id=str(self._device.remote_value.group_address),
|
||||
entity_config=config,
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_send_message(self, message: str, title: str | None = None) -> None:
|
||||
"""Send a notification to knx bus."""
|
||||
await self._device.set(message)
|
||||
|
||||
class KnxUiNotify(_KnxNotify, KnxUiEntity):
|
||||
"""Representation of a KNX notification entity configured from UI."""
|
||||
|
||||
_device: XknxNotification
|
||||
|
||||
def __init__(
|
||||
self, knx_module: KNXModule, unique_id: str, config: ConfigType
|
||||
) -> None:
|
||||
"""Initialize a KNX notification."""
|
||||
super().__init__(
|
||||
knx_module=knx_module,
|
||||
unique_id=unique_id,
|
||||
entity_config=config[CONF_ENTITY],
|
||||
)
|
||||
knx_conf = ConfigExtractor(config[DOMAIN])
|
||||
self._device = XknxNotification(
|
||||
knx_module.xknx,
|
||||
name=config[CONF_ENTITY][CONF_NAME],
|
||||
group_address=knx_conf.get_write(CONF_GA_SEND),
|
||||
value_type=knx_conf.get_dpt(CONF_GA_SEND),
|
||||
)
|
||||
|
||||
@@ -485,6 +485,15 @@ LIGHT_KNX_SCHEMA = AllSerializeFirst(
|
||||
)
|
||||
|
||||
|
||||
NOTIFY_KNX_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_GA_SEND): GASelector(
|
||||
state=False, passive=False, write_required=True, dpt=["string"]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _number_limit_sub_validator(config: dict) -> dict:
|
||||
"""Validate min, max, and step values for a number entity."""
|
||||
dpt = config[CONF_GA_SENSOR][CONF_DPT]
|
||||
@@ -802,6 +811,7 @@ KNX_SCHEMA_FOR_PLATFORM = {
|
||||
Platform.DATETIME: DATETIME_KNX_SCHEMA,
|
||||
Platform.FAN: FAN_KNX_SCHEMA,
|
||||
Platform.LIGHT: LIGHT_KNX_SCHEMA,
|
||||
Platform.NOTIFY: NOTIFY_KNX_SCHEMA,
|
||||
Platform.NUMBER: NUMBER_KNX_SCHEMA,
|
||||
Platform.SCENE: SCENE_KNX_SCHEMA,
|
||||
Platform.SENSOR: SENSOR_KNX_SCHEMA,
|
||||
|
||||
@@ -860,6 +860,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"notify": {
|
||||
"description": "The KNX notify platform allows you to send text messages to the KNX bus.",
|
||||
"knx": {
|
||||
"ga_send": {
|
||||
"description": "The group address messages are sent to.",
|
||||
"label": "Address"
|
||||
}
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"description": "Entity for numeric datapoints. Temperature, percent, etc.",
|
||||
"knx": {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"version": 2,
|
||||
"minor_version": 4,
|
||||
"key": "knx/config_store.json",
|
||||
"data": {
|
||||
"entities": {
|
||||
"notify": {
|
||||
"knx_es_01KCXYT0WEJEQQ13SGCY1NHCYX": {
|
||||
"entity": {
|
||||
"name": "test",
|
||||
"device_info": null,
|
||||
"entity_category": null
|
||||
},
|
||||
"knx": {
|
||||
"ga_send": {
|
||||
"write": "1/0/0",
|
||||
"dpt": "16.001",
|
||||
"passive": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"expose": {},
|
||||
"time_server": {}
|
||||
}
|
||||
}
|
||||
@@ -1649,6 +1649,30 @@
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_knx_get_schema[notify]
|
||||
dict({
|
||||
'id': 1,
|
||||
'result': list([
|
||||
dict({
|
||||
'name': 'ga_send',
|
||||
'options': dict({
|
||||
'dptClasses': list([
|
||||
'string',
|
||||
]),
|
||||
'passive': False,
|
||||
'state': False,
|
||||
'write': dict({
|
||||
'required': True,
|
||||
}),
|
||||
}),
|
||||
'required': True,
|
||||
'type': 'knx_group_address',
|
||||
}),
|
||||
]),
|
||||
'success': True,
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_knx_get_schema[number]
|
||||
dict({
|
||||
'id': 1,
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
from homeassistant.components import notify
|
||||
from homeassistant.components.knx.const import KNX_ADDRESS
|
||||
from homeassistant.components.knx.schema import NotifySchema
|
||||
from homeassistant.const import CONF_NAME, CONF_TYPE
|
||||
from homeassistant.const import CONF_NAME, CONF_TYPE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import KnxEntityGenerator
|
||||
from .conftest import KNXTestKit
|
||||
|
||||
|
||||
@@ -96,3 +97,48 @@ async def test_notify_multiple_sends_with_different_encodings(
|
||||
"1/0/1",
|
||||
(71, 228, 110, 115, 101, 102, 252, 223, 99, 104, 101, 110, 0, 0),
|
||||
)
|
||||
|
||||
|
||||
async def test_notify_ui_create(
|
||||
hass: HomeAssistant,
|
||||
knx: KNXTestKit,
|
||||
create_ui_entity: KnxEntityGenerator,
|
||||
) -> None:
|
||||
"""Test creating a notify entity from the UI."""
|
||||
await knx.setup_integration()
|
||||
await create_ui_entity(
|
||||
platform=Platform.NOTIFY,
|
||||
entity_data={"name": "test"},
|
||||
knx_data={"ga_send": {"write": "1/0/0", "dpt": "16.000"}},
|
||||
)
|
||||
await hass.services.async_call(
|
||||
notify.DOMAIN,
|
||||
notify.SERVICE_SEND_MESSAGE,
|
||||
{"entity_id": "notify.test", notify.ATTR_MESSAGE: "Home Assistant"},
|
||||
blocking=True,
|
||||
)
|
||||
await knx.assert_write(
|
||||
"1/0/0",
|
||||
(72, 111, 109, 101, 32, 65, 115, 115, 105, 115, 116, 97, 110, 116),
|
||||
)
|
||||
|
||||
|
||||
async def test_notify_ui_load(
|
||||
hass: HomeAssistant,
|
||||
knx: KNXTestKit,
|
||||
) -> None:
|
||||
"""Test loading a notify entity from storage."""
|
||||
await knx.setup_integration(config_store_fixture="config_store_notify.json")
|
||||
|
||||
assert hass.states.get("notify.test")
|
||||
|
||||
await hass.services.async_call(
|
||||
notify.DOMAIN,
|
||||
notify.SERVICE_SEND_MESSAGE,
|
||||
{"entity_id": "notify.test", notify.ATTR_MESSAGE: "Home Assistant"},
|
||||
blocking=True,
|
||||
)
|
||||
await knx.assert_write(
|
||||
"1/0/0",
|
||||
(72, 111, 109, 101, 32, 65, 115, 115, 105, 115, 116, 97, 110, 116),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user