@camstack/types 1.2.243 → 1.2.245
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/dist/addon.js +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/capabilities/device-admin-link-url.d.ts +87 -0
- package/dist/capabilities/device-admin-link.cap.d.ts +118 -0
- package/dist/capabilities/index.d.ts +8 -2
- package/dist/capabilities/recording-onboard-rules.d.ts +135 -0
- package/dist/capabilities/recording-onboard.cap.d.ts +705 -0
- package/dist/capabilities/videoclips.cap.d.ts +25 -0
- package/dist/generated/addon-api.d.ts +44 -0
- package/dist/generated/cap-status-types.d.ts +3 -1
- package/dist/generated/capability-router-map.d.ts +8 -2
- package/dist/generated/device-local-state.d.ts +3 -0
- package/dist/generated/device-proxy.d.ts +5 -0
- package/dist/generated/device-scoped-caps.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/generated/runtime-state-durability.d.ts +1 -1
- package/dist/index.js +1000 -2
- package/dist/index.mjs +968 -3
- package/dist/{sleep-mVRRyKVq.js → sleep-Da9UCU5_.js} +10 -1
- package/dist/{sleep-De1BvmWo.mjs → sleep-i3eUVc-d.mjs} +10 -1
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-Da9UCU5_.js");
|
|
3
3
|
const require_event_category = require("./event-category-BVfsrBYA.js");
|
|
4
4
|
const require_err_msg = require("./err-msg-COpsHMw2.js");
|
|
5
5
|
//#region src/generated/cap-input-defaults.ts
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as DeviceType, Dt as DisposerChain, G as readNodePin, J as ReadinessTimeoutError, L as expandCapMethods, Mt as emitReadiness, Ot as BaseAddon, S as DEVICE_CHILDREN_BATCH_MAX, T as describeCustomActions, Tt as DATAPLANE_SECRET_HEADER, W as nodePin, Z as scopeKey, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, h as createEventBusSliceSource, j as adminUiCapability, kt as normalizeAddonInitResult, m as createDeviceProxy, p as isDeviceScopedCap, q as ReadinessRegistry, s as asString, t as sleep, u as parseJsonUnknown, x as viewerUiCapability } from "./sleep-
|
|
1
|
+
import { A as DeviceType, Dt as DisposerChain, G as readNodePin, J as ReadinessTimeoutError, L as expandCapMethods, Mt as emitReadiness, Ot as BaseAddon, S as DEVICE_CHILDREN_BATCH_MAX, T as describeCustomActions, Tt as DATAPLANE_SECRET_HEADER, W as nodePin, Z as scopeKey, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, h as createEventBusSliceSource, j as adminUiCapability, kt as normalizeAddonInitResult, m as createDeviceProxy, p as isDeviceScopedCap, q as ReadinessRegistry, s as asString, t as sleep, u as parseJsonUnknown, x as viewerUiCapability } from "./sleep-i3eUVc-d.mjs";
|
|
2
2
|
import { t as EventCategory } from "./event-category-BVDXG4tB.mjs";
|
|
3
3
|
import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
|
|
4
4
|
//#region src/generated/cap-input-defaults.ts
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE place a device-admin-link URL is built.
|
|
3
|
+
*
|
|
4
|
+
* Every provider of `device-admin-link` calls {@link buildDeviceAdminUrl}. No
|
|
5
|
+
* provider concatenates a URL itself, and `scripts/check-admin-link-builder-
|
|
6
|
+
* is-the-only-url-source.ts` is what makes that true rather than hoped for.
|
|
7
|
+
*
|
|
8
|
+
* ## Why a builder at all, for a string that looks like `http://` + host
|
|
9
|
+
*
|
|
10
|
+
* Because the one thing that must never happen to this string is easy to do by
|
|
11
|
+
* accident. Every provider that knows a device's host knows its PASSWORD too —
|
|
12
|
+
* they sit next to each other in the same device config (`{ host, port,
|
|
13
|
+
* username, password }` on Hikvision, Reolink, Amcrest, ONVIF alike). A
|
|
14
|
+
* convenience that "pre-fills the login" is one template literal away, and
|
|
15
|
+
* `http://admin:hunter2@192.168.50.139/` is a working URL that browsers accept,
|
|
16
|
+
* that lands in the DOM, in a right-click → copy, in a screenshot, and in any
|
|
17
|
+
* log line that prints what was opened. `scripts/check-no-credential-urls-in-
|
|
18
|
+
* fixtures.ts` already exists because this repo shipped exactly that leak on
|
|
19
|
+
* the RTSP surfaces.
|
|
20
|
+
*
|
|
21
|
+
* So the builder takes host/port/scheme/path as SEPARATE arguments — there is
|
|
22
|
+
* no parameter a credential could be passed in — and then re-checks the result
|
|
23
|
+
* it produced. A camera's admin page asks for its own login; that is correct,
|
|
24
|
+
* and pre-filling it is not ours to do.
|
|
25
|
+
*/
|
|
26
|
+
/** Scheme of a device admin page. Only these two; nothing else is a web page. */
|
|
27
|
+
export type DeviceAdminScheme = 'http' | 'https';
|
|
28
|
+
/** Everything needed to address a management page, with no room for a secret. */
|
|
29
|
+
export interface DeviceAdminUrlParts {
|
|
30
|
+
/** Hostname or IP. Never a URL, never `user@host`. */
|
|
31
|
+
readonly host: string;
|
|
32
|
+
/**
|
|
33
|
+
* TCP port of the WEB interface. `null` means "the scheme default" and the
|
|
34
|
+
* port is omitted from the URL.
|
|
35
|
+
*
|
|
36
|
+
* Not the vendor's control port. Reolink's device config carries `port: 9000`
|
|
37
|
+
* — the Baichuan media port — and `http://<reolink>:9000/` answers nothing
|
|
38
|
+
* (verified against 192.168.50.226 on 2026-09-22: `:9000` refuses the
|
|
39
|
+
* connection, `:80` returns 200 text/html). A provider that reads a port
|
|
40
|
+
* field without knowing what that port IS produces a button that opens a
|
|
41
|
+
* browser error.
|
|
42
|
+
*/
|
|
43
|
+
readonly port: number | null;
|
|
44
|
+
readonly scheme: DeviceAdminScheme;
|
|
45
|
+
/** Absolute path, starting with `/`. `'/'` for the site root. */
|
|
46
|
+
readonly path: string;
|
|
47
|
+
/**
|
|
48
|
+
* Query parameters, already decided by the caller. Values are encoded here.
|
|
49
|
+
* A key named like a credential is REFUSED — see {@link CREDENTIAL_QUERY_KEYS}.
|
|
50
|
+
*/
|
|
51
|
+
readonly query?: Readonly<Record<string, string>>;
|
|
52
|
+
}
|
|
53
|
+
/** Why a link could not be built. Named, because a silent `null` is a defect. */
|
|
54
|
+
export type DeviceAdminUrlRefusal = 'empty-host' | 'host-not-plain' | 'host-carries-userinfo' | 'port-out-of-range' | 'path-not-absolute' | 'credential-query-key' | 'userinfo-in-result';
|
|
55
|
+
/** Discriminated result — a refusal always carries its reason. */
|
|
56
|
+
export type DeviceAdminUrlResult = {
|
|
57
|
+
readonly ok: true;
|
|
58
|
+
readonly url: string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly ok: false;
|
|
61
|
+
readonly reason: DeviceAdminUrlRefusal;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Build the admin-page URL, or refuse by name.
|
|
65
|
+
*
|
|
66
|
+
* The refusal is never thrown: a provider answering "no page for this device"
|
|
67
|
+
* is an ordinary answer (`getAdminLink` → `null`), and a throw here would turn
|
|
68
|
+
* a missing host on one device into a failed query for the whole surface.
|
|
69
|
+
*/
|
|
70
|
+
export declare function buildDeviceAdminUrl(parts: DeviceAdminUrlParts): DeviceAdminUrlResult;
|
|
71
|
+
/** Host/port/scheme recovered from an operator-configured base URL. */
|
|
72
|
+
export interface DeviceAdminBase {
|
|
73
|
+
readonly ok: true;
|
|
74
|
+
readonly host: string;
|
|
75
|
+
readonly port: number | null;
|
|
76
|
+
readonly scheme: DeviceAdminScheme;
|
|
77
|
+
/** Path prefix the base URL carried (`''` when it was just an origin). */
|
|
78
|
+
readonly basePath: string;
|
|
79
|
+
}
|
|
80
|
+
/** Refusal shape for {@link parseAdminBase}. */
|
|
81
|
+
export type DeviceAdminBaseResult = DeviceAdminBase | {
|
|
82
|
+
readonly ok: false;
|
|
83
|
+
readonly reason: DeviceAdminBaseRefusal;
|
|
84
|
+
};
|
|
85
|
+
/** Why a configured base URL cannot be used to build a link. */
|
|
86
|
+
export type DeviceAdminBaseRefusal = 'empty' | 'unparseable' | 'scheme-not-http' | 'base-carries-userinfo';
|
|
87
|
+
export declare function parseAdminBase(baseUrl: string): DeviceAdminBaseResult;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* device-admin-link — "this device has a management page of its own, and here
|
|
3
|
+
* is its address".
|
|
4
|
+
*
|
|
5
|
+
* ## Why this is not a `deviceConfig` cap
|
|
6
|
+
*
|
|
7
|
+
* There is nothing to edit. A `deviceConfig` cap (D14) exists so the framework
|
|
8
|
+
* can DERIVE a settings form from `getOptions` + `getStatus` and route a flat
|
|
9
|
+
* patch back through a setter; it costs a `builderId` reducer in
|
|
10
|
+
* `device-config-contribution.ts` and a `*-config-schema.ts` beside it, and it
|
|
11
|
+
* renders a form section. This cap answers ONE question with ONE read and
|
|
12
|
+
* renders a button. Nothing about it is a form, so it carries no `deviceConfig`
|
|
13
|
+
* block, no `settings`, no `runtimeState` and no reducer — exactly like
|
|
14
|
+
* `reboot`, the other pure-RPC device-native cap.
|
|
15
|
+
*
|
|
16
|
+
* ## Absent, and the difference between "no page" and "we cannot say"
|
|
17
|
+
*
|
|
18
|
+
* The two are answered at DIFFERENT layers, on purpose:
|
|
19
|
+
*
|
|
20
|
+
* - **"We cannot say"** → the provider never registers the cap for that
|
|
21
|
+
* device. A VeSync humidifier, a Petkit feeder, a Dreame vacuum and a Dreo
|
|
22
|
+
* fan are reached only through a vendor cloud; there is no address to hand
|
|
23
|
+
* out and no page to open. A Tuya plug, a Wyze camera and a Gree air
|
|
24
|
+
* conditioner DO have a LAN IP, and still have no HTTP management page
|
|
25
|
+
* behind it. None of them register, so `deviceManager.getBindings` never
|
|
26
|
+
* lists the cap and no surface asks.
|
|
27
|
+
* - **"This device has no page, and I know that"** → the provider registers
|
|
28
|
+
* and `getAdminLink` returns `null`. This is the answer for a device whose
|
|
29
|
+
* sibling DOES have a page: a Reolink battery camera reached over UDP by
|
|
30
|
+
* `uid` with a blank `host`, an Ecowitt gateway configured in `listener`
|
|
31
|
+
* transport, a Home Assistant broker authenticated by supervisor token
|
|
32
|
+
* (which carries no `baseUrl` at all).
|
|
33
|
+
*
|
|
34
|
+
* Both draw NOTHING. A button that opens a browser error is worse than no
|
|
35
|
+
* button, and D62 is the same rule from the other side: an off switch is
|
|
36
|
+
* reported off, never made to look broken. There is no third state where the
|
|
37
|
+
* UI renders a disabled button "because the device might have a page".
|
|
38
|
+
*
|
|
39
|
+
* ## The URL never carries credentials
|
|
40
|
+
*
|
|
41
|
+
* Not in userinfo, not in a query string. Every provider builds through
|
|
42
|
+
* `buildDeviceAdminUrl` (`device-admin-link-url.ts`), which takes host, port,
|
|
43
|
+
* scheme and path as separate arguments — there is no parameter a secret could
|
|
44
|
+
* arrive in — and re-checks its own output for the `scheme://user:pass@` shape
|
|
45
|
+
* that `scripts/check-no-credential-urls-in-fixtures.ts` bans from recorded
|
|
46
|
+
* output. `scripts/check-admin-link-builder-is-the-only-url-source.ts` is what
|
|
47
|
+
* keeps providers from hand-rolling one anyway.
|
|
48
|
+
*
|
|
49
|
+
* This matters here more than anywhere else in the repo, because every provider
|
|
50
|
+
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
51
|
+
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
52
|
+
* and `http://admin:hunter2@192.168.50.139/` is a URL a browser accepts. The
|
|
53
|
+
* camera's own page will ask for its own login. That is correct, and pre-
|
|
54
|
+
* filling it is the operator's business, not ours.
|
|
55
|
+
*
|
|
56
|
+
* ## It is a LAN fact
|
|
57
|
+
*
|
|
58
|
+
* The URL addresses the device where the NODE can see it. It is not proxied,
|
|
59
|
+
* not made reachable from outside, and not sent anywhere. A surface renders it
|
|
60
|
+
* as a link the operator's own browser follows, on the operator's own network,
|
|
61
|
+
* or renders nothing.
|
|
62
|
+
*/
|
|
63
|
+
import { z } from 'zod';
|
|
64
|
+
import { type InferProvider } from './capability-definition.js';
|
|
65
|
+
/**
|
|
66
|
+
* Whose page is it. The distinction is for the OPERATOR, who needs to know
|
|
67
|
+
* before clicking whether he is about to land on a camera's own web server or
|
|
68
|
+
* inside Home Assistant.
|
|
69
|
+
*/
|
|
70
|
+
export declare const AdminLinkTargetEnum: z.ZodEnum<{
|
|
71
|
+
device: "device";
|
|
72
|
+
integration: "integration";
|
|
73
|
+
}>;
|
|
74
|
+
export type AdminLinkTarget = z.infer<typeof AdminLinkTargetEnum>;
|
|
75
|
+
export declare const DeviceAdminLinkSchema: z.ZodObject<{
|
|
76
|
+
url: z.ZodString;
|
|
77
|
+
label: z.ZodString;
|
|
78
|
+
target: z.ZodEnum<{
|
|
79
|
+
device: "device";
|
|
80
|
+
integration: "integration";
|
|
81
|
+
}>;
|
|
82
|
+
host: z.ZodString;
|
|
83
|
+
}, z.core.$strip>;
|
|
84
|
+
export type DeviceAdminLink = z.infer<typeof DeviceAdminLinkSchema>;
|
|
85
|
+
export declare const deviceAdminLinkCapability: {
|
|
86
|
+
readonly name: "device-admin-link";
|
|
87
|
+
readonly scope: "device";
|
|
88
|
+
readonly deviceNative: true;
|
|
89
|
+
readonly mode: "singleton";
|
|
90
|
+
readonly methods: {
|
|
91
|
+
/**
|
|
92
|
+
* The device's management page, or `null` when this device has none.
|
|
93
|
+
*
|
|
94
|
+
* `auth: 'admin'` deliberately. This is administration, not actuation —
|
|
95
|
+
* the same bucket as `reboot` and `camera-credentials`, and explicitly NOT
|
|
96
|
+
* the actuation set `scripts/check-actuation-not-admin.ts` protects (D403).
|
|
97
|
+
* The URL is also a statement about the LAN, which a household member with
|
|
98
|
+
* a `view` grant on a light has no reason to be handed.
|
|
99
|
+
*
|
|
100
|
+
* The surfaces gate on the QUERY, never on a role they guessed: a caller
|
|
101
|
+
* without the right loses the query and draws nothing, which is the same
|
|
102
|
+
* thing a device with no page draws. There is no path on which a button
|
|
103
|
+
* appears and then fails — the D403 failure mode, from the other end.
|
|
104
|
+
*/
|
|
105
|
+
readonly getAdminLink: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
|
|
106
|
+
deviceId: z.ZodNumber;
|
|
107
|
+
}, z.core.$strip>, z.ZodNullable<z.ZodObject<{
|
|
108
|
+
url: z.ZodString;
|
|
109
|
+
label: z.ZodString;
|
|
110
|
+
target: z.ZodEnum<{
|
|
111
|
+
device: "device";
|
|
112
|
+
integration: "integration";
|
|
113
|
+
}>;
|
|
114
|
+
host: z.ZodString;
|
|
115
|
+
}, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
export type IDeviceAdminLinkProvider = InferProvider<typeof deviceAdminLinkCapability>;
|
|
@@ -48,6 +48,8 @@ export type { DecoderHwAccelConfig, HwAccelChoice, IDecoderCapProvider, ShmRingS
|
|
|
48
48
|
export { DEFAULT_DECODER_HWACCEL_CONFIG, DecoderSessionConfigSchema, decoderCapability, HWACCEL_OPTIONS, ShmRingStatsSchema, } from './decoder.cap.js';
|
|
49
49
|
export { detectionPipelineCapability, type IDetectionPipelineProvider, } from './detection-pipeline.cap.js';
|
|
50
50
|
export { AdoptInputSchema as AdoptionAdoptInputSchema, type AdoptionFilter, AdoptionFilterSchema, type AdoptionStatus, AdoptionStatusSchema, AdoptResultSchema as AdoptionAdoptResultSchema, CandidateQueryFilterSchema, deviceAdoptionCapability, GetCandidateInputSchema as AdoptionGetCandidateInputSchema, type IDeviceAdoptionProvider, ListCandidatesInputSchema as AdoptionListCandidatesInputSchema, ListCandidatesOutputSchema as AdoptionListCandidatesOutputSchema, ReleaseInputSchema as AdoptionReleaseInputSchema, } from './device-adoption.cap.js';
|
|
51
|
+
export { type AdminLinkTarget, AdminLinkTargetEnum, type DeviceAdminLink, DeviceAdminLinkSchema, deviceAdminLinkCapability, type IDeviceAdminLinkProvider, } from './device-admin-link.cap.js';
|
|
52
|
+
export { buildDeviceAdminUrl, type DeviceAdminBase, type DeviceAdminBaseRefusal, type DeviceAdminBaseResult, type DeviceAdminScheme, type DeviceAdminUrlParts, type DeviceAdminUrlRefusal, type DeviceAdminUrlResult, parseAdminBase, } from './device-admin-link-url.js';
|
|
51
53
|
export type { IDeviceExportProvider } from './device-export.cap.js';
|
|
52
54
|
export { DeviceExportStatusSchema, deviceExportCapability, ExportSetupFieldSchema, ExportSetupSchema, ExposedDeviceSchema, ExposeInputSchema as DeviceExportExposeInputSchema, UnexposeInputSchema as DeviceExportUnexposeInputSchema, } from './device-export.cap.js';
|
|
53
55
|
export type { DeviceInfo, DeviceManagerApplyInitialMetaInput } from './device-manager.cap.js';
|
|
@@ -117,7 +119,7 @@ export { PasskeySummarySchema, userPasskeysCapability } from './user-passkeys.ca
|
|
|
117
119
|
export type { IVectorStoreProvider } from './vector-store.cap.js';
|
|
118
120
|
export { VectorDeclareIndexInputSchema, VectorDeleteByFilterInputSchema, VectorDeleteInputSchema, VectorDeleteResultSchema, type VectorFilter, VectorFilterSchema, VectorGetInputSchema, VectorGetResultSchema, type VectorItem, VectorItemSchema, type VectorMatch, VectorMatchSchema, type VectorMetadata, VectorMetadataSchema, type VectorMetric, VectorMetricSchema, VectorQueryInputSchema, VectorQueryResultSchema, VectorStatsInputSchema, VectorStatsResultSchema, VectorUpsertInputSchema, VectorUpsertResultSchema, vectorStoreCapability, } from './vector-store.cap.js';
|
|
119
121
|
export type { Clip, ClipBytes, ClipPlayback, ClipSource, ClipSourceAvailability, ClipStillDisposition, ClipStillRefusalCode, ClipStreamAudio, ClipStreamAudioReason, ClipStreamDial, ClipWake, IVideoclipsProvider, } from './videoclips.cap.js';
|
|
120
|
-
export { CLIP_STILL_DISPOSITION_HEADER, CLIP_STILL_REASON_CODE_HEADER, CLIP_STILL_REASON_HEADER, CLIP_STREAM_TRANSPORT_HEADER, ClipBytesSchema, ClipPlaybackSchema, ClipSchema, ClipSourceAvailabilitySchema, ClipSourceSchema, ClipStillDispositionSchema, ClipStillRefusalCodeSchema, ClipStreamAudioReasonSchema, ClipStreamAudioSchema, ClipStreamDialSchema, ClipWakeSchema, MAX_CLIP_EVENT_IDS, MAX_CLIP_LABELS, VIDEOCLIPS_MAX_READ_BYTES, videoclipsCapability, } from './videoclips.cap.js';
|
|
122
|
+
export { CLIP_STILL_DISPOSITION_HEADER, CLIP_STILL_REASON_CODE_HEADER, CLIP_REASON_HEADER_MAX, CLIP_STILL_REASON_HEADER, CLIP_STREAM_TRANSPORT_HEADER, ClipBytesSchema, ClipPlaybackSchema, ClipSchema, ClipSourceAvailabilitySchema, ClipSourceSchema, ClipStillDispositionSchema, ClipStillRefusalCodeSchema, ClipStreamAudioReasonSchema, ClipStreamAudioSchema, ClipStreamDialSchema, ClipWakeSchema, MAX_CLIP_EVENT_IDS, MAX_CLIP_LABELS, VIDEOCLIPS_MAX_READ_BYTES, clipReasonHeaderValue, videoclipsCapability, } from './videoclips.cap.js';
|
|
121
123
|
export type { IViewerUiProvider } from './viewer-ui.cap.js';
|
|
122
124
|
export { viewerUiCapability } from './viewer-ui.cap.js';
|
|
123
125
|
export { type IWebrtcSessionProvider, type WebrtcClientHints, type WebrtcLadderDecision, WebrtcLadderDecisionSchema, type WebrtcSessionDebug, WebrtcSessionDebugSchema, type WebrtcStreamChoice, WebrtcStreamChoiceSchema, type WebrtcStreamTarget, WebrtcStreamTargetSchema, type WebrtcTierFailure, WebrtcTierFailureSchema, webrtcClientHintsSchema, webrtcSessionCapability, } from './webrtc-session.cap.js';
|
|
@@ -143,6 +145,8 @@ export { type ContactStatus, ContactStatusSchema, contactCapability, type IConta
|
|
|
143
145
|
export { type ControlKind, ControlKindSchema, type ControlSetValueInput, type ControlStatus, ControlStatusSchema, controlCapability, type IControlProvider, } from './control.cap.js';
|
|
144
146
|
export { type CoverState, CoverStateSchema, type CoverStatus, CoverStatusSchema, coverCapability, type ICoverProvider, } from './cover.cap.js';
|
|
145
147
|
export { type DayNightMode, DayNightModeSchema, type DayNightOptions, DayNightOptionsSchema, type DayNightSettingsPatch, DayNightSettingsPatchSchema, type DayNightStatus, DayNightStatusSchema, dayNightCapability, type IDayNightProvider, } from './day-night.cap.js';
|
|
148
|
+
export { type OnboardAllowedValues, type OnboardFieldSupport, OnboardFieldSupportSchema, type OnboardRecordTrack, OnboardRecordTrackSchema, type OnboardScheduleSupport, OnboardScheduleSupportSchema, type OnboardStorage, OnboardStorageSchema, type OnboardStorageVolume, OnboardStorageVolumeSchema, type IRecordingOnboardProvider, type RecordTrigger, RecordTriggerSchema, type RecordWindow, RecordWindowSchema, type RecordingOnboardOptions, RecordingOnboardOptionsSchema, type RecordingOnboardPatch, RecordingOnboardPatchSchema, type RecordingOnboardStatus, RecordingOnboardStatusSchema, recordingOnboardCapability, } from './recording-onboard.cap.js';
|
|
149
|
+
export { DAYS_PER_WEEK, DAY_NAMES, HOURS_PER_DAY, MINUTES_PER_DAY, WEEKLY_MASK_LENGTH, dayOfWeekToIndex, describeOnboardClamp, describeOnboardRefusal, formatMinutes, minutesToTimeOfDay, timeOfDayToMinutes, weeklyMaskIndex, weeklyMaskIsUniform, weeklyMaskToWindows, windowsToWeeklyMask, } from './recording-onboard-rules.js';
|
|
146
150
|
export { type DeviceDiscoveryStatus, DeviceDiscoveryStatusSchema, type DiscoveredChildDevice, DiscoveredChildDeviceSchema, type DiscoveredChildStatus, DiscoveredChildStatusSchema, deviceDiscoveryCapability, type IDeviceDiscoveryNativeProvider, type IDeviceDiscoveryProvider, } from './device-discovery.cap.js';
|
|
147
151
|
export { deviceOpsCapability, type IDeviceOpsProvider, type RawStateResult, RawStateResultSchema, } from './device-ops.cap.js';
|
|
148
152
|
export { type DeviceStatus, DeviceStatusSchema, deviceStatusCapability, type IDeviceStatusProvider, } from './device-status.cap.js';
|
|
@@ -258,9 +262,11 @@ import type { coverCapability } from './cover.cap.js';
|
|
|
258
262
|
import type { customModelRegistryCapability } from './custom-model-registry.cap.js';
|
|
259
263
|
import type { dataStoreProviderCapability } from './data-store-provider.cap.js';
|
|
260
264
|
import type { dayNightCapability } from './day-night.cap.js';
|
|
265
|
+
import type { recordingOnboardCapability } from './recording-onboard.cap.js';
|
|
261
266
|
import type { decoderCapability } from './decoder.cap.js';
|
|
262
267
|
import type { detectionPipelineCapability } from './detection-pipeline.cap.js';
|
|
263
268
|
import type { deviceAdoptionCapability } from './device-adoption.cap.js';
|
|
269
|
+
import type { deviceAdminLinkCapability } from './device-admin-link.cap.js';
|
|
264
270
|
import type { deviceDiscoveryCapability } from './device-discovery.cap.js';
|
|
265
271
|
import type { deviceExportCapability } from './device-export.cap.js';
|
|
266
272
|
import type { deviceManagerCapability } from './device-manager.cap.js';
|
|
@@ -374,6 +380,6 @@ import type { webrtcSessionCapability } from './webrtc-session.cap.js';
|
|
|
374
380
|
import type { zoneAnalyticsCapability } from './zone-analytics.cap.js';
|
|
375
381
|
import type { zoneRulesCapability } from './zone-rules.cap.js';
|
|
376
382
|
import type { zonesCapability } from './zones.cap.js';
|
|
377
|
-
type AnyCapability = typeof streamSignalsCapability | typeof addonSettingsCapability | typeof alertsCapability | typeof storageCapability | typeof storageMigrationCapability | typeof storageProviderCapability | typeof storageEvictableCapability | typeof storageOccupancyCapability | typeof filesystemBrowseCapability | typeof backupCapability | typeof terminalSessionCapability | typeof settingsStoreCapability | typeof dataStoreProviderCapability | typeof logChannelsCapability | typeof logDestinationCapability | typeof loadContributionCapability | typeof failureContributionCapability | typeof adminUiCapability | typeof viewerUiCapability | typeof ssoBridgeCapability | typeof userPasskeysCapability | typeof smtpProviderCapability | typeof mqttBrokerCapability | typeof brokerCapability | typeof deviceAdoptionCapability | typeof deviceExportCapability | typeof addonPagesCapability | typeof addonPagesSourceCapability | typeof addonWidgetsCapability | typeof addonWidgetsSourceCapability | typeof customModelRegistryCapability | typeof modelDistributorCapability | typeof modelConvertCapability | typeof addonRoutesCapability | typeof streamBrokerCapability | typeof decoderCapability | typeof webrtcSessionCapability | typeof cameraStreamsCapability | typeof motionDetectionCapability | typeof pipelineExecutorCapability | typeof detectionPipelineCapability | typeof cameraPipelineConfigCapability | typeof pipelineRunnerCapability | typeof pipelineOrchestratorCapability | typeof audioAnalyzerCapability | typeof audioAnalysisCapability | typeof audioCodecCapability | typeof embeddingEncoderCapability | typeof vectorStoreCapability | typeof deviceProviderCapability | typeof deviceManagerCapability | typeof deviceStateCapability | typeof authProviderCapability | typeof loginMethodCapability | typeof networkAccessCapability | typeof turnProviderCapability | typeof snapshotCapability | typeof llmCapability | typeof llmRuntimeCapability | typeof notificationOutputCapability | typeof coreBlocksCapability | typeof notificationRulesCapability | typeof pipelineAnalyticsCapability | typeof metricsProviderCapability | typeof ptzCapability | typeof ptzAutotrackCapability | typeof navigationCapability | typeof consumablesCapability | typeof connectionTestCapability | typeof rebootCapability | typeof deviceDiscoveryCapability | typeof brightnessCapability | typeof colorCapability | typeof climateControlCapability | typeof coverCapability | typeof valveCapability | typeof humidifierCapability | typeof waterHeaterCapability | typeof weatherCapability | typeof imageCapability | typeof lockControlCapability | typeof vacuumControlCapability | typeof petFeederCapability | typeof lawnMowerControlCapability | typeof fanControlCapability | typeof controlCapability | typeof notifierCapability | typeof mediaPlayerCapability | typeof alarmPanelCapability | typeof presenceCapability | typeof scriptRunnerCapability | typeof automationControlCapability | typeof motionTriggerCapability | typeof eventsCapability | typeof zonesCapability | typeof zoneRulesCapability | typeof zoneAnalyticsCapability | typeof audioMetricsCapability | typeof motionCapability | typeof contactCapability | typeof floodCapability | typeof smokeCapability | typeof carbonMonoxideCapability | typeof gasCapability | typeof tamperCapability | typeof vibrationCapability | typeof connectivityCapability | typeof binaryCapability | typeof temperatureSensorCapability | typeof humiditySensorCapability | typeof ambientLightSensorCapability | typeof pressureSensorCapability | typeof powerMeterCapability | typeof airQualitySensorCapability | typeof numericSensorCapability | typeof enumSensorCapability | typeof recordingCapability | typeof recordingExportCapability | typeof recordingSignalCapability | typeof deviceOpsCapability | typeof platformProbeCapability | typeof localNetworkCapability | typeof meshNetworkCapability | typeof userManagementCapability | typeof systemCapability | typeof networkQualityCapability | typeof toastCapability | typeof nodesCapability | typeof serverManagementCapability | typeof integrationsCapability | typeof addonsCapability | typeof oauthIntegrationCapability | typeof streamParamsCapability | typeof streamCatalogCapability | typeof motionZonesCapability | typeof cameraGridLayoutCapability | typeof sceneMonitorCapability | typeof privacyMaskCapability | typeof dayNightCapability | typeof imageSettingsCapability | typeof osdCapability | typeof osdManagerCapability | typeof accessoriesCapability | typeof batteryCapability | typeof networkLinkCapability | typeof buttonCapability | typeof cameraCredentialsCapability | typeof deviceStatusCapability | typeof doorbellCapability | typeof eventEmitterCapability | typeof faceGalleryCapability | typeof featureProbeCapability | typeof intercomCapability | typeof nativeObjectDetectionCapability | typeof plateGalleryCapability | typeof switchCapability | typeof updateCapability | typeof videoclipsCapability;
|
|
383
|
+
type AnyCapability = typeof streamSignalsCapability | typeof addonSettingsCapability | typeof alertsCapability | typeof storageCapability | typeof storageMigrationCapability | typeof storageProviderCapability | typeof storageEvictableCapability | typeof storageOccupancyCapability | typeof filesystemBrowseCapability | typeof backupCapability | typeof terminalSessionCapability | typeof settingsStoreCapability | typeof dataStoreProviderCapability | typeof logChannelsCapability | typeof logDestinationCapability | typeof loadContributionCapability | typeof failureContributionCapability | typeof adminUiCapability | typeof viewerUiCapability | typeof ssoBridgeCapability | typeof userPasskeysCapability | typeof smtpProviderCapability | typeof mqttBrokerCapability | typeof brokerCapability | typeof deviceAdoptionCapability | typeof deviceAdminLinkCapability | typeof deviceExportCapability | typeof addonPagesCapability | typeof addonPagesSourceCapability | typeof addonWidgetsCapability | typeof addonWidgetsSourceCapability | typeof customModelRegistryCapability | typeof modelDistributorCapability | typeof modelConvertCapability | typeof addonRoutesCapability | typeof streamBrokerCapability | typeof decoderCapability | typeof webrtcSessionCapability | typeof cameraStreamsCapability | typeof motionDetectionCapability | typeof pipelineExecutorCapability | typeof detectionPipelineCapability | typeof cameraPipelineConfigCapability | typeof pipelineRunnerCapability | typeof pipelineOrchestratorCapability | typeof audioAnalyzerCapability | typeof audioAnalysisCapability | typeof audioCodecCapability | typeof embeddingEncoderCapability | typeof vectorStoreCapability | typeof deviceProviderCapability | typeof deviceManagerCapability | typeof deviceStateCapability | typeof authProviderCapability | typeof loginMethodCapability | typeof networkAccessCapability | typeof turnProviderCapability | typeof snapshotCapability | typeof llmCapability | typeof llmRuntimeCapability | typeof notificationOutputCapability | typeof coreBlocksCapability | typeof notificationRulesCapability | typeof pipelineAnalyticsCapability | typeof metricsProviderCapability | typeof ptzCapability | typeof ptzAutotrackCapability | typeof navigationCapability | typeof consumablesCapability | typeof connectionTestCapability | typeof rebootCapability | typeof deviceDiscoveryCapability | typeof brightnessCapability | typeof colorCapability | typeof climateControlCapability | typeof coverCapability | typeof valveCapability | typeof humidifierCapability | typeof waterHeaterCapability | typeof weatherCapability | typeof imageCapability | typeof lockControlCapability | typeof vacuumControlCapability | typeof petFeederCapability | typeof lawnMowerControlCapability | typeof fanControlCapability | typeof controlCapability | typeof notifierCapability | typeof mediaPlayerCapability | typeof alarmPanelCapability | typeof presenceCapability | typeof scriptRunnerCapability | typeof automationControlCapability | typeof motionTriggerCapability | typeof eventsCapability | typeof zonesCapability | typeof zoneRulesCapability | typeof zoneAnalyticsCapability | typeof audioMetricsCapability | typeof motionCapability | typeof contactCapability | typeof floodCapability | typeof smokeCapability | typeof carbonMonoxideCapability | typeof gasCapability | typeof tamperCapability | typeof vibrationCapability | typeof connectivityCapability | typeof binaryCapability | typeof temperatureSensorCapability | typeof humiditySensorCapability | typeof ambientLightSensorCapability | typeof pressureSensorCapability | typeof powerMeterCapability | typeof airQualitySensorCapability | typeof numericSensorCapability | typeof enumSensorCapability | typeof recordingCapability | typeof recordingExportCapability | typeof recordingSignalCapability | typeof deviceOpsCapability | typeof platformProbeCapability | typeof localNetworkCapability | typeof meshNetworkCapability | typeof userManagementCapability | typeof systemCapability | typeof networkQualityCapability | typeof toastCapability | typeof nodesCapability | typeof serverManagementCapability | typeof integrationsCapability | typeof addonsCapability | typeof oauthIntegrationCapability | typeof streamParamsCapability | typeof streamCatalogCapability | typeof motionZonesCapability | typeof cameraGridLayoutCapability | typeof sceneMonitorCapability | typeof privacyMaskCapability | typeof dayNightCapability | typeof recordingOnboardCapability | typeof imageSettingsCapability | typeof osdCapability | typeof osdManagerCapability | typeof accessoriesCapability | typeof batteryCapability | typeof networkLinkCapability | typeof buttonCapability | typeof cameraCredentialsCapability | typeof deviceStatusCapability | typeof doorbellCapability | typeof eventEmitterCapability | typeof faceGalleryCapability | typeof featureProbeCapability | typeof intercomCapability | typeof nativeObjectDetectionCapability | typeof plateGalleryCapability | typeof switchCapability | typeof updateCapability | typeof videoclipsCapability;
|
|
378
384
|
export type CapabilityName = AnyCapability['name'];
|
|
379
385
|
export type ITypedReadinessRegistry = IReadinessRegistry<CapabilityName>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recording-onboard` — the vendor-neutral rules both providers share.
|
|
3
|
+
*
|
|
4
|
+
* Three things live here rather than in each addon, because two
|
|
5
|
+
* hand-written copies of them would be two different opinions about the
|
|
6
|
+
* same question:
|
|
7
|
+
*
|
|
8
|
+
* 1. {@link describeOnboardRefusal} — THE refusal vocabulary. A write
|
|
9
|
+
* a camera cannot honour is refused with one sentence an operator
|
|
10
|
+
* can read, and the sentence is the same whoever refuses it.
|
|
11
|
+
* 2. {@link weeklyMaskToWindows} / {@link windowsToWeeklyMask} —
|
|
12
|
+
* Reolink's 7×24 hour mask ↔ the cap's {@link RecordWindow} list.
|
|
13
|
+
* 3. {@link timeOfDayToMinutes} / {@link minutesToTimeOfDay} —
|
|
14
|
+
* Hikvision's `TimeOfDay` strings ↔ minutes since midnight.
|
|
15
|
+
*
|
|
16
|
+
* Pure. No I/O, no clock, no logger.
|
|
17
|
+
*/
|
|
18
|
+
import type { RecordTrigger, RecordWindow, RecordingOnboardOptions, RecordingOnboardPatch } from './recording-onboard.cap.js';
|
|
19
|
+
/** Minutes in a day. `endMinute === 1440` means "to end of day". */
|
|
20
|
+
export declare const MINUTES_PER_DAY = 1440;
|
|
21
|
+
/** Days in the cap's week, 0 = Monday. */
|
|
22
|
+
export declare const DAYS_PER_WEEK = 7;
|
|
23
|
+
/** Hours per day — the resolution of Reolink's mask. */
|
|
24
|
+
export declare const HOURS_PER_DAY = 24;
|
|
25
|
+
/** Length of a Reolink weekly `valueTable`: 7 days × 24 hours. */
|
|
26
|
+
export declare const WEEKLY_MASK_LENGTH: number;
|
|
27
|
+
/**
|
|
28
|
+
* Day-of-week names in the cap's index order (0 = Monday), for messages
|
|
29
|
+
* an operator reads and for Hikvision's `<DayOfWeek>` element.
|
|
30
|
+
*/
|
|
31
|
+
export declare const DAY_NAMES: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* Does `patch` ask this camera for something it cannot do?
|
|
34
|
+
*
|
|
35
|
+
* Returns the operator-readable reason, or `null` when every field in
|
|
36
|
+
* the patch is within what `options` says this camera accepts. A
|
|
37
|
+
* provider calls this BEFORE touching the camera and throws the string:
|
|
38
|
+
* refusing is the point, and refusing identically on both vendors is why
|
|
39
|
+
* this is one function.
|
|
40
|
+
*
|
|
41
|
+
* The order of checks is the order an operator would read them: the
|
|
42
|
+
* scalar knobs first, then the schedule, because a schedule complaint is
|
|
43
|
+
* longer and a scalar one is usually the real problem.
|
|
44
|
+
*/
|
|
45
|
+
export declare function describeOnboardRefusal(options: RecordingOnboardOptions, patch: RecordingOnboardPatch): string | null;
|
|
46
|
+
/** `510` → `08:30`. For messages, not for the wire. */
|
|
47
|
+
export declare function formatMinutes(minute: number): string;
|
|
48
|
+
/**
|
|
49
|
+
* Index of the mask character covering `day` at `hour`.
|
|
50
|
+
*
|
|
51
|
+
* **Layout: day-major, Monday first** — `day * 24 + hour`.
|
|
52
|
+
*
|
|
53
|
+
* This is an ASSUMPTION, and it is recorded as one because the fleet
|
|
54
|
+
* cannot currently confirm it: every `valueTable` on every Reolink
|
|
55
|
+
* measured on 2026-09-22 is uniform (all `1` or all `0`), and a uniform
|
|
56
|
+
* mask reads identically under either layout. To settle it, set a single
|
|
57
|
+
* hour on one day from the Reolink app and re-read `getRecordSchedule`.
|
|
58
|
+
* Until then, a NON-uniform mask is reported as windows under this
|
|
59
|
+
* layout and the day labels may be transposed; a uniform one is exact.
|
|
60
|
+
*/
|
|
61
|
+
export declare function weeklyMaskIndex(day: number, hour: number): number;
|
|
62
|
+
/**
|
|
63
|
+
* True when every slot of the mask carries the same value — the case in
|
|
64
|
+
* which {@link weeklyMaskIndex}'s layout assumption cannot be wrong.
|
|
65
|
+
*/
|
|
66
|
+
export declare function weeklyMaskIsUniform(mask: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Expand one trigger's weekly hour mask into windows, merging adjacent
|
|
69
|
+
* set hours into one window per run so a full day is ONE window rather
|
|
70
|
+
* than twenty-four.
|
|
71
|
+
*
|
|
72
|
+
* A mask of the wrong length yields no windows: a truncated table is not
|
|
73
|
+
* a schedule of fewer days, it is an answer we did not understand.
|
|
74
|
+
*/
|
|
75
|
+
export declare function weeklyMaskToWindows(mask: string, trigger: RecordTrigger): RecordWindow[];
|
|
76
|
+
/**
|
|
77
|
+
* Collapse this trigger's windows back into a weekly hour mask.
|
|
78
|
+
*
|
|
79
|
+
* Windows for other triggers are ignored — the mask is per trigger. A
|
|
80
|
+
* window that is not hour-aligned is REFUSED upstream by
|
|
81
|
+
* {@link describeOnboardRefusal}; this function rounds nothing, it
|
|
82
|
+
* simply sets every hour the window fully or partly covers, so a caller
|
|
83
|
+
* that skipped the refusal cannot silently lose coverage.
|
|
84
|
+
*/
|
|
85
|
+
export declare function windowsToWeeklyMask(windows: readonly RecordWindow[], trigger: RecordTrigger): string;
|
|
86
|
+
/**
|
|
87
|
+
* Parse a Hikvision `<TimeOfDay>` into minutes since midnight.
|
|
88
|
+
*
|
|
89
|
+
* The firmware is not self-consistent and both spellings are real, on
|
|
90
|
+
* the same camera in the same block: a start time reads `00:00:00` and
|
|
91
|
+
* the matching end time reads `24:00`. Seconds are accepted and
|
|
92
|
+
* discarded — the cap's resolution is minutes — and `24:00` maps to
|
|
93
|
+
* {@link MINUTES_PER_DAY}, not to 0.
|
|
94
|
+
*
|
|
95
|
+
* Returns null for anything else, which a caller reports as a window it
|
|
96
|
+
* could not read rather than as midnight.
|
|
97
|
+
*/
|
|
98
|
+
export declare function timeOfDayToMinutes(value: string): number | null;
|
|
99
|
+
/**
|
|
100
|
+
* Render minutes back as a Hikvision `TimeOfDay`.
|
|
101
|
+
*
|
|
102
|
+
* Emits the camera's own two spellings: `24:00` for end-of-day, because
|
|
103
|
+
* that is what the firmware writes and `24:00:00` is not observed, and
|
|
104
|
+
* `HH:MM:SS` otherwise.
|
|
105
|
+
*/
|
|
106
|
+
export declare function minutesToTimeOfDay(minute: number): string;
|
|
107
|
+
/** `'Monday'` → 0. Case-insensitive. Null for anything unrecognised. */
|
|
108
|
+
export declare function dayOfWeekToIndex(value: string): number | null;
|
|
109
|
+
/** One field a camera stored differently from what it was asked. */
|
|
110
|
+
export interface OnboardClamp {
|
|
111
|
+
readonly field: string;
|
|
112
|
+
readonly asked: number | boolean | string;
|
|
113
|
+
/** What the camera holds now. `null` when the read-back could not say. */
|
|
114
|
+
readonly stored: number | boolean | string | null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Which fields of a patch the camera did NOT take verbatim.
|
|
118
|
+
*
|
|
119
|
+
* Measured on a Hikvision I91DN (1436, 2026-09-22): a `PUT` of
|
|
120
|
+
* `PreRecordTimeSeconds: 8` answered `200`, `statusCode 1`, `OK` — and stored
|
|
121
|
+
* **5**. Neither the asked value nor the previous one. The camera declares no
|
|
122
|
+
* allowed set for that field, so there is nothing to refuse against before the
|
|
123
|
+
* wire: `/capabilities` returns a plain value where a constrained field would
|
|
124
|
+
* carry an `opt=` list.
|
|
125
|
+
*
|
|
126
|
+
* So the only honest moment is after the read-back, and re-reading alone is
|
|
127
|
+
* not enough — it makes the difference VISIBLE while leaving it unexplained.
|
|
128
|
+
* A write that reports success for a value the camera never took is the same
|
|
129
|
+
* silent substitution D599 removed from the clip path, wearing a different hat.
|
|
130
|
+
*
|
|
131
|
+
* Compares only the fields the patch actually named: a field nobody asked
|
|
132
|
+
* about cannot have been clamped, and a read-back that could not answer it is
|
|
133
|
+
* `stored: null` rather than a claim.
|
|
134
|
+
*/
|
|
135
|
+
export declare function describeOnboardClamp(patch: Readonly<Record<string, unknown>>, landed: Readonly<Record<string, unknown>> | null): readonly OnboardClamp[];
|