docs(wiki): DS-2CD1047G3H-LIU main-stream ISAPI snapshot is a firmware bug — camera line to be replaced
CI / check (push) Successful in 1m1s
Build & push images / images (push) Successful in 3m20s

Full live investigation of the persistent 503 "deviceBusy" on main-stream ISAPI
snapshots (10.0.10.13): ruled out config (byte-identical to a working sibling
model), ruled out firmware age (reproduced on both the original V5.8.11 and
current V5.11.0 builds, ~15 months apart), and ruled out real resource
contention (a full channel-ID sweep shows every ID fails identically except
the one hardcoded working value, including nonexistent channels) — pointing
at a broken/incomplete ISAPI snapshot handler that mislabels itself as
"busy," not a real encoder ceiling.

RTSP main-stream frame-grab was confirmed as a working route around it, but
given the bug and the sub-stream's real-world plate-read accuracy problems,
the owner decided to replace the DS-2CD1047G3H-LIU units rather than carry
an ffmpeg/RTSP dependency to work around vendor firmware. Ingested the
vendor datasheet as a source page along the way.

Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
This commit is contained in:
2026-08-23 14:50:22 +02:00
parent 19dff97c74
commit 3a176c5cc8
5 changed files with 255 additions and 3 deletions
+108 -2
View File
@@ -1,8 +1,8 @@
---
type: entity
tags: [parking, hardware, readers, offline-first]
sources: [parking-system-architecture]
updated: 2026-07-07
sources: [parking-system-architecture, DS-2CD1047G3H-LIU]
updated: 2026-08-23
---
# LPR Camera
@@ -110,6 +110,112 @@ Covered by `packages/devices/src/drivers/camera.test.ts` (retry behaviour + the
selection). `healthCheck()` deliberately reports a live 503 as `degraded` (it surfaces a genuinely
saturated main stream rather than hiding it behind a retry).
### Main-stream ISAPI snapshot 503 is model-specific, not config — and RTSP routes around it (2026-08-23)
Live comparison, same site (park-buzi), same day, both cameras reachable via the site's port
forwards (`park-buzi.msai.al:8081` / `:8082`) and directly on the LAN (`10.0.10.13` = the `:8082`
unit):
| | `:8081` (works) | `:8082` = `10.0.10.13` (503s) |
|---|---|---|
| Model | **DS-2CD1043G2-LIU** | **DS-2CD1047G3H-LIU** |
| Firmware | V5.8.10 | V5.8.11 |
| Channel 101 config | 2560×1440, VBR, 6144 Kbps cap, 20fps | **identical** — 2560×1440, VBR, 6144 Kbps cap, 20fps |
| `SmartCodec` | disabled | disabled |
| `GET /ISAPI/Streaming/channels/101/picture` | **200**, valid JPEG | **503**, `statusCode 2 / deviceBusy` (3/3 retries, instant) |
| `GET /ISAPI/Streaming/channels/102/picture` (sub) | — | **200**, valid JPEG |
Channel-101 config is **byte-identical** between the two units (bitrate, resolution, frame rate,
SmartCodec) — this rules out "misconfigured over some ceiling" definitively; the only things that
differ are model + firmware. Combined with the [[#Source: HIKVISION DS-2CD1047G3H-LIU-F datasheet|
vendor datasheet]] fact that the G3H's **main stream has no MJPEG option** (sub-stream does), the
working theory is that this SKU's snapshot codepath has to transcode a live H.264/H.265 frame into
JPEG on demand for main, and its firmware/encoder can't do that reliably at this resolution —
while sub can serve JPEG more natively. **Treat this as a `DS-2CD1047G3H-LIU`-model limitation
(this firmware line), not a config or ISAPI-usage bug** — matches every earlier finding on this
same unit (`10.0.10.13`) in the sections below, now cross-confirmed against a working sibling model
on the same network with identical settings.
**RTSP main-stream frame-grab works and routes around it entirely**, confirmed live against
`10.0.10.13`:
```bash
ffmpeg -rtsp_transport tcp -y \
-i "rtsp://admin:<pw>@10.0.10.13:554/Streaming/Channels/101" \
-frames:v 1 -update 1 snapshot.jpg
```
Returned a valid 2560×1440 JPEG (94 KB) on the first try — same camera, same main-stream
resolution the ISAPI endpoint 503s on. This makes sense mechanically: RTSP just taps the H.264
stream the encoder is **already producing continuously** for live-view/recording; there's no
on-demand "pause and re-encode as standalone JPEG" step for the firmware to choke on, unlike the
ISAPI snapshot path. Port 554 is open on the LAN (`10.0.10.13`) but **not** forwarded through the
site's public port-forward (`park-buzi.msai.al` only exposes the HTTP/ISAPI ports, consistent with
[[network-isolation|the camera/controller network staying LAN-only]] — RTSP was only reachable
from inside the site network, never tested through the public forward).
**Not yet built**: `packages/devices/src/drivers/camera.ts` is HTTP-Digest/ISAPI only today: no
RTSP client, no `ffmpeg` child-process dependency. Adding an RTSP fallback (or RTSP-first path for
cameras that report persistent `deviceBusy` on ISAPI main) is a real architectural addition — new
process-spawn dependency, RTSP auth handling, transport selection (TCP confirmed working; UDP
untested) — not implemented as of this writing.
**Escalated from "nice to have" to a real requirement (2026-08-23): the sub-stream (768×432) is
too weak for reliable plate reads** — it fails to read plates "from time to time" in practice, so
sub-stream-only is not an acceptable permanent mitigation for this camera; RTSP-for-main is needed
for ANPR accuracy, not just for a higher-res evidence photo.
**Firmware update tested and RULED OUT as the fix (2026-08-23).** Before building the RTSP path,
checked whether this was simply a day-one bug: the camera shipped on `V5.8.11` build 250415 —
confirmed via the official Hikvision release note to be **the very first H13U firmware build that
added support for the DS-2CD1XX7G3H-LIU family at all** ("Newly add 1 series 4MP fixed-focus
cameras: DS-2CD1XX7G3H-LIU"), a plausible day-one-bug candidate. Upgraded live to **`V5.11.0` build
260701** (over a year of firmware progress, incl. an intermediate `V5.8.21_SP1` release explicitly
noting "Fix network and image potential bugs to enhance device stability"). **Result: NO CHANGE.**
Post-upgrade, `channels/101/picture` still returns `HTTP 503 / statusCode 2 / deviceBusy`, 5/5
consecutive attempts, byte-identical error body to pre-upgrade. Sub-stream (`102`) still healthy
(200, ~15KB) — camera is fine post-upgrade, just this one limitation persists.
**Superseded finding, below: "durable hardware/encoder ceiling" was the wrong framing.** At this
point in the investigation it looked like a real capacity limit (reproduced across ~15 months of
firmware). The channel-sweep test below shows that's not what's actually happening.
### The real cause: a broken/incomplete ISAPI snapshot handler, not "busy" (2026-08-23)
`deviceBusy` never meant "busy." Swept every channel/stream ID against the snapshot endpoint in
one sitting, including IDs that don't exist on this camera at all:
| channel | `GET .../channels/<id>/picture` |
|---|---|
| 1 | 503 `deviceBusy` |
| 100 | 503 `deviceBusy` |
| **101** (real main) | **503 `deviceBusy`** |
| **102** (real sub) | **200 OK** |
| 103 | 503 `deviceBusy` |
| 201 (channel 2 doesn't exist — single-channel camera) | 503 `deviceBusy` |
| 999 (garbage) | 503 `deviceBusy` |
**Every ID fails identically except exactly `102`.** A genuinely busy/saturated encoder would not
succeed on one specific value and fail the same way on nonexistent channel IDs — a real resource
contention error would 404 or behave differently on garbage input, not return the identical `Device
Busy` XML body regardless of whether the target exists. This is the signature of a **generic
fallback error path**: the firmware's snapshot handler appears to only be correctly wired for
`102` (the one channel/stream combination Hikvision evidently tested for this SKU) and returns a
stock, misleading `deviceBusy` for every other case — valid main-stream `101` included. It is a
**firmware bug that mislabels itself as resource contention**, not a real capacity ceiling — which
also fits the firmware-upgrade non-result above (a wrong-code-path bug doesn't get fixed by
"more capacity," so no firmware version fixing it would be surprising).
**Decision (2026-08-23): replace this camera line rather than build around it.** RTSP main-stream
capture is proven to work (see above) and could still be built as a `camera.ts` addition, but given
the ISAPI snapshot path is flatly broken for anything but one hardcoded channel value, and the
site's actual need (reliable plate reads — sub-stream alone isn't accurate enough) requires
full-resolution captures, the owner chose to swap out the `DS-2CD1047G3H-LIU` units rather than
carry a `ffmpeg`/RTSP dependency to route around a vendor firmware bug. The working `DS-2CD1043G2-
LIU` (`:8081` in the comparison above) has no such issue — ISAPI main-stream snapshot works
natively — and is the reference model for replacements. RTSP-frame-grab remains documented above
as a viable fallback if a `G3H`-family camera is ever unavoidable.
## Clock sync — the 1970 power-cut reset (built 2026-07-07)
Field observation (park-buzi): after a power cut these cameras come back with their clock at the