Core Classes¶
Info
See the Class Diagram for how these relate to each other.
custom_components.supernotify.engine.SupernotifyEngine ¶
Owns the Context/registries/transports and actually delivers notifications.
This is the shared engine behind every entrypoint - notify.supernotify (via the SuperNotificationService legacy shim), supernotify.notify, and the NotifyEntity platform (RecipientNotifyEntity) - so it deliberately has no dependency on BaseNotificationService or anything else specific to the legacy notify platform. If/when HA core drops BaseNotificationService, only SuperNotificationService and its wiring in init.py need to go; this class and everything else built on it are unaffected.
| METHOD | DESCRIPTION |
|---|---|
__init__ | Initialize the service. |
async_send_message | Send a message via chosen transport, returning the notification, if one could be made |
on_mobile_action | Listen for mobile actions relevant to snooze and silence notifications |
refresh_entities | Re-publish the current state of every entity SuperNotify provides. |
reset_overrides | Put everything switched on or off at runtime back to its configured enabled state, |
tag_matches | The scenarios and entities a tag snooze would cover now, as scenario names and entity_ids |
__init__(hass, deliveries=None, template_path=None, media_path=None, media_url_prefix=None, archive=None, housekeeping=None, recipients_discovery=True, mobile_discovery=True, recipients=None, mobile_actions=None, scenarios=None, transport_configs=None, cameras=None, dupe_check=None, snooze=None, scenario_control=None, delivery_control=None) ¶
Initialize the service.
async_send_message(message='', title=None, target=None, context=None, via_notify=None, **kwargs) async ¶
Send a message via chosen transport, returning the notification, if one could be made
via_notify is the notify.* entity or action of this integration's own that the message came in through. It's refused while a notification is being delivered, since that can only be a delivery calling back into Supernotify, which could otherwise go round in a loop.
on_mobile_action(event) async ¶
Listen for mobile actions relevant to snooze and silence notifications
Example Action: event_type: mobile_app_notification_action data: foo: a origin: REMOTE time_fired: "2024-04-20T13:14:09.360708+00:00" context: id: 01HVXT93JGWEDW0KE57Z0X6Z1K parent_id: null user_id: a9dbae1a5abf33dbbad52ff82201bb17
refresh_entities() ¶
Re-publish the current state of every entity SuperNotify provides.
Entities are only refreshed once added to Home Assistant, so this is a safe no-op for any whose platform hasn't loaded (e.g. in tests that build SupernotifyEngine directly without a config entry). Must run in the event loop, as it writes entity state.
reset_overrides(kinds=OVERRIDE_KINDS, context=None) ¶
Put everything switched on or off at runtime back to its configured enabled state, returning the names reset for each kind. The state changes are attributed to context, the action call or button press asking for the reset, if given.
Walks the scenarios, recipients, deliveries and transports themselves rather than their switches, so one whose switch is disabled in the entity registry is reset too.
tag_matches(tag) ¶
The scenarios and entities a tag snooze would cover now, as scenario names and entity_ids
custom_components.supernotify.archive.NotificationArchive ¶
custom_components.supernotify.context.Context ¶
custom_components.supernotify.hass_api.HomeAssistantAPI ¶
| METHOD | DESCRIPTION |
|---|---|
async_get_camera_image | Fetch a still image directly from a camera entity, via HA's own camera component API, |
async_get_image_entity_image | Fetch a still image directly from an image entity, via HA's own image component API. |
async_real_user_ids | Active, non-system HA user ids mapped to their login username - for discovering |
build_mobile_app_cache | All enabled mobile apps |
config_entry_title_for_entity | The title of the config entry that registered this entity, if any. |
config_path | A path relative to the Home Assistant config directory, or the path itself if absolute. |
create_job | Wrap a blocking function call in a HomeAssistant awaitable job |
device_for_entity | The device this entity belongs to, if any. |
entity_ids_for_platform | entity_ids in |
entity_ids_named | Entities that can be called this, see entity_spoken_names() |
entity_spoken_names | What an entity can be called, by entity_id, object_id, friendly name or alias - and by |
find_config_entry_data | Return the data of the first enabled, non-ignored config entry for domain, if any. |
group_members | Fully expanded members of a |
hass_avail | Guard for HA functionality, largely for tests or docgen |
http_session | Client aiohttp session for async web requests |
is_own_device | True if |
load_storage | Load integration state previously persisted to Home Assistant's .storage/ area, |
mobile_app_action_exists | Whether a mobile app can be notified, by its notify action or its notify entity |
platform_for_entity | The integration that registered this entity (RegistryEntry.platform), if any. |
resolve_target_exclusion | Entity ids and device ids an |
resolve_target_selectors | Resolve HA area/floor/label selectors to the entities they reference, through the same |
save_storage | Persist integration state to Home Assistant's .storage/ area, via HA's own Store |
sender_entity_ids | The automations and scripts whose current run carries this context, i.e. what sent a notification. |
smtp_recipients | E-mail address of each recipient set up in Home Assistant's SMTP integration, to its notify entity |
subscribe_mobile_app_changes | Call |
translations | Supernotify's own strings for a translation category, in the given language or else the |
| ATTRIBUTE | DESCRIPTION |
|---|---|
media_dirs | Folders Home Assistant's media source serves, by their name in TYPE: |
media_dirs property ¶
Folders Home Assistant's media source serves, by their name in media-source://media_source/<name>/
async_get_camera_image(entity_id, timeout=10) async ¶
Fetch a still image directly from a camera entity, via HA's own camera component API, rather than triggering the camera.snapshot service and polling the filesystem for the resulting file to appear.
async_get_image_entity_image(entity_id, timeout=10) async ¶
Fetch a still image directly from an image entity, via HA's own image component API.
async_real_user_ids() async ¶
Active, non-system HA user ids mapped to their login username - for discovering recipients that have no Person record (see CONF_USER_ID in const.py), excluding internal accounts like Supervisor/Home Assistant Content that aren't real people.
build_mobile_app_cache() ¶
All enabled mobile apps
config_entry_title_for_entity(entity_id) ¶
The title of the config entry that registered this entity, if any.
config_path(path) ¶
A path relative to the Home Assistant config directory, or the path itself if absolute.
create_job(func, *args) ¶
Wrap a blocking function call in a HomeAssistant awaitable job
device_for_entity(entity_id) ¶
The device this entity belongs to, if any.
entity_ids_for_platform(domain, platform, device_model_select=None) ¶
entity_ids in domain (e.g. "notify") registered by a specific integration.
Reads the entity registry directly (not the state machine), so a freshly registered entity counts even before it has reported a first state.
device_model_select optionally filters by the backing device's model (e.g. {"exclude": ["Speaker Group"]}), same include/exclude rule shape used elsewhere.
entity_ids_named(name) ¶
Entities that can be called this, see entity_spoken_names()
entity_spoken_names(entity_id) ¶
What an entity can be called, by entity_id, object_id, friendly name or alias - and by object_id then domain, so 'driveway camera' is camera.driveway - as spoken_name() has them
find_config_entry_data(domain) ¶
Return the data of the first enabled, non-ignored config entry for domain, if any.
group_members(entity_id, _seen=None) ¶
Fully expanded members of a group.* helper or a platform group (media_player, light... groups created by the group integration expose members in an entity_id state attribute). None if not a group.
Other entities, e.g. scene.* or min/max sensor.*, also expose an entity_id attribute, so anything outside the group domain is only treated as a group if the entity registry says its platform is group.
hass_avail(property) ¶
Guard for HA functionality, largely for tests or docgen
http_session() ¶
Client aiohttp session for async web requests
is_own_device(device_id) ¶
True if device_id is this integration's own 'SuperNotify' device (see ha_device_info)
load_storage(key, version=1) async ¶
Load integration state previously persisted to Home Assistant's .storage/ area, via HA's own Store helper, or None if nothing has been persisted yet for this key.
mobile_app_action_exists(mobile_app_id) ¶
Whether a mobile app can be notified, by its notify action or its notify entity
platform_for_entity(entity_id) ¶
The integration that registered this entity (RegistryEntry.platform), if any.
resolve_target_exclusion(exclude) ¶
Entity ids and device ids an exclude block of a target leaves out, as Home Assistant 2026.11 does for entity actions - config and diagnostic entities included, and with the members of any group, so one can't come back when its group is expanded.
resolve_target_selectors(area_ids=None, floor_ids=None, label_ids=None) ¶
Resolve HA area/floor/label selectors to the entities they reference, through the same core helper as HA entity actions, so groups are expanded and entities inherit the area of their device.
save_storage(key, data, version=1) ¶
Persist integration state to Home Assistant's .storage/ area, via HA's own Store helper. Fire-and-forget: the write happens in a tracked background task rather than blocking the caller, since this is called from both sync and async contexts. Sync callers include actions without @callback (e.g. clear_snoozes), which Home Assistant runs in its executor, so off the event loop the thread-safe hass.create_task is used.
sender_entity_ids(ha_context) ¶
The automations and scripts whose current run carries this context, i.e. what sent a notification.
An automation or script writes its state with the context of the run it starts, and the actions of that run carry the same context (a script started by an automation gets it as parent), so the sender is the automation or script whose state has the context's id or its parent's
WARNING: best effort only, and not to be built on further. Home Assistant has no native way to get the original cause of a context, so this relies on the state still carrying the context of that run - a later or parallel run replaces it, and a sender further up the chain than the parent isn't found. It also scans every automation and script state on each call, so callers should only use it when the answer could matter.
smtp_recipients() ¶
E-mail address of each recipient set up in Home Assistant's SMTP integration, to its notify entity
subscribe_mobile_app_changes(on_change, cooldown=10) ¶
Call on_change once things settle after a mobile_app device, or its notify action, comes or goes
Re-pairing or renaming a phone changes its notify action, and HA registers that action a little after the device itself, so both kinds of change are debounced into one call
translations(category, language=None) async ¶
Supernotify's own strings for a translation category, in the given language or else the configured one, keyed component.supernotify.<category>.<key>, English filling in any not translated