Refactor from one-entry-one-identity to a hub config entry (shared RNS stack) plus config subentries of type "identity", each an independent LXMF identity with its own LXMRouter, address, device and entities. This is required because LXMRouter allows only one delivery identity per instance. - ReticulumStack: owns the single process-wide RNS instance, peer discovery and interface telemetry (hub device). - IdentityManager: one per subentry, its own LXMRouter/identity/destination and delivery callback (identity device). Signal handlers suppressed and atexit handlers tamed for each router too. - Config subentry flow (add / reconfigure identity); a first identity is seeded on stack creation. Editable announce display name = subentry title. - Per-identity "Regenerate identity" button: new address + re-announce (clears the router's single delivery destination first). - Services and events gain an "identity" field to target/distinguish identities. - Per-identity assist bridge, greeting-when-assist-off, allow-list, notify, announce/sync buttons, message counters; hub-level connectivity/telemetry/peers. Verified against current HA config_entries/entity_platform/selector and RNS/LXMF sources. Docs and en/ru translations updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
"""Notify platform for Reticulum (per identity).
|
|
|
|
Each identity exposes a ``notify`` entity that sends an LXMF message from that
|
|
identity to its configured default recipient. For arbitrary destinations use
|
|
the ``reticulum.send_message`` service.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from homeassistant.components.notify import NotifyEntity, NotifyEntityFeature
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import ServiceValidationError
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import (
|
|
CONF_DEFAULT_RECIPIENT,
|
|
CONF_DELIVERY_METHOD,
|
|
DEFAULT_DELIVERY_METHOD,
|
|
DOMAIN,
|
|
SUBENTRY_TYPE_IDENTITY,
|
|
)
|
|
from .entity import ReticulumIdentityEntity
|
|
from .reticulum_client import ReticulumError
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up per-identity notify entities."""
|
|
runtime = hass.data[DOMAIN][entry.entry_id]
|
|
for subentry in entry.subentries.values():
|
|
if subentry.subentry_type != SUBENTRY_TYPE_IDENTITY:
|
|
continue
|
|
manager = runtime.identities.get(subentry.subentry_id)
|
|
if manager is None:
|
|
continue
|
|
async_add_entities(
|
|
[ReticulumNotify(manager, entry, subentry)],
|
|
config_subentry_id=subentry.subentry_id,
|
|
)
|
|
|
|
|
|
class ReticulumNotify(ReticulumIdentityEntity, NotifyEntity):
|
|
"""Send LXMF messages from this identity to its default recipient."""
|
|
|
|
_attr_translation_key = "message"
|
|
_attr_icon = "mdi:message-fast"
|
|
_attr_supported_features = NotifyEntityFeature.TITLE
|
|
|
|
def __init__(self, manager, entry, subentry) -> None:
|
|
super().__init__(manager, entry, subentry)
|
|
self._attr_unique_id = f"{subentry.subentry_id}_notify"
|
|
|
|
async def async_send_message(self, message: str, title: str | None = None) -> None:
|
|
recipient = self._subentry.data.get(CONF_DEFAULT_RECIPIENT)
|
|
if not recipient:
|
|
raise ServiceValidationError(
|
|
"No default recipient configured for this identity. Set one in "
|
|
"the identity's options, or use the reticulum.send_message service "
|
|
"with an explicit destination."
|
|
)
|
|
method = self._subentry.data.get(
|
|
CONF_DELIVERY_METHOD, DEFAULT_DELIVERY_METHOD
|
|
)
|
|
try:
|
|
await self._manager.async_send_message(
|
|
recipient, message, title=title or "", method=method
|
|
)
|
|
except ReticulumError as err:
|
|
raise ServiceValidationError(str(err)) from err
|