From 518e6f287a4fba184624b447b18654802cd58079 Mon Sep 17 00:00:00 2001 From: serversdown Date: Sat, 29 Aug 2026 07:52:52 +0000 Subject: [PATCH] docs: add CLAUDE.md for SLMM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split out of the shared ~/CLAUDE.md, which had drifted badly — it described SLMM at v0.1.0/v0.2.1 with none of the v0.4.0 design in it. Written from the changelog and the actual tree. Leads with the three things that define the current architecture: the fan-out monitor (the NL-43 has ONE TCP control connection, which is the constraint the whole design works around), the alert engine that pins the monitor on so rules evaluate 24/7, and the nl43_readings history trail for live-chart backfill. Defers to CHANGELOG.md for history rather than duplicating a version list. Stack-level context lives in ../terra-view/docs/tmi-stack.md, loaded as ~/CLAUDE.md. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HgTe8CamXAHcAmaQ6QNcog --- CLAUDE.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..129973e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,91 @@ +# CLAUDE.md — SLMM (Sound Level Meter Manager) + +Device module for **Rion NL-43 / NL-53** sound level meters. Translates +Terra-View's REST calls into the meter's ASCII command protocol over TCP, and +pulls stored data over FTP. Current version: **v0.4.0**. + +Stack-level context (which repo owns what, version pairing) lives in +`../terra-view/docs/tmi-stack.md`, which is also loaded as `~/CLAUDE.md`. + +**Terra-View never talks to a meter directly** — it always goes through here. +SLMM owns the protocol; Terra-View owns the UI and the measurement records. + +--- + +## Where things stand (updated 2026-08-29) + +v0.4.0 (2026-06-22) is the current release. The three things that define the +current design: + +- **Fan-out live monitor.** The NL-43 has **one** TCP control connection, and + every dashboard used to fight for it. Now a single poller reads the device and + all subscribers share one cached feed: `WS /api/nl43/{unit_id}/monitor` + delivers an instant first frame from cache, then live updates. Poll rate + adapts to demand, unreachable devices back off, and the background poller + skips units already covered by an active monitor so nothing double-polls. +- **Alert engine.** Per-device threshold rules (metric + threshold + cooldown) + with full CRUD, an onset/clear state machine, and acknowledgement. Enabled + rules **pin the monitor on**, so they evaluate 24/7 with no UI client + connected. Editing or deleting a rule resets its state and closes any open + event. +- **History for chart backfill.** A downsampled trail persists to `nl43_readings` + and is served from `GET /api/nl43/{unit_id}/history`, so live charts can fill + in recent history on load. L1/L10 percentiles are surfaced in status and the + live feed. + +`CHANGELOG.md` is the authority for anything older; prefer it over prose here. + +--- + +## Layout + +``` +app/ + main.py FastAPI app + health checks + routers.py all REST endpoints + services.py NL43Client — TCP + FTP protocol + monitor.py the fan-out live feed + background_poller.py scheduled polling + alerts.py rule evaluation + event state machine + models.py NL43Config, NL43Status, nl43_readings + database.py SQLAlchemy / SQLite (data/slmm.db) + device_logger.py +docs/ manuals/ templates/ nl52/ SLM-stress-test/ +``` + +Key docs: `docs/API.md` (endpoint reference with curl examples), +`docs/COMMUNICATION_GUIDE.md` and `docs/nl43_Command_ref.md` (protocol). + +--- + +## API surface + +``` +GET/PUT /api/nl43/{unit}/config +GET /api/nl43/{unit}/status cached snapshot +GET /api/nl43/{unit}/live fresh read +POST /api/nl43/{unit}/{start|stop|pause|resume|reset|store} +GET /api/nl43/{unit}/{battery|clock|results|settings} +WS /api/nl43/{unit}/monitor fan-out live feed +POST /api/nl43/{unit}/monitor/{start|stop} +GET /api/nl43/_monitor/status +GET /api/nl43/{unit}/history backfill trail + .../alerts/rules .../alerts/events .../events/{id}/ack +POST/GET /api/nl43/{unit}/ftp/{enable|disable|status|files|download} +GET /api/nl43/{unit}/overwrite-check BEFORE changing a store name +``` + +--- + +## Gotchas + +- **One TCP connection per meter.** This is the constraint the whole monitor + design exists to work around. Never add a code path that opens its own + connection alongside the monitor. +- **1-second minimum between commands.** The NL-43 protocol requires it; SLMM + enforces it automatically. Do not "optimise" it away. +- **Check `overwrite-check` before changing a store name** — otherwise you can + destroy data on the meter's SD card. +- **FTP is active mode** — the device connects *back* to the server on port 21. +- **`network_mode: host`** in compose, for direct network access to meters. +- Environment: `PORT` (8100), `CORS_ORIGINS`, `TIMEZONE_OFFSET`, `TIMEZONE_NAME`.