1 """Support for displaying persistent notifications."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Mapping
6 from datetime
import datetime
7 from enum
import StrEnum
8 from functools
import partial
10 from typing
import Any, Final, TypedDict
12 import voluptuous
as vol
18 async_dispatcher_connect,
19 async_dispatcher_send,
27 DOMAIN =
"persistent_notification"
29 ATTR_CREATED_AT: Final =
"created_at"
30 ATTR_MESSAGE: Final =
"message"
31 ATTR_NOTIFICATION_ID: Final =
"notification_id"
32 ATTR_TITLE: Final =
"title"
33 ATTR_STATUS: Final =
"status"
37 """Persistent notification."""
46 """Persistent notification update type."""
54 SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED = SignalType[
55 UpdateType, dict[str, Notification]
56 ](
"persistent_notifications_updated")
58 SCHEMA_SERVICE_NOTIFICATION = vol.Schema(
59 {vol.Required(ATTR_NOTIFICATION_ID): cv.string}
62 _LOGGER = logging.getLogger(__name__)
64 CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
70 _callback: Callable[[UpdateType, dict[str, Notification]],
None],
72 """Register a callback."""
74 hass, SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED, _callback
82 title: str |
None =
None,
83 notification_id: str |
None =
None,
85 """Generate a notification."""
86 hass.add_job(async_create, hass, message, title, notification_id)
90 def dismiss(hass: HomeAssistant, notification_id: str) ->
None:
91 """Remove a notification."""
92 hass.add_job(async_dismiss, hass, notification_id)
100 title: str |
None =
None,
101 notification_id: str |
None =
None,
103 """Generate a notification."""
105 if notification_id
is None:
107 notifications[notification_id] = {
108 ATTR_MESSAGE: message,
109 ATTR_NOTIFICATION_ID: notification_id,
111 ATTR_CREATED_AT: dt_util.utcnow(),
116 SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED,
118 {notification_id: notifications[notification_id]},
123 @singleton.singleton(DOMAIN)
125 """Get or create notifications data."""
132 """Remove a notification."""
134 if not (notification := notifications.pop(notification_id,
None)):
138 SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED,
140 {notification_id: notification},
146 """Remove all notifications."""
148 notifications_copy = notifications.copy()
149 notifications.clear()
152 SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED,
158 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
159 """Set up the persistent notification component."""
162 def create_service(call: ServiceCall) ->
None:
163 """Handle a create notification service call."""
166 call.data[ATTR_MESSAGE],
167 call.data.get(ATTR_TITLE),
168 call.data.get(ATTR_NOTIFICATION_ID),
172 def dismiss_service(call: ServiceCall) ->
None:
173 """Handle the dismiss notification service call."""
177 def dismiss_all_service(call: ServiceCall) ->
None:
178 """Handle the dismiss all notification service call."""
181 hass.services.async_register(
187 vol.Required(ATTR_MESSAGE): cv.string,
188 vol.Optional(ATTR_TITLE): cv.string,
189 vol.Optional(ATTR_NOTIFICATION_ID): cv.string,
194 hass.services.async_register(
195 DOMAIN,
"dismiss", dismiss_service, SCHEMA_SERVICE_NOTIFICATION
198 hass.services.async_register(DOMAIN,
"dismiss_all", dismiss_all_service,
None)
200 websocket_api.async_register_command(hass, websocket_get_notifications)
201 websocket_api.async_register_command(hass, websocket_subscribe_notifications)
207 @websocket_api.websocket_command({vol.Required("type"):
"persistent_notification/get"})
211 msg: Mapping[str, Any],
213 """Return a list of persistent_notifications."""
214 connection.send_message(
215 websocket_api.result_message(
223 connection: websocket_api.ActiveConnection,
225 update_type: UpdateType,
226 notifications: dict[str, Notification],
228 """Send persistent_notification update."""
229 connection.send_message(
230 websocket_api.event_message(
231 msg_id, {
"type": update_type,
"notifications": notifications}
237 @websocket_api.websocket_command(
{vol.Required("type"):
"persistent_notification/subscribe"}
242 msg: Mapping[str, Any],
244 """Return a list of persistent_notifications."""
247 notify_func = partial(_async_send_notification_update, connection, msg_id)
249 hass, SIGNAL_PERSISTENT_NOTIFICATIONS_UPDATED, notify_func
251 connection.send_result(msg_id)
252 notify_func(UpdateType.CURRENT, notifications)
253
None _async_send_notification_update(websocket_api.ActiveConnection connection, int msg_id, UpdateType update_type, dict[str, Notification] notifications)
None create(HomeAssistant hass, str message, str|None title=None, str|None notification_id=None)
dict[str, Notification] _async_get_or_create_notifications(HomeAssistant hass)
None dismiss(HomeAssistant hass, str notification_id)
None websocket_get_notifications(HomeAssistant hass, websocket_api.ActiveConnection connection, Mapping[str, Any] msg)
None async_dismiss_all(HomeAssistant hass)
None async_dismiss(HomeAssistant hass, str notification_id)
CALLBACK_TYPE async_register_callback(HomeAssistant hass, Callable[[UpdateType, dict[str, Notification]], None] _callback)
None websocket_subscribe_notifications(HomeAssistant hass, websocket_api.ActiveConnection connection, Mapping[str, Any] msg)
bool async_setup(HomeAssistant hass, ConfigType config)
None async_create(HomeAssistant hass, str message, str|None title=None, str|None notification_id=None)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)