Document motion detection rollout status

This commit is contained in:
2026-03-11 14:30:00 +00:00
parent ab35b00a91
commit 662d8d7b90
4 changed files with 335 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
# Foreground Web Motion Detection Absolute Checklist
- `MWM-001` Confirm first-release scope is web camera role only and foreground-tab only.
- `MWM-002` Add detector-related state fields to [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4).
- `MWM-003` Define default motion detector config values for low-power foreground operation.
- `MWM-004` Create a dedicated detector module under `WebApp/src/lib/app/`.
- `MWM-005` Implement low-resolution frame sampling from the existing local camera stream.
- `MWM-006` Implement grayscale conversion and normalized frame-difference scoring.
- `MWM-007` Implement score smoothing or block aggregation to reduce noise flicker.
- `MWM-008` Implement detector state machine transitions `idle`, `warming_up`, `monitoring`, `triggered`, `cooldown`.
- `MWM-009` Implement adaptive sampling so idle sampling is slower than candidate-motion sampling.
- `MWM-010` Ensure the detector starts only when the device role is `camera`, preview is ready, and detection is armed.
- `MWM-011` Ensure the detector pauses or stops on camera permission loss, preview teardown, socket disconnect, or page hide.
- `MWM-012` Add camera dashboard controls for arm/disarm and sensitivity.
- `MWM-013` Add camera dashboard status UI for detector state and live motion score.
- `MWM-014` Keep existing manual motion buttons intact and usable.
- `MWM-015` Wire automatic detector trigger to the existing `startMotion` flow with `triggeredBy: "auto_motion"`.
- `MWM-016` Prevent duplicate `startMotion` calls while a motion event is already active.
- `MWM-017` Implement minimum event duration and quiet cooldown before automatic end.
- `MWM-018` Wire automatic quiet-state completion to the existing `endMotion` flow.
- `MWM-019` Add activity-log messages for detector armed/disarmed, trigger start, trigger end, and detector pause reasons.
- `MWM-020` Add local persistence for detector settings so operator choices survive reloads.
- `MWM-021` Validate that existing client notifications still fire through the unchanged backend event routes.
- `MWM-022` Validate that existing recording behavior still works for auto-started motion events.
- `MWM-023` Add unit-level tests for detector scoring and state-machine transitions.
- `MWM-024` Add integration tests or deterministic mocks for event deduplication and cooldown handling.
- `MWM-025` Perform manual runtime validation for no-motion idle scene, real person entry, lighting flicker, and camera shake.
- `MWM-026` Measure runtime CPU/thermal behavior during a long foreground session and tune defaults if needed.
- `MWM-027` Document the foreground-only assumption and known limits in project docs.
- `MWM-028` Document recommended operator settings for lowest battery and heat.
- `MWM-029` Add rollback behavior so disabling detection immediately stops the detector loop and leaves manual controls intact.
- `MWM-030` Finalize a rollout note describing first-release non-goals such as background detection and ML classification.

View File

@@ -0,0 +1,40 @@
# Foreground Web Motion Detection Execution Prompt
Implement automatic foreground-only motion detection for the web camera role using the artifacts below as the source of truth:
- [FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md)
- [FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md)
- [FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md)
## Delivery Rules
- Treat the implementation plan as authoritative for architecture and sequencing.
- Complete checklist items atomically and update the validation matrix with evidence as work lands.
- Do not silently skip hidden work such as store updates, detector lifecycle cleanup, tests, docs, and runtime validation.
- Reuse the existing backend motion lifecycle before introducing any new backend motion pipeline.
- Preserve manual motion controls and existing client notification behavior.
## Evidence Rules
- Every completed checklist item must have at least one evidence entry in the validation matrix.
- `Code` evidence must reference the file changed.
- `Test` evidence must reference a deterministic automated or manual validation step.
- `Runtime` evidence must reference an observed app behavior, command result, or manual scenario outcome.
## Completion Gates
- Automatic motion detection works only for the web `camera` role.
- The detector runs only while the browser tab is in the foreground and the detector is armed.
- The detector starts and ends existing motion events automatically without duplicate starts.
- Client notifications and recordings continue to function through existing backend routes.
- Manual motion controls still work.
- Detector settings are user-visible and persisted locally.
- Tests and runtime validation cover idle scenes, real motion, flicker, and camera shake.
## Suggested First Batch
1. Add store fields and camera dashboard controls.
2. Add the detector module with live score reporting only.
3. Tune thresholds manually on the camera dashboard.
4. Wire automatic start/end to the existing motion event flow.
5. Add tests, docs, and validation evidence.

View File

