@camstack/addon-provider-ecowitt 0.1.15 → 0.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
@@ -4645,7 +4645,7 @@ function preprocess(fn, schema) {
4645
4645
  });
4646
4646
  }
4647
4647
  //#endregion
4648
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4648
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4649
4649
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4650
4650
  EventCategory["SystemBoot"] = "system.boot";
4651
4651
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7256,7 +7256,16 @@ var DecoderStatsSchema = object({
7256
7256
  inputFps: number(),
7257
7257
  outputFps: number(),
7258
7258
  avgDecodeTimeMs: number(),
7259
- droppedFrames: number()
7259
+ droppedFrames: number(),
7260
+ /**
7261
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7262
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7263
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7264
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7265
+ */
7266
+ lagMs: number().optional(),
7267
+ effectiveFps: number().optional(),
7268
+ adaptiveFps: number().optional()
7260
7269
  });
7261
7270
  var DecoderSessionConfigSchema = object({
7262
7271
  codec: string(),
@@ -7297,7 +7306,15 @@ var DecoderSessionConfigSchema = object({
7297
7306
  * other — `pullFrames` returns nothing for an `'shm'` session and
7298
7307
  * `pullHandles` returns nothing for a `'callback'` session.
7299
7308
  */
7300
- frameSink: _enum(["callback", "shm"]).default("callback")
7309
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7310
+ /**
7311
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7312
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7313
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7314
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7315
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7316
+ */
7317
+ debug: boolean().optional()
7301
7318
  });
7302
7319
  var EncodeProfileSchema = object({
7303
7320
  video: object({
@@ -10322,6 +10339,100 @@ var coverCapability = {
10322
10339
  runtimeState: CoverStatusSchema
10323
10340
  };
10324
10341
  /**
10342
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10343
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10344
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10345
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10346
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10347
+ * the shape so ONE derived-form renders every camera.
10348
+ *
10349
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10350
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10351
+ * injected from `status`) reports the live values, and a single
10352
+ * `setSettings` mutation applies a partial change. No hand-written
10353
+ * settings-contribution methods — the framework derives the UI + save
10354
+ * routing from this surface.
10355
+ */
10356
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10357
+ var DayNightModeSchema = _enum([
10358
+ "auto",
10359
+ "day",
10360
+ "night",
10361
+ "schedule"
10362
+ ]);
10363
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10364
+ * getOptions availability convention. Normalized values are 0–100. */
10365
+ var NormalizedRangeSchema$1 = object({
10366
+ min: number(),
10367
+ max: number(),
10368
+ step: number()
10369
+ });
10370
+ /**
10371
+ * Current day/night state. Optional fields are absent when the camera
10372
+ * does not expose that knob (a photocell-less model reports no
10373
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10374
+ */
10375
+ var DayNightStatusSchema = object({
10376
+ mode: DayNightModeSchema,
10377
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10378
+ sensitivity: number().optional(),
10379
+ /** Delay before the IR-cut filter flips, in seconds. */
10380
+ switchDelaySec: number().optional(),
10381
+ lastFetchedAt: number()
10382
+ });
10383
+ /**
10384
+ * Per-camera availability descriptor — drives which controls the admin UI
10385
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10386
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10387
+ * honest, camera-probed values — never hardcoded.
10388
+ */
10389
+ var DayNightOptionsSchema = object({
10390
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10391
+ modes: array(DayNightModeSchema),
10392
+ supportsSensitivity: boolean(),
10393
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10394
+ sensitivity: NormalizedRangeSchema$1.optional(),
10395
+ supportsSwitchDelay: boolean(),
10396
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10397
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10398
+ });
10399
+ /**
10400
+ * Partial change to the day/night config — every field optional. A
10401
+ * provider ignores fields it does not support.
10402
+ */
10403
+ var DayNightSettingsPatchSchema = object({
10404
+ mode: DayNightModeSchema.optional(),
10405
+ sensitivity: number().optional(),
10406
+ switchDelaySec: number().optional()
10407
+ });
10408
+ var dayNightCapability = {
10409
+ name: "day-night",
10410
+ scope: "device",
10411
+ deviceNative: true,
10412
+ mode: "singleton",
10413
+ deviceTypes: [DeviceType.Camera],
10414
+ deviceConfig: { ui: {
10415
+ kind: "derived-form",
10416
+ builderId: "day-night",
10417
+ tab: "image"
10418
+ } },
10419
+ methods: {
10420
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10421
+ setSettings: method(object({
10422
+ deviceId: number(),
10423
+ settings: DayNightSettingsPatchSchema
10424
+ }), _void(), {
10425
+ kind: "mutation",
10426
+ auth: "admin"
10427
+ })
10428
+ },
10429
+ status: {
10430
+ schema: DayNightStatusSchema,
10431
+ kind: "poll"
10432
+ },
10433
+ runtimeState: DayNightStatusSchema
10434
+ };
10435
+ /**
10325
10436
  * Identity envelope for a device's upstream-system metadata.
10326
10437
  *
10327
10438
  * Two jobs:
@@ -10980,6 +11091,155 @@ var imageCapability = {
10980
11091
  runtimeState: ImageStatusSchema
10981
11092
  };
10982
11093
  /**
11094
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11095
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11096
+ * surface: the four picture sliders (brightness / contrast / saturation /
11097
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11098
+ * exposure and backlight-compensation modes.
11099
+ *
11100
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11101
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11102
+ * its native range to/from this normalized 0–100 space so the cap surface
11103
+ * (and the derived form) is identical across cameras. `warmth` (manual
11104
+ * white-balance) is likewise normalized 0–100.
11105
+ *
11106
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11107
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11108
+ * injected from `status`) reports the live values, and a single
11109
+ * `setSettings` mutation applies a partial change. No hand-written
11110
+ * settings-contribution methods — the framework derives the UI + save
11111
+ * routing from this surface.
11112
+ */
11113
+ /** Sensor/image rotation, degrees clockwise. */
11114
+ var ImageRotateSchema = _enum([
11115
+ "0",
11116
+ "90",
11117
+ "180",
11118
+ "270"
11119
+ ]);
11120
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11121
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11122
+ /** Exposure mode. */
11123
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11124
+ /**
11125
+ * Backlight-compensation mode:
11126
+ * - `off` — disabled
11127
+ * - `blc` — backlight compensation
11128
+ * - `wdr` — wide dynamic range
11129
+ * - `hlc` — highlight compensation
11130
+ */
11131
+ var BacklightModeSchema = _enum([
11132
+ "off",
11133
+ "blc",
11134
+ "wdr",
11135
+ "hlc"
11136
+ ]);
11137
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11138
+ * getOptions availability convention. Slider values are normalized 0–100. */
11139
+ var NormalizedRangeSchema = object({
11140
+ min: number(),
11141
+ max: number(),
11142
+ step: number()
11143
+ });
11144
+ /**
11145
+ * Current image-adjustment state. Every field optional — absent when the
11146
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11147
+ * `lastFetchedAt` feeds the runtime-state bridge.
11148
+ */
11149
+ var ImageSettingsStatusSchema = object({
11150
+ /** Normalized 0–100. */
11151
+ brightness: number().optional(),
11152
+ /** Normalized 0–100. */
11153
+ contrast: number().optional(),
11154
+ /** Normalized 0–100. */
11155
+ saturation: number().optional(),
11156
+ /** Normalized 0–100. */
11157
+ sharpness: number().optional(),
11158
+ mirror: boolean().optional(),
11159
+ flip: boolean().optional(),
11160
+ rotate: ImageRotateSchema.optional(),
11161
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11162
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11163
+ warmth: number().optional(),
11164
+ exposureMode: ExposureModeSchema.optional(),
11165
+ backlightMode: BacklightModeSchema.optional(),
11166
+ lastFetchedAt: number()
11167
+ });
11168
+ /**
11169
+ * Per-camera availability descriptor — drives which controls the admin UI
11170
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11171
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11172
+ * array → control hidden). A provider returns honest, camera-probed values
11173
+ * — never hardcoded.
11174
+ */
11175
+ var ImageSettingsOptionsSchema = object({
11176
+ supportsBrightness: boolean(),
11177
+ brightness: NormalizedRangeSchema.optional(),
11178
+ supportsContrast: boolean(),
11179
+ contrast: NormalizedRangeSchema.optional(),
11180
+ supportsSaturation: boolean(),
11181
+ saturation: NormalizedRangeSchema.optional(),
11182
+ supportsSharpness: boolean(),
11183
+ sharpness: NormalizedRangeSchema.optional(),
11184
+ supportsMirror: boolean(),
11185
+ supportsFlip: boolean(),
11186
+ /** Supported rotation values. Empty → rotation not configurable. */
11187
+ rotateOptions: array(ImageRotateSchema),
11188
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11189
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11190
+ supportsWarmth: boolean(),
11191
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11192
+ warmth: NormalizedRangeSchema.optional(),
11193
+ /** Supported exposure modes. Empty → exposure not configurable. */
11194
+ exposureModes: array(ExposureModeSchema),
11195
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11196
+ backlightModes: array(BacklightModeSchema)
11197
+ });
11198
+ /**
11199
+ * Partial change to the image config — every field optional. Slider values
11200
+ * are normalized 0–100. A provider ignores fields it does not support.
11201
+ */
11202
+ var ImageSettingsPatchSchema = object({
11203
+ brightness: number().optional(),
11204
+ contrast: number().optional(),
11205
+ saturation: number().optional(),
11206
+ sharpness: number().optional(),
11207
+ mirror: boolean().optional(),
11208
+ flip: boolean().optional(),
11209
+ rotate: ImageRotateSchema.optional(),
11210
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11211
+ warmth: number().optional(),
11212
+ exposureMode: ExposureModeSchema.optional(),
11213
+ backlightMode: BacklightModeSchema.optional()
11214
+ });
11215
+ var imageSettingsCapability = {
11216
+ name: "image-settings",
11217
+ scope: "device",
11218
+ deviceNative: true,
11219
+ mode: "singleton",
11220
+ deviceTypes: [DeviceType.Camera],
11221
+ deviceConfig: { ui: {
11222
+ kind: "derived-form",
11223
+ builderId: "image-settings",
11224
+ tab: "image"
11225
+ } },
11226
+ methods: {
11227
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11228
+ setSettings: method(object({
11229
+ deviceId: number(),
11230
+ settings: ImageSettingsPatchSchema
11231
+ }), _void(), {
11232
+ kind: "mutation",
11233
+ auth: "admin"
11234
+ })
11235
+ },
11236
+ status: {
11237
+ schema: ImageSettingsStatusSchema,
11238
+ kind: "poll"
11239
+ },
11240
+ runtimeState: ImageSettingsStatusSchema
11241
+ };
11242
+ /**
10983
11243
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10984
11244
  * with a mowing lifecycle plus a dock action.
10985
11245
  *
@@ -11978,6 +12238,16 @@ var RunnerCameraConfigSchema = object({
11978
12238
  * this gate is bypassed.
11979
12239
  */
11980
12240
  onboardMotionDrivesAnalyzer: boolean().default(true),
12241
+ /**
12242
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12243
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12244
+ * this is off by default because the recheck re-subscribes a detection session
12245
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12246
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12247
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12248
+ * (and only render) when this is enabled.
12249
+ */
12250
+ occupancyRecheckEnabled: boolean().default(false),
11981
12251
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
11982
12252
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
11983
12253
  /**
@@ -13983,6 +14253,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13983
14253
  contact: contactCapability,
13984
14254
  control: controlCapability,
13985
14255
  cover: coverCapability,
14256
+ dayNight: dayNightCapability,
13986
14257
  deviceDiscovery: deviceDiscoveryCapability,
13987
14258
  deviceStatus: deviceStatusCapability,
13988
14259
  doorbell: doorbellCapability,
@@ -13995,6 +14266,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13995
14266
  humidifier: humidifierCapability,
13996
14267
  humiditySensor: humiditySensorCapability,
13997
14268
  image: imageCapability,
14269
+ imageSettings: imageSettingsCapability,
13998
14270
  lawnMowerControl: lawnMowerControlCapability,
13999
14271
  lockControl: lockControlCapability,
14000
14272
  mediaPlayer: mediaPlayerCapability,
@@ -15909,7 +16181,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15909
16181
  id: string(),
15910
16182
  name: string(),
15911
16183
  isPullMode: boolean().optional(),
15912
- priority: number().optional()
16184
+ priority: number().optional(),
16185
+ hwaccel: string().optional(),
16186
+ probedBestHwaccel: string().optional()
15913
16187
  })), method(DecoderSessionConfigSchema, object({
15914
16188
  sessionId: string(),
15915
16189
  nodeId: string()
@@ -17823,7 +18097,17 @@ var AgentAddonConfigSchema = object({
17823
18097
  });
17824
18098
  var AgentPipelineSettingsSchema = object({
17825
18099
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17826
- maxCameras: number().int().nonnegative().nullable().default(null)
18100
+ maxCameras: number().int().nonnegative().nullable().default(null),
18101
+ /** Per-node detection weight (relative share for the quota balancer). */
18102
+ detectWeight: number().positive().optional(),
18103
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18104
+ detect: boolean().optional(),
18105
+ /** Node is eligible to host decoder sessions. */
18106
+ decode: boolean().optional(),
18107
+ /** Node is eligible to run audio-analyzer sessions. */
18108
+ audio: boolean().optional(),
18109
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18110
+ ingest: boolean().optional()
17827
18111
  });
17828
18112
  var CameraPipelineForAgentSchema = object({
17829
18113
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18129,6 +18413,21 @@ method(object({
18129
18413
  }), object({ success: literal(true) }), {
18130
18414
  kind: "mutation",
18131
18415
  auth: "admin"
18416
+ }), method(object({
18417
+ agentNodeId: string(),
18418
+ detectWeight: number().positive().nullable()
18419
+ }), object({ success: literal(true) }), {
18420
+ kind: "mutation",
18421
+ auth: "admin"
18422
+ }), method(object({
18423
+ agentNodeId: string(),
18424
+ detect: boolean().nullable().optional(),
18425
+ decode: boolean().nullable().optional(),
18426
+ audio: boolean().nullable().optional(),
18427
+ ingest: boolean().nullable().optional()
18428
+ }), object({ success: literal(true) }), {
18429
+ kind: "mutation",
18430
+ auth: "admin"
18132
18431
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18133
18432
  deviceId: number(),
18134
18433
  addonId: string(),
@@ -21876,6 +22175,18 @@ Object.freeze({
21876
22175
  addonId: null,
21877
22176
  access: "view"
21878
22177
  },
22178
+ "dayNight.getOptions": {
22179
+ capName: "day-night",
22180
+ capScope: "device",
22181
+ addonId: null,
22182
+ access: "view"
22183
+ },
22184
+ "dayNight.setSettings": {
22185
+ capName: "day-night",
22186
+ capScope: "device",
22187
+ addonId: null,
22188
+ access: "create"
22189
+ },
21879
22190
  "decoder.createSession": {
21880
22191
  capName: "decoder",
21881
22192
  capScope: "system",
@@ -22806,6 +23117,18 @@ Object.freeze({
22806
23117
  addonId: null,
22807
23118
  access: "create"
22808
23119
  },
23120
+ "imageSettings.getOptions": {
23121
+ capName: "image-settings",
23122
+ capScope: "device",
23123
+ addonId: null,
23124
+ access: "view"
23125
+ },
23126
+ "imageSettings.setSettings": {
23127
+ capName: "image-settings",
23128
+ capScope: "device",
23129
+ addonId: null,
23130
+ access: "create"
23131
+ },
22809
23132
  "integrations.create": {
22810
23133
  capName: "integrations",
22811
23134
  capScope: "system",
@@ -23988,6 +24311,18 @@ Object.freeze({
23988
24311
  addonId: null,
23989
24312
  access: "create"
23990
24313
  },
24314
+ "pipelineOrchestrator.setAgentCapabilities": {
24315
+ capName: "pipeline-orchestrator",
24316
+ capScope: "system",
24317
+ addonId: null,
24318
+ access: "create"
24319
+ },
24320
+ "pipelineOrchestrator.setAgentDetectWeight": {
24321
+ capName: "pipeline-orchestrator",
24322
+ capScope: "system",
24323
+ addonId: null,
24324
+ access: "create"
24325
+ },
23991
24326
  "pipelineOrchestrator.setAgentMaxCameras": {
23992
24327
  capName: "pipeline-orchestrator",
23993
24328
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -4644,7 +4644,7 @@ function preprocess(fn, schema) {
4644
4644
  });
4645
4645
  }
4646
4646
  //#endregion
4647
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4647
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4648
4648
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4649
4649
  EventCategory["SystemBoot"] = "system.boot";
4650
4650
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7255,7 +7255,16 @@ var DecoderStatsSchema = object({
7255
7255
  inputFps: number(),
7256
7256
  outputFps: number(),
7257
7257
  avgDecodeTimeMs: number(),
7258
- droppedFrames: number()
7258
+ droppedFrames: number(),
7259
+ /**
7260
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7261
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7262
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7263
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7264
+ */
7265
+ lagMs: number().optional(),
7266
+ effectiveFps: number().optional(),
7267
+ adaptiveFps: number().optional()
7259
7268
  });
7260
7269
  var DecoderSessionConfigSchema = object({
7261
7270
  codec: string(),
@@ -7296,7 +7305,15 @@ var DecoderSessionConfigSchema = object({
7296
7305
  * other — `pullFrames` returns nothing for an `'shm'` session and
7297
7306
  * `pullHandles` returns nothing for a `'callback'` session.
7298
7307
  */
7299
- frameSink: _enum(["callback", "shm"]).default("callback")
7308
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7309
+ /**
7310
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7311
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7312
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7313
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7314
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7315
+ */
7316
+ debug: boolean().optional()
7300
7317
  });
7301
7318
  var EncodeProfileSchema = object({
7302
7319
  video: object({
@@ -10321,6 +10338,100 @@ var coverCapability = {
10321
10338
  runtimeState: CoverStatusSchema
10322
10339
  };
10323
10340
  /**
10341
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10342
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10343
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10344
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10345
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10346
+ * the shape so ONE derived-form renders every camera.
10347
+ *
10348
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10349
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10350
+ * injected from `status`) reports the live values, and a single
10351
+ * `setSettings` mutation applies a partial change. No hand-written
10352
+ * settings-contribution methods — the framework derives the UI + save
10353
+ * routing from this surface.
10354
+ */
10355
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10356
+ var DayNightModeSchema = _enum([
10357
+ "auto",
10358
+ "day",
10359
+ "night",
10360
+ "schedule"
10361
+ ]);
10362
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10363
+ * getOptions availability convention. Normalized values are 0–100. */
10364
+ var NormalizedRangeSchema$1 = object({
10365
+ min: number(),
10366
+ max: number(),
10367
+ step: number()
10368
+ });
10369
+ /**
10370
+ * Current day/night state. Optional fields are absent when the camera
10371
+ * does not expose that knob (a photocell-less model reports no
10372
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10373
+ */
10374
+ var DayNightStatusSchema = object({
10375
+ mode: DayNightModeSchema,
10376
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10377
+ sensitivity: number().optional(),
10378
+ /** Delay before the IR-cut filter flips, in seconds. */
10379
+ switchDelaySec: number().optional(),
10380
+ lastFetchedAt: number()
10381
+ });
10382
+ /**
10383
+ * Per-camera availability descriptor — drives which controls the admin UI
10384
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10385
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10386
+ * honest, camera-probed values — never hardcoded.
10387
+ */
10388
+ var DayNightOptionsSchema = object({
10389
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10390
+ modes: array(DayNightModeSchema),
10391
+ supportsSensitivity: boolean(),
10392
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10393
+ sensitivity: NormalizedRangeSchema$1.optional(),
10394
+ supportsSwitchDelay: boolean(),
10395
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10396
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10397
+ });
10398
+ /**
10399
+ * Partial change to the day/night config — every field optional. A
10400
+ * provider ignores fields it does not support.
10401
+ */
10402
+ var DayNightSettingsPatchSchema = object({
10403
+ mode: DayNightModeSchema.optional(),
10404
+ sensitivity: number().optional(),
10405
+ switchDelaySec: number().optional()
10406
+ });
10407
+ var dayNightCapability = {
10408
+ name: "day-night",
10409
+ scope: "device",
10410
+ deviceNative: true,
10411
+ mode: "singleton",
10412
+ deviceTypes: [DeviceType.Camera],
10413
+ deviceConfig: { ui: {
10414
+ kind: "derived-form",
10415
+ builderId: "day-night",
10416
+ tab: "image"
10417
+ } },
10418
+ methods: {
10419
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10420
+ setSettings: method(object({
10421
+ deviceId: number(),
10422
+ settings: DayNightSettingsPatchSchema
10423
+ }), _void(), {
10424
+ kind: "mutation",
10425
+ auth: "admin"
10426
+ })
10427
+ },
10428
+ status: {
10429
+ schema: DayNightStatusSchema,
10430
+ kind: "poll"
10431
+ },
10432
+ runtimeState: DayNightStatusSchema
10433
+ };
10434
+ /**
10324
10435
  * Identity envelope for a device's upstream-system metadata.
10325
10436
  *
10326
10437
  * Two jobs:
@@ -10979,6 +11090,155 @@ var imageCapability = {
10979
11090
  runtimeState: ImageStatusSchema
10980
11091
  };
10981
11092
  /**
11093
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11094
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11095
+ * surface: the four picture sliders (brightness / contrast / saturation /
11096
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11097
+ * exposure and backlight-compensation modes.
11098
+ *
11099
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11100
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11101
+ * its native range to/from this normalized 0–100 space so the cap surface
11102
+ * (and the derived form) is identical across cameras. `warmth` (manual
11103
+ * white-balance) is likewise normalized 0–100.
11104
+ *
11105
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11106
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11107
+ * injected from `status`) reports the live values, and a single
11108
+ * `setSettings` mutation applies a partial change. No hand-written
11109
+ * settings-contribution methods — the framework derives the UI + save
11110
+ * routing from this surface.
11111
+ */
11112
+ /** Sensor/image rotation, degrees clockwise. */
11113
+ var ImageRotateSchema = _enum([
11114
+ "0",
11115
+ "90",
11116
+ "180",
11117
+ "270"
11118
+ ]);
11119
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11120
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11121
+ /** Exposure mode. */
11122
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11123
+ /**
11124
+ * Backlight-compensation mode:
11125
+ * - `off` — disabled
11126
+ * - `blc` — backlight compensation
11127
+ * - `wdr` — wide dynamic range
11128
+ * - `hlc` — highlight compensation
11129
+ */
11130
+ var BacklightModeSchema = _enum([
11131
+ "off",
11132
+ "blc",
11133
+ "wdr",
11134
+ "hlc"
11135
+ ]);
11136
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11137
+ * getOptions availability convention. Slider values are normalized 0–100. */
11138
+ var NormalizedRangeSchema = object({
11139
+ min: number(),
11140
+ max: number(),
11141
+ step: number()
11142
+ });
11143
+ /**
11144
+ * Current image-adjustment state. Every field optional — absent when the
11145
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11146
+ * `lastFetchedAt` feeds the runtime-state bridge.
11147
+ */
11148
+ var ImageSettingsStatusSchema = object({
11149
+ /** Normalized 0–100. */
11150
+ brightness: number().optional(),
11151
+ /** Normalized 0–100. */
11152
+ contrast: number().optional(),
11153
+ /** Normalized 0–100. */
11154
+ saturation: number().optional(),
11155
+ /** Normalized 0–100. */
11156
+ sharpness: number().optional(),
11157
+ mirror: boolean().optional(),
11158
+ flip: boolean().optional(),
11159
+ rotate: ImageRotateSchema.optional(),
11160
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11161
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11162
+ warmth: number().optional(),
11163
+ exposureMode: ExposureModeSchema.optional(),
11164
+ backlightMode: BacklightModeSchema.optional(),
11165
+ lastFetchedAt: number()
11166
+ });
11167
+ /**
11168
+ * Per-camera availability descriptor — drives which controls the admin UI
11169
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11170
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11171
+ * array → control hidden). A provider returns honest, camera-probed values
11172
+ * — never hardcoded.
11173
+ */
11174
+ var ImageSettingsOptionsSchema = object({
11175
+ supportsBrightness: boolean(),
11176
+ brightness: NormalizedRangeSchema.optional(),
11177
+ supportsContrast: boolean(),
11178
+ contrast: NormalizedRangeSchema.optional(),
11179
+ supportsSaturation: boolean(),
11180
+ saturation: NormalizedRangeSchema.optional(),
11181
+ supportsSharpness: boolean(),
11182
+ sharpness: NormalizedRangeSchema.optional(),
11183
+ supportsMirror: boolean(),
11184
+ supportsFlip: boolean(),
11185
+ /** Supported rotation values. Empty → rotation not configurable. */
11186
+ rotateOptions: array(ImageRotateSchema),
11187
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11188
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11189
+ supportsWarmth: boolean(),
11190
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11191
+ warmth: NormalizedRangeSchema.optional(),
11192
+ /** Supported exposure modes. Empty → exposure not configurable. */
11193
+ exposureModes: array(ExposureModeSchema),
11194
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11195
+ backlightModes: array(BacklightModeSchema)
11196
+ });
11197
+ /**
11198
+ * Partial change to the image config — every field optional. Slider values
11199
+ * are normalized 0–100. A provider ignores fields it does not support.
11200
+ */
11201
+ var ImageSettingsPatchSchema = object({
11202
+ brightness: number().optional(),
11203
+ contrast: number().optional(),
11204
+ saturation: number().optional(),
11205
+ sharpness: number().optional(),
11206
+ mirror: boolean().optional(),
11207
+ flip: boolean().optional(),
11208
+ rotate: ImageRotateSchema.optional(),
11209
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11210
+ warmth: number().optional(),
11211
+ exposureMode: ExposureModeSchema.optional(),
11212
+ backlightMode: BacklightModeSchema.optional()
11213
+ });
11214
+ var imageSettingsCapability = {
11215
+ name: "image-settings",
11216
+ scope: "device",
11217
+ deviceNative: true,
11218
+ mode: "singleton",
11219
+ deviceTypes: [DeviceType.Camera],
11220
+ deviceConfig: { ui: {
11221
+ kind: "derived-form",
11222
+ builderId: "image-settings",
11223
+ tab: "image"
11224
+ } },
11225
+ methods: {
11226
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11227
+ setSettings: method(object({
11228
+ deviceId: number(),
11229
+ settings: ImageSettingsPatchSchema
11230
+ }), _void(), {
11231
+ kind: "mutation",
11232
+ auth: "admin"
11233
+ })
11234
+ },
11235
+ status: {
11236
+ schema: ImageSettingsStatusSchema,
11237
+ kind: "poll"
11238
+ },
11239
+ runtimeState: ImageSettingsStatusSchema
11240
+ };
11241
+ /**
10982
11242
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10983
11243
  * with a mowing lifecycle plus a dock action.
10984
11244
  *
@@ -11977,6 +12237,16 @@ var RunnerCameraConfigSchema = object({
11977
12237
  * this gate is bypassed.
11978
12238
  */
11979
12239
  onboardMotionDrivesAnalyzer: boolean().default(true),
12240
+ /**
12241
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12242
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12243
+ * this is off by default because the recheck re-subscribes a detection session
12244
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12245
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12246
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12247
+ * (and only render) when this is enabled.
12248
+ */
12249
+ occupancyRecheckEnabled: boolean().default(false),
11980
12250
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
11981
12251
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
11982
12252
  /**
@@ -13982,6 +14252,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13982
14252
  contact: contactCapability,
13983
14253
  control: controlCapability,
13984
14254
  cover: coverCapability,
14255
+ dayNight: dayNightCapability,
13985
14256
  deviceDiscovery: deviceDiscoveryCapability,
13986
14257
  deviceStatus: deviceStatusCapability,
13987
14258
  doorbell: doorbellCapability,
@@ -13994,6 +14265,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13994
14265
  humidifier: humidifierCapability,
13995
14266
  humiditySensor: humiditySensorCapability,
13996
14267
  image: imageCapability,
14268
+ imageSettings: imageSettingsCapability,
13997
14269
  lawnMowerControl: lawnMowerControlCapability,
13998
14270
  lockControl: lockControlCapability,
13999
14271
  mediaPlayer: mediaPlayerCapability,
@@ -15908,7 +16180,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15908
16180
  id: string(),
15909
16181
  name: string(),
15910
16182
  isPullMode: boolean().optional(),
15911
- priority: number().optional()
16183
+ priority: number().optional(),
16184
+ hwaccel: string().optional(),
16185
+ probedBestHwaccel: string().optional()
15912
16186
  })), method(DecoderSessionConfigSchema, object({
15913
16187
  sessionId: string(),
15914
16188
  nodeId: string()
@@ -17822,7 +18096,17 @@ var AgentAddonConfigSchema = object({
17822
18096
  });
17823
18097
  var AgentPipelineSettingsSchema = object({
17824
18098
  addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
17825
- maxCameras: number().int().nonnegative().nullable().default(null)
18099
+ maxCameras: number().int().nonnegative().nullable().default(null),
18100
+ /** Per-node detection weight (relative share for the quota balancer). */
18101
+ detectWeight: number().positive().optional(),
18102
+ /** Node is eligible to run the detection pipeline (decode + inference). */
18103
+ detect: boolean().optional(),
18104
+ /** Node is eligible to host decoder sessions. */
18105
+ decode: boolean().optional(),
18106
+ /** Node is eligible to run audio-analyzer sessions. */
18107
+ audio: boolean().optional(),
18108
+ /** Node is eligible to be the ingest / source-owner (serve the restream). */
18109
+ ingest: boolean().optional()
17826
18110
  });
17827
18111
  var CameraPipelineForAgentSchema = object({
17828
18112
  steps: array(PipelineStepInputSchema).readonly(),
@@ -18128,6 +18412,21 @@ method(object({
18128
18412
  }), object({ success: literal(true) }), {
18129
18413
  kind: "mutation",
18130
18414
  auth: "admin"
18415
+ }), method(object({
18416
+ agentNodeId: string(),
18417
+ detectWeight: number().positive().nullable()
18418
+ }), object({ success: literal(true) }), {
18419
+ kind: "mutation",
18420
+ auth: "admin"
18421
+ }), method(object({
18422
+ agentNodeId: string(),
18423
+ detect: boolean().nullable().optional(),
18424
+ decode: boolean().nullable().optional(),
18425
+ audio: boolean().nullable().optional(),
18426
+ ingest: boolean().nullable().optional()
18427
+ }), object({ success: literal(true) }), {
18428
+ kind: "mutation",
18429
+ auth: "admin"
18131
18430
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18132
18431
  deviceId: number(),
18133
18432
  addonId: string(),
@@ -21875,6 +22174,18 @@ Object.freeze({
21875
22174
  addonId: null,
21876
22175
  access: "view"
21877
22176
  },
22177
+ "dayNight.getOptions": {
22178
+ capName: "day-night",
22179
+ capScope: "device",
22180
+ addonId: null,
22181
+ access: "view"
22182
+ },
22183
+ "dayNight.setSettings": {
22184
+ capName: "day-night",
22185
+ capScope: "device",
22186
+ addonId: null,
22187
+ access: "create"
22188
+ },
21878
22189
  "decoder.createSession": {
21879
22190
  capName: "decoder",
21880
22191
  capScope: "system",
@@ -22805,6 +23116,18 @@ Object.freeze({
22805
23116
  addonId: null,
22806
23117
  access: "create"
22807
23118
  },
23119
+ "imageSettings.getOptions": {
23120
+ capName: "image-settings",
23121
+ capScope: "device",
23122
+ addonId: null,
23123
+ access: "view"
23124
+ },
23125
+ "imageSettings.setSettings": {
23126
+ capName: "image-settings",
23127
+ capScope: "device",
23128
+ addonId: null,
23129
+ access: "create"
23130
+ },
22808
23131
  "integrations.create": {
22809
23132
  capName: "integrations",
22810
23133
  capScope: "system",
@@ -23987,6 +24310,18 @@ Object.freeze({
23987
24310
  addonId: null,
23988
24311
  access: "create"
23989
24312
  },
24313
+ "pipelineOrchestrator.setAgentCapabilities": {
24314
+ capName: "pipeline-orchestrator",
24315
+ capScope: "system",
24316
+ addonId: null,
24317
+ access: "create"
24318
+ },
24319
+ "pipelineOrchestrator.setAgentDetectWeight": {
24320
+ capName: "pipeline-orchestrator",
24321
+ capScope: "system",
24322
+ addonId: null,
24323
+ access: "create"
24324
+ },
23990
24325
  "pipelineOrchestrator.setAgentMaxCameras": {
23991
24326
  capName: "pipeline-orchestrator",
23992
24327
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-ecowitt",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Ecowitt weather-station device-provider addon for CamStack — wraps the @apocaliss92/nodewitt local-poll / push client",
5
5
  "keywords": [
6
6
  "camstack",