From 226a473d4da48a0395ab977addb370537e59dd09 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 5 Apr 2026 09:44:41 -0400 Subject: [PATCH] docs: add events subsystem reference --- docs/architecture/subsystems/events.md | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/architecture/subsystems/events.md diff --git a/docs/architecture/subsystems/events.md b/docs/architecture/subsystems/events.md new file mode 100644 index 0000000..a57147f --- /dev/null +++ b/docs/architecture/subsystems/events.md @@ -0,0 +1,43 @@ +# events + +## Purpose + +Central classifier and persistence layer for everything that happens on the MQTT bus. Subscribes to the whole bus, parses topic paths into `EventType`/`Severity`/`source_id`, writes rows into `events`, evaluates the rule engine against the arm-state FSM, and executes resulting actions (send alert, broadcast system-alert, command all cameras to record). + +## Key files + +- `vigilar/events/processor.py` — `EventProcessor`: subscribes via `bus.subscribe_all`, classifies topics in `_classify_event` (a big if-chain, no routing table), writes via `insert_event`, executes rule actions +- `vigilar/events/state.py` — `ArmStateFSM` (HOME/AWAY/NIGHT/DISARMED), publishes `Topics.SYSTEM_ARM_STATE`, persists to `arm_state_log` +- `vigilar/events/rules.py` — `RuleEngine` evaluating TOML-configured rules against topic/payload/arm-state +- `vigilar/events/history.py` — thin wrapper around `get_events`/`acknowledge_event` + +## MQTT topics + +**Subscribes:** `vigilar/#` (wildcard via `bus.subscribe_all`) +**Publishes:** +- `vigilar/system/arm_state` (from `ArmStateFSM`) +- `vigilar/system/alert` (when a rule fires `alert_all`/`push_and_record`) +- `vigilar/camera/{id}/command/record` (per-camera record command for `push_and_record`/`record_all_cameras`) + +## Database tables + +- `events` — canonical event log; every classified message becomes a row +- `arm_state_log` — arm-state transitions written by the FSM +- `pet_sightings` — inserted when classification produces `PET_DETECTED`, `PET_ESCAPE`, or `UNKNOWN_ANIMAL` +- `wildlife_sightings` — inserted for `WILDLIFE_PREDATOR`/`NUISANCE`/`PASSIVE` + +## Depends on + +- Every publisher on the bus (camera, sensors, ups, presence, detection, health, highlights, etc.) +- `storage` — uses `vigilar.storage.queries` for all inserts +- `alerts` — calls `send_alert` from `vigilar.alerts.sender` when a rule requests it + +## Consumed by + +- `alerts` — triggered indirectly via rule actions +- `web` — reads `events` table through `vigilar.storage.queries` for the timeline and SSE stream +- `highlights` — consumes the `events` table for reel scoring + +## Notes + +Classification is a hand-written if-chain keyed on the topic path. Camera `heartbeat` and `error` topics are intentionally ignored (return `None`). Person and vehicle YOLO detections ride on `camera/{id}/motion/start` and currently collapse back to a plain `MOTION_START` event — a known artefact of the publishing quirk in the camera worker. Arm-state change messages on `vigilar/system/*` are also deliberately ignored by the classifier to avoid feedback loops.