@@ -0,0 +1,229 @@
# Foreground Web Motion Detection Implementation Plan
## Summary
Implement automatic motion detection for the `camera` role in the web app while the browser remains open in the foreground on a plugged-in phone. Reuse the existing backend motion event, notification, recording, and stream flows instead of introducing a new backend motion pipeline.
## Goals
- Detect motion automatically from the local camera preview in the web app.
- Trigger the existing motion event lifecycle with minimal backend change.
- Minimize battery and heat by using low-resolution frame analysis and adaptive sampling.
- Keep the first release heuristic and deterministic rather than ML-based.
- Make behavior observable and tunable from the camera dashboard.
## Constraints
- The browser tab is assumed to remain visible in the foreground.
- The initial target is the web app camera dashboard, not the Expo mobile app.
- Existing backend endpoints remain the source of truth for motion events.
- The current camera role UX in [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:31) must continue to work.
- The current motion event routes in [Backend/routes/events.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/events.ts:35) and [Backend/routes/events.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/events.ts:142) should be reused.
## Assumptions
- Manual motion controls remain available as an operator override.
- `triggeredBy` can distinguish manual versus automatic events without a schema change.
- Persisted per-device motion settings are desirable, but an in-memory first pass is acceptable.
- The existing recording behavior tied to stream/motion events remains the intended user experience.
## Non-Goals
- True background detection while the browser tab is hidden.
- ML person/pet/vehicle classification in the first release.
- Replacing the current notification or recording architecture.
- Solving appliance-grade uptime guarantees.
## Existing Integration Points
- Camera preview and camera dashboard actions are already hosted in [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:105).
- Local camera capture and preview lifecycle already exist in [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:233).
- Manual motion start/end already call the backend in [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:1374).
- Camera-side state is stored in [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4).
## Strategy
### Phase 1: Add Motion Detector State And Controls
Add camera-side detector state to the Svelte store:
- `motionDetectionEnabled`
- `motionDetectorStatus` such as `idle`, `warming_up`, `monitoring`, `triggered`, `cooldown`
- `motionSensitivity`
- `motionSampleIntervalMs`
- `motionTriggerConsecutiveFrames`
- `motionQuietCooldownMs`
- `motionMinimumEventMs`
- `motionScore`
- `motionDebugEnabled`
Expose controls on the camera dashboard:
- Arm/disarm automatic detection
- Sensitivity slider or preset selector
- Low-power mode preset
- Live debug score and current detector state
Keep the existing manual `Simulate Motion Event` and `Stop Recording` actions for fallback.
### Phase 2: Build A Lightweight Detector Engine
Create a dedicated detector module, for example `WebApp/src/lib/app/motion-detector.js`, owned by the camera dashboard flow.
Detector design:
- Read from the existing `localCameraStream`
- Draw frames into an offscreen or hidden canvas
- Downsample aggressively to about `160x90` or `192x108`
- Convert to grayscale
- Compare the current frame against the previous smoothed frame
- Compute a normalized motion score such as changed-pixel ratio or block-delta score
- Ignore tiny isolated noise with thresholding and optional block aggregation
Battery and heat controls:
- Default sampling at `1 fps`
- Burst to `4-6 fps` only after suspicious motion begins
- Return to low sampling after cooldown
- Skip work if preview is not ready, detector is disarmed, or document visibility changes
- Avoid full-resolution processing and avoid network uploads during detection itself
### Phase 3: Add Event State Machine And Backend Reuse
Implement a camera-side state machine:
- `idle` -> `monitoring`
- `monitoring` -> `candidate_motion`
- `candidate_motion` -> `triggered`
- `triggered` -> `cooldown`
- `cooldown` -> `monitoring`
Trigger rules:
- Require `N` consecutive high-motion frames before starting an event
- Call the existing backend motion start endpoint once
- Set `triggeredBy` to `auto_motion`
- Hold the event open for at least `motionMinimumEventMs`
- Only end after the score stays below threshold for `motionQuietCooldownMs`
This keeps backend changes minimal because the existing event lifecycle already fans out realtime alerts and push notifications.
### Phase 4: Make Recording Behavior Predictable
The detector should not record constantly.
Recommended behavior:
- Motion detection itself only analyzes low-res frames locally
- When automatic motion is confirmed, call the existing start-motion flow
- Continue using the current recording logic already associated with motion and streaming
- End the motion event only after quiet cooldown, not on every instantaneous dip
This avoids repeated start/stop loops that waste device resources.
### Phase 5: Add Persistence For Operator Settings
Initial implementation can use local storage on the web app for speed.
Second step:
- Add motion settings persistence per camera device
- Store settings either in `devices.metadata` if introduced later, or in a new `device_motion_settings` table
- Load persisted settings on device registration or camera dashboard open
Suggested settings:
- Enabled/armed
- Sensitivity
- Sample interval
- Quiet cooldown
- Minimum event duration
- Optional region of interest
### Phase 6: Observability And Debugging
Add operator-visible debug surfaces:
- Current motion score
- Detector state
- Last trigger time
- Count of suppressed candidate triggers
Add activity log entries for:
- Detector armed/disarmed
- Detector warmed up
- Automatic motion started
- Automatic motion ended
- Detector paused because preview or socket is unavailable
### Phase 7: Test And Tune
Testing should cover:
- Low-motion idle scenes
- Moderate lighting flicker
- Real person entry into frame
- Camera shake false positives
- Reconnection behavior
- Event deduplication
Tuning targets:
- Low false positive rate in static indoor scenes
- Trigger latency below about `2 seconds`
- CPU usage low enough to avoid obvious thermal throttling during foreground operation
## File-Level Change Plan
Primary files:
- [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4)
- [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:233)
- [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:105)
Likely new files:
- `WebApp/src/lib/app/motion-detector.js`
- `WebApp/src/lib/app/motion-detector.test.js` or equivalent
Optional later backend files:
- [Backend/db/schema.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/db/schema.ts:14)
- [Backend/routes/devices.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/devices.ts:41)
## Risk Controls
- Use hysteresis so one threshold starts motion and a lower threshold ends it.
- Require consecutive-frame confirmation before starting events.
- Pause detection when preview, permission, or socket connectivity is unavailable.
- Keep all frame processing local and low resolution.
- Keep manual controls available during rollout.
- Ship with debug mode so threshold tuning is possible without code changes.
## Recommended Operator Settings
- Start with the `Balanced` profile on a plugged-in phone.
- Use `Low Power` if the phone runs warm or the scene is mostly static.
- Keep the browser tab visible and the camera dashboard open while detection is armed.
- Leave debug mode off during normal operation and enable it only while tuning thresholds.
- Prefer a stable camera mount and a consistent indoor lighting setup to reduce false positives.
## Acceptance Criteria
- A camera-role web device can arm automatic motion detection from the camera dashboard.
- When visible motion enters frame, the web app starts one backend motion event without duplicate starts.
- Linked clients receive the same notifications they currently receive for manual motion events.
- Motion events remain open through continuous motion and close only after quiet cooldown.
- The detector does not continuously upload frames or full video for analysis.
- Manual motion controls continue to work.
- Detector state survives normal page usage and fails safely on disconnect or permission loss.
## Recommended Delivery Order
1. Add store state and camera dashboard controls.
2. Add local detector engine with score reporting only, no event triggering.
3. Tune thresholds against manual test scenes.
4. Wire score transitions to automatic event start/end.
5. Add persistence for detector settings.
6. Add tests, docs, and rollout notes.

