Commit Graph

5 Commits

Author SHA1 Message Date
claude
3be19028b1 Run interface poll on the event loop (fix async_dispatcher_send off-thread)
The interface-status poll was registered as a plain lambda, so
async_track_time_interval ran it in an executor thread, where its
_push_state()->async_dispatcher_send() call tripped HA's thread-safety guard.

Make refresh_interface_status a @callback (it only reads fast in-memory
interface attributes) and pass it to async_track_time_interval directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 19:19:21 +03:00
claude
f02d48777b Suppress signal handlers for the whole init (LXMF.LXMRouter too)
v1.0.2 only neutralised signal.signal around RNS.Reticulum(), but
LXMF.LXMRouter.__init__ also calls signal.signal(SIGINT/SIGTERM) (LXMRouter.py
308-309), so init still crashed with "signal only works in main thread of the
main interpreter" when the router was constructed in the executor thread.

Wrap the entire _start init (both constructors) with signal.signal neutralised
instead of just the RNS constructor. Confirmed via upstream source that the
only relevant signal registration sites are RNS/Reticulum.py:366-367 and
LXMF/LXMRouter.py:308-309, both module-attribute calls, so the module-level
patch intercepts both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 18:53:30 +03:00
claude
a80f65c442 Embed RNS cleanly: fix signal-thread crash, tame atexit/stdout, persist on stop
Root cause of setup failure: Reticulum.__init__ calls signal.signal() with no
main-thread guard, but we (correctly) initialise off the event loop in an
executor thread, where signal.signal() raises ValueError. It failed after
setting the __instance singleton, which both broke setup and caused the
"Attempt to reinitialise Reticulum" error on every retry.

- Temporarily neutralise signal.signal during RNS init so init completes in the
  executor, and so RNS does not hijack HA's SIGINT/SIGTERM (needed for clean
  shutdown under Kubernetes).
- Unregister RNS's and LXMF's atexit exit handlers, which otherwise persist
  state with blocking file I/O on the event-loop thread and detach HA's
  stdout/stderr at interpreter exit (the loop-blocking warnings seen in logs).
- Persist RNS/LXMF state ourselves off-loop on the homeassistant_stop event.

Documents the remaining non-daemon RNS worker threads as a known shutdown note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 18:46:06 +03:00
claude
f75235f9df Fix "Attempt to reinitialise Reticulum" on setup/retry
RNS.Reticulum.__init__ sets its internal singleton before it can fail partway
through init, which left our module-level _RNS_INSTANCE cache out of sync (None)
while RNS believed it was already running. Every setup retry then hit RNS's
reinit guard and raised "Attempt to reinitialise Reticulum, when it was already
running".

Use RNS.Reticulum.get_instance() as the source of truth and adopt an existing
instance instead of re-creating it (with an OSError fallback that also adopts).
Also cache and reuse the LXMF router, delivery destination, identity and
announce handler across reloads so a reload never spawns a duplicate router or
stacks announce handlers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 18:30:43 +03:00
claude
b40c527515 Add Reticulum/LXMF integration for Home Assistant
Custom integration connecting Home Assistant to a Reticulum network over a
TCPClientInterface and exchanging LXMF messages, with an Assist conversation
bridge, notify entity, sensors (incl. interface telemetry), buttons, services,
bus events and device triggers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 18:08:12 +03:00