When a blob briefly drops below CV_MIN_BLOB_PX, its track is killed and respawns, causing the same person to generate multiple counts per visit (~50/min observed in field). Add a per-direction cooldown (default 5 frames ≈ 0.8s @ 5 fps) that drops subsequent entries (or exits) within the window of the last counted one. Entry and exit cooldowns are tracked independently. Fixed at compile time for now; exposing as a server-push tunable is deferred until the server-push-config branch lands. See docs/server-prompt-crossing- cooldown.md for the server-side coordination notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.5 KiB
Server-Side Prompt — Crossing Cooldown Awareness
Give this to your server-side agent after the firmware commit that introduces
CV_CROSSING_COOLDOWN_FRAMESinfirmware/lib/cv/cv.hhas been flashed to devices.
Context
The DoorCounter firmware now enforces a per-direction crossing cooldown in its CV pipeline. After a counted entry, subsequent entries within 5 frames (~1 second at 5 fps) are silently dropped on-device. Exits follow the same rule independently. This is a device-side fix for the known track-churn bug (single person producing 5+ counts per visit when their blob briefly drops below the minimum-blob-pixel threshold).
Constants live in firmware/lib/cv/cv.h:
static const uint32_t CV_CROSSING_COOLDOWN_FRAMES = 5; // per-direction
Cooldown is fixed at compile time. It is not currently a server- pushable tuning parameter.
What the server should do
-
Expect lower per-hour entry/exit counts from devices running this firmware compared to their historical baseline. This reflects suppression of false positives, not a device regression. Do not alert on the drop.
-
If you have a per-device tuning-config push mechanism (the one planned in
.agent/plan.md— server-push CV config via heartbeat response), addcooldown_framesto the sendable tuning set with:- Default:
5 - Valid range:
0..60(0 disables cooldown; 60 ≈ 12s at 5 fps) - Semantics: per-direction, applied to both entries and exits
- Persist alongside other CV tuning keys in NVS under a new key
cv_cool. - Bump the
cfg_versionscheme accordingly.
Do not ship this server-side change yet — the firmware change in this commit keeps the cooldown as a compile-time constant. A future firmware commit on
feature/server-push-configwill expose it as a runtime tunable and bumpcfg_version. Coordinate the rollout: firmware first, then server. - Default:
-
Dashboard: if you render device CV parameters in a per-device settings view, add a read-only row "Crossing cooldown (frames): 5" sourced from the firmware's compiled default. Mark it editable only once the firmware exposes it as a tunable.
-
Telemetry (optional, low priority): consider adding a field
suppressed_crossings_deltato the heartbeat or camera-events payload so operators can see how often cooldown is kicking in. This would require a firmware change; flag it as future work only if churn continues.
What NOT to do
- Do not attempt to push
cooldown_framesvia the existing config channel today — the firmware will ignore unknown fields, which is fine, but shipping server changes that assume the firmware-side plumbing exists will break the integration contract. - Do not "correct" the lower counts via server-side multiplication. The cooldown is the correct behavior; old counts were inflated by the churn bug.
Verification checklist
- Historical counts chart annotated with "firmware v{N} deployed" marker on the rollout date.
- Per-device tuning view renders cooldown row (read-only for now).
- No alert fires on the per-device count drop post-rollout.
Reference
- Firmware change:
firmware/lib/cv/cv.h(CV_CROSSING_COOLDOWN_FRAMES),firmware/lib/cv/cv.cpp(suppression logic incv_process). - Design spec:
docs/superpowers/specs/2026-04-13-door-counter-design.md§ 3.1 "Counting logic". - Unit test:
firmware/test/test_cv/test_cv.cpp::test_cooldown_suppresses_rapid_re_entry.