View File

@@ -0,0 +1,34 @@
# Foreground Web Motion Detection Validation Matrix
| Row ID | Checklist Item | Status | Code | Test | Runtime |
| --- | --- | --- | --- | --- | --- |
| `VM-MWM-001` | Confirm first-release scope is web camera role only and foreground-tab only | done | `WebApp/src/lib/app/controller.js` `shouldRunMotionDetector`; `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Constraints/Non-Goals | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-002` | Add detector-related state fields to store | done | `WebApp/src/lib/app/store.js` `createInitialState`; `WebApp/src/lib/app/controller.js` `getDefaultMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-003` | Define default detector config values | done | `WebApp/src/lib/app/controller.js` `MOTION_DETECTION_PROFILES`, `buildMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-004` | Create dedicated detector module | done | `WebApp/src/lib/app/motion-detector.js` `createMotionDetector` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-005` | Implement low-resolution frame sampling | done | `WebApp/src/lib/app/motion-detector.js` `DEFAULT_FRAME_WIDTH`, `DEFAULT_FRAME_HEIGHT`, `analyzeFrame` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-006` | Implement grayscale conversion and frame-difference scoring | done | `WebApp/src/lib/app/motion-detector.js` `computeLuma`, `computeChangedPixelRatio` | `src/lib/app/motion-detector.spec.js` `computes grayscale luminance...`, `reports the ratio...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-007` | Implement score smoothing or block aggregation | done | `WebApp/src/lib/app/motion-detector.js` `DEFAULT_SMOOTHING_FACTOR`, `analyzeFrame` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-008` | Implement detector state machine transitions | done | `WebApp/src/lib/app/motion-detector.js` `createMotionMachineSnapshot`, `applyMotionStateMachine` | `src/lib/app/motion-detector.spec.js` `requires consecutive high-motion frames...`, `holds motion until minimum duration...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-009` | Implement adaptive sampling | done | `WebApp/src/lib/app/motion-detector.js` `tick`; `WebApp/src/lib/app/controller.js` `MOTION_DETECTION_PROFILES` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-010` | Start detector only when camera role, preview, and armed state are valid | done | `WebApp/src/lib/app/controller.js` `shouldRunMotionDetector`, `applyMotionDetectionReadiness` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-011` | Pause detector on permission loss, preview teardown, disconnect, or page hide | done | `WebApp/src/lib/app/controller.js` `getMotionDetectionPauseReason`, `applyMotionDetectionReadiness`, `onVisibilityChange` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-012` | Add camera dashboard arm/disarm and sensitivity controls | done | `WebApp/src/routes/camera/+page.svelte` Automatic Detection controls; `WebApp/src/lib/app/controller.js` `setMotionDetectionEnabled`, `setMotionDetectionProfile` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-013` | Add camera dashboard detector status and score UI | done | `WebApp/src/routes/camera/+page.svelte` Detector State/Motion Score cards | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-014` | Preserve manual motion controls | done | `WebApp/src/routes/camera/+page.svelte` manual buttons; `WebApp/src/lib/app/controller.js` `actions.startMotion`, `actions.endMotion` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-015` | Trigger existing start-motion flow with `auto_motion` | done | `WebApp/src/lib/app/controller.js` `getMotionStartPayload`, `startMotionEvent`, `syncAutoMotionLifecycle`; `WebApp/src/lib/app/api.js` `events.startMotion` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-016` | Prevent duplicate automatic motion starts | done | `WebApp/src/lib/app/controller.js` `startMotionEvent`, `syncAutoMotionLifecycle`, `autoMotionTransitionInFlight` | `src/lib/app/motion-detector.spec.js` `requires consecutive high-motion frames...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-017` | Implement minimum event duration and quiet cooldown | done | `WebApp/src/lib/app/motion-detector.js` `applyMotionStateMachine`; `WebApp/src/lib/app/controller.js` `syncAutoMotionLifecycle` | `src/lib/app/motion-detector.spec.js` `holds motion until minimum duration...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-018` | Wire quiet-state completion to existing end-motion flow | done | `WebApp/src/lib/app/controller.js` `endMotionEvent`, `syncAutoMotionLifecycle`, `applyMotionDetectionReadiness` | `src/lib/app/motion-detector.spec.js` `holds motion until minimum duration...` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-019` | Add activity-log messages for detector lifecycle | done | `WebApp/src/lib/app/controller.js` `addActivity` calls in `applyMotionDetectionReadiness`, `setMotionDetectionEnabled`, `startMotionEvent`, `endMotionEvent` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-020` | Add local persistence for detector settings | done | `WebApp/src/lib/app/controller.js` `loadMotionDetectionSettings`, `persistMotionDetectionSettings`, `updateMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-021` | Validate existing client notifications still work | pending | Existing backend fan-out remains unchanged in `Backend/routes/events.ts` | | Runtime validation still required with linked client devices |
| `VM-MWM-022` | Validate recording behavior still works for auto-started events | pending | Existing recording paths remain in `WebApp/src/lib/app/controller.js` `startLocalRecording`, `endMotionEvent`, `uploadStandaloneMotionRecording` | | Runtime validation still required with an actual auto-triggered event |
| `VM-MWM-023` | Add unit tests for scoring and state-machine transitions | done | `WebApp/src/lib/app/motion-detector.js` exported helpers; `WebApp/src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` |
| `VM-MWM-024` | Add integration tests or deterministic mocks for cooldown and dedupe | in_progress | `WebApp/src/lib/app/motion-detector.spec.js` covers deterministic cooldown and trigger gating; controller dedupe still untested | `bun run test -- src/lib/app/motion-detector.spec.js` | Additional controller-level mock coverage still needed |
| `VM-MWM-025` | Perform manual validation for idle, real motion, flicker, and camera shake | pending | | | |
| `VM-MWM-026` | Measure runtime CPU and thermal behavior during long foreground session | pending | | | |
| `VM-MWM-027` | Document foreground-only assumption and limits | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Constraints/Non-Goals/Acceptance Criteria | | Doc updated in repo |
| `VM-MWM-028` | Document recommended low-battery and low-heat settings | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Battery and heat controls; Recommended Operator Settings | | Doc updated in repo |
| `VM-MWM-029` | Add immediate rollback behavior when detection is disabled | done | `WebApp/src/lib/app/controller.js` `setMotionDetectionEnabled`, `applyMotionDetectionReadiness`, `endMotionEvent` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` |
| `VM-MWM-030` | Publish rollout note for first-release non-goals | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Non-Goals | | Doc updated in repo |