@camstack/addon-provider-rtsp 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/addon.js CHANGED
@@ -4642,7 +4642,7 @@ function preprocess(fn, schema) {
4642
4642
  });
4643
4643
  }
4644
4644
  //#endregion
4645
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4645
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4646
4646
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4647
4647
  EventCategory["SystemBoot"] = "system.boot";
4648
4648
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7273,7 +7273,16 @@ var DecoderStatsSchema = object({
7273
7273
  inputFps: number(),
7274
7274
  outputFps: number(),
7275
7275
  avgDecodeTimeMs: number(),
7276
- droppedFrames: number()
7276
+ droppedFrames: number(),
7277
+ /**
7278
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7279
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7280
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7281
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7282
+ */
7283
+ lagMs: number().optional(),
7284
+ effectiveFps: number().optional(),
7285
+ adaptiveFps: number().optional()
7277
7286
  });
7278
7287
  var DecoderSessionConfigSchema = object({
7279
7288
  codec: string(),
@@ -7314,7 +7323,15 @@ var DecoderSessionConfigSchema = object({
7314
7323
  * other — `pullFrames` returns nothing for an `'shm'` session and
7315
7324
  * `pullHandles` returns nothing for a `'callback'` session.
7316
7325
  */
7317
- frameSink: _enum(["callback", "shm"]).default("callback")
7326
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7327
+ /**
7328
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7329
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7330
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7331
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7332
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7333
+ */
7334
+ debug: boolean().optional()
7318
7335
  });
7319
7336
  var EncodeProfileSchema = object({
7320
7337
  video: object({
@@ -10339,6 +10356,100 @@ var coverCapability = {
10339
10356
  runtimeState: CoverStatusSchema
10340
10357
  };
10341
10358
  /**
10359
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10360
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10361
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10362
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10363
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10364
+ * the shape so ONE derived-form renders every camera.
10365
+ *
10366
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10367
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10368
+ * injected from `status`) reports the live values, and a single
10369
+ * `setSettings` mutation applies a partial change. No hand-written
10370
+ * settings-contribution methods — the framework derives the UI + save
10371
+ * routing from this surface.
10372
+ */
10373
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10374
+ var DayNightModeSchema = _enum([
10375
+ "auto",
10376
+ "day",
10377
+ "night",
10378
+ "schedule"
10379
+ ]);
10380
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10381
+ * getOptions availability convention. Normalized values are 0–100. */
10382
+ var NormalizedRangeSchema$1 = object({
10383
+ min: number(),
10384
+ max: number(),
10385
+ step: number()
10386
+ });
10387
+ /**
10388
+ * Current day/night state. Optional fields are absent when the camera
10389
+ * does not expose that knob (a photocell-less model reports no
10390
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10391
+ */
10392
+ var DayNightStatusSchema = object({
10393
+ mode: DayNightModeSchema,
10394
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10395
+ sensitivity: number().optional(),
10396
+ /** Delay before the IR-cut filter flips, in seconds. */
10397
+ switchDelaySec: number().optional(),
10398
+ lastFetchedAt: number()
10399
+ });
10400
+ /**
10401
+ * Per-camera availability descriptor — drives which controls the admin UI
10402
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10403
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10404
+ * honest, camera-probed values — never hardcoded.
10405
+ */
10406
+ var DayNightOptionsSchema = object({
10407
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10408
+ modes: array(DayNightModeSchema),
10409
+ supportsSensitivity: boolean(),
10410
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10411
+ sensitivity: NormalizedRangeSchema$1.optional(),
10412
+ supportsSwitchDelay: boolean(),
10413
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10414
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10415
+ });
10416
+ /**
10417
+ * Partial change to the day/night config — every field optional. A
10418
+ * provider ignores fields it does not support.
10419
+ */
10420
+ var DayNightSettingsPatchSchema = object({
10421
+ mode: DayNightModeSchema.optional(),
10422
+ sensitivity: number().optional(),
10423
+ switchDelaySec: number().optional()
10424
+ });
10425
+ var dayNightCapability = {
10426
+ name: "day-night",
10427
+ scope: "device",
10428
+ deviceNative: true,
10429
+ mode: "singleton",
10430
+ deviceTypes: [DeviceType.Camera],
10431
+ deviceConfig: { ui: {
10432
+ kind: "derived-form",
10433
+ builderId: "day-night",
10434
+ tab: "image"
10435
+ } },
10436
+ methods: {
10437
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10438
+ setSettings: method(object({
10439
+ deviceId: number(),
10440
+ settings: DayNightSettingsPatchSchema
10441
+ }), _void(), {
10442
+ kind: "mutation",
10443
+ auth: "admin"
10444
+ })
10445
+ },
10446
+ status: {
10447
+ schema: DayNightStatusSchema,
10448
+ kind: "poll"
10449
+ },
10450
+ runtimeState: DayNightStatusSchema
10451
+ };
10452
+ /**
10342
10453
  * Identity envelope for a device's upstream-system metadata.
10343
10454
  *
10344
10455
  * Two jobs:
@@ -10997,6 +11108,155 @@ var imageCapability = {
10997
11108
  runtimeState: ImageStatusSchema
10998
11109
  };
10999
11110
  /**
11111
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11112
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11113
+ * surface: the four picture sliders (brightness / contrast / saturation /
11114
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11115
+ * exposure and backlight-compensation modes.
11116
+ *
11117
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11118
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11119
+ * its native range to/from this normalized 0–100 space so the cap surface
11120
+ * (and the derived form) is identical across cameras. `warmth` (manual
11121
+ * white-balance) is likewise normalized 0–100.
11122
+ *
11123
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11124
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11125
+ * injected from `status`) reports the live values, and a single
11126
+ * `setSettings` mutation applies a partial change. No hand-written
11127
+ * settings-contribution methods — the framework derives the UI + save
11128
+ * routing from this surface.
11129
+ */
11130
+ /** Sensor/image rotation, degrees clockwise. */
11131
+ var ImageRotateSchema = _enum([
11132
+ "0",
11133
+ "90",
11134
+ "180",
11135
+ "270"
11136
+ ]);
11137
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11138
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11139
+ /** Exposure mode. */
11140
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11141
+ /**
11142
+ * Backlight-compensation mode:
11143
+ * - `off` — disabled
11144
+ * - `blc` — backlight compensation
11145
+ * - `wdr` — wide dynamic range
11146
+ * - `hlc` — highlight compensation
11147
+ */
11148
+ var BacklightModeSchema = _enum([
11149
+ "off",
11150
+ "blc",
11151
+ "wdr",
11152
+ "hlc"
11153
+ ]);
11154
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11155
+ * getOptions availability convention. Slider values are normalized 0–100. */
11156
+ var NormalizedRangeSchema = object({
11157
+ min: number(),
11158
+ max: number(),
11159
+ step: number()
11160
+ });
11161
+ /**
11162
+ * Current image-adjustment state. Every field optional — absent when the
11163
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11164
+ * `lastFetchedAt` feeds the runtime-state bridge.
11165
+ */
11166
+ var ImageSettingsStatusSchema = object({
11167
+ /** Normalized 0–100. */
11168
+ brightness: number().optional(),
11169
+ /** Normalized 0–100. */
11170
+ contrast: number().optional(),
11171
+ /** Normalized 0–100. */
11172
+ saturation: number().optional(),
11173
+ /** Normalized 0–100. */
11174
+ sharpness: number().optional(),
11175
+ mirror: boolean().optional(),
11176
+ flip: boolean().optional(),
11177
+ rotate: ImageRotateSchema.optional(),
11178
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11179
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11180
+ warmth: number().optional(),
11181
+ exposureMode: ExposureModeSchema.optional(),
11182
+ backlightMode: BacklightModeSchema.optional(),
11183
+ lastFetchedAt: number()
11184
+ });
11185
+ /**
11186
+ * Per-camera availability descriptor — drives which controls the admin UI
11187
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11188
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11189
+ * array → control hidden). A provider returns honest, camera-probed values
11190
+ * — never hardcoded.
11191
+ */
11192
+ var ImageSettingsOptionsSchema = object({
11193
+ supportsBrightness: boolean(),
11194
+ brightness: NormalizedRangeSchema.optional(),
11195
+ supportsContrast: boolean(),
11196
+ contrast: NormalizedRangeSchema.optional(),
11197
+ supportsSaturation: boolean(),
11198
+ saturation: NormalizedRangeSchema.optional(),
11199
+ supportsSharpness: boolean(),
11200
+ sharpness: NormalizedRangeSchema.optional(),
11201
+ supportsMirror: boolean(),
11202
+ supportsFlip: boolean(),
11203
+ /** Supported rotation values. Empty → rotation not configurable. */
11204
+ rotateOptions: array(ImageRotateSchema),
11205
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11206
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11207
+ supportsWarmth: boolean(),
11208
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11209
+ warmth: NormalizedRangeSchema.optional(),
11210
+ /** Supported exposure modes. Empty → exposure not configurable. */
11211
+ exposureModes: array(ExposureModeSchema),
11212
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11213
+ backlightModes: array(BacklightModeSchema)
11214
+ });
11215
+ /**
11216
+ * Partial change to the image config — every field optional. Slider values
11217
+ * are normalized 0–100. A provider ignores fields it does not support.
11218
+ */
11219
+ var ImageSettingsPatchSchema = object({
11220
+ brightness: number().optional(),
11221
+ contrast: number().optional(),
11222
+ saturation: number().optional(),
11223
+ sharpness: number().optional(),
11224
+ mirror: boolean().optional(),
11225
+ flip: boolean().optional(),
11226
+ rotate: ImageRotateSchema.optional(),
11227
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11228
+ warmth: number().optional(),
11229
+ exposureMode: ExposureModeSchema.optional(),
11230
+ backlightMode: BacklightModeSchema.optional()
11231
+ });
11232
+ var imageSettingsCapability = {
11233
+ name: "image-settings",
11234
+ scope: "device",
11235
+ deviceNative: true,
11236
+ mode: "singleton",
11237
+ deviceTypes: [DeviceType.Camera],
11238
+ deviceConfig: { ui: {
11239
+ kind: "derived-form",
11240
+ builderId: "image-settings",
11241
+ tab: "image"
11242
+ } },
11243
+ methods: {
11244
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11245
+ setSettings: method(object({
11246
+ deviceId: number(),
11247
+ settings: ImageSettingsPatchSchema
11248
+ }), _void(), {
11249
+ kind: "mutation",
11250
+ auth: "admin"
11251
+ })
11252
+ },
11253
+ status: {
11254
+ schema: ImageSettingsStatusSchema,
11255
+ kind: "poll"
11256
+ },
11257
+ runtimeState: ImageSettingsStatusSchema
11258
+ };
11259
+ /**
11000
11260
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
11001
11261
  * with a mowing lifecycle plus a dock action.
11002
11262
  *
@@ -11995,6 +12255,16 @@ var RunnerCameraConfigSchema = object({
11995
12255
  * this gate is bypassed.
11996
12256
  */
11997
12257
  onboardMotionDrivesAnalyzer: boolean().default(true),
12258
+ /**
12259
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12260
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12261
+ * this is off by default because the recheck re-subscribes a detection session
12262
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12263
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12264
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12265
+ * (and only render) when this is enabled.
12266
+ */
12267
+ occupancyRecheckEnabled: boolean().default(false),
11998
12268
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
11999
12269
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
12000
12270
  /**
@@ -14000,6 +14270,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14000
14270
  contact: contactCapability,
14001
14271
  control: controlCapability,
14002
14272
  cover: coverCapability,
14273
+ dayNight: dayNightCapability,
14003
14274
  deviceDiscovery: deviceDiscoveryCapability,
14004
14275
  deviceStatus: deviceStatusCapability,
14005
14276
  doorbell: doorbellCapability,
@@ -14012,6 +14283,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14012
14283
  humidifier: humidifierCapability,
14013
14284
  humiditySensor: humiditySensorCapability,
14014
14285
  image: imageCapability,
14286
+ imageSettings: imageSettingsCapability,
14015
14287
  lawnMowerControl: lawnMowerControlCapability,
14016
14288
  lockControl: lockControlCapability,
14017
14289
  mediaPlayer: mediaPlayerCapability,
@@ -15926,7 +16198,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15926
16198
  id: string(),
15927
16199
  name: string(),
15928
16200
  isPullMode: boolean().optional(),
15929
- priority: number().optional()
16201
+ priority: number().optional(),
16202
+ hwaccel: string().optional(),
16203
+ probedBestHwaccel: string().optional()
15930
16204
  })), method(DecoderSessionConfigSchema, object({
15931
16205
  sessionId: string(),
15932
16206
  nodeId: string()
@@ -17840,7 +18114,17 @@ var AgentAddonConfigSchema = object({
17840
18114
  });
17841
18115
  var AgentPipelineSettingsSchema = object({
17842
18116
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17843
- maxCameras: number().int().nonnegative().nullable().default(null)
18117
+ maxCameras: number().int().nonnegative().nullable().default(null),
18118
+ /** Per-node detection weight (relative share for the quota balancer). */
18119
+ detectWeight: number().positive().optional(),
18120
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18121
+ detect: boolean().optional(),
18122
+ /** Node is eligible to host decoder sessions. */
18123
+ decode: boolean().optional(),
18124
+ /** Node is eligible to run audio-analyzer sessions. */
18125
+ audio: boolean().optional(),
18126
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18127
+ ingest: boolean().optional()
17844
18128
  });
17845
18129
  var CameraPipelineForAgentSchema = object({
17846
18130
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18146,6 +18430,21 @@ method(object({
18146
18430
  }), object({ success: literal(true) }), {
18147
18431
  kind: "mutation",
18148
18432
  auth: "admin"
18433
+ }), method(object({
18434
+ agentNodeId: string(),
18435
+ detectWeight: number().positive().nullable()
18436
+ }), object({ success: literal(true) }), {
18437
+ kind: "mutation",
18438
+ auth: "admin"
18439
+ }), method(object({
18440
+ agentNodeId: string(),
18441
+ detect: boolean().nullable().optional(),
18442
+ decode: boolean().nullable().optional(),
18443
+ audio: boolean().nullable().optional(),
18444
+ ingest: boolean().nullable().optional()
18445
+ }), object({ success: literal(true) }), {
18446
+ kind: "mutation",
18447
+ auth: "admin"
18149
18448
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18150
18449
  deviceId: number(),
18151
18450
  addonId: string(),
@@ -21949,6 +22248,18 @@ Object.freeze({
21949
22248
  addonId: null,
21950
22249
  access: "view"
21951
22250
  },
22251
+ "dayNight.getOptions": {
22252
+ capName: "day-night",
22253
+ capScope: "device",
22254
+ addonId: null,
22255
+ access: "view"
22256
+ },
22257
+ "dayNight.setSettings": {
22258
+ capName: "day-night",
22259
+ capScope: "device",
22260
+ addonId: null,
22261
+ access: "create"
22262
+ },
21952
22263
  "decoder.createSession": {
21953
22264
  capName: "decoder",
21954
22265
  capScope: "system",
@@ -22879,6 +23190,18 @@ Object.freeze({
22879
23190
  addonId: null,
22880
23191
  access: "create"
22881
23192
  },
23193
+ "imageSettings.getOptions": {
23194
+ capName: "image-settings",
23195
+ capScope: "device",
23196
+ addonId: null,
23197
+ access: "view"
23198
+ },
23199
+ "imageSettings.setSettings": {
23200
+ capName: "image-settings",
23201
+ capScope: "device",
23202
+ addonId: null,
23203
+ access: "create"
23204
+ },
22882
23205
  "integrations.create": {
22883
23206
  capName: "integrations",
22884
23207
  capScope: "system",
@@ -24061,6 +24384,18 @@ Object.freeze({
24061
24384
  addonId: null,
24062
24385
  access: "create"
24063
24386
  },
24387
+ "pipelineOrchestrator.setAgentCapabilities": {
24388
+ capName: "pipeline-orchestrator",
24389
+ capScope: "system",
24390
+ addonId: null,
24391
+ access: "create"
24392
+ },
24393
+ "pipelineOrchestrator.setAgentDetectWeight": {
24394
+ capName: "pipeline-orchestrator",
24395
+ capScope: "system",
24396
+ addonId: null,
24397
+ access: "create"
24398
+ },
24064
24399
  "pipelineOrchestrator.setAgentMaxCameras": {
24065
24400
  capName: "pipeline-orchestrator",
24066
24401
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -4641,7 +4641,7 @@ function preprocess(fn, schema) {
4641
4641
  });
4642
4642
  }
4643
4643
  //#endregion
4644
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4644
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4645
4645
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4646
4646
  EventCategory["SystemBoot"] = "system.boot";
4647
4647
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7272,7 +7272,16 @@ var DecoderStatsSchema = object({
7272
7272
  inputFps: number(),
7273
7273
  outputFps: number(),
7274
7274
  avgDecodeTimeMs: number(),
7275
- droppedFrames: number()
7275
+ droppedFrames: number(),
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().optional(),
7283
+ effectiveFps: number().optional(),
7284
+ adaptiveFps: number().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({
@@ -10338,6 +10355,100 @@ var coverCapability = {
10338
10355
  runtimeState: CoverStatusSchema
10339
10356
  };
10340
10357
  /**
10358
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10359
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10360
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10361
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10362
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10363
+ * the shape so ONE derived-form renders every camera.
10364
+ *
10365
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10366
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10367
+ * injected from `status`) reports the live values, and a single
10368
+ * `setSettings` mutation applies a partial change. No hand-written
10369
+ * settings-contribution methods — the framework derives the UI + save
10370
+ * routing from this surface.
10371
+ */
10372
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10373
+ var DayNightModeSchema = _enum([
10374
+ "auto",
10375
+ "day",
10376
+ "night",
10377
+ "schedule"
10378
+ ]);
10379
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10380
+ * getOptions availability convention. Normalized values are 0–100. */
10381
+ var NormalizedRangeSchema$1 = object({
10382
+ min: number(),
10383
+ max: number(),
10384
+ step: number()
10385
+ });
10386
+ /**
10387
+ * Current day/night state. Optional fields are absent when the camera
10388
+ * does not expose that knob (a photocell-less model reports no
10389
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10390
+ */
10391
+ var DayNightStatusSchema = object({
10392
+ mode: DayNightModeSchema,
10393
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10394
+ sensitivity: number().optional(),
10395
+ /** Delay before the IR-cut filter flips, in seconds. */
10396
+ switchDelaySec: number().optional(),
10397
+ lastFetchedAt: number()
10398
+ });
10399
+ /**
10400
+ * Per-camera availability descriptor — drives which controls the admin UI
10401
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10402
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10403
+ * honest, camera-probed values — never hardcoded.
10404
+ */
10405
+ var DayNightOptionsSchema = object({
10406
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10407
+ modes: array(DayNightModeSchema),
10408
+ supportsSensitivity: boolean(),
10409
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10410
+ sensitivity: NormalizedRangeSchema$1.optional(),
10411
+ supportsSwitchDelay: boolean(),
10412
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10413
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10414
+ });
10415
+ /**
10416
+ * Partial change to the day/night config — every field optional. A
10417
+ * provider ignores fields it does not support.
10418
+ */
10419
+ var DayNightSettingsPatchSchema = object({
10420
+ mode: DayNightModeSchema.optional(),
10421
+ sensitivity: number().optional(),
10422
+ switchDelaySec: number().optional()
10423
+ });
10424
+ var dayNightCapability = {
10425
+ name: "day-night",
10426
+ scope: "device",
10427
+ deviceNative: true,
10428
+ mode: "singleton",
10429
+ deviceTypes: [DeviceType.Camera],
10430
+ deviceConfig: { ui: {
10431
+ kind: "derived-form",
10432
+ builderId: "day-night",
10433
+ tab: "image"
10434
+ } },
10435
+ methods: {
10436
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10437
+ setSettings: method(object({
10438
+ deviceId: number(),
10439
+ settings: DayNightSettingsPatchSchema
10440
+ }), _void(), {
10441
+ kind: "mutation",
10442
+ auth: "admin"
10443
+ })
10444
+ },
10445
+ status: {
10446
+ schema: DayNightStatusSchema,
10447
+ kind: "poll"
10448
+ },
10449
+ runtimeState: DayNightStatusSchema
10450
+ };
10451
+ /**
10341
10452
  * Identity envelope for a device's upstream-system metadata.
10342
10453
  *
10343
10454
  * Two jobs:
@@ -10996,6 +11107,155 @@ var imageCapability = {
10996
11107
  runtimeState: ImageStatusSchema
10997
11108
  };
10998
11109
  /**
11110
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11111
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11112
+ * surface: the four picture sliders (brightness / contrast / saturation /
11113
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11114
+ * exposure and backlight-compensation modes.
11115
+ *
11116
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11117
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11118
+ * its native range to/from this normalized 0–100 space so the cap surface
11119
+ * (and the derived form) is identical across cameras. `warmth` (manual
11120
+ * white-balance) is likewise normalized 0–100.
11121
+ *
11122
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11123
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11124
+ * injected from `status`) reports the live values, and a single
11125
+ * `setSettings` mutation applies a partial change. No hand-written
11126
+ * settings-contribution methods — the framework derives the UI + save
11127
+ * routing from this surface.
11128
+ */
11129
+ /** Sensor/image rotation, degrees clockwise. */
11130
+ var ImageRotateSchema = _enum([
11131
+ "0",
11132
+ "90",
11133
+ "180",
11134
+ "270"
11135
+ ]);
11136
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11137
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11138
+ /** Exposure mode. */
11139
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11140
+ /**
11141
+ * Backlight-compensation mode:
11142
+ * - `off` — disabled
11143
+ * - `blc` — backlight compensation
11144
+ * - `wdr` — wide dynamic range
11145
+ * - `hlc` — highlight compensation
11146
+ */
11147
+ var BacklightModeSchema = _enum([
11148
+ "off",
11149
+ "blc",
11150
+ "wdr",
11151
+ "hlc"
11152
+ ]);
11153
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11154
+ * getOptions availability convention. Slider values are normalized 0–100. */
11155
+ var NormalizedRangeSchema = object({
11156
+ min: number(),
11157
+ max: number(),
11158
+ step: number()
11159
+ });
11160
+ /**
11161
+ * Current image-adjustment state. Every field optional — absent when the
11162
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11163
+ * `lastFetchedAt` feeds the runtime-state bridge.
11164
+ */
11165
+ var ImageSettingsStatusSchema = object({
11166
+ /** Normalized 0–100. */
11167
+ brightness: number().optional(),
11168
+ /** Normalized 0–100. */
11169
+ contrast: number().optional(),
11170
+ /** Normalized 0–100. */
11171
+ saturation: number().optional(),
11172
+ /** Normalized 0–100. */
11173
+ sharpness: number().optional(),
11174
+ mirror: boolean().optional(),
11175
+ flip: boolean().optional(),
11176
+ rotate: ImageRotateSchema.optional(),
11177
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11178
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11179
+ warmth: number().optional(),
11180
+ exposureMode: ExposureModeSchema.optional(),
11181
+ backlightMode: BacklightModeSchema.optional(),
11182
+ lastFetchedAt: number()
11183
+ });
11184
+ /**
11185
+ * Per-camera availability descriptor — drives which controls the admin UI
11186
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11187
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11188
+ * array → control hidden). A provider returns honest, camera-probed values
11189
+ * — never hardcoded.
11190
+ */
11191
+ var ImageSettingsOptionsSchema = object({
11192
+ supportsBrightness: boolean(),
11193
+ brightness: NormalizedRangeSchema.optional(),
11194
+ supportsContrast: boolean(),
11195
+ contrast: NormalizedRangeSchema.optional(),
11196
+ supportsSaturation: boolean(),
11197
+ saturation: NormalizedRangeSchema.optional(),
11198
+ supportsSharpness: boolean(),
11199
+ sharpness: NormalizedRangeSchema.optional(),
11200
+ supportsMirror: boolean(),
11201
+ supportsFlip: boolean(),
11202
+ /** Supported rotation values. Empty → rotation not configurable. */
11203
+ rotateOptions: array(ImageRotateSchema),
11204
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11205
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11206
+ supportsWarmth: boolean(),
11207
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11208
+ warmth: NormalizedRangeSchema.optional(),
11209
+ /** Supported exposure modes. Empty → exposure not configurable. */
11210
+ exposureModes: array(ExposureModeSchema),
11211
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11212
+ backlightModes: array(BacklightModeSchema)
11213
+ });
11214
+ /**
11215
+ * Partial change to the image config — every field optional. Slider values
11216
+ * are normalized 0–100. A provider ignores fields it does not support.
11217
+ */
11218
+ var ImageSettingsPatchSchema = object({
11219
+ brightness: number().optional(),
11220
+ contrast: number().optional(),
11221
+ saturation: number().optional(),
11222
+ sharpness: number().optional(),
11223
+ mirror: boolean().optional(),
11224
+ flip: boolean().optional(),
11225
+ rotate: ImageRotateSchema.optional(),
11226
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11227
+ warmth: number().optional(),
11228
+ exposureMode: ExposureModeSchema.optional(),
11229
+ backlightMode: BacklightModeSchema.optional()
11230
+ });
11231
+ var imageSettingsCapability = {
11232
+ name: "image-settings",
11233
+ scope: "device",
11234
+ deviceNative: true,
11235
+ mode: "singleton",
11236
+ deviceTypes: [DeviceType.Camera],
11237
+ deviceConfig: { ui: {
11238
+ kind: "derived-form",
11239
+ builderId: "image-settings",
11240
+ tab: "image"
11241
+ } },
11242
+ methods: {
11243
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11244
+ setSettings: method(object({
11245
+ deviceId: number(),
11246
+ settings: ImageSettingsPatchSchema
11247
+ }), _void(), {
11248
+ kind: "mutation",
11249
+ auth: "admin"
11250
+ })
11251
+ },
11252
+ status: {
11253
+ schema: ImageSettingsStatusSchema,
11254
+ kind: "poll"
11255
+ },
11256
+ runtimeState: ImageSettingsStatusSchema
11257
+ };
11258
+ /**
10999
11259
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
11000
11260
  * with a mowing lifecycle plus a dock action.
11001
11261
  *
@@ -11994,6 +12254,16 @@ var RunnerCameraConfigSchema = object({
11994
12254
  * this gate is bypassed.
11995
12255
  */
11996
12256
  onboardMotionDrivesAnalyzer: boolean().default(true),
12257
+ /**
12258
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12259
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12260
+ * this is off by default because the recheck re-subscribes a detection session
12261
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12262
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12263
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12264
+ * (and only render) when this is enabled.
12265
+ */
12266
+ occupancyRecheckEnabled: boolean().default(false),
11997
12267
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
11998
12268
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
11999
12269
  /**
@@ -13999,6 +14269,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13999
14269
  contact: contactCapability,
14000
14270
  control: controlCapability,
14001
14271
  cover: coverCapability,
14272
+ dayNight: dayNightCapability,
14002
14273
  deviceDiscovery: deviceDiscoveryCapability,
14003
14274
  deviceStatus: deviceStatusCapability,
14004
14275
  doorbell: doorbellCapability,
@@ -14011,6 +14282,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14011
14282
  humidifier: humidifierCapability,
14012
14283
  humiditySensor: humiditySensorCapability,
14013
14284
  image: imageCapability,
14285
+ imageSettings: imageSettingsCapability,
14014
14286
  lawnMowerControl: lawnMowerControlCapability,
14015
14287
  lockControl: lockControlCapability,
14016
14288
  mediaPlayer: mediaPlayerCapability,
@@ -15925,7 +16197,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15925
16197
  id: string(),
15926
16198
  name: string(),
15927
16199
  isPullMode: boolean().optional(),
15928
- priority: number().optional()
16200
+ priority: number().optional(),
16201
+ hwaccel: string().optional(),
16202
+ probedBestHwaccel: string().optional()
15929
16203
  })), method(DecoderSessionConfigSchema, object({
15930
16204
  sessionId: string(),
15931
16205
  nodeId: string()
@@ -17839,7 +18113,17 @@ var AgentAddonConfigSchema = object({
17839
18113
  });
17840
18114
  var AgentPipelineSettingsSchema = object({
17841
18115
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17842
- maxCameras: number().int().nonnegative().nullable().default(null)
18116
+ maxCameras: number().int().nonnegative().nullable().default(null),
18117
+ /** Per-node detection weight (relative share for the quota balancer). */
18118
+ detectWeight: number().positive().optional(),
18119
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18120
+ detect: boolean().optional(),
18121
+ /** Node is eligible to host decoder sessions. */
18122
+ decode: boolean().optional(),
18123
+ /** Node is eligible to run audio-analyzer sessions. */
18124
+ audio: boolean().optional(),
18125
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18126
+ ingest: boolean().optional()
17843
18127
  });
17844
18128
  var CameraPipelineForAgentSchema = object({
17845
18129
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18145,6 +18429,21 @@ method(object({
18145
18429
  }), object({ success: literal(true) }), {
18146
18430
  kind: "mutation",
18147
18431
  auth: "admin"
18432
+ }), method(object({
18433
+ agentNodeId: string(),
18434
+ detectWeight: number().positive().nullable()
18435
+ }), object({ success: literal(true) }), {
18436
+ kind: "mutation",
18437
+ auth: "admin"
18438
+ }), method(object({
18439
+ agentNodeId: string(),
18440
+ detect: boolean().nullable().optional(),
18441
+ decode: boolean().nullable().optional(),
18442
+ audio: boolean().nullable().optional(),
18443
+ ingest: boolean().nullable().optional()
18444
+ }), object({ success: literal(true) }), {
18445
+ kind: "mutation",
18446
+ auth: "admin"
18148
18447
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18149
18448
  deviceId: number(),
18150
18449
  addonId: string(),
@@ -21948,6 +22247,18 @@ Object.freeze({
21948
22247
  addonId: null,
21949
22248
  access: "view"
21950
22249
  },
22250
+ "dayNight.getOptions": {
22251
+ capName: "day-night",
22252
+ capScope: "device",
22253
+ addonId: null,
22254
+ access: "view"
22255
+ },
22256
+ "dayNight.setSettings": {
22257
+ capName: "day-night",
22258
+ capScope: "device",
22259
+ addonId: null,
22260
+ access: "create"
22261
+ },
21951
22262
  "decoder.createSession": {
21952
22263
  capName: "decoder",
21953
22264
  capScope: "system",
@@ -22878,6 +23189,18 @@ Object.freeze({
22878
23189
  addonId: null,
22879
23190
  access: "create"
22880
23191
  },
23192
+ "imageSettings.getOptions": {
23193
+ capName: "image-settings",
23194
+ capScope: "device",
23195
+ addonId: null,
23196
+ access: "view"
23197
+ },
23198
+ "imageSettings.setSettings": {
23199
+ capName: "image-settings",
23200
+ capScope: "device",
23201
+ addonId: null,
23202
+ access: "create"
23203
+ },
22881
23204
  "integrations.create": {
22882
23205
  capName: "integrations",
22883
23206
  capScope: "system",
@@ -24060,6 +24383,18 @@ Object.freeze({
24060
24383
  addonId: null,
24061
24384
  access: "create"
24062
24385
  },
24386
+ "pipelineOrchestrator.setAgentCapabilities": {
24387
+ capName: "pipeline-orchestrator",
24388
+ capScope: "system",
24389
+ addonId: null,
24390
+ access: "create"
24391
+ },
24392
+ "pipelineOrchestrator.setAgentDetectWeight": {
24393
+ capName: "pipeline-orchestrator",
24394
+ capScope: "system",
24395
+ addonId: null,
24396
+ access: "create"
24397
+ },
24063
24398
  "pipelineOrchestrator.setAgentMaxCameras": {
24064
24399
  capName: "pipeline-orchestrator",
24065
24400
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rtsp",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Generic RTSP camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",