docs(wiki): camera 503/stream, alarm URL helper, reader ICMP liveness

- lpr-camera.md: "503 Device Busy" can be PERSISTENT (main-stream saturation on
  the G3H) — the real fix is sub-stream selection, not just retry.
- device-status-monitoring.md: QR reader health was false-healthy (hardcoded
  "ready") until the ICMP-ping fix; document the push-device monitoring model.
- log entries for both 2026-06-26 sessions.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-26 16:47:19 +02:00
parent dd0f6e483a
commit 898cf1953a
3 changed files with 83 additions and 2 deletions
+37 -1
View File
@@ -2,7 +2,7 @@
type: entity
tags: [parking, hardware, readers, offline-first]
sources: [parking-system-architecture]
updated: 2026-06-15
updated: 2026-06-26
---
# LPR Camera
@@ -59,6 +59,42 @@ A **Hikvision** unit ("Camera 20", MAC `94:e1:ac:…`, Hikvision OUI) at `10.0.1
- Reaching it from the WSL dev box required forcing the source address (`config.localAddress`,
threaded into the driver) — see [[wsl-dev-networking]] (multi-subnet source-selection trap).
### HTTP 503 "Device Busy" — can be PERSISTENT; the real fix is stream selection (2026-06-26)
The snapshot endpoint returns **HTTP 503** with the ISAPI body `statusCode 2` / `"Device Busy"` /
`subStatusCode deviceBusy` (occasionally **500**). It comes in two flavours, and they need different
fixes — **don't assume it's a momentary blip**:
- **Transient** — the encoder is briefly occupied (another snapshot in flight, a stream starting).
Clears on retry within a frame or two.
- **Persistent** — the **MAIN-stream encoder is saturated** and 503s on EVERY main-stream snapshot.
Confirmed on hardware (**DS-2CD1047G3H-LIU**, 2026-06-26): `channels/101/picture` → 503 on five
consecutive probes 800 ms apart, while **`channels/102/picture` (the SUB stream) → 200 every time**,
a clean ~15 KB JPEG. So the path/API was correct (the camera answered with a structured Hikvision
status); the main encoder was simply never free. A retry loop **cannot** fix this — it just delays
the failure.
**The fix that actually works: snapshot from the SUB stream.** The Hikvision ISAPI channel id is
`<channel><stream>` (e.g. ch1 main = `101`, ch1 **sub = `102`**). The driver now has a **`stream`
config field** (`1` = main, default for back-compat; `2` = sub). Set the G3H camera to **Sub (02)** in
the setup form → its status flips `degraded → ready` (verified live: pulled a 14.7 KB JPEG in ~87 ms).
The sub-stream is also the better fit for snapshot/ANPR anyway (smaller/faster; doesn't contend with
live-view/recording for the main encoder).
Two more complementary mitigations (both BUILT, for the *transient* case):
1. **Don't cause concurrent busy.** On a vehicle entry two server paths used to snapshot the same
camera at once (the ANPR bridge + the advisory `snapshotAsync`); the 2nd concurrent GET drew a 503.
They now share ONE pull via `captureSnapshotShared` (deviceId-keyed, `apps/server/src/snapshot.ts`)
— the main cause of the slow 2026-06-25 subscriber entry. See [[lane-presence-and-anpr-entry]].
2. **Retry a transient one.** `HttpCamera.captureSnapshot` retries 503/500 with a short linear backoff
(250/500/750 ms, ≤4 attempts), then fails naming it `(device busy)`; it does NOT retry 401/404
(config errors won't self-heal). This recovers a momentary blip but, by design, still fails a
PERSISTENTLY-busy main stream — the cue to switch that camera to the sub-stream.
Covered by `packages/devices/src/drivers/camera.test.ts` (retry behaviour + the main/sub path
selection). `healthCheck()` deliberately reports a live 503 as `degraded` (it surfaces a genuinely
saturated main stream rather than hiding it behind a retry).
## Camera PUSH — "Alarm Server" event notifications (2026-06-22)
Separate from the **pull** snapshot path above: newer Hikvision firmware can **push** an event to