@camstack/addon-export-ha-mqtt 1.1.15 → 1.1.17
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/export-ha-mqtt.addon.js +288 -5
- package/dist/export-ha-mqtt.addon.mjs +288 -5
- package/package.json +1 -1
|
@@ -4679,7 +4679,7 @@ function number(params) {
|
|
|
4679
4679
|
return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
|
|
4680
4680
|
}
|
|
4681
4681
|
//#endregion
|
|
4682
|
-
//#region ../types/dist/sleep-
|
|
4682
|
+
//#region ../types/dist/sleep-CZDdRBua.mjs
|
|
4683
4683
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4684
4684
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4685
4685
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -7274,7 +7274,16 @@ var DecoderStatsSchema = object({
|
|
|
7274
7274
|
inputFps: number$1(),
|
|
7275
7275
|
outputFps: number$1(),
|
|
7276
7276
|
avgDecodeTimeMs: number$1(),
|
|
7277
|
-
droppedFrames: number$1()
|
|
7277
|
+
droppedFrames: number$1(),
|
|
7278
|
+
/**
|
|
7279
|
+
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
7280
|
+
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
7281
|
+
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
7282
|
+
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
7283
|
+
*/
|
|
7284
|
+
lagMs: number$1().optional(),
|
|
7285
|
+
effectiveFps: number$1().optional(),
|
|
7286
|
+
adaptiveFps: number$1().optional()
|
|
7278
7287
|
});
|
|
7279
7288
|
var DecoderSessionConfigSchema = object({
|
|
7280
7289
|
codec: string(),
|
|
@@ -7315,7 +7324,15 @@ var DecoderSessionConfigSchema = object({
|
|
|
7315
7324
|
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
7316
7325
|
* `pullHandles` returns nothing for a `'callback'` session.
|
|
7317
7326
|
*/
|
|
7318
|
-
frameSink: _enum(["callback", "shm"]).default("callback")
|
|
7327
|
+
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
7328
|
+
/**
|
|
7329
|
+
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
7330
|
+
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
7331
|
+
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
7332
|
+
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
7333
|
+
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
7334
|
+
*/
|
|
7335
|
+
debug: boolean().optional()
|
|
7319
7336
|
});
|
|
7320
7337
|
var EncodeProfileSchema = object({
|
|
7321
7338
|
video: object({
|
|
@@ -9473,6 +9490,75 @@ DeviceType.Cover, method(object({ deviceId: number$1().int().nonnegative() }), _
|
|
|
9473
9490
|
auth: "admin"
|
|
9474
9491
|
});
|
|
9475
9492
|
/**
|
|
9493
|
+
* Vendor-neutral day/night (IR-cut) control — the per-camera config cap
|
|
9494
|
+
* shared by reolink / hikvision / amcrest. Models the common firmware
|
|
9495
|
+
* surface: the IR-cut switching MODE plus the two knobs that gate it
|
|
9496
|
+
* (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
|
|
9497
|
+
* onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
|
|
9498
|
+
* the shape so ONE derived-form renders every camera.
|
|
9499
|
+
*
|
|
9500
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9501
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9502
|
+
* injected from `status`) reports the live values, and a single
|
|
9503
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9504
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9505
|
+
* routing from this surface.
|
|
9506
|
+
*/
|
|
9507
|
+
/** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
|
|
9508
|
+
var DayNightModeSchema = _enum([
|
|
9509
|
+
"auto",
|
|
9510
|
+
"day",
|
|
9511
|
+
"night",
|
|
9512
|
+
"schedule"
|
|
9513
|
+
]);
|
|
9514
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9515
|
+
* getOptions availability convention. Normalized values are 0–100. */
|
|
9516
|
+
var NormalizedRangeSchema$1 = object({
|
|
9517
|
+
min: number$1(),
|
|
9518
|
+
max: number$1(),
|
|
9519
|
+
step: number$1()
|
|
9520
|
+
});
|
|
9521
|
+
object({
|
|
9522
|
+
mode: DayNightModeSchema,
|
|
9523
|
+
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
9524
|
+
sensitivity: number$1().optional(),
|
|
9525
|
+
/** Delay before the IR-cut filter flips, in seconds. */
|
|
9526
|
+
switchDelaySec: number$1().optional(),
|
|
9527
|
+
lastFetchedAt: number$1()
|
|
9528
|
+
});
|
|
9529
|
+
/**
|
|
9530
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9531
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9532
|
+
* (normalized 0–100); the mode choice-set as an array. A provider returns
|
|
9533
|
+
* honest, camera-probed values — never hardcoded.
|
|
9534
|
+
*/
|
|
9535
|
+
var DayNightOptionsSchema = object({
|
|
9536
|
+
/** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
|
|
9537
|
+
modes: array(DayNightModeSchema),
|
|
9538
|
+
supportsSensitivity: boolean(),
|
|
9539
|
+
/** Present when `supportsSensitivity` — the normalized 0–100 range. */
|
|
9540
|
+
sensitivity: NormalizedRangeSchema$1.optional(),
|
|
9541
|
+
supportsSwitchDelay: boolean(),
|
|
9542
|
+
/** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
|
|
9543
|
+
switchDelaySec: NormalizedRangeSchema$1.optional()
|
|
9544
|
+
});
|
|
9545
|
+
/**
|
|
9546
|
+
* Partial change to the day/night config — every field optional. A
|
|
9547
|
+
* provider ignores fields it does not support.
|
|
9548
|
+
*/
|
|
9549
|
+
var DayNightSettingsPatchSchema = object({
|
|
9550
|
+
mode: DayNightModeSchema.optional(),
|
|
9551
|
+
sensitivity: number$1().optional(),
|
|
9552
|
+
switchDelaySec: number$1().optional()
|
|
9553
|
+
});
|
|
9554
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), DayNightOptionsSchema), method(object({
|
|
9555
|
+
deviceId: number$1(),
|
|
9556
|
+
settings: DayNightSettingsPatchSchema
|
|
9557
|
+
}), _void(), {
|
|
9558
|
+
kind: "mutation",
|
|
9559
|
+
auth: "admin"
|
|
9560
|
+
});
|
|
9561
|
+
/**
|
|
9476
9562
|
* Identity envelope for a device's upstream-system metadata.
|
|
9477
9563
|
*
|
|
9478
9564
|
* Two jobs:
|
|
@@ -9828,6 +9914,130 @@ object({
|
|
|
9828
9914
|
});
|
|
9829
9915
|
DeviceType.Image;
|
|
9830
9916
|
/**
|
|
9917
|
+
* Vendor-neutral image / picture-adjustment cap — the per-camera config
|
|
9918
|
+
* cap shared by reolink / hikvision / amcrest. Models the common ISP
|
|
9919
|
+
* surface: the four picture sliders (brightness / contrast / saturation /
|
|
9920
|
+
* sharpness), orientation (mirror / flip / rotate), white-balance,
|
|
9921
|
+
* exposure and backlight-compensation modes.
|
|
9922
|
+
*
|
|
9923
|
+
* NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
|
|
9924
|
+
* these natively as 0–100 or 0–255 (or other ranges); each provider maps
|
|
9925
|
+
* its native range to/from this normalized 0–100 space so the cap surface
|
|
9926
|
+
* (and the derived form) is identical across cameras. `warmth` (manual
|
|
9927
|
+
* white-balance) is likewise normalized 0–100.
|
|
9928
|
+
*
|
|
9929
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9930
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9931
|
+
* injected from `status`) reports the live values, and a single
|
|
9932
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9933
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9934
|
+
* routing from this surface.
|
|
9935
|
+
*/
|
|
9936
|
+
/** Sensor/image rotation, degrees clockwise. */
|
|
9937
|
+
var ImageRotateSchema = _enum([
|
|
9938
|
+
"0",
|
|
9939
|
+
"90",
|
|
9940
|
+
"180",
|
|
9941
|
+
"270"
|
|
9942
|
+
]);
|
|
9943
|
+
/** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
|
|
9944
|
+
var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
|
|
9945
|
+
/** Exposure mode. */
|
|
9946
|
+
var ExposureModeSchema = _enum(["auto", "manual"]);
|
|
9947
|
+
/**
|
|
9948
|
+
* Backlight-compensation mode:
|
|
9949
|
+
* - `off` — disabled
|
|
9950
|
+
* - `blc` — backlight compensation
|
|
9951
|
+
* - `wdr` — wide dynamic range
|
|
9952
|
+
* - `hlc` — highlight compensation
|
|
9953
|
+
*/
|
|
9954
|
+
var BacklightModeSchema = _enum([
|
|
9955
|
+
"off",
|
|
9956
|
+
"blc",
|
|
9957
|
+
"wdr",
|
|
9958
|
+
"hlc"
|
|
9959
|
+
]);
|
|
9960
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9961
|
+
* getOptions availability convention. Slider values are normalized 0–100. */
|
|
9962
|
+
var NormalizedRangeSchema = object({
|
|
9963
|
+
min: number$1(),
|
|
9964
|
+
max: number$1(),
|
|
9965
|
+
step: number$1()
|
|
9966
|
+
});
|
|
9967
|
+
object({
|
|
9968
|
+
/** Normalized 0–100. */
|
|
9969
|
+
brightness: number$1().optional(),
|
|
9970
|
+
/** Normalized 0–100. */
|
|
9971
|
+
contrast: number$1().optional(),
|
|
9972
|
+
/** Normalized 0–100. */
|
|
9973
|
+
saturation: number$1().optional(),
|
|
9974
|
+
/** Normalized 0–100. */
|
|
9975
|
+
sharpness: number$1().optional(),
|
|
9976
|
+
mirror: boolean().optional(),
|
|
9977
|
+
flip: boolean().optional(),
|
|
9978
|
+
rotate: ImageRotateSchema.optional(),
|
|
9979
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
9980
|
+
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
9981
|
+
warmth: number$1().optional(),
|
|
9982
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
9983
|
+
backlightMode: BacklightModeSchema.optional(),
|
|
9984
|
+
lastFetchedAt: number$1()
|
|
9985
|
+
});
|
|
9986
|
+
/**
|
|
9987
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9988
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9989
|
+
* (the normalized 0–100 range); enums as arrays of supported values (empty
|
|
9990
|
+
* array → control hidden). A provider returns honest, camera-probed values
|
|
9991
|
+
* — never hardcoded.
|
|
9992
|
+
*/
|
|
9993
|
+
var ImageSettingsOptionsSchema = object({
|
|
9994
|
+
supportsBrightness: boolean(),
|
|
9995
|
+
brightness: NormalizedRangeSchema.optional(),
|
|
9996
|
+
supportsContrast: boolean(),
|
|
9997
|
+
contrast: NormalizedRangeSchema.optional(),
|
|
9998
|
+
supportsSaturation: boolean(),
|
|
9999
|
+
saturation: NormalizedRangeSchema.optional(),
|
|
10000
|
+
supportsSharpness: boolean(),
|
|
10001
|
+
sharpness: NormalizedRangeSchema.optional(),
|
|
10002
|
+
supportsMirror: boolean(),
|
|
10003
|
+
supportsFlip: boolean(),
|
|
10004
|
+
/** Supported rotation values. Empty → rotation not configurable. */
|
|
10005
|
+
rotateOptions: array(ImageRotateSchema),
|
|
10006
|
+
/** Supported white-balance modes. Empty → white-balance not configurable. */
|
|
10007
|
+
whiteBalanceModes: array(WhiteBalanceModeSchema),
|
|
10008
|
+
supportsWarmth: boolean(),
|
|
10009
|
+
/** Present when `supportsWarmth` — the normalized 0–100 range. */
|
|
10010
|
+
warmth: NormalizedRangeSchema.optional(),
|
|
10011
|
+
/** Supported exposure modes. Empty → exposure not configurable. */
|
|
10012
|
+
exposureModes: array(ExposureModeSchema),
|
|
10013
|
+
/** Supported backlight modes. Empty → backlight-compensation not configurable. */
|
|
10014
|
+
backlightModes: array(BacklightModeSchema)
|
|
10015
|
+
});
|
|
10016
|
+
/**
|
|
10017
|
+
* Partial change to the image config — every field optional. Slider values
|
|
10018
|
+
* are normalized 0–100. A provider ignores fields it does not support.
|
|
10019
|
+
*/
|
|
10020
|
+
var ImageSettingsPatchSchema = object({
|
|
10021
|
+
brightness: number$1().optional(),
|
|
10022
|
+
contrast: number$1().optional(),
|
|
10023
|
+
saturation: number$1().optional(),
|
|
10024
|
+
sharpness: number$1().optional(),
|
|
10025
|
+
mirror: boolean().optional(),
|
|
10026
|
+
flip: boolean().optional(),
|
|
10027
|
+
rotate: ImageRotateSchema.optional(),
|
|
10028
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10029
|
+
warmth: number$1().optional(),
|
|
10030
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10031
|
+
backlightMode: BacklightModeSchema.optional()
|
|
10032
|
+
});
|
|
10033
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), ImageSettingsOptionsSchema), method(object({
|
|
10034
|
+
deviceId: number$1(),
|
|
10035
|
+
settings: ImageSettingsPatchSchema
|
|
10036
|
+
}), _void(), {
|
|
10037
|
+
kind: "mutation",
|
|
10038
|
+
auth: "admin"
|
|
10039
|
+
});
|
|
10040
|
+
/**
|
|
9831
10041
|
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
9832
10042
|
* with a mowing lifecycle plus a dock action.
|
|
9833
10043
|
*
|
|
@@ -10722,6 +10932,16 @@ var RunnerCameraConfigSchema = object({
|
|
|
10722
10932
|
* this gate is bypassed.
|
|
10723
10933
|
*/
|
|
10724
10934
|
onboardMotionDrivesAnalyzer: boolean().default(true),
|
|
10935
|
+
/**
|
|
10936
|
+
* Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
|
|
10937
|
+
* never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
|
|
10938
|
+
* this is off by default because the recheck re-subscribes a detection session
|
|
10939
|
+
* every N seconds while `watching`, a major source of pull-decoder re-dial
|
|
10940
|
+
* churn (each cycle creates+tears a session → RTSP re-dial → latency). The
|
|
10941
|
+
* `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
|
|
10942
|
+
* (and only render) when this is enabled.
|
|
10943
|
+
*/
|
|
10944
|
+
occupancyRecheckEnabled: boolean().default(false),
|
|
10725
10945
|
occupancyRecheckSec: number$1().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
10726
10946
|
occupancyRecheckFrames: number$1().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
10727
10947
|
/**
|
|
@@ -13018,7 +13238,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
|
|
|
13018
13238
|
id: string(),
|
|
13019
13239
|
name: string(),
|
|
13020
13240
|
isPullMode: boolean().optional(),
|
|
13021
|
-
priority: number$1().optional()
|
|
13241
|
+
priority: number$1().optional(),
|
|
13242
|
+
hwaccel: string().optional(),
|
|
13243
|
+
probedBestHwaccel: string().optional()
|
|
13022
13244
|
})), method(DecoderSessionConfigSchema, object({
|
|
13023
13245
|
sessionId: string(),
|
|
13024
13246
|
nodeId: string()
|
|
@@ -14957,7 +15179,17 @@ var AgentAddonConfigSchema = object({
|
|
|
14957
15179
|
});
|
|
14958
15180
|
var AgentPipelineSettingsSchema = object({
|
|
14959
15181
|
addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
|
|
14960
|
-
maxCameras: number$1().int().nonnegative().nullable().default(null)
|
|
15182
|
+
maxCameras: number$1().int().nonnegative().nullable().default(null),
|
|
15183
|
+
/** Per-node detection weight (relative share for the quota balancer). */
|
|
15184
|
+
detectWeight: number$1().positive().optional(),
|
|
15185
|
+
/** Node is eligible to run the detection pipeline (decode + inference). */
|
|
15186
|
+
detect: boolean().optional(),
|
|
15187
|
+
/** Node is eligible to host decoder sessions. */
|
|
15188
|
+
decode: boolean().optional(),
|
|
15189
|
+
/** Node is eligible to run audio-analyzer sessions. */
|
|
15190
|
+
audio: boolean().optional(),
|
|
15191
|
+
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
15192
|
+
ingest: boolean().optional()
|
|
14961
15193
|
});
|
|
14962
15194
|
var CameraPipelineForAgentSchema = object({
|
|
14963
15195
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -15263,6 +15495,21 @@ method(object({
|
|
|
15263
15495
|
}), object({ success: literal(true) }), {
|
|
15264
15496
|
kind: "mutation",
|
|
15265
15497
|
auth: "admin"
|
|
15498
|
+
}), method(object({
|
|
15499
|
+
agentNodeId: string(),
|
|
15500
|
+
detectWeight: number$1().positive().nullable()
|
|
15501
|
+
}), object({ success: literal(true) }), {
|
|
15502
|
+
kind: "mutation",
|
|
15503
|
+
auth: "admin"
|
|
15504
|
+
}), method(object({
|
|
15505
|
+
agentNodeId: string(),
|
|
15506
|
+
detect: boolean().nullable().optional(),
|
|
15507
|
+
decode: boolean().nullable().optional(),
|
|
15508
|
+
audio: boolean().nullable().optional(),
|
|
15509
|
+
ingest: boolean().nullable().optional()
|
|
15510
|
+
}), object({ success: literal(true) }), {
|
|
15511
|
+
kind: "mutation",
|
|
15512
|
+
auth: "admin"
|
|
15266
15513
|
}), method(object({ deviceId: number$1() }), CameraPipelineSettingsSchema.nullable()), method(object({
|
|
15267
15514
|
deviceId: number$1(),
|
|
15268
15515
|
addonId: string(),
|
|
@@ -19010,6 +19257,18 @@ Object.freeze({
|
|
|
19010
19257
|
addonId: null,
|
|
19011
19258
|
access: "view"
|
|
19012
19259
|
},
|
|
19260
|
+
"dayNight.getOptions": {
|
|
19261
|
+
capName: "day-night",
|
|
19262
|
+
capScope: "device",
|
|
19263
|
+
addonId: null,
|
|
19264
|
+
access: "view"
|
|
19265
|
+
},
|
|
19266
|
+
"dayNight.setSettings": {
|
|
19267
|
+
capName: "day-night",
|
|
19268
|
+
capScope: "device",
|
|
19269
|
+
addonId: null,
|
|
19270
|
+
access: "create"
|
|
19271
|
+
},
|
|
19013
19272
|
"decoder.createSession": {
|
|
19014
19273
|
capName: "decoder",
|
|
19015
19274
|
capScope: "system",
|
|
@@ -19940,6 +20199,18 @@ Object.freeze({
|
|
|
19940
20199
|
addonId: null,
|
|
19941
20200
|
access: "create"
|
|
19942
20201
|
},
|
|
20202
|
+
"imageSettings.getOptions": {
|
|
20203
|
+
capName: "image-settings",
|
|
20204
|
+
capScope: "device",
|
|
20205
|
+
addonId: null,
|
|
20206
|
+
access: "view"
|
|
20207
|
+
},
|
|
20208
|
+
"imageSettings.setSettings": {
|
|
20209
|
+
capName: "image-settings",
|
|
20210
|
+
capScope: "device",
|
|
20211
|
+
addonId: null,
|
|
20212
|
+
access: "create"
|
|
20213
|
+
},
|
|
19943
20214
|
"integrations.create": {
|
|
19944
20215
|
capName: "integrations",
|
|
19945
20216
|
capScope: "system",
|
|
@@ -21122,6 +21393,18 @@ Object.freeze({
|
|
|
21122
21393
|
addonId: null,
|
|
21123
21394
|
access: "create"
|
|
21124
21395
|
},
|
|
21396
|
+
"pipelineOrchestrator.setAgentCapabilities": {
|
|
21397
|
+
capName: "pipeline-orchestrator",
|
|
21398
|
+
capScope: "system",
|
|
21399
|
+
addonId: null,
|
|
21400
|
+
access: "create"
|
|
21401
|
+
},
|
|
21402
|
+
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
21403
|
+
capName: "pipeline-orchestrator",
|
|
21404
|
+
capScope: "system",
|
|
21405
|
+
addonId: null,
|
|
21406
|
+
access: "create"
|
|
21407
|
+
},
|
|
21125
21408
|
"pipelineOrchestrator.setAgentMaxCameras": {
|
|
21126
21409
|
capName: "pipeline-orchestrator",
|
|
21127
21410
|
capScope: "system",
|
|
@@ -4677,7 +4677,7 @@ function number(params) {
|
|
|
4677
4677
|
return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
|
|
4678
4678
|
}
|
|
4679
4679
|
//#endregion
|
|
4680
|
-
//#region ../types/dist/sleep-
|
|
4680
|
+
//#region ../types/dist/sleep-CZDdRBua.mjs
|
|
4681
4681
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4682
4682
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4683
4683
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -7272,7 +7272,16 @@ var DecoderStatsSchema = object({
|
|
|
7272
7272
|
inputFps: number$1(),
|
|
7273
7273
|
outputFps: number$1(),
|
|
7274
7274
|
avgDecodeTimeMs: number$1(),
|
|
7275
|
-
droppedFrames: number$1()
|
|
7275
|
+
droppedFrames: number$1(),
|
|
7276
|
+
/**
|
|
7277
|
+
* Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
|
|
7278
|
+
* lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
|
|
7279
|
+
* the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
|
|
7280
|
+
* is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
|
|
7281
|
+
*/
|
|
7282
|
+
lagMs: number$1().optional(),
|
|
7283
|
+
effectiveFps: number$1().optional(),
|
|
7284
|
+
adaptiveFps: number$1().optional()
|
|
7276
7285
|
});
|
|
7277
7286
|
var DecoderSessionConfigSchema = object({
|
|
7278
7287
|
codec: string(),
|
|
@@ -7313,7 +7322,15 @@ var DecoderSessionConfigSchema = object({
|
|
|
7313
7322
|
* other — `pullFrames` returns nothing for an `'shm'` session and
|
|
7314
7323
|
* `pullHandles` returns nothing for a `'callback'` session.
|
|
7315
7324
|
*/
|
|
7316
|
-
frameSink: _enum(["callback", "shm"]).default("callback")
|
|
7325
|
+
frameSink: _enum(["callback", "shm"]).default("callback"),
|
|
7326
|
+
/**
|
|
7327
|
+
* Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
|
|
7328
|
+
* a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
|
|
7329
|
+
* real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
|
|
7330
|
+
* stream-broker's `streamingDebug` gate — off by default so production logs
|
|
7331
|
+
* stay quiet and the emit path pays zero per-frame cost when disabled.
|
|
7332
|
+
*/
|
|
7333
|
+
debug: boolean().optional()
|
|
7317
7334
|
});
|
|
7318
7335
|
var EncodeProfileSchema = object({
|
|
7319
7336
|
video: object({
|
|
@@ -9471,6 +9488,75 @@ DeviceType.Cover, method(object({ deviceId: number$1().int().nonnegative() }), _
|
|
|
9471
9488
|
auth: "admin"
|
|
9472
9489
|
});
|
|
9473
9490
|
/**
|
|
9491
|
+
* Vendor-neutral day/night (IR-cut) control — the per-camera config cap
|
|
9492
|
+
* shared by reolink / hikvision / amcrest. Models the common firmware
|
|
9493
|
+
* surface: the IR-cut switching MODE plus the two knobs that gate it
|
|
9494
|
+
* (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
|
|
9495
|
+
* onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
|
|
9496
|
+
* the shape so ONE derived-form renders every camera.
|
|
9497
|
+
*
|
|
9498
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9499
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9500
|
+
* injected from `status`) reports the live values, and a single
|
|
9501
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9502
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9503
|
+
* routing from this surface.
|
|
9504
|
+
*/
|
|
9505
|
+
/** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
|
|
9506
|
+
var DayNightModeSchema = _enum([
|
|
9507
|
+
"auto",
|
|
9508
|
+
"day",
|
|
9509
|
+
"night",
|
|
9510
|
+
"schedule"
|
|
9511
|
+
]);
|
|
9512
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9513
|
+
* getOptions availability convention. Normalized values are 0–100. */
|
|
9514
|
+
var NormalizedRangeSchema$1 = object({
|
|
9515
|
+
min: number$1(),
|
|
9516
|
+
max: number$1(),
|
|
9517
|
+
step: number$1()
|
|
9518
|
+
});
|
|
9519
|
+
object({
|
|
9520
|
+
mode: DayNightModeSchema,
|
|
9521
|
+
/** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
|
|
9522
|
+
sensitivity: number$1().optional(),
|
|
9523
|
+
/** Delay before the IR-cut filter flips, in seconds. */
|
|
9524
|
+
switchDelaySec: number$1().optional(),
|
|
9525
|
+
lastFetchedAt: number$1()
|
|
9526
|
+
});
|
|
9527
|
+
/**
|
|
9528
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9529
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9530
|
+
* (normalized 0–100); the mode choice-set as an array. A provider returns
|
|
9531
|
+
* honest, camera-probed values — never hardcoded.
|
|
9532
|
+
*/
|
|
9533
|
+
var DayNightOptionsSchema = object({
|
|
9534
|
+
/** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
|
|
9535
|
+
modes: array(DayNightModeSchema),
|
|
9536
|
+
supportsSensitivity: boolean(),
|
|
9537
|
+
/** Present when `supportsSensitivity` — the normalized 0–100 range. */
|
|
9538
|
+
sensitivity: NormalizedRangeSchema$1.optional(),
|
|
9539
|
+
supportsSwitchDelay: boolean(),
|
|
9540
|
+
/** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
|
|
9541
|
+
switchDelaySec: NormalizedRangeSchema$1.optional()
|
|
9542
|
+
});
|
|
9543
|
+
/**
|
|
9544
|
+
* Partial change to the day/night config — every field optional. A
|
|
9545
|
+
* provider ignores fields it does not support.
|
|
9546
|
+
*/
|
|
9547
|
+
var DayNightSettingsPatchSchema = object({
|
|
9548
|
+
mode: DayNightModeSchema.optional(),
|
|
9549
|
+
sensitivity: number$1().optional(),
|
|
9550
|
+
switchDelaySec: number$1().optional()
|
|
9551
|
+
});
|
|
9552
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), DayNightOptionsSchema), method(object({
|
|
9553
|
+
deviceId: number$1(),
|
|
9554
|
+
settings: DayNightSettingsPatchSchema
|
|
9555
|
+
}), _void(), {
|
|
9556
|
+
kind: "mutation",
|
|
9557
|
+
auth: "admin"
|
|
9558
|
+
});
|
|
9559
|
+
/**
|
|
9474
9560
|
* Identity envelope for a device's upstream-system metadata.
|
|
9475
9561
|
*
|
|
9476
9562
|
* Two jobs:
|
|
@@ -9826,6 +9912,130 @@ object({
|
|
|
9826
9912
|
});
|
|
9827
9913
|
DeviceType.Image;
|
|
9828
9914
|
/**
|
|
9915
|
+
* Vendor-neutral image / picture-adjustment cap — the per-camera config
|
|
9916
|
+
* cap shared by reolink / hikvision / amcrest. Models the common ISP
|
|
9917
|
+
* surface: the four picture sliders (brightness / contrast / saturation /
|
|
9918
|
+
* sharpness), orientation (mirror / flip / rotate), white-balance,
|
|
9919
|
+
* exposure and backlight-compensation modes.
|
|
9920
|
+
*
|
|
9921
|
+
* NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
|
|
9922
|
+
* these natively as 0–100 or 0–255 (or other ranges); each provider maps
|
|
9923
|
+
* its native range to/from this normalized 0–100 space so the cap surface
|
|
9924
|
+
* (and the derived form) is identical across cameras. `warmth` (manual
|
|
9925
|
+
* white-balance) is likewise normalized 0–100.
|
|
9926
|
+
*
|
|
9927
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
9928
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
9929
|
+
* injected from `status`) reports the live values, and a single
|
|
9930
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
9931
|
+
* settings-contribution methods — the framework derives the UI + save
|
|
9932
|
+
* routing from this surface.
|
|
9933
|
+
*/
|
|
9934
|
+
/** Sensor/image rotation, degrees clockwise. */
|
|
9935
|
+
var ImageRotateSchema = _enum([
|
|
9936
|
+
"0",
|
|
9937
|
+
"90",
|
|
9938
|
+
"180",
|
|
9939
|
+
"270"
|
|
9940
|
+
]);
|
|
9941
|
+
/** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
|
|
9942
|
+
var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
|
|
9943
|
+
/** Exposure mode. */
|
|
9944
|
+
var ExposureModeSchema = _enum(["auto", "manual"]);
|
|
9945
|
+
/**
|
|
9946
|
+
* Backlight-compensation mode:
|
|
9947
|
+
* - `off` — disabled
|
|
9948
|
+
* - `blc` — backlight compensation
|
|
9949
|
+
* - `wdr` — wide dynamic range
|
|
9950
|
+
* - `hlc` — highlight compensation
|
|
9951
|
+
*/
|
|
9952
|
+
var BacklightModeSchema = _enum([
|
|
9953
|
+
"off",
|
|
9954
|
+
"blc",
|
|
9955
|
+
"wdr",
|
|
9956
|
+
"hlc"
|
|
9957
|
+
]);
|
|
9958
|
+
/** Normalized numeric range descriptor — `{ min, max, step }` per the
|
|
9959
|
+
* getOptions availability convention. Slider values are normalized 0–100. */
|
|
9960
|
+
var NormalizedRangeSchema = object({
|
|
9961
|
+
min: number$1(),
|
|
9962
|
+
max: number$1(),
|
|
9963
|
+
step: number$1()
|
|
9964
|
+
});
|
|
9965
|
+
object({
|
|
9966
|
+
/** Normalized 0–100. */
|
|
9967
|
+
brightness: number$1().optional(),
|
|
9968
|
+
/** Normalized 0–100. */
|
|
9969
|
+
contrast: number$1().optional(),
|
|
9970
|
+
/** Normalized 0–100. */
|
|
9971
|
+
saturation: number$1().optional(),
|
|
9972
|
+
/** Normalized 0–100. */
|
|
9973
|
+
sharpness: number$1().optional(),
|
|
9974
|
+
mirror: boolean().optional(),
|
|
9975
|
+
flip: boolean().optional(),
|
|
9976
|
+
rotate: ImageRotateSchema.optional(),
|
|
9977
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
9978
|
+
/** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
|
|
9979
|
+
warmth: number$1().optional(),
|
|
9980
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
9981
|
+
backlightMode: BacklightModeSchema.optional(),
|
|
9982
|
+
lastFetchedAt: number$1()
|
|
9983
|
+
});
|
|
9984
|
+
/**
|
|
9985
|
+
* Per-camera availability descriptor — drives which controls the admin UI
|
|
9986
|
+
* renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
|
|
9987
|
+
* (the normalized 0–100 range); enums as arrays of supported values (empty
|
|
9988
|
+
* array → control hidden). A provider returns honest, camera-probed values
|
|
9989
|
+
* — never hardcoded.
|
|
9990
|
+
*/
|
|
9991
|
+
var ImageSettingsOptionsSchema = object({
|
|
9992
|
+
supportsBrightness: boolean(),
|
|
9993
|
+
brightness: NormalizedRangeSchema.optional(),
|
|
9994
|
+
supportsContrast: boolean(),
|
|
9995
|
+
contrast: NormalizedRangeSchema.optional(),
|
|
9996
|
+
supportsSaturation: boolean(),
|
|
9997
|
+
saturation: NormalizedRangeSchema.optional(),
|
|
9998
|
+
supportsSharpness: boolean(),
|
|
9999
|
+
sharpness: NormalizedRangeSchema.optional(),
|
|
10000
|
+
supportsMirror: boolean(),
|
|
10001
|
+
supportsFlip: boolean(),
|
|
10002
|
+
/** Supported rotation values. Empty → rotation not configurable. */
|
|
10003
|
+
rotateOptions: array(ImageRotateSchema),
|
|
10004
|
+
/** Supported white-balance modes. Empty → white-balance not configurable. */
|
|
10005
|
+
whiteBalanceModes: array(WhiteBalanceModeSchema),
|
|
10006
|
+
supportsWarmth: boolean(),
|
|
10007
|
+
/** Present when `supportsWarmth` — the normalized 0–100 range. */
|
|
10008
|
+
warmth: NormalizedRangeSchema.optional(),
|
|
10009
|
+
/** Supported exposure modes. Empty → exposure not configurable. */
|
|
10010
|
+
exposureModes: array(ExposureModeSchema),
|
|
10011
|
+
/** Supported backlight modes. Empty → backlight-compensation not configurable. */
|
|
10012
|
+
backlightModes: array(BacklightModeSchema)
|
|
10013
|
+
});
|
|
10014
|
+
/**
|
|
10015
|
+
* Partial change to the image config — every field optional. Slider values
|
|
10016
|
+
* are normalized 0–100. A provider ignores fields it does not support.
|
|
10017
|
+
*/
|
|
10018
|
+
var ImageSettingsPatchSchema = object({
|
|
10019
|
+
brightness: number$1().optional(),
|
|
10020
|
+
contrast: number$1().optional(),
|
|
10021
|
+
saturation: number$1().optional(),
|
|
10022
|
+
sharpness: number$1().optional(),
|
|
10023
|
+
mirror: boolean().optional(),
|
|
10024
|
+
flip: boolean().optional(),
|
|
10025
|
+
rotate: ImageRotateSchema.optional(),
|
|
10026
|
+
whiteBalance: WhiteBalanceModeSchema.optional(),
|
|
10027
|
+
warmth: number$1().optional(),
|
|
10028
|
+
exposureMode: ExposureModeSchema.optional(),
|
|
10029
|
+
backlightMode: BacklightModeSchema.optional()
|
|
10030
|
+
});
|
|
10031
|
+
DeviceType.Camera, method(object({ deviceId: number$1() }), ImageSettingsOptionsSchema), method(object({
|
|
10032
|
+
deviceId: number$1(),
|
|
10033
|
+
settings: ImageSettingsPatchSchema
|
|
10034
|
+
}), _void(), {
|
|
10035
|
+
kind: "mutation",
|
|
10036
|
+
auth: "admin"
|
|
10037
|
+
});
|
|
10038
|
+
/**
|
|
9829
10039
|
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
9830
10040
|
* with a mowing lifecycle plus a dock action.
|
|
9831
10041
|
*
|
|
@@ -10720,6 +10930,16 @@ var RunnerCameraConfigSchema = object({
|
|
|
10720
10930
|
* this gate is bypassed.
|
|
10721
10931
|
*/
|
|
10722
10932
|
onboardMotionDrivesAnalyzer: boolean().default(true),
|
|
10933
|
+
/**
|
|
10934
|
+
* Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
|
|
10935
|
+
* never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
|
|
10936
|
+
* this is off by default because the recheck re-subscribes a detection session
|
|
10937
|
+
* every N seconds while `watching`, a major source of pull-decoder re-dial
|
|
10938
|
+
* churn (each cycle creates+tears a session → RTSP re-dial → latency). The
|
|
10939
|
+
* `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
|
|
10940
|
+
* (and only render) when this is enabled.
|
|
10941
|
+
*/
|
|
10942
|
+
occupancyRecheckEnabled: boolean().default(false),
|
|
10723
10943
|
occupancyRecheckSec: number$1().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
10724
10944
|
occupancyRecheckFrames: number$1().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
10725
10945
|
/**
|
|
@@ -13016,7 +13236,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
|
|
|
13016
13236
|
id: string(),
|
|
13017
13237
|
name: string(),
|
|
13018
13238
|
isPullMode: boolean().optional(),
|
|
13019
|
-
priority: number$1().optional()
|
|
13239
|
+
priority: number$1().optional(),
|
|
13240
|
+
hwaccel: string().optional(),
|
|
13241
|
+
probedBestHwaccel: string().optional()
|
|
13020
13242
|
})), method(DecoderSessionConfigSchema, object({
|
|
13021
13243
|
sessionId: string(),
|
|
13022
13244
|
nodeId: string()
|
|
@@ -14955,7 +15177,17 @@ var AgentAddonConfigSchema = object({
|
|
|
14955
15177
|
});
|
|
14956
15178
|
var AgentPipelineSettingsSchema = object({
|
|
14957
15179
|
addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
|
|
14958
|
-
maxCameras: number$1().int().nonnegative().nullable().default(null)
|
|
15180
|
+
maxCameras: number$1().int().nonnegative().nullable().default(null),
|
|
15181
|
+
/** Per-node detection weight (relative share for the quota balancer). */
|
|
15182
|
+
detectWeight: number$1().positive().optional(),
|
|
15183
|
+
/** Node is eligible to run the detection pipeline (decode + inference). */
|
|
15184
|
+
detect: boolean().optional(),
|
|
15185
|
+
/** Node is eligible to host decoder sessions. */
|
|
15186
|
+
decode: boolean().optional(),
|
|
15187
|
+
/** Node is eligible to run audio-analyzer sessions. */
|
|
15188
|
+
audio: boolean().optional(),
|
|
15189
|
+
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
15190
|
+
ingest: boolean().optional()
|
|
14959
15191
|
});
|
|
14960
15192
|
var CameraPipelineForAgentSchema = object({
|
|
14961
15193
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -15261,6 +15493,21 @@ method(object({
|
|
|
15261
15493
|
}), object({ success: literal(true) }), {
|
|
15262
15494
|
kind: "mutation",
|
|
15263
15495
|
auth: "admin"
|
|
15496
|
+
}), method(object({
|
|
15497
|
+
agentNodeId: string(),
|
|
15498
|
+
detectWeight: number$1().positive().nullable()
|
|
15499
|
+
}), object({ success: literal(true) }), {
|
|
15500
|
+
kind: "mutation",
|
|
15501
|
+
auth: "admin"
|
|
15502
|
+
}), method(object({
|
|
15503
|
+
agentNodeId: string(),
|
|
15504
|
+
detect: boolean().nullable().optional(),
|
|
15505
|
+
decode: boolean().nullable().optional(),
|
|
15506
|
+
audio: boolean().nullable().optional(),
|
|
15507
|
+
ingest: boolean().nullable().optional()
|
|
15508
|
+
}), object({ success: literal(true) }), {
|
|
15509
|
+
kind: "mutation",
|
|
15510
|
+
auth: "admin"
|
|
15264
15511
|
}), method(object({ deviceId: number$1() }), CameraPipelineSettingsSchema.nullable()), method(object({
|
|
15265
15512
|
deviceId: number$1(),
|
|
15266
15513
|
addonId: string(),
|
|
@@ -19008,6 +19255,18 @@ Object.freeze({
|
|
|
19008
19255
|
addonId: null,
|
|
19009
19256
|
access: "view"
|
|
19010
19257
|
},
|
|
19258
|
+
"dayNight.getOptions": {
|
|
19259
|
+
capName: "day-night",
|
|
19260
|
+
capScope: "device",
|
|
19261
|
+
addonId: null,
|
|
19262
|
+
access: "view"
|
|
19263
|
+
},
|
|
19264
|
+
"dayNight.setSettings": {
|
|
19265
|
+
capName: "day-night",
|
|
19266
|
+
capScope: "device",
|
|
19267
|
+
addonId: null,
|
|
19268
|
+
access: "create"
|
|
19269
|
+
},
|
|
19011
19270
|
"decoder.createSession": {
|
|
19012
19271
|
capName: "decoder",
|
|
19013
19272
|
capScope: "system",
|
|
@@ -19938,6 +20197,18 @@ Object.freeze({
|
|
|
19938
20197
|
addonId: null,
|
|
19939
20198
|
access: "create"
|
|
19940
20199
|
},
|
|
20200
|
+
"imageSettings.getOptions": {
|
|
20201
|
+
capName: "image-settings",
|
|
20202
|
+
capScope: "device",
|
|
20203
|
+
addonId: null,
|
|
20204
|
+
access: "view"
|
|
20205
|
+
},
|
|
20206
|
+
"imageSettings.setSettings": {
|
|
20207
|
+
capName: "image-settings",
|
|
20208
|
+
capScope: "device",
|
|
20209
|
+
addonId: null,
|
|
20210
|
+
access: "create"
|
|
20211
|
+
},
|
|
19941
20212
|
"integrations.create": {
|
|
19942
20213
|
capName: "integrations",
|
|
19943
20214
|
capScope: "system",
|
|
@@ -21120,6 +21391,18 @@ Object.freeze({
|
|
|
21120
21391
|
addonId: null,
|
|
21121
21392
|
access: "create"
|
|
21122
21393
|
},
|
|
21394
|
+
"pipelineOrchestrator.setAgentCapabilities": {
|
|
21395
|
+
capName: "pipeline-orchestrator",
|
|
21396
|
+
capScope: "system",
|
|
21397
|
+
addonId: null,
|
|
21398
|
+
access: "create"
|
|
21399
|
+
},
|
|
21400
|
+
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
21401
|
+
capName: "pipeline-orchestrator",
|
|
21402
|
+
capScope: "system",
|
|
21403
|
+
addonId: null,
|
|
21404
|
+
access: "create"
|
|
21405
|
+
},
|
|
21123
21406
|
"pipelineOrchestrator.setAgentMaxCameras": {
|
|
21124
21407
|
capName: "pipeline-orchestrator",
|
|
21125
21408
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-ha-mqtt",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.17",
|
|
4
4
|
"description": "HomeAssistant MQTT discovery exporter for CamStack devices. Publishes discovery topics so HA auto-creates entities for exposed cameras/switches/intercoms/sensors.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|