docs: add CLAUDE.md for SLMM
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) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HgTe8CamXAHcAmaQ6QNcog
This commit is contained in:
@@ -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`.
|
||||
Reference in New Issue
Block a user