3 Commits

Author SHA1 Message Date
julian 3a176c5cc8 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
2026-08-23 14:50:22 +02:00
julian 19dff97c74 fix(web): permission-degrade the app shell for merchant-only users
Build desktop / desktop (push) Successful in 4m51s
Build & push images / images (push) Successful in 3m8s
CI / check (push) Successful in 52s
A user whose role has only validation:create (the bar/lavazh validator) made
the shell misbehave: useLiveFeed() connected /api/ws unconditionally, the
server's report:read guard 403'd the upgrade, and the capped-backoff
reconnect hammered it forever — a 403 in the server log every few seconds.
Gate the socket on report:read (mirrors routes/ws.ts WATCH_PERMISSION) and
render StatusDot / ShiftButton / DeviceFooter only with their backing
permissions (report:read / shift:read / device:read), so a merchant's shell
is just the nav + their /validate screen, with zero doomed requests.

Claude-Session: https://claude.ai/code/session_01YYkpEsLmoQPaize5ec3oUm
2026-07-13 20:12:43 +02:00
julian 0ed43239c3 bump(resources): update TAG to stage-28bd838 for deployment consistency
Build & push images / images (push) Successful in 3m1s
CI / check (push) Successful in 48s
2026-07-13 20:11:27 +02:00
9 changed files with 290 additions and 14 deletions
+15 -3
View File
@@ -23,7 +23,14 @@ type WsMessage =
| { kind: "plate-recognized"; plate: { identity: string; plate: string; direction: "entry" | "exit" } }; | { kind: "plate-recognized"; plate: { identity: string; plate: string; direction: "entry" | "exit" } };
export function useLiveFeed(): void { /**
* @param enabled Gate on the WATCHER permission (`report:read` — mirrors the server's
* WS guard in routes/ws.ts). A user whose role lacks it (e.g. a merchant validator
* with only `validation:create`) must not attempt the socket at all: the server
* 403s the upgrade and the capped-backoff reconnect would otherwise hammer it
* forever, filling the server log with a 403 every few seconds.
*/
export function useLiveFeed(enabled: boolean = true): void {
const qc = useQueryClient(); const qc = useQueryClient();
const { setStatus, setOccupancy, pushEvent, setDevices, upsertDevice, setLanes, setRadar, patchPlate } = const { setStatus, setOccupancy, pushEvent, setDevices, upsertDevice, setLanes, setRadar, patchPlate } =
useLiveStore(); useLiveStore();
@@ -34,6 +41,10 @@ export function useLiveFeed(): void {
const closedRef = useRef(false); const closedRef = useRef(false);
useEffect(() => { useEffect(() => {
if (!enabled) {
setStatus("closed");
return;
}
closedRef.current = false; closedRef.current = false;
const connect = () => { const connect = () => {
@@ -117,7 +128,8 @@ export function useLiveFeed(): void {
sockRef.current?.close(); sockRef.current?.close();
sockRef.current = null; sockRef.current = null;
}; };
// qc / store setters are stable; run once on mount. // qc / store setters are stable; re-run only if the permission gate flips
// (login as a different role without a full reload).
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, [enabled]);
} }
+14 -6
View File
@@ -448,11 +448,17 @@ function ConfirmFigure({ label, value, bold, sub }: { label: string; value: stri
function RootLayout() { function RootLayout() {
const { user, setUser } = rootRoute.useRouteContext(); const { user, setUser } = rootRoute.useRouteContext();
const { t } = useTranslation(); const { t } = useTranslation();
// One app-wide WebSocket for the live feed (booth + any live widget).
useLiveFeed();
// Nav is gated by PERMISSION, not role — a tab shows iff the user's role grants // Nav is gated by PERMISSION, not role — a tab shows iff the user's role grants
// the permission its screen needs (the route guards enforce the same server-side). // the permission its screen needs (the route guards enforce the same server-side).
const show = (perm: Permission) => can(user, perm); const show = (perm: Permission) => can(user, perm);
// One app-wide WebSocket for the live feed (booth + any live widget) — but ONLY
// for roles the server would accept (routes/ws.ts gates on report:read). A
// merchant validator must not even attempt it: the 403'd upgrade would reconnect
// on backoff forever and spam the server log. Same rule for the widgets that feed
// off it (StatusDot) or make their own gated calls (ShiftButton → shift:read,
// DeviceFooter → device:read).
const canWatch = show("report:read");
useLiveFeed(canWatch);
return ( return (
<div className="flex h-screen flex-col bg-term-bg text-term-text"> <div className="flex h-screen flex-col bg-term-bg text-term-text">
@@ -489,11 +495,11 @@ function RootLayout() {
show("shift:read")) && <NavLink to="/setup" label={t("nav.setup")} />} show("shift:read")) && <NavLink to="/setup" label={t("nav.setup")} />}
</nav> </nav>
<div className="ml-auto flex items-center gap-3"> <div className="ml-auto flex items-center gap-3">
{user && <ShiftButton />} {user && show("shift:read") && <ShiftButton />}
{user && <LanguageToggle user={user} setUser={setUser} />} {user && <LanguageToggle user={user} setUser={setUser} />}
{user && <ThemeToggle user={user} setUser={setUser} />} {user && <ThemeToggle user={user} setUser={setUser} />}
{user && <FontScaleToggle user={user} setUser={setUser} />} {user && <FontScaleToggle user={user} setUser={setUser} />}
<StatusDot /> {canWatch && <StatusDot />}
{user && ( {user && (
<Link <Link
to="/profile" to="/profile"
@@ -518,8 +524,10 @@ function RootLayout() {
<main className="min-h-0 flex-1 overflow-auto p-3"> <main className="min-h-0 flex-1 overflow-auto p-3">
<Outlet /> <Outlet />
</main> </main>
{/* Fixed device-status footer — relays, readers, cameras, printers. */} {/* Fixed device-status footer — relays, readers, cameras, printers. Its REST
{user && <DeviceFooter />} seed needs device:read (and its live updates ride the report:read WS), so
it's hidden for roles without device visibility (e.g. merchant validators). */}
{user && show("device:read") && <DeviceFooter />}
</div> </div>
); );
} }
+1 -1
View File
@@ -85,7 +85,7 @@ REGISTRY=git.infra.msai.al/mca/parking_solution
# Staging booth: pinned immutable stage-<sha>. After each promotion (merge dev → stage, CI builds # Staging booth: pinned immutable stage-<sha>. After each promotion (merge dev → stage, CI builds
# :stage-<sha>), bump this to the new sha and re-sync/deploy from Core. The moving `:stage` tag # :stage-<sha>), bump this to the new sha and re-sync/deploy from Core. The moving `:stage` tag
# exists as the pointer; we deploy the sha, not the mover. # exists as the pointer; we deploy the sha, not the mover.
TAG=stage-22544ec TAG=stage-28bd838
COOKIE_SECURE=0 COOKIE_SECURE=0
VISION_ENABLED=1 VISION_ENABLED=1
WS_ALLOWED_ORIGINS= WS_ALLOWED_ORIGINS=
+5 -1
View File
@@ -100,7 +100,11 @@ priced at booth check-in, inside the normal walk-back-grace flow).
both; mode/params/caps/receipt-label/bound-users). `/validate` (`ValidateScreen.tsx`) is the both; mode/params/caps/receipt-label/bound-users). `/validate` (`ValidateScreen.tsx`) is the
merchant's whole surface (scan/key → apply → void own unused), mobile-friendly, autofocused merchant's whole surface (scan/key → apply → void own unused), mobile-friendly, autofocused
input works with HID scanners; merchant-only users (no `session:read`) land there on login and input works with HID scanners; merchant-only users (no `session:read`) land there on login and
the permission-gated nav shows them nothing else. Booth pay modal shows gross → lines → net; the permission-gated nav shows them nothing else. The app SHELL also degrades by permission
(2026-07-13 follow-up): the live-feed WebSocket connects only with `report:read` (the server's
WS guard — a merchant's socket would 403 and the capped-backoff reconnect would spam the server
log forever), and the StatusDot / ShiftButton / DeviceFooter widgets render only with their
backing permissions (`report:read` / `shift:read` / `device:read`). Booth pay modal shows gross → lines → net;
the zero-net comp settles through the normal pay path (grace starts, voucher/exit unchanged). the zero-net comp settles through the normal pay path (grace starts, voucher/exit unchanged).
Feed label `VALIDIM`/`VALIDATION`. RolesManager picks the new resource up generically. Feed label `VALIDIM`/`VALIDATION`. RolesManager picks the new resource up generically.
- **Verified**: 8 route-level integration tests (guards, signed events, money cycle, void locks, - **Verified**: 8 route-level integration tests (guards, signed events, money cycle, void locks,
+108 -2
View File
@@ -1,8 +1,8 @@
--- ---
type: entity type: entity
tags: [parking, hardware, readers, offline-first] tags: [parking, hardware, readers, offline-first]
sources: [parking-system-architecture] sources: [parking-system-architecture, DS-2CD1047G3H-LIU]
updated: 2026-07-07 updated: 2026-08-23
--- ---
# LPR Camera # 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 selection). `healthCheck()` deliberately reports a live 503 as `degraded` (it surfaces a genuinely
saturated main stream rather than hiding it behind a retry). 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) ## 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 Field observation (park-buzi): after a power cut these cameras come back with their clock at the
+2 -1
View File
@@ -19,6 +19,7 @@ Counts: 4 sources · 19 entities · 47 concepts · 8 decision records.
- [[dingtian-dt008]] — Dingtian DT-008 product page: QR/RFID access reader (QR/barcode + ID/IC/NFC; Wiegand/TCP-IP/USB/RS485; HTTP-GET push). - [[dingtian-dt008]] — Dingtian DT-008 product page: QR/RFID access reader (QR/barcode + ID/IC/NFC; Wiegand/TCP-IP/USB/RS485; HTTP-GET push).
- [[qrcode-sdk]] — QRCode SDK v1.6.5: the reader's HTTP-GET-poll protocol + JSON verdict (beep/output). - [[qrcode-sdk]] — QRCode SDK v1.6.5: the reader's HTTP-GET-poll protocol + JSON verdict (beep/output).
- [[parksql2017-legacy-schema]] — predecessor SQL Server schema (Albanian market): legacy tariff/discount/membership/shift/fiscal model; confirms blocks, adds time-windows + categories, lacks postpaid sponsors. - [[parksql2017-legacy-schema]] — predecessor SQL Server schema (Albanian market): legacy tariff/discount/membership/shift/fiscal model; confirms blocks, adds time-windows + categories, lacks postpaid sponsors.
- [[ds-2cd1047g3h-liu]] — HIKVISION DS-2CD1047G3H-LIU-F datasheet: 4MP, main stream has no MJPEG option (sub does) — likely explains the model's persistent ISAPI snapshot 503 on main; confirms ISAPI/RTSP both fully in-spec.
## Entities — technology stack ## Entities — technology stack
- [[technology-stack]] — the full stack table; all MIT/Apache/BSD, chosen to avoid lock-in. - [[technology-stack]] — the full stack table; all MIT/Apache/BSD, chosen to avoid lock-in.
@@ -39,7 +40,7 @@ Counts: 4 sources · 19 entities · 47 concepts · 8 decision records.
- [[esp32-custom-controller]] — prevention-grade upgrade; device-level auth. - [[esp32-custom-controller]] — prevention-grade upgrade; device-level auth.
- [[atecc608]] — secure element; non-extractable signing key (host events + controller auth). - [[atecc608]] — secure element; non-extractable signing key (host events + controller auth).
- [[wiegand]] — reader standard feeding the controller directly (autonomous permit-holder path). - [[wiegand]] — reader standard feeding the controller directly (autonomous permit-holder path).
- [[lpr-camera]] — edge-AI plate recognition; host-side casual-identity source. - [[lpr-camera]] — edge-AI plate recognition; host-side casual-identity source; DS-2CD1047G3H-LIU main-stream ISAPI snapshot 503 is a firmware bug (only channel 102 ever works, ALL other IDs incl. garbage 503 identically) — firmware update tested, no fix; owner decided to replace the camera line rather than build an RTSP workaround.
- [[dingtian-dt008-reader]] — Dingtian DT-008 QR/RFID reader on hand; host-side serial → `read` bus (the QR-ticket scanner). - [[dingtian-dt008-reader]] — Dingtian DT-008 QR/RFID reader on hand; host-side serial → `read` bus (the QR-ticket scanner).
- [[zkteco-controller]] — ❌ rejected/historical; aux-input path was a contender, not pursued. - [[zkteco-controller]] — ❌ rejected/historical; aux-input path was a contender, not pursued.
- [[dingtian-relay]] — ✅ CHOSEN access controller; decoupled inputs solve the button blocker (driver verified on hardware); spare relays drive aux outputs (`setAux`). - [[dingtian-relay]] — ✅ CHOSEN access controller; decoupled inputs solve the button blocker (driver verified on hardware); spare relays drive aux outputs (`setAux`).
+54
View File
@@ -2619,3 +2619,57 @@ scanning (blocked on secure-context TLS for LAN phones + weak Code128-via-camera
QR-on-ticket first) and a Tauri v2 Android merchant app (native ML Kit scanning via the official QR-on-ticket first) and a Tauri v2 Android merchant app (native ML Kit scanning via the official
barcode-scanner plugin; deferred over Android build/distribution overhead + the barcode-scanner plugin; deferred over Android build/distribution overhead + the
configurable-server-URL prerequisite). Full analysis on [[validation-discounts]]. configurable-server-URL prerequisite). Full analysis on [[validation-discounts]].
## [2026-08-23] ingest | HIKVISION DS-2CD1047G3H-LIU-F datasheet
Vendor datasheet dropped in `raw/DS-2CD1047G3H-LIU.md`. Key new fact: main stream on this model
supports H.265+/H.265/H.264+/H.264 only — **no MJPEG**; sub-stream adds MJPEG. Likely mechanical
explanation for the persistent ISAPI main-stream snapshot 503 (`deviceBusy`) already logged on this
model in [[lpr-camera]] (2026-06-26/27): the on-demand JPEG snapshot has no native path on main,
so it has to transcode from H.264/H.265 live, which this SKU's firmware apparently can't do
reliably at 2560×1440. Bitrate spec (32Kbps–16Mbps) also confirms the site's main-stream config
(6144–12288Kbps) was never out of range — rules out misconfiguration definitively.
## [2026-08-23] query | Main-stream 503: model-specific or config? RTSP as a workaround?
Live-compared two Hikvision units at park-buzi via their public port forwards
(`park-buzi.msai.al:8081`/`:8082`) plus the `:8082` unit directly on the LAN (`10.0.10.13`).
Channel-101 (main) config is **byte-identical** between a working `DS-2CD1043G2-LIU` (8081, 200 OK)
and the failing `DS-2CD1047G3H-LIU` (8082 / `10.0.10.13`, persistent 503 `deviceBusy`, 3/3 retries
instant) — same resolution/bitrate/framerate/SmartCodec state. Rules out config as the cause;
confirms it's model/firmware-specific (matches the datasheet finding above). Then tested RTSP
(`rtsp://…@10.0.10.13:554/Streaming/Channels/101` via ffmpeg, TCP transport) against the SAME
failing camera: returned a valid 2560×1440 JPEG on the first try. RTSP taps the continuously-
running encode rather than asking for an on-demand re-encoded JPEG, so it sidesteps whatever the
ISAPI snapshot path chokes on. Not yet built into `camera.ts` (would add an `ffmpeg` child-process
dependency + RTSP auth/transport handling) — filed as a viable, proven fallback if full-resolution
main-stream stills are ever needed; sub-stream ISAPI snapshot remains sufficient for current ANPR
use. Full comparison table + RTSP command on [[lpr-camera]].
## [2026-08-23] update | Firmware update tested and ruled out; sub-stream confirmed too weak for ANPR — RTSP is now required
Two developments on the DS-2CD1047G3H-LIU (`10.0.10.13`) main-stream 503: (1) the owner reports the
sub-stream (768×432) **fails to read plates "from time to time"** in real use — sub-stream-only is
no longer an acceptable mitigation, it's an accuracy problem. (2) Before building RTSP, tested
whether this was a day-one firmware bug: the camera's original `V5.8.11`/250415 build was confirmed
(via Hikvision's own release note) to be the FIRST H13U firmware to support this camera family at
all. Upgraded live to `V5.11.0`/260701 (~15 months newer, spanning an intermediate release that
explicitly claimed "image stability" fixes). Result: **no change** — identical `deviceBusy` 503,
5/5 attempts, post-upgrade. Firmware is now a ruled-out cause, not a theory; this looks like a real
encoder/hardware ceiling on this SKU. Next step: build the RTSP-based main-stream capture path into
`packages/devices/src/drivers/camera.ts` (not yet started). Full detail on [[lpr-camera]].
## [2026-08-23] update | Root cause nailed down: broken ISAPI handler, not "busy" — decision to REPLACE the camera line
Final test on the DS-2CD1047G3H-LIU snapshot 503: swept every channel/stream ID against
`GET .../channels/<id>/picture`, including nonexistent ones (1, 100, 103, 201, 999). Every single
ID returns the identical `503 deviceBusy` body EXCEPT exactly `102` (the real sub-stream), which is
always 200. A real busy/saturated encoder would not succeed on one specific value while failing
garbage IDs identically — this is a generic fallback error: the firmware's snapshot handler is only
correctly wired for channel 102, and everything else (valid main-stream 101 included) falls through
to a stock, mislabeled "Device Busy" response. Confirms the firmware-upgrade non-result from
earlier today (a wrong-code-path bug wouldn't be fixed by more capacity). Owner's decision: replace
the DS-2CD1047G3H-LIU units rather than carry an RTSP/ffmpeg workaround dependency — the sibling
DS-2CD1043G2-LIU (no such bug, ISAPI main-stream snapshot works natively) is the reference model
going forward. RTSP main-stream capture remains documented as a proven, viable fallback if a G3H
camera is ever unavoidable, but is not being built. Full sweep table + reasoning on [[lpr-camera]].
+50
View File
@@ -0,0 +1,50 @@
#### HIKVISION DS-2CD1047G3H-LIU-F 4 MP ColorVu 3.0 Fixed Bullet Network Camera
![HIKVISION-DS-2CD1047G3H-LIU-F-4-MP-ColorVu-3.0-Fixed-Bullet-Network-Camera-PRODUCT](https://manuals.plus/wp-content/uploads/2025/07/HIKVISION-DS-2CD1047G3H-LIU-F-4-MP-ColorVu-3.0-Fixed-Bullet-Network-Camera-PRODUCT.png)
#### FEATURE
- HikAI-ISP for excellent noise reduction effect
- Super clear 24/7 colorful imaging with ColorVu 3.0 technology
- Motion Detection 3.0, more accurate on person and vehicle classification
- Strobe Light & Audio Alarm to deter intruders (optional)
- Two-Way Audio via camera and Hik-Connect
- Smart Hybrid Light: integrates IR and white lights, 3 supplemental lighting modes
- On-board storage with SD card up to 512 GB (optional)
- Water and dust resistant (IP67)![HIKVISION-DS-2CD1047G3H-LIU-F-4-MP-ColorVu-3.0-Fixed-Bullet-Network-Camera-FIG-1](https://manuals.plus/wp-content/uploads/2025/07/HIKVISION-DS-2CD1047G3H-LIU-F-4-MP-ColorVu-3.0-Fixed-Bullet-Network-Camera-FIG-1.png)
#### Specification
<table><tbody><tr><td colspan="2" width="681">n <strong>Specification</strong></td></tr><tr><td colspan="2" width="681"><strong>Camera</strong></td></tr><tr><td width="194">Max. Resolution</td><td width="487">2560 × 1440</td></tr><tr><td width="194">Min. Illumination</td><td width="487">Color: 0.0001 Lux @ (F1.0, AGC ON)</td></tr><tr><td width="194">Shutter Time</td><td width="487">1 s to 1/100,000 s</td></tr><tr><td width="194">Day & Night</td><td width="487">IR cut filter</td></tr><tr><td width="194">Angle Adjustment</td><td width="487">Pan: 0° to 360°,tilt: 0° to 90°,rotate: 0° to 360°</td></tr><tr><td colspan="2" width="681"><strong>Lens</strong></td></tr><tr><td width="194">Lens Type</td><td width="487">Fixed focal lens, 2.8 and 4 mm optional</td></tr><tr><td width="194">Focal Length & FOV</td><td width="487">2.8 mm, horizontal FOV 104°, vertical FOV 54.4°, diagonal FOV 126.7°<p>4 mm, horizontal FOV 89.3°, vertical FOV 48.2°, diagonal FOV 106.5°</p></td></tr><tr><td width="194">Lens Mount</td><td width="487">M16</td></tr><tr><td width="194">Iris Type</td><td width="487">Fixed</td></tr><tr><td width="194">Aperture</td><td width="487">F1.0</td></tr><tr><td width="194">Depth of Field</td><td width="487">2.8 mm: 2.5 m to ∞<p>4 mm: 2.8 m to ∞</p></td></tr><tr><td colspan="2" width="681"><strong>DORI</strong></td></tr><tr><td width="194">DORI</td><td width="487">2.8 mm, D: 61 m, O: 24 m, R: 12 m, I: 6 m<p>4 mm, D: 68 m, O: 27 m, R: 13 m, I: 6 m</p></td></tr><tr><td colspan="2" width="681"><strong>Illuminator</strong></td></tr><tr><td width="194">Supplement Light Type</td><td width="487">IR,White Light</td></tr><tr><td width="194">Supplement Light Range</td><td width="487">IR: up to 30 m<p>White Light: up to 20 m</p></td></tr><tr><td width="194">Smart Supplement Light</td><td width="487">Yes</td></tr><tr><td width="194">IR Wavelength</td><td width="487">850 nm</td></tr><tr><td colspan="2" width="681"><strong>Video</strong></td></tr><tr><td width="194"><strong>&nbsp;</strong><p><strong>&nbsp;</strong></p><p>Main Stream</p></td><td width="487">50 Hz:<p>25 fps (2560 × 1440, 1920 × 1080, 1280 × 720)</p><p>60 Hz:</p><p>24 fps (2560 × 1440, 1920 × 1080, 1280 × 720)</p></td></tr><tr><td width="194">Sub-Stream</td><td width="487">50 Hz: 25 fps (768 × 432, 640 × 360)<p>60 Hz: 24 fps (768 × 432, 640 × 360)</p></td></tr><tr><td width="194">Video Compression</td><td width="487">Main stream: H.265+/H.265/H.264+/H.264,<p>Sub-stream: H.265/H.264/MJPEG</p></td></tr><tr><td width="194">Video Bit Rate</td><td width="487">32 Kbps to 16 Mbps</td></tr><tr><td width="194">H.264 Type</td><td width="487">Baseline Profile,Main Profile,High Profile</td></tr><tr><td width="194">H.265 Type</td><td width="487">Main Profile</td></tr><tr><td width="194">Bit Rate Control</td><td width="487">CBR,VBR</td></tr><tr><td width="194">Scalable Video Coding (SVC)</td><td width="487">H.264 and H.265 encoding</td></tr><tr><td width="194">Region of Interest (ROI)</td><td width="487">1 fixed region for main stream</td></tr><tr><td colspan="2" width="681"><strong>Audio</strong></td></tr><tr><td width="194">Audio Type</td><td width="487">Mono sound</td></tr><tr><td width="194">Audio Compression</td><td width="487">G.711/G.722.1/G.726/MP2L2/PCM/MP3/AAC-LC</td></tr><tr><td width="194">Audio Bit Rate</td><td width="487">64 Kbps (G.711)/16 Kbps (G.722.1)/16 Kbps (G.726)/32 to 160 Kbps (MP2L2)/16 to 64<p>Kbps (AAC-LC)</p></td></tr><tr><td width="194">Audio Sampling Rate</td><td width="487">8 kHz/16 kHz</td></tr></tbody></table>
<table><tbody><tr><td width="199">Environment Noise Filtering</td><td width="482">Yes</td></tr><tr><td colspan="2" width="681"><strong>Network</strong></td></tr><tr><td width="199">Protocols</td><td width="482">TCP/IP, ICMP, DHCP, DNS, HTTP, RTP, RTSP, RTCP, NTP, IPv4, IPv6, IGMP, UDP, QoS,<p>FTP, SMTP</p></td></tr><tr><td width="199">Simultaneous Live View</td><td width="482">Up to 6 channels</td></tr><tr><td width="199">API</td><td width="482">ONVIF (Profile S, Profile G),ISAPI,SDK</td></tr><tr><td width="199">User/Host</td><td width="482">Up to 32 users<p>3 user levels: administrator, operator, and user</p></td></tr><tr><td width="199"><strong>&nbsp;</strong><p>Security</p></td><td width="482">Password protection, complicated password, watermark, basic and digest<p>authentication for HTTP, WSSE and digest authentication for Open Network Video</p><p>Interface, security audit log, host authentication (MAC address)</p></td></tr><tr><td width="199">Client</td><td width="482">iVMS-4200,Hik-Connect</td></tr><tr><td width="199">Web Browser</td><td width="482">Plug-in required live view: Chrome 80+, Firefox 80+, Edge 89+, Safari 13+,<p>Plug-in free live view: Chrome 80+, Firefox 80+, Edge 89+</p></td></tr><tr><td colspan="2" width="681"><strong>Image</strong></td></tr><tr><td width="199">Image Settings</td><td width="482">Rotate&nbsp; mode,saturation,brightness,contrast,sharpness,gain,white balance,adjustable<p>by client software or web browser</p></td></tr><tr><td width="199">Day/Night Switch</td><td width="482">Day,Night,Auto,Schedule</td></tr><tr><td width="199">Wide Dynamic Range (WDR)</td><td width="482">120 dB</td></tr><tr><td width="199">SNR</td><td width="482">≥ 52 dB</td></tr><tr><td width="199">Image Enhancement</td><td width="482">BLC,HLC,3D DNR</td></tr><tr><td width="199">Privacy Mask</td><td width="482">4 programmable polygon privacy masks</td></tr><tr><td colspan="2" width="681"><strong>Interface</strong></td></tr><tr><td width="199">Ethernet Interface</td><td width="482">1 RJ45 10 M/100 M self-adaptive Ethernet port</td></tr><tr><td width="199"><strong>&nbsp;</strong><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p>On-Board Storage</p></td><td width="482">DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-SL/SRB/LIUF:&nbsp; Yes<p>-LIU: NA</p></td></tr><tr><td width="199">Built-in Microphone</td><td width="482">Yes,1 built-in microphone</td></tr></tbody></table>
| Built-in Speaker | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-SL/SRB:  Yes \-LIU/LIUF: NA |
| --- | --- |
| Audio | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU:  NA |
| Alarm | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU:  NA |
| Reset Key | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-SL/SRB/LIUF:  Yes, \-LIU: NA |
<table><tbody><tr><td colspan="2" width="681"><strong>Event</strong></td></tr><tr><td width="192">Basic Event</td><td width="489">Motion detection (support alarm triggering by specified target types (human and<p>vehicle)),video tampering alarm,exception</p></td></tr><tr><td width="192">Linkage</td><td width="489">Upload to FTP,notify surveillance center,send email,trigger recording,trigger capture</td></tr><tr><td colspan="2" width="681"><strong>General</strong></td></tr><tr><td width="192">Power</td><td width="489">DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU: 12 VDC ± 25%, 0.58 A, max. 7 W, Ø5.5 mm<p>coaxial power plug, reverse polarity protection, PoE: IEEE 802.3af, Class 3,max. 9 W LIUF: 12 VDC ± 25%, 0.67 A, max. 8 W, Ø5.5 mm coaxial power plug, reverse polarity protection, PoE: IEEE 802.3af, Class 3,max. 10 W</p><p>-SL/SRB: 12 VDC ± 25%, 0.84 A, max. 10.1 W, Ø5.5 mm coaxial power plug, reverse polarity protection, PoE: IEEE 802.3af, Class 3,max. 12.1 W</p><p>&nbsp;</p></td></tr><tr><td width="192"><strong>&nbsp;</strong><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p><strong>&nbsp;</strong></p><p>Dimension</p></td><td width="489">DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU: 69.1 mm × 66.9 mm × 172.9 mm (2.7″ × 2.6″ ×<p>6.8″)</p><p>-LIUF/SL/SRB: 69.1 mm × 67.4 mm × 179 mm (2.7″ × 2.7″ × 7.1″)</p><p>&nbsp;</p></td></tr><tr><td width="192">Package Dimension</td><td width="489">210 mm × 116 mm × 106 mm (8.3″ × 4.6″ × 4.2″)</td></tr></tbody></table>
| Weight | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU: Approx. 310 g (0.7 lb.) \-LIUF: Approx. 315 g (0.7 lb.) \-SL/SRB: Approx. 325 g (0.7 lb.) |
| --- | --- |
| With Package Weight | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-LIU: Approx. 465 g (1.0 lb.) \-LIUF: Approx. 470 g (1.0 lb.) \-SL/SRB: Approx. 495 g (1.1 lb.) |
| Storage Conditions | \-30 °C to 60 °C (-22 °F to 140 °F). Humidity 95% or less (non-condensing) |
| Startup and Operating Conditions | \-30 °C to 60 °C (-22 °F to 140 °F). Humidity 95% or less (non-condensing) |
| Language | English, Russian, Ukrainian, Arabic, Spanish, French, Portuguese, Turkish, Polish, German |
| General Function | Heartbeat,mirror,flash log,password reset via email,password protection,anti -banding |
| Flashing Light | DS-2CD1047G3H-LIU(F)(/SL)(/SRB):-SL/SRB:  Yes \-LIU/LIUF: NA |
<table><tbody><tr><td colspan="2" width="681"><strong>Approval</strong></td></tr><tr><td width="194">EMC</td><td width="487">CE-EMC: EN 55032:2015+A1:2020, EN 50130-4:2011+A1:2014, EN IEC<p>61000-3-2:2019+A1:2021, EN&nbsp; 61000-3-3:2013+A1:2019+A2:2021</p></td></tr><tr><td width="194">Safety</td><td width="487">CB: IEC 62368-1: 2014+A11,<p>CE-LVD: EN 62368-1: 2014/A11: 2017</p></td></tr><tr><td width="194">Environment</td><td width="487">CE-RoHS: 2011/65/EU,<p>WEEE: 2012/19/EU</p></td></tr><tr><td width="194">Protection</td><td width="487">IP67: IEC 60529-2013</td></tr></tbody></table>
#### Available Model
- DS-2CD1047G3H-LIUF/SRB(2.8mm)
- DS-2CD1047G3H-LIUF/SRB(4mm)
- DS-2CD1047G3H-LIU(2.8mm)
- DS-2CD1047G3H-LIU(4mm)
- DS-2CD1047G3H-LIUF(2.8mm)
- DS-2CD1047G3H-LIUF(4mm)
- DS-2CD1047G3H-LIUF/SL(2.8mm)
- DS-2CD1047G3H-LIUF/SL(4mm)
+41
View File
@@ -0,0 +1,41 @@
---
type: source
tags: [parking, hardware, cameras, hikvision, datasheet]
sources: [DS-2CD1047G3H-LIU]
updated: 2026-08-23
---
# Source: HIKVISION DS-2CD1047G3H-LIU-F datasheet
Vendor spec sheet (`raw/DS-2CD1047G3H-LIU.md`) for the **DS-2CD1047G3H-LIU** — the exit-lane
camera at `10.0.10.13` (park-buzi) already covered extensively in [[lpr-camera]] for its
persistent main-stream ISAPI 503 (`deviceBusy`) and its 2026-06-27 config-DB-corruption incident.
This is the first *vendor-sourced* spec data for the model; everything before it was field-derived.
## Key takeaways
- **4 MP, max resolution 2560×1440** (ColorVu 3.0 — color night imaging, not IR-only).
- **Main stream: H.265+/H.265/H.264+/H.264 only — no MJPEG option.** **Sub-stream: H.265/H.264/
MJPEG** (MJPEG is sub-only). This is a concrete, spec-level asymmetry that plausibly explains
*why* the ISAPI on-demand JPEG snapshot is reliable on sub but structurally broken on main: sub
can serve a snapshot natively, main has to transcode out of H.264/H.265 on demand. Consistent
with — and a likely root cause for — the persistent `deviceBusy` behavior already logged in
[[lpr-camera]].
- **Bit rate range 32 Kbps–16 Mbps.** The site's main-stream config (6144–12288 Kbps, confirmed
live 2026-08-23) is well inside spec — rules out "misconfigured over the camera's own ceiling"
as a cause, confirming what live testing already showed.
- **ROI: 1 fixed region for main stream** — another main-only constraint/asymmetry vs. sub.
- **API: ONVIF (Profile S, Profile G), ISAPI, SDK.** ISAPI is fully in-spec for this model — the
503 is a real firmware/hardware limitation, not a case of using an unsupported API.
- **Protocols include RTSP** (alongside HTTP/ONVIF/etc.) — confirms RTSP is a documented, supported
surface on this model, not a workaround outside its design.
- Simultaneous live view: up to 6 channels. Available in `-LIU`/`-LIUF`/`-LIUF/SL`/`-LIUF/SRB`
variants at 2.8mm/4mm focal lengths; the deployed unit is the base `-LIU`.
## How this changes the picture
Confirms rather than overturns [[lpr-camera]]'s existing conclusion (sub-stream-only for ISAPI
snapshots on this model) — but gives it a concrete mechanical explanation (main has no MJPEG path)
instead of just an empirically-observed limitation. See [[lpr-camera]] § "Main-stream ISAPI
snapshot 503 vs. RTSP" for the 2026-08-23 live comparison against a `DS-2CD1043G2-LIU` sibling
(main-stream ISAPI snapshot works fine there) and the confirmed RTSP frame-grab workaround.