feat(mesh): drive MeshService through the MeshMonitor HTTP gateway (Phase 2)
CI / build + unit (pull_request) Successful in 1m17s
CI / build + unit (pull_request) Successful in 1m17s
Rewire MeshService off the raw TCP socket + codec onto the Phase-1 MeshMonitorClient contract (HttpMeshMonitorClient in production, FakeMeshMonitorClient in tests): status/messages/nodes/channels/telemetry are polled (15s/1s/30s/5min/60s) instead of streamed, outbound broadcasts and DMs go through client.send(), respond/inject/notifier/command/battery/ weather behavior and all /api/* + MCP endpoint shapes are preserved. The fake TCP bridge is deleted and every consumer spec (mesh service, MCP controller, command auto-responder, battery alerts) now drives the real service through the widened fake client. Docker compose drops MESH_HOST/MESH_PORT and adds the MESHMONITOR_* env (token from .env, self-signed TLS via NODE_TLS_REJECT_UNAUTHORIZED=0). Live smoke against https://meshmonitor.kkhost.pl: getStatus -> {connected:true, myNodeNum:3994646728, longName:'SP8MK Bot', nodeResponsive:true}; getNodes -> 104 nodes. Build green, suite 17 files / 245 tests (baseline 234).
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## v0.22.0 — 2026-10-13 00:42
|
||||
|
||||
- **Phase 2: the service now reaches the Meshtastic device through the MeshMonitor HTTP gateway** (`MeshMonitorClient`) instead of a raw TCP socket + codec. `MeshService` takes an injectable client (`HttpMeshMonitorClient` in production via `MESHMONITOR_API_TOKEN`, `FakeMeshMonitorClient` in tests); a missing token means "no gateway" — the service stays disconnected and sends throw 503. The `net.Socket` connection, frame buffer, codec framing, idle watchdog and periodic reconnect are all gone; all `/api/*` REST and MCP endpoint shapes, the notifier, the command auto-responder, the battery alerts and the weather job behave as before.
|
||||
- Poll loops replace the socket: status every 15 s (5 s retries while down) gates everything; on first success the service syncs nodes → channels → telemetry → messages (the message poll takes a seen-set baseline so pre-existing traffic is not re-processed) and starts the loops: messages every `MESH_POLL_MS` (default 1 s) in `{limit: 50}` newest-first windows, nodes every 30 s, channels every 5 min, telemetry every 60 s (long-format rows are grouped into per-packet records and deduped).
|
||||
- Outbound: broadcasts ride `send({ text, channel })` on the pinned send channel (default 3, `MESH_SEND_CHANNEL`); DMs ride `send({ text, toNodeId: '!hex' })` on the primary channel in mesh terms. Gateway-rejected sends are recorded as failed tx history entries; HTTP 413 → 400 BadRequest, anything else → 503 ServiceUnavailable. `respond()` semantics are unchanged (rx → DM back to the sender unless the original was a broadcast, tx → its destination, injected → broadcast; always threaded via `replyId`).
|
||||
- Documented degradations vs the raw socket: `GET /api/device` is degraded (no device metadata / local+module config — only the firmware version when present in the node record); there is no idle-watchdog/periodic-reconnect (steady polling replaces it); world state (nodes/channels/telemetry) is not cleared when the status drops — each refreshes on its own interval.
|
||||
- **Test migration:** the `MeshService`, MCP controller, command auto-responder and battery-alert specs now drive the real service through `FakeMeshMonitorClient` — the fake TCP bridge is gone (`src/mesh/fake-bridge.ts` deleted, zero imports remain). The fake client's test API was widened to match: the constructor takes the source identity (`{ connected, nodeNum, longName, shortName }`), auto-seeds the bot's own node (the gateway always reports it), `pushNode` upserts by num, plus the existing `pushInbound`/`setDeliveryState`/`clearTraffic`/`sends[]` mirror. Suite: 17 files / 245 tests green (baseline 234).
|
||||
- **Docker:** compose drops `MESH_HOST`/`MESH_PORT` and adds `MESHMONITOR_API_TOKEN` (from `.env`, never committed), `MESHMONITOR_API_BASE` (default `https://meshmonitor.kkhost.pl/api/v1`), `MESHMONITOR_SOURCE` (default `default`), `MESHMONITOR_TIMEOUT_MS` (default 15000) and `NODE_TLS_REJECT_UNAUTHORIZED=0` (the gateway uses a self-signed certificate).
|
||||
|
||||
## v0.21.12 — 2026-10-06 08:01
|
||||
|
||||
- Battery monitoring now ignores a 0% reading: a 0 (or any non-positive) `batteryLevel` is treated as an invalid/no-data value (node has no battery wired or is misconfigured) and no longer produces a "⚠️ battery low" alert, while genuinely-low readings (1–20%) still alert exactly as before. One-line guard added to `BatteryAlertService.shouldAlert` right after the `undefined` check. Tests: 3 new specs in the `check threshold` block — a 0% node is excluded from the batch (and a lone 0% sends nothing) while a 1% node still alerts.
|
||||
|
||||
Reference in New Issue
Block a user