@7365admin1/core 3.32.2-staging.63 → 3.32.2-staging.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/camera-integration-layer.md +60 -0
- package/.changeset/camera-setup-from-recorder.md +43 -0
- package/dist/index.d.ts +415 -51
- package/dist/index.js +2192 -823
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2165 -823
- package/dist/index.mjs.map +1 -1
- package/docs/camera-integration-config.md +191 -0
- package/package.json +2 -2
- package/test/camera-capability.util.test.mjs +545 -0
- package/test/camera-device-http.test.mjs +792 -0
- package/test/camera-view.util.test.mjs +157 -5
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Camera integration layer: a capability descriptor, a transport registry, and the
|
|
6
|
+
Dahua device HTTP adapter (written, tested, switched off).
|
|
7
|
+
|
|
8
|
+
Every camera in the wall and status responses now carries a `capabilities`
|
|
9
|
+
descriptor: `liveVideo`, `stillFrame`, `digitalZoom`, `ptz`, `presets`,
|
|
10
|
+
`playback`, `events`, `audio`, `deviceInfo`, each `supported` / `unsupported` /
|
|
11
|
+
`unknown` with a machine-readable reason code and one sentence. A client renders
|
|
12
|
+
itself from it without knowing anything about relays, recorders or networks.
|
|
13
|
+
`unknown` is distinct on purpose: "we have not been allowed to ask" is not the
|
|
14
|
+
same fact as "this camera cannot".
|
|
15
|
+
|
|
16
|
+
Capabilities resolve through a transport registry instead of the service picking
|
|
17
|
+
a path. `RELAY_PLAYER` is the stored player-page URL rendered in a WebView (the
|
|
18
|
+
live product's picture path, live video only, no control channel). `RTSP_FRAME`
|
|
19
|
+
is one ffmpeg still off the recorder. `DEVICE_HTTP` is the camera's own CGI API.
|
|
20
|
+
Registration order is preference order, so one camera serves live video over the
|
|
21
|
+
relay and evidence stills over RTSP at the same time, and adding a transport
|
|
22
|
+
later needs no service change.
|
|
23
|
+
|
|
24
|
+
`DEVICE_HTTP` covers device info/version, snapshot, PTZ (continuous, absolute,
|
|
25
|
+
stop), presets (list and recall), recorded-file query with playback URL
|
|
26
|
+
construction, and event subscription - digest auth only, values percent-encoded,
|
|
27
|
+
403 treated as bad credentials and 401 as an ordinary challenge. It contacts
|
|
28
|
+
nothing today: the recorder in this estate answers on RTSP only. Enabling it is
|
|
29
|
+
configuration, not a code change.
|
|
30
|
+
|
|
31
|
+
A shared, persistent authentication failure budget is mandatory on that path. The
|
|
32
|
+
device locks an account for 1800 s after 3 failed logins in 30 s, so failures are
|
|
33
|
+
counted per device in the cache, the budget stops at 2, and once spent no request
|
|
34
|
+
leaves the process. Nothing retries anywhere.
|
|
35
|
+
|
|
36
|
+
Mutating operations are structurally unreachable while disabled: the adapter is
|
|
37
|
+
`null` without `CAMERA_DEVICE_HTTP_ENABLED`, and its `control` object is `null`
|
|
38
|
+
without `CAMERA_DEVICE_CONTROL_ENABLED`. Movement codes are an allow-list;
|
|
39
|
+
`SetPreset`, `ClearPreset`, tours, patterns, `configManager` writes and reboot are
|
|
40
|
+
absent.
|
|
41
|
+
|
|
42
|
+
Capability probing is read-only, cached, budget-aware, never throws, and happens
|
|
43
|
+
only on a deliberate single-camera status request - never as a side effect of a
|
|
44
|
+
list.
|
|
45
|
+
|
|
46
|
+
`host` is now returned for `type: "ip"` cameras on the wall response. It is the
|
|
47
|
+
video relay's player-page URL, not a device address and not a credential, and
|
|
48
|
+
`GET /site-cameras` already returns it to every authenticated caller. `anpr`
|
|
49
|
+
records, whose `host` is a real device endpoint, are excluded by the allow-list
|
|
50
|
+
itself.
|
|
51
|
+
|
|
52
|
+
New configuration, all optional and all off by default: `CAMERA_DEVICE_HTTP`
|
|
53
|
+
(JSON keyed by relay authority, credential referenced by environment variable
|
|
54
|
+
name), `CAMERA_DEVICE_HTTP_ENABLED`, `CAMERA_DEVICE_CONTROL_ENABLED`,
|
|
55
|
+
`CAMERA_DEVICE_HTTP_TIMEOUT_MS` (8000),
|
|
56
|
+
`CAMERA_DEVICE_HTTP_PROBE_TTL_SECONDS` (900). See
|
|
57
|
+
`docs/camera-integration-config.md`.
|
|
58
|
+
|
|
59
|
+
Existing responses keep every field they had, with the same wording, so current
|
|
60
|
+
consumers are unaffected.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Camera setup from the recorder and channel, and a read-only test before saving.
|
|
6
|
+
|
|
7
|
+
A CCTV camera record stores a video-relay player-page URL. Nothing printed on a
|
|
8
|
+
camera or shown in a recorder's own screens tells anybody what that URL is, so
|
|
9
|
+
adding a camera meant asking whoever runs the video service for one address per
|
|
10
|
+
camera and pasting it in unverified.
|
|
11
|
+
|
|
12
|
+
`POST /site-cameras` and `PATCH /site-cameras/id/:id` now also accept
|
|
13
|
+
`recorderHost`, `recorderPort` and `channel`. The server reads the existing
|
|
14
|
+
`CAMERA_RTSP_DEVICES` map backwards - relay authority to recorder becomes
|
|
15
|
+
recorder to relay authority - and derives the same `https://<relay>/<channel>`
|
|
16
|
+
address it has always stored. There is deliberately no second map and no new
|
|
17
|
+
stored field: the recorder fields are consumed by the controller and never reach
|
|
18
|
+
the model, so `site.cameras` keeps exactly the shape it has today.
|
|
19
|
+
|
|
20
|
+
Additive and ordered so: a request that sends `host` behaves exactly as it
|
|
21
|
+
always has, so every camera configured that way and anyone holding a ready-made
|
|
22
|
+
address is unaffected. A recorder with no configured entry is refused with a
|
|
23
|
+
sentence a property manager can act on rather than a code.
|
|
24
|
+
|
|
25
|
+
New: `POST /site-cameras/site/:siteId/test` - does this address actually show a
|
|
26
|
+
picture? Site-scoped because the camera does not exist yet, and it requires
|
|
27
|
+
`site-settings:manage-cctv-camera`. The probe is read only: one TCP connect with
|
|
28
|
+
no credential, then at most one video frame off the stream. There is no mutating
|
|
29
|
+
call in the path.
|
|
30
|
+
|
|
31
|
+
It is rationed before it can reach a device - one test per camera per 15 s, four
|
|
32
|
+
per recorder per 5 minutes - and it consults the shared authentication failure
|
|
33
|
+
budget first, so pressing the button cannot walk a recorder into its own
|
|
34
|
+
3-failures-in-30-seconds, 1800-second lockout. It answers with one of five plain
|
|
35
|
+
sentences and never an address, port, credential or device message.
|
|
36
|
+
|
|
37
|
+
`ffmpeg`'s stderr is now read for one fact - was the handshake rejected - and
|
|
38
|
+
discarded chunk by chunk without being accumulated, logged or returned, so "the
|
|
39
|
+
recorder refused the credential" can be told apart from "the channel is not
|
|
40
|
+
sending video". Snapshot failures gain that distinction too.
|
|
41
|
+
|
|
42
|
+
`authorizeSite` takes an optional permission list; existing callers are unchanged
|
|
43
|
+
and still require the camera view permissions.
|