Files
parking_solution/wiki/entities/lpr-camera.md
T
julian fa65b2df86 Real Hikvision/Dahua camera driver; gate Backend-push-IP on capability
Replace the camera stub with HttpCamera: Hikvision ISAPI and Dahua CGI
snapshots over client-side HTTP Digest (new drivers/http-digest.ts).
healthCheck() now pulls a real frame instead of returning ready/stub.
Snapshot carries bytes (driver fetches); storage/imageRef is the caller's
job, keeping the adapter free of storage deps.

Fix the cosmetic Backend-push-IP field: add pushesToBackend to DeviceDriver
(only Dingtian sets it), expose as pushCapable in the catalog, and gate the
wizard's backend-IP fetch + field on it so pull-only devices hide it.

Verified on hardware (Hikvision 10.0.10.121): healthCheck ready,
captureSnapshot returns a valid JPEG.
2026-06-15 16:17:49 +02:00

3.1 KiB
Raw Blame History

type, tags, sources, updated
type tags sources updated
entity
parking
hardware
readers
offline-first
parking-system-architecture
2026-06-15

LPR Camera

License-plate-recognition camera (recommended: Milesight edge-AI LPR). For casual/transient vehicles, the plate acts as ticket + an independent record. (See parking-system-architecture §8, §9.)

  • Edge AI: recognition runs on-device, so it keeps working with no internet — fits offline-first.
  • It's a host-side identity source: only the host sees the read; the host decides and commands the relay open (the uhppote-controller is demoted to a commanded relay for that lane). See entry-exit-readers.
  • Being host-in-the-loop is good for fraud detection — you get two independent records (the host's signed append-only-event-chain entry + the controller's remote-open event) that should reconcile one-to-one; any mismatch is an anomaly.
  • Mounting: within ~15° of vehicle travel at a controlled chokepoint for best reads.

Snapshot driver (entry/exit fraud-control record)

Separate from edge-AI LPR: the camera driver (packages/devices/src/drivers/camera.ts) does snapshot-on-event — the host pulls a still over HTTP when an entry/exit fires and stores it, referenced from the signed append-only-event-chain entry as an independent record. The camera pulls, it does not push — so it is NOT pushesToBackend and the setup wizard correctly hides the "Backend push IP" field for it (gated on the driver's pushesToBackend flag; only dingtian-relay sets it).

  • Hikvision uses ISAPI: GET /ISAPI/Streaming/channels/<id>/picture (101 = ch1 main stream) with HTTP Digest auth. The "Enable Hikvision-CGI" toggle (Network → Advanced → Integration Protocol) is a different legacy CGI surface — not needed for ISAPI.
  • Dahua uses CGI: GET /cgi-bin/snapshot.cgi?channel=<n> (0-based channel; the wizard's 1-based channel is decremented).

Driver / storage boundary: the driver FETCHES the image bytes (client-side HTTP Digest in drivers/http-digest.ts) and returns them on Snapshot.bytes; storage is the caller's job (the future entry/exit flow stores the bytes + mints a durable imageRef). This keeps the device adapter free of any filesystem/blob-store dependency. healthCheck() is honest — it actually pulls a frame (exercising reachability + auth + path/channel in one shot), not a fake ready/stub.

Verified on hardware (2026-06-15)

A Hikvision unit ("Camera 20", MAC 94:e1:ac:…, Hikvision OUI) at 10.0.10.121, creds admin / admin123 (Digest), TCP 80:

  • Initial curl test confirmed the ISAPI path returns a 2688×1520 JPEG (~306 KB).
  • The real driver (no longer a stub) was then run end to end against it: healthCheck() → ready (pulled a frame), captureSnapshot() → valid image/jpeg, ~322 KB, correct JPEG magic. Digest handshake works through HttpCamera.
  • 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).