feat(anpr): poll snapshots until a confident plate, so auto-exit works
The ANPR bridge took ONE snapshot at the camera's vehicle-alarm instant — but the
alarm fires as the car APPROACHES, so that frame's plate is small/blurry/half-in-
frame and ANPR returns a low-confidence misread ('111'@0.20). The manual test reads
the SAME car at ~100% because by then it's STOPPED at the barrier, well-framed. So
subscriber auto-exit silently never fired (read below the 0.85 floor → ignored).
Fix (the car-stops-at-the-barrier insight): the bridge now PULLS A FRESH FRAME every
ANPR_POLL_MS (1000) and re-runs ANPR until one clears VISION_ENTRY_MIN_CONFIDENCE, or
ANPR_POLL_WINDOW_MS (8000) elapses (drove off / non-subscriber → give up cleanly).
- One loop per camera (#polling set) — the camera's ~1Hz alarm re-fires JOIN the
running loop instead of spawning N concurrent loops.
- Fresh camera.captureSnapshot each tick, NOT captureSnapshotShared (its 1.5s TTL
would re-serve the same bad approach frame).
- Camera-level debounce stamp moved to AFTER a successful emit (suppresses re-fires
for ANPR_DEBOUNCE_MS once we've acted), not before the loop.
VERIFIED on hardware (DS-2CD1047G3H-LIU exit lane): 7 garbage approach frames →
AA890XX@0.999 at the barrier → signed vehicle_exit. Still advisory + fail-soft; a
barrier never opens on a low-confidence read. anpr-entry.test.ts +1 (poll
escalation low→low→high); 169 server tests green. Documented in
lane-presence-and-anpr-entry + the lpr-camera camera-fault writeup.
Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
+36
@@ -1717,3 +1717,39 @@ Gotchas that bit us (now in [[appliance-provisioning]] §7 + gotchas 7–11): `c
|
||||
(blank registry account → `no basic auth credentials`); user-mode + `/etc/komodo` root_directory →
|
||||
`Permission denied`; config key is **`core_address`** singular. [[appliance-provisioning]] §6 split:
|
||||
§6 = engine, §7 = Komodo deploy (PRIMARY) with §7c manual `booth.sh` break-glass.
|
||||
|
||||
## [2026-06-27] query | "Subscribers auto-enter but don't auto-exit" → NOT a bug; G3H main-stream snapshot is structurally dead
|
||||
|
||||
Investigated via a read-only VACUUM copy of the dev DB. Caca subscriber's ledger: clean
|
||||
entry/exit pairs until ~16:38, then 6 entries + 0 exits. Traced to the **exit camera 10.0.10.13
|
||||
(DS-2CD1047G3H-LIU)** producing only 2 reads ever (vs 60 on the entry cam) — every exit-direction
|
||||
snapshot after 16:38 was **HTTP 503 "device busy"**, so the ANPR exit read never got a frame →
|
||||
no `emitRead` → no auto-exit. The subscription-flow exit logic, camera→relay binding (relay 2 =
|
||||
exit, anpr on), and `stream: "2"` config were all **correct**. Direct hardware re-probe after a
|
||||
camera reboot + closing web connections: **sub (102) 10/10 rapid → 200 (~50 ms)**, **main (101)
|
||||
3/3 → 503 in ~20 ms (instant reject)**. So main-stream snapshots are **structurally unavailable**
|
||||
on this model (sub mandatory), and the 503 storm was **connection-slot exhaustion from manual
|
||||
main-stream testing** holding the camera's slots (reboot clears). Recorded in the
|
||||
the `g3h-main-stream-snapshot-503` LLM memory + a 2026-06-27 sharper-finding note in [[lpr-camera]]
|
||||
("503 Device Busy"). No code changed — diagnosis only.
|
||||
|
||||
## [2026-06-27] query | "Auto-exit" RESOLVED — a 4-layer CAMERA fault on the G3H, never our code
|
||||
|
||||
Continuation of the above. Drove the full diagnosis to ground using a **dumb HTTP sink**
|
||||
(`scratch-camera-sink.py`) the exit camera's Alarm Server was pointed at, to capture the verbatim
|
||||
push. Every assumption about *our* code was wrong; all real causes were camera-side on the
|
||||
**DS-2CD1047G3H-LIU** (`10.0.10.13`):
|
||||
(1) 503s were mostly **manual main-stream testing** (main 101 = instant 503 structurally; sub 102 =
|
||||
perfect) + connection-slot exhaustion (reboot clears) — NOT a retry/flow bug.
|
||||
(2) **Blocker #1:** the camera never POSTed at all (0 alarms ever vs 1126 on the entry cam); its
|
||||
**Diagnose dump showed a CORRUPT config DB** (`Main Db is broken`/`db_restore failed`/`reset cfg`) —
|
||||
factory-reset fixed it.
|
||||
(3) Gateway/DNS was a **red herring** (working cam had none; broken cam had both).
|
||||
(4) **Blocker #2:** post-reset it pushed **plain `VMD` with no target** → backend gates on
|
||||
`target=="vehicle"` (`hikvision-alarm.ts` reads `<targetType>`/`<detectionTarget>`/`<objectType>`)
|
||||
→ ignored. Enabling the AcuSense **Vehicle target filter** made the push carry
|
||||
`<targetType>vehicle</targetType>` (confirmed live on a drive-through). "VMD/Motion" is the right
|
||||
event for this class — it's the *target filter* that matters.
|
||||
Flagged an **observability gap**: a camera with `alarmPushEnabled=true` and 0 pushes ever should be
|
||||
a surfaced status (cf. the reader-liveness fix). Recorded in the `g3h-anpr-push-gotchas` memory + a
|
||||
new troubleshooting section in [[lpr-camera]]. No code changed — diagnosis + camera reconfig only.
|
||||
|
||||
Reference in New Issue
Block a user