@camstack/addon-provider-homeassistant 1.1.18 → 1.1.20

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
@@ -4629,7 +4629,7 @@ function _instanceof(cls, params = {}) {
4629
4629
  return inst;
4630
4630
  }
4631
4631
  //#endregion
4632
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4632
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4633
4633
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4634
4634
  EventCategory["SystemBoot"] = "system.boot";
4635
4635
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7240,7 +7240,16 @@ var DecoderStatsSchema = object({
7240
7240
  inputFps: number(),
7241
7241
  outputFps: number(),
7242
7242
  avgDecodeTimeMs: number(),
7243
- droppedFrames: number()
7243
+ droppedFrames: number(),
7244
+ /**
7245
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7246
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7247
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7248
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7249
+ */
7250
+ lagMs: number().optional(),
7251
+ effectiveFps: number().optional(),
7252
+ adaptiveFps: number().optional()
7244
7253
  });
7245
7254
  var DecoderSessionConfigSchema = object({
7246
7255
  codec: string(),
@@ -7281,7 +7290,15 @@ var DecoderSessionConfigSchema = object({
7281
7290
  * other — `pullFrames` returns nothing for an `'shm'` session and
7282
7291
  * `pullHandles` returns nothing for a `'callback'` session.
7283
7292
  */
7284
- frameSink: _enum(["callback", "shm"]).default("callback")
7293
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7294
+ /**
7295
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7296
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7297
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7298
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7299
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7300
+ */
7301
+ debug: boolean().optional()
7285
7302
  });
7286
7303
  var EncodeProfileSchema = object({
7287
7304
  video: object({
@@ -10499,6 +10516,100 @@ var coverCapability = {
10499
10516
  runtimeState: CoverStatusSchema
10500
10517
  };
10501
10518
  /**
10519
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10520
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10521
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10522
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10523
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10524
+ * the shape so ONE derived-form renders every camera.
10525
+ *
10526
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10527
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10528
+ * injected from `status`) reports the live values, and a single
10529
+ * `setSettings` mutation applies a partial change. No hand-written
10530
+ * settings-contribution methods — the framework derives the UI + save
10531
+ * routing from this surface.
10532
+ */
10533
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10534
+ var DayNightModeSchema = _enum([
10535
+ "auto",
10536
+ "day",
10537
+ "night",
10538
+ "schedule"
10539
+ ]);
10540
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10541
+ * getOptions availability convention. Normalized values are 0–100. */
10542
+ var NormalizedRangeSchema$1 = object({
10543
+ min: number(),
10544
+ max: number(),
10545
+ step: number()
10546
+ });
10547
+ /**
10548
+ * Current day/night state. Optional fields are absent when the camera
10549
+ * does not expose that knob (a photocell-less model reports no
10550
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10551
+ */
10552
+ var DayNightStatusSchema = object({
10553
+ mode: DayNightModeSchema,
10554
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10555
+ sensitivity: number().optional(),
10556
+ /** Delay before the IR-cut filter flips, in seconds. */
10557
+ switchDelaySec: number().optional(),
10558
+ lastFetchedAt: number()
10559
+ });
10560
+ /**
10561
+ * Per-camera availability descriptor — drives which controls the admin UI
10562
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10563
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10564
+ * honest, camera-probed values — never hardcoded.
10565
+ */
10566
+ var DayNightOptionsSchema = object({
10567
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10568
+ modes: array(DayNightModeSchema),
10569
+ supportsSensitivity: boolean(),
10570
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10571
+ sensitivity: NormalizedRangeSchema$1.optional(),
10572
+ supportsSwitchDelay: boolean(),
10573
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10574
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10575
+ });
10576
+ /**
10577
+ * Partial change to the day/night config — every field optional. A
10578
+ * provider ignores fields it does not support.
10579
+ */
10580
+ var DayNightSettingsPatchSchema = object({
10581
+ mode: DayNightModeSchema.optional(),
10582
+ sensitivity: number().optional(),
10583
+ switchDelaySec: number().optional()
10584
+ });
10585
+ var dayNightCapability = {
10586
+ name: "day-night",
10587
+ scope: "device",
10588
+ deviceNative: true,
10589
+ mode: "singleton",
10590
+ deviceTypes: [DeviceType.Camera],
10591
+ deviceConfig: { ui: {
10592
+ kind: "derived-form",
10593
+ builderId: "day-night",
10594
+ tab: "image"
10595
+ } },
10596
+ methods: {
10597
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10598
+ setSettings: method(object({
10599
+ deviceId: number(),
10600
+ settings: DayNightSettingsPatchSchema
10601
+ }), _void(), {
10602
+ kind: "mutation",
10603
+ auth: "admin"
10604
+ })
10605
+ },
10606
+ status: {
10607
+ schema: DayNightStatusSchema,
10608
+ kind: "poll"
10609
+ },
10610
+ runtimeState: DayNightStatusSchema
10611
+ };
10612
+ /**
10502
10613
  * Identity envelope for a device's upstream-system metadata.
10503
10614
  *
10504
10615
  * Two jobs:
@@ -11202,6 +11313,155 @@ var imageCapability = {
11202
11313
  runtimeState: ImageStatusSchema
11203
11314
  };
11204
11315
  /**
11316
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11317
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11318
+ * surface: the four picture sliders (brightness / contrast / saturation /
11319
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11320
+ * exposure and backlight-compensation modes.
11321
+ *
11322
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11323
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11324
+ * its native range to/from this normalized 0–100 space so the cap surface
11325
+ * (and the derived form) is identical across cameras. `warmth` (manual
11326
+ * white-balance) is likewise normalized 0–100.
11327
+ *
11328
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11329
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11330
+ * injected from `status`) reports the live values, and a single
11331
+ * `setSettings` mutation applies a partial change. No hand-written
11332
+ * settings-contribution methods — the framework derives the UI + save
11333
+ * routing from this surface.
11334
+ */
11335
+ /** Sensor/image rotation, degrees clockwise. */
11336
+ var ImageRotateSchema = _enum([
11337
+ "0",
11338
+ "90",
11339
+ "180",
11340
+ "270"
11341
+ ]);
11342
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11343
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11344
+ /** Exposure mode. */
11345
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11346
+ /**
11347
+ * Backlight-compensation mode:
11348
+ * - `off` — disabled
11349
+ * - `blc` — backlight compensation
11350
+ * - `wdr` — wide dynamic range
11351
+ * - `hlc` — highlight compensation
11352
+ */
11353
+ var BacklightModeSchema = _enum([
11354
+ "off",
11355
+ "blc",
11356
+ "wdr",
11357
+ "hlc"
11358
+ ]);
11359
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11360
+ * getOptions availability convention. Slider values are normalized 0–100. */
11361
+ var NormalizedRangeSchema = object({
11362
+ min: number(),
11363
+ max: number(),
11364
+ step: number()
11365
+ });
11366
+ /**
11367
+ * Current image-adjustment state. Every field optional — absent when the
11368
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11369
+ * `lastFetchedAt` feeds the runtime-state bridge.
11370
+ */
11371
+ var ImageSettingsStatusSchema = object({
11372
+ /** Normalized 0–100. */
11373
+ brightness: number().optional(),
11374
+ /** Normalized 0–100. */
11375
+ contrast: number().optional(),
11376
+ /** Normalized 0–100. */
11377
+ saturation: number().optional(),
11378
+ /** Normalized 0–100. */
11379
+ sharpness: number().optional(),
11380
+ mirror: boolean().optional(),
11381
+ flip: boolean().optional(),
11382
+ rotate: ImageRotateSchema.optional(),
11383
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11384
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11385
+ warmth: number().optional(),
11386
+ exposureMode: ExposureModeSchema.optional(),
11387
+ backlightMode: BacklightModeSchema.optional(),
11388
+ lastFetchedAt: number()
11389
+ });
11390
+ /**
11391
+ * Per-camera availability descriptor — drives which controls the admin UI
11392
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11393
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11394
+ * array → control hidden). A provider returns honest, camera-probed values
11395
+ * — never hardcoded.
11396
+ */
11397
+ var ImageSettingsOptionsSchema = object({
11398
+ supportsBrightness: boolean(),
11399
+ brightness: NormalizedRangeSchema.optional(),
11400
+ supportsContrast: boolean(),
11401
+ contrast: NormalizedRangeSchema.optional(),
11402
+ supportsSaturation: boolean(),
11403
+ saturation: NormalizedRangeSchema.optional(),
11404
+ supportsSharpness: boolean(),
11405
+ sharpness: NormalizedRangeSchema.optional(),
11406
+ supportsMirror: boolean(),
11407
+ supportsFlip: boolean(),
11408
+ /** Supported rotation values. Empty → rotation not configurable. */
11409
+ rotateOptions: array(ImageRotateSchema),
11410
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11411
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11412
+ supportsWarmth: boolean(),
11413
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11414
+ warmth: NormalizedRangeSchema.optional(),
11415
+ /** Supported exposure modes. Empty → exposure not configurable. */
11416
+ exposureModes: array(ExposureModeSchema),
11417
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11418
+ backlightModes: array(BacklightModeSchema)
11419
+ });
11420
+ /**
11421
+ * Partial change to the image config — every field optional. Slider values
11422
+ * are normalized 0–100. A provider ignores fields it does not support.
11423
+ */
11424
+ var ImageSettingsPatchSchema = object({
11425
+ brightness: number().optional(),
11426
+ contrast: number().optional(),
11427
+ saturation: number().optional(),
11428
+ sharpness: number().optional(),
11429
+ mirror: boolean().optional(),
11430
+ flip: boolean().optional(),
11431
+ rotate: ImageRotateSchema.optional(),
11432
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11433
+ warmth: number().optional(),
11434
+ exposureMode: ExposureModeSchema.optional(),
11435
+ backlightMode: BacklightModeSchema.optional()
11436
+ });
11437
+ var imageSettingsCapability = {
11438
+ name: "image-settings",
11439
+ scope: "device",
11440
+ deviceNative: true,
11441
+ mode: "singleton",
11442
+ deviceTypes: [DeviceType.Camera],
11443
+ deviceConfig: { ui: {
11444
+ kind: "derived-form",
11445
+ builderId: "image-settings",
11446
+ tab: "image"
11447
+ } },
11448
+ methods: {
11449
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11450
+ setSettings: method(object({
11451
+ deviceId: number(),
11452
+ settings: ImageSettingsPatchSchema
11453
+ }), _void(), {
11454
+ kind: "mutation",
11455
+ auth: "admin"
11456
+ })
11457
+ },
11458
+ status: {
11459
+ schema: ImageSettingsStatusSchema,
11460
+ kind: "poll"
11461
+ },
11462
+ runtimeState: ImageSettingsStatusSchema
11463
+ };
11464
+ /**
11205
11465
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
11206
11466
  * with a mowing lifecycle plus a dock action.
11207
11467
  *
@@ -12200,6 +12460,16 @@ var RunnerCameraConfigSchema = object({
12200
12460
  * this gate is bypassed.
12201
12461
  */
12202
12462
  onboardMotionDrivesAnalyzer: boolean().default(true),
12463
+ /**
12464
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12465
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12466
+ * this is off by default because the recheck re-subscribes a detection session
12467
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12468
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12469
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12470
+ * (and only render) when this is enabled.
12471
+ */
12472
+ occupancyRecheckEnabled: boolean().default(false),
12203
12473
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
12204
12474
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
12205
12475
  /**
@@ -14205,6 +14475,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14205
14475
  contact: contactCapability,
14206
14476
  control: controlCapability,
14207
14477
  cover: coverCapability,
14478
+ dayNight: dayNightCapability,
14208
14479
  deviceDiscovery: deviceDiscoveryCapability,
14209
14480
  deviceStatus: deviceStatusCapability,
14210
14481
  doorbell: doorbellCapability,
@@ -14217,6 +14488,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14217
14488
  humidifier: humidifierCapability,
14218
14489
  humiditySensor: humiditySensorCapability,
14219
14490
  image: imageCapability,
14491
+ imageSettings: imageSettingsCapability,
14220
14492
  lawnMowerControl: lawnMowerControlCapability,
14221
14493
  lockControl: lockControlCapability,
14222
14494
  mediaPlayer: mediaPlayerCapability,
@@ -16180,7 +16452,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
16180
16452
  id: string(),
16181
16453
  name: string(),
16182
16454
  isPullMode: boolean().optional(),
16183
- priority: number().optional()
16455
+ priority: number().optional(),
16456
+ hwaccel: string().optional(),
16457
+ probedBestHwaccel: string().optional()
16184
16458
  })), method(DecoderSessionConfigSchema, object({
16185
16459
  sessionId: string(),
16186
16460
  nodeId: string()
@@ -18125,7 +18399,17 @@ var AgentAddonConfigSchema = object({
18125
18399
  });
18126
18400
  var AgentPipelineSettingsSchema = object({
18127
18401
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
18128
- maxCameras: number().int().nonnegative().nullable().default(null)
18402
+ maxCameras: number().int().nonnegative().nullable().default(null),
18403
+ /** Per-node detection weight (relative share for the quota balancer). */
18404
+ detectWeight: number().positive().optional(),
18405
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18406
+ detect: boolean().optional(),
18407
+ /** Node is eligible to host decoder sessions. */
18408
+ decode: boolean().optional(),
18409
+ /** Node is eligible to run audio-analyzer sessions. */
18410
+ audio: boolean().optional(),
18411
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18412
+ ingest: boolean().optional()
18129
18413
  });
18130
18414
  var CameraPipelineForAgentSchema = object({
18131
18415
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18431,6 +18715,21 @@ method(object({
18431
18715
  }), object({ success: literal(true) }), {
18432
18716
  kind: "mutation",
18433
18717
  auth: "admin"
18718
+ }), method(object({
18719
+ agentNodeId: string(),
18720
+ detectWeight: number().positive().nullable()
18721
+ }), object({ success: literal(true) }), {
18722
+ kind: "mutation",
18723
+ auth: "admin"
18724
+ }), method(object({
18725
+ agentNodeId: string(),
18726
+ detect: boolean().nullable().optional(),
18727
+ decode: boolean().nullable().optional(),
18728
+ audio: boolean().nullable().optional(),
18729
+ ingest: boolean().nullable().optional()
18730
+ }), object({ success: literal(true) }), {
18731
+ kind: "mutation",
18732
+ auth: "admin"
18434
18733
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18435
18734
  deviceId: number(),
18436
18735
  addonId: string(),
@@ -22267,6 +22566,18 @@ Object.freeze({
22267
22566
  addonId: null,
22268
22567
  access: "view"
22269
22568
  },
22569
+ "dayNight.getOptions": {
22570
+ capName: "day-night",
22571
+ capScope: "device",
22572
+ addonId: null,
22573
+ access: "view"
22574
+ },
22575
+ "dayNight.setSettings": {
22576
+ capName: "day-night",
22577
+ capScope: "device",
22578
+ addonId: null,
22579
+ access: "create"
22580
+ },
22270
22581
  "decoder.createSession": {
22271
22582
  capName: "decoder",
22272
22583
  capScope: "system",
@@ -23197,6 +23508,18 @@ Object.freeze({
23197
23508
  addonId: null,
23198
23509
  access: "create"
23199
23510
  },
23511
+ "imageSettings.getOptions": {
23512
+ capName: "image-settings",
23513
+ capScope: "device",
23514
+ addonId: null,
23515
+ access: "view"
23516
+ },
23517
+ "imageSettings.setSettings": {
23518
+ capName: "image-settings",
23519
+ capScope: "device",
23520
+ addonId: null,
23521
+ access: "create"
23522
+ },
23200
23523
  "integrations.create": {
23201
23524
  capName: "integrations",
23202
23525
  capScope: "system",
@@ -24379,6 +24702,18 @@ Object.freeze({
24379
24702
  addonId: null,
24380
24703
  access: "create"
24381
24704
  },
24705
+ "pipelineOrchestrator.setAgentCapabilities": {
24706
+ capName: "pipeline-orchestrator",
24707
+ capScope: "system",
24708
+ addonId: null,
24709
+ access: "create"
24710
+ },
24711
+ "pipelineOrchestrator.setAgentDetectWeight": {
24712
+ capName: "pipeline-orchestrator",
24713
+ capScope: "system",
24714
+ addonId: null,
24715
+ access: "create"
24716
+ },
24382
24717
  "pipelineOrchestrator.setAgentMaxCameras": {
24383
24718
  capName: "pipeline-orchestrator",
24384
24719
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -4628,7 +4628,7 @@ function _instanceof(cls, params = {}) {
4628
4628
  return inst;
4629
4629
  }
4630
4630
  //#endregion
4631
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4631
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4632
4632
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4633
4633
  EventCategory["SystemBoot"] = "system.boot";
4634
4634
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7239,7 +7239,16 @@ var DecoderStatsSchema = object({
7239
7239
  inputFps: number(),
7240
7240
  outputFps: number(),
7241
7241
  avgDecodeTimeMs: number(),
7242
- droppedFrames: number()
7242
+ droppedFrames: number(),
7243
+ /**
7244
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7245
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7246
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7247
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7248
+ */
7249
+ lagMs: number().optional(),
7250
+ effectiveFps: number().optional(),
7251
+ adaptiveFps: number().optional()
7243
7252
  });
7244
7253
  var DecoderSessionConfigSchema = object({
7245
7254
  codec: string(),
@@ -7280,7 +7289,15 @@ var DecoderSessionConfigSchema = object({
7280
7289
  * other — `pullFrames` returns nothing for an `'shm'` session and
7281
7290
  * `pullHandles` returns nothing for a `'callback'` session.
7282
7291
  */
7283
- frameSink: _enum(["callback", "shm"]).default("callback")
7292
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7293
+ /**
7294
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7295
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7296
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7297
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7298
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7299
+ */
7300
+ debug: boolean().optional()
7284
7301
  });
7285
7302
  var EncodeProfileSchema = object({
7286
7303
  video: object({
@@ -10498,6 +10515,100 @@ var coverCapability = {
10498
10515
  runtimeState: CoverStatusSchema
10499
10516
  };
10500
10517
  /**
10518
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10519
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10520
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10521
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10522
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10523
+ * the shape so ONE derived-form renders every camera.
10524
+ *
10525
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10526
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10527
+ * injected from `status`) reports the live values, and a single
10528
+ * `setSettings` mutation applies a partial change. No hand-written
10529
+ * settings-contribution methods — the framework derives the UI + save
10530
+ * routing from this surface.
10531
+ */
10532
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10533
+ var DayNightModeSchema = _enum([
10534
+ "auto",
10535
+ "day",
10536
+ "night",
10537
+ "schedule"
10538
+ ]);
10539
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10540
+ * getOptions availability convention. Normalized values are 0–100. */
10541
+ var NormalizedRangeSchema$1 = object({
10542
+ min: number(),
10543
+ max: number(),
10544
+ step: number()
10545
+ });
10546
+ /**
10547
+ * Current day/night state. Optional fields are absent when the camera
10548
+ * does not expose that knob (a photocell-less model reports no
10549
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10550
+ */
10551
+ var DayNightStatusSchema = object({
10552
+ mode: DayNightModeSchema,
10553
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10554
+ sensitivity: number().optional(),
10555
+ /** Delay before the IR-cut filter flips, in seconds. */
10556
+ switchDelaySec: number().optional(),
10557
+ lastFetchedAt: number()
10558
+ });
10559
+ /**
10560
+ * Per-camera availability descriptor — drives which controls the admin UI
10561
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10562
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10563
+ * honest, camera-probed values — never hardcoded.
10564
+ */
10565
+ var DayNightOptionsSchema = object({
10566
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10567
+ modes: array(DayNightModeSchema),
10568
+ supportsSensitivity: boolean(),
10569
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10570
+ sensitivity: NormalizedRangeSchema$1.optional(),
10571
+ supportsSwitchDelay: boolean(),
10572
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10573
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10574
+ });
10575
+ /**
10576
+ * Partial change to the day/night config — every field optional. A
10577
+ * provider ignores fields it does not support.
10578
+ */
10579
+ var DayNightSettingsPatchSchema = object({
10580
+ mode: DayNightModeSchema.optional(),
10581
+ sensitivity: number().optional(),
10582
+ switchDelaySec: number().optional()
10583
+ });
10584
+ var dayNightCapability = {
10585
+ name: "day-night",
10586
+ scope: "device",
10587
+ deviceNative: true,
10588
+ mode: "singleton",
10589
+ deviceTypes: [DeviceType.Camera],
10590
+ deviceConfig: { ui: {
10591
+ kind: "derived-form",
10592
+ builderId: "day-night",
10593
+ tab: "image"
10594
+ } },
10595
+ methods: {
10596
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10597
+ setSettings: method(object({
10598
+ deviceId: number(),
10599
+ settings: DayNightSettingsPatchSchema
10600
+ }), _void(), {
10601
+ kind: "mutation",
10602
+ auth: "admin"
10603
+ })
10604
+ },
10605
+ status: {
10606
+ schema: DayNightStatusSchema,
10607
+ kind: "poll"
10608
+ },
10609
+ runtimeState: DayNightStatusSchema
10610
+ };
10611
+ /**
10501
10612
  * Identity envelope for a device's upstream-system metadata.
10502
10613
  *
10503
10614
  * Two jobs:
@@ -11201,6 +11312,155 @@ var imageCapability = {
11201
11312
  runtimeState: ImageStatusSchema
11202
11313
  };
11203
11314
  /**
11315
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11316
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11317
+ * surface: the four picture sliders (brightness / contrast / saturation /
11318
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11319
+ * exposure and backlight-compensation modes.
11320
+ *
11321
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11322
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11323
+ * its native range to/from this normalized 0–100 space so the cap surface
11324
+ * (and the derived form) is identical across cameras. `warmth` (manual
11325
+ * white-balance) is likewise normalized 0–100.
11326
+ *
11327
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11328
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11329
+ * injected from `status`) reports the live values, and a single
11330
+ * `setSettings` mutation applies a partial change. No hand-written
11331
+ * settings-contribution methods — the framework derives the UI + save
11332
+ * routing from this surface.
11333
+ */
11334
+ /** Sensor/image rotation, degrees clockwise. */
11335
+ var ImageRotateSchema = _enum([
11336
+ "0",
11337
+ "90",
11338
+ "180",
11339
+ "270"
11340
+ ]);
11341
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11342
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11343
+ /** Exposure mode. */
11344
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11345
+ /**
11346
+ * Backlight-compensation mode:
11347
+ * - `off` — disabled
11348
+ * - `blc` — backlight compensation
11349
+ * - `wdr` — wide dynamic range
11350
+ * - `hlc` — highlight compensation
11351
+ */
11352
+ var BacklightModeSchema = _enum([
11353
+ "off",
11354
+ "blc",
11355
+ "wdr",
11356
+ "hlc"
11357
+ ]);
11358
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11359
+ * getOptions availability convention. Slider values are normalized 0–100. */
11360
+ var NormalizedRangeSchema = object({
11361
+ min: number(),
11362
+ max: number(),
11363
+ step: number()
11364
+ });
11365
+ /**
11366
+ * Current image-adjustment state. Every field optional — absent when the
11367
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11368
+ * `lastFetchedAt` feeds the runtime-state bridge.
11369
+ */
11370
+ var ImageSettingsStatusSchema = object({
11371
+ /** Normalized 0–100. */
11372
+ brightness: number().optional(),
11373
+ /** Normalized 0–100. */
11374
+ contrast: number().optional(),
11375
+ /** Normalized 0–100. */
11376
+ saturation: number().optional(),
11377
+ /** Normalized 0–100. */
11378
+ sharpness: number().optional(),
11379
+ mirror: boolean().optional(),
11380
+ flip: boolean().optional(),
11381
+ rotate: ImageRotateSchema.optional(),
11382
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11383
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11384
+ warmth: number().optional(),
11385
+ exposureMode: ExposureModeSchema.optional(),
11386
+ backlightMode: BacklightModeSchema.optional(),
11387
+ lastFetchedAt: number()
11388
+ });
11389
+ /**
11390
+ * Per-camera availability descriptor — drives which controls the admin UI
11391
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11392
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11393
+ * array → control hidden). A provider returns honest, camera-probed values
11394
+ * — never hardcoded.
11395
+ */
11396
+ var ImageSettingsOptionsSchema = object({
11397
+ supportsBrightness: boolean(),
11398
+ brightness: NormalizedRangeSchema.optional(),
11399
+ supportsContrast: boolean(),
11400
+ contrast: NormalizedRangeSchema.optional(),
11401
+ supportsSaturation: boolean(),
11402
+ saturation: NormalizedRangeSchema.optional(),
11403
+ supportsSharpness: boolean(),
11404
+ sharpness: NormalizedRangeSchema.optional(),
11405
+ supportsMirror: boolean(),
11406
+ supportsFlip: boolean(),
11407
+ /** Supported rotation values. Empty → rotation not configurable. */
11408
+ rotateOptions: array(ImageRotateSchema),
11409
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11410
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11411
+ supportsWarmth: boolean(),
11412
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11413
+ warmth: NormalizedRangeSchema.optional(),
11414
+ /** Supported exposure modes. Empty → exposure not configurable. */
11415
+ exposureModes: array(ExposureModeSchema),
11416
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11417
+ backlightModes: array(BacklightModeSchema)
11418
+ });
11419
+ /**
11420
+ * Partial change to the image config — every field optional. Slider values
11421
+ * are normalized 0–100. A provider ignores fields it does not support.
11422
+ */
11423
+ var ImageSettingsPatchSchema = object({
11424
+ brightness: number().optional(),
11425
+ contrast: number().optional(),
11426
+ saturation: number().optional(),
11427
+ sharpness: number().optional(),
11428
+ mirror: boolean().optional(),
11429
+ flip: boolean().optional(),
11430
+ rotate: ImageRotateSchema.optional(),
11431
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11432
+ warmth: number().optional(),
11433
+ exposureMode: ExposureModeSchema.optional(),
11434
+ backlightMode: BacklightModeSchema.optional()
11435
+ });
11436
+ var imageSettingsCapability = {
11437
+ name: "image-settings",
11438
+ scope: "device",
11439
+ deviceNative: true,
11440
+ mode: "singleton",
11441
+ deviceTypes: [DeviceType.Camera],
11442
+ deviceConfig: { ui: {
11443
+ kind: "derived-form",
11444
+ builderId: "image-settings",
11445
+ tab: "image"
11446
+ } },
11447
+ methods: {
11448
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11449
+ setSettings: method(object({
11450
+ deviceId: number(),
11451
+ settings: ImageSettingsPatchSchema
11452
+ }), _void(), {
11453
+ kind: "mutation",
11454
+ auth: "admin"
11455
+ })
11456
+ },
11457
+ status: {
11458
+ schema: ImageSettingsStatusSchema,
11459
+ kind: "poll"
11460
+ },
11461
+ runtimeState: ImageSettingsStatusSchema
11462
+ };
11463
+ /**
11204
11464
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
11205
11465
  * with a mowing lifecycle plus a dock action.
11206
11466
  *
@@ -12199,6 +12459,16 @@ var RunnerCameraConfigSchema = object({
12199
12459
  * this gate is bypassed.
12200
12460
  */
12201
12461
  onboardMotionDrivesAnalyzer: boolean().default(true),
12462
+ /**
12463
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12464
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12465
+ * this is off by default because the recheck re-subscribes a detection session
12466
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12467
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12468
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12469
+ * (and only render) when this is enabled.
12470
+ */
12471
+ occupancyRecheckEnabled: boolean().default(false),
12202
12472
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
12203
12473
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
12204
12474
  /**
@@ -14204,6 +14474,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14204
14474
  contact: contactCapability,
14205
14475
  control: controlCapability,
14206
14476
  cover: coverCapability,
14477
+ dayNight: dayNightCapability,
14207
14478
  deviceDiscovery: deviceDiscoveryCapability,
14208
14479
  deviceStatus: deviceStatusCapability,
14209
14480
  doorbell: doorbellCapability,
@@ -14216,6 +14487,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
14216
14487
  humidifier: humidifierCapability,
14217
14488
  humiditySensor: humiditySensorCapability,
14218
14489
  image: imageCapability,
14490
+ imageSettings: imageSettingsCapability,
14219
14491
  lawnMowerControl: lawnMowerControlCapability,
14220
14492
  lockControl: lockControlCapability,
14221
14493
  mediaPlayer: mediaPlayerCapability,
@@ -16179,7 +16451,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
16179
16451
  id: string(),
16180
16452
  name: string(),
16181
16453
  isPullMode: boolean().optional(),
16182
- priority: number().optional()
16454
+ priority: number().optional(),
16455
+ hwaccel: string().optional(),
16456
+ probedBestHwaccel: string().optional()
16183
16457
  })), method(DecoderSessionConfigSchema, object({
16184
16458
  sessionId: string(),
16185
16459
  nodeId: string()
@@ -18124,7 +18398,17 @@ var AgentAddonConfigSchema = object({
18124
18398
  });
18125
18399
  var AgentPipelineSettingsSchema = object({
18126
18400
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
18127
- maxCameras: number().int().nonnegative().nullable().default(null)
18401
+ maxCameras: number().int().nonnegative().nullable().default(null),
18402
+ /** Per-node detection weight (relative share for the quota balancer). */
18403
+ detectWeight: number().positive().optional(),
18404
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18405
+ detect: boolean().optional(),
18406
+ /** Node is eligible to host decoder sessions. */
18407
+ decode: boolean().optional(),
18408
+ /** Node is eligible to run audio-analyzer sessions. */
18409
+ audio: boolean().optional(),
18410
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18411
+ ingest: boolean().optional()
18128
18412
  });
18129
18413
  var CameraPipelineForAgentSchema = object({
18130
18414
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18430,6 +18714,21 @@ method(object({
18430
18714
  }), object({ success: literal(true) }), {
18431
18715
  kind: "mutation",
18432
18716
  auth: "admin"
18717
+ }), method(object({
18718
+ agentNodeId: string(),
18719
+ detectWeight: number().positive().nullable()
18720
+ }), object({ success: literal(true) }), {
18721
+ kind: "mutation",
18722
+ auth: "admin"
18723
+ }), method(object({
18724
+ agentNodeId: string(),
18725
+ detect: boolean().nullable().optional(),
18726
+ decode: boolean().nullable().optional(),
18727
+ audio: boolean().nullable().optional(),
18728
+ ingest: boolean().nullable().optional()
18729
+ }), object({ success: literal(true) }), {
18730
+ kind: "mutation",
18731
+ auth: "admin"
18433
18732
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18434
18733
  deviceId: number(),
18435
18734
  addonId: string(),
@@ -22266,6 +22565,18 @@ Object.freeze({
22266
22565
  addonId: null,
22267
22566
  access: "view"
22268
22567
  },
22568
+ "dayNight.getOptions": {
22569
+ capName: "day-night",
22570
+ capScope: "device",
22571
+ addonId: null,
22572
+ access: "view"
22573
+ },
22574
+ "dayNight.setSettings": {
22575
+ capName: "day-night",
22576
+ capScope: "device",
22577
+ addonId: null,
22578
+ access: "create"
22579
+ },
22269
22580
  "decoder.createSession": {
22270
22581
  capName: "decoder",
22271
22582
  capScope: "system",
@@ -23196,6 +23507,18 @@ Object.freeze({
23196
23507
  addonId: null,
23197
23508
  access: "create"
23198
23509
  },
23510
+ "imageSettings.getOptions": {
23511
+ capName: "image-settings",
23512
+ capScope: "device",
23513
+ addonId: null,
23514
+ access: "view"
23515
+ },
23516
+ "imageSettings.setSettings": {
23517
+ capName: "image-settings",
23518
+ capScope: "device",
23519
+ addonId: null,
23520
+ access: "create"
23521
+ },
23199
23522
  "integrations.create": {
23200
23523
  capName: "integrations",
23201
23524
  capScope: "system",
@@ -24378,6 +24701,18 @@ Object.freeze({
24378
24701
  addonId: null,
24379
24702
  access: "create"
24380
24703
  },
24704
+ "pipelineOrchestrator.setAgentCapabilities": {
24705
+ capName: "pipeline-orchestrator",
24706
+ capScope: "system",
24707
+ addonId: null,
24708
+ access: "create"
24709
+ },
24710
+ "pipelineOrchestrator.setAgentDetectWeight": {
24711
+ capName: "pipeline-orchestrator",
24712
+ capScope: "system",
24713
+ addonId: null,
24714
+ access: "create"
24715
+ },
24381
24716
  "pipelineOrchestrator.setAgentMaxCameras": {
24382
24717
  capName: "pipeline-orchestrator",
24383
24718
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",