Rename the package directory, imports, brand strings, env-var prefixes,
console-script entry point, and the config/data dir (~/.config/meshterm).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Decouple listening from consuming as the first step toward a full MeshCore
client. A new always-on EventHub owns the single device subscription and fans
typed MeshEvents out to any number of subscribers; passive-monitor history
logging becomes just one subscriber, so listening is now unconditional while the
on/off toggle controls only persistence.
- core/events.py: MeshEvent envelope + EventKind (OBSERVATION/MESSAGE/ACK)
- services/event_hub.py: subscribe/stream/wait_for fan-out, always-on pump
- connection.py: Device.subscribe_observations -> unified subscribe_events
emitting observations, inbound messages, and acks; add message_from_event /
ack_from_event mappers and a simulated message stream on MockDevice
- core/models.py: Message and Ack domain models
- monitor_service.py: slim to a hub subscriber (recording, not listening)
- context.py/menu.py: wire ctx.events into the session lifecycle
- config.py: connect_on_start setting (default on) to allow lazy connect
- Remove monitor --seconds / foreground capture and Device.listen; monitoring
is passive/background only
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The monitor was a blocking listen window that monopolized the app. Convert
it to an always-on background subscription that logs overheard adverts/
telemetry while the user keeps using the menu.
- Device: add subscribe_observations() as the non-blocking capture primitive;
listen() is now a thin foreground wrapper over it. Mock streams a live
packet burst + cadence instead of a bounded synth loop.
- MonitorService (ctx.monitor): owns the subscription, session/total counters,
and the on/off preference; logs each packet as it arrives.
- MonitorStore: persist on/off in <config_dir>/monitor.json, default off,
remembered between sessions and auto-resumed at launch.
- Menu: the monitor entry is now a toggle/heard-nodes control panel; the
header shows live session/total counts and repaints ~1s via refresh_interval.
- CLI monitor gains --on/--off (preference) and keeps --seconds for a scripted
foreground capture.
- Add Repository.observation_count(); README + tests (129 pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a Device.listen capability (real + mock), an Observation/HeardNode
domain model, an observations table with Repository.record_observation /
heard_nodes aggregation, and a `monitor` tool that listens for a window and
logs every overheard advert/telemetry (SNR, RSSI, shared location) to the
database. This is the longitudinal substrate later features read back.
The real-hardware event-payload mapping is best-effort and, like the trace
mapping, flagged for validation against the firmware's event schema; the mock
device synthesizes plausible adverts so the tool and tests run without a radio.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>