@camstack/addon-provider-tuya 0.1.3 → 0.1.5

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
@@ -4646,7 +4646,7 @@ function preprocess(fn, schema) {
4646
4646
  });
4647
4647
  }
4648
4648
  //#endregion
4649
- //#region ../types/dist/sleep-BiDFW0E7.mjs
4649
+ //#region ../types/dist/sleep-CZDdRBua.mjs
4650
4650
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4651
4651
  EventCategory["SystemBoot"] = "system.boot";
4652
4652
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -7257,7 +7257,16 @@ var DecoderStatsSchema = object({
7257
7257
  inputFps: number(),
7258
7258
  outputFps: number(),
7259
7259
  avgDecodeTimeMs: number(),
7260
- droppedFrames: number()
7260
+ droppedFrames: number(),
7261
+ /**
7262
+ * Pull-mode adaptive-fps telemetry (optional — only pull sessions run the
7263
+ * lag-driven controller; push sessions omit these). `lagMs` is the EWMA of
7264
+ * the decoder's real-time drift (rising = falling behind live); `adaptiveFps`
7265
+ * is the current lag-throttled emit rate (≤ `effectiveFps` ceiling).
7266
+ */
7267
+ lagMs: number().optional(),
7268
+ effectiveFps: number().optional(),
7269
+ adaptiveFps: number().optional()
7261
7270
  });
7262
7271
  var DecoderSessionConfigSchema = object({
7263
7272
  codec: string(),
@@ -7298,7 +7307,15 @@ var DecoderSessionConfigSchema = object({
7298
7307
  * other — `pullFrames` returns nothing for an `'shm'` session and
7299
7308
  * `pullHandles` returns nothing for a `'callback'` session.
7300
7309
  */
7301
- frameSink: _enum(["callback", "shm"]).default("callback")
7310
+ frameSink: _enum(["callback", "shm"]).default("callback"),
7311
+ /**
7312
+ * Per-camera decoder DEBUG facility. When `true`, a pull-mode session emits
7313
+ * a throttled (~1Hz) structured `decoder debug` line (effective/adaptive fps,
7314
+ * real-time lag, dropped-frame delta, avg decode time, hwaccel). Mirrors the
7315
+ * stream-broker's `streamingDebug` gate — off by default so production logs
7316
+ * stay quiet and the emit path pays zero per-frame cost when disabled.
7317
+ */
7318
+ debug: boolean().optional()
7302
7319
  });
7303
7320
  var EncodeProfileSchema = object({
7304
7321
  video: object({
@@ -10323,6 +10340,100 @@ var coverCapability = {
10323
10340
  runtimeState: CoverStatusSchema
10324
10341
  };
10325
10342
  /**
10343
+ * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
10344
+ * shared by reolink / hikvision / amcrest. Models the common firmware
10345
+ * surface: the IR-cut switching MODE plus the two knobs that gate it
10346
+ * (photocell `sensitivity` + `switchDelaySec`). Each vendor maps these
10347
+ * onto its own ISAPI / Baichuan / Dahua-CGI fields; the cap standardises
10348
+ * the shape so ONE derived-form renders every camera.
10349
+ *
10350
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
10351
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
10352
+ * injected from `status`) reports the live values, and a single
10353
+ * `setSettings` mutation applies a partial change. No hand-written
10354
+ * settings-contribution methods — the framework derives the UI + save
10355
+ * routing from this surface.
10356
+ */
10357
+ /** IR-cut switching mode. `schedule` = time-of-day table configured on the camera. */
10358
+ var DayNightModeSchema = _enum([
10359
+ "auto",
10360
+ "day",
10361
+ "night",
10362
+ "schedule"
10363
+ ]);
10364
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
10365
+ * getOptions availability convention. Normalized values are 0–100. */
10366
+ var NormalizedRangeSchema$1 = object({
10367
+ min: number(),
10368
+ max: number(),
10369
+ step: number()
10370
+ });
10371
+ /**
10372
+ * Current day/night state. Optional fields are absent when the camera
10373
+ * does not expose that knob (a photocell-less model reports no
10374
+ * `sensitivity`). `lastFetchedAt` feeds the runtime-state bridge.
10375
+ */
10376
+ var DayNightStatusSchema = object({
10377
+ mode: DayNightModeSchema,
10378
+ /** IR-cut trigger sensitivity, NORMALIZED 0–100 (higher = switches to night sooner). */
10379
+ sensitivity: number().optional(),
10380
+ /** Delay before the IR-cut filter flips, in seconds. */
10381
+ switchDelaySec: number().optional(),
10382
+ lastFetchedAt: number()
10383
+ });
10384
+ /**
10385
+ * Per-camera availability descriptor — drives which controls the admin UI
10386
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
10387
+ * (normalized 0–100); the mode choice-set as an array. A provider returns
10388
+ * honest, camera-probed values — never hardcoded.
10389
+ */
10390
+ var DayNightOptionsSchema = object({
10391
+ /** Modes this camera accepts. Empty → the camera has no configurable day/night mode. */
10392
+ modes: array(DayNightModeSchema),
10393
+ supportsSensitivity: boolean(),
10394
+ /** Present when `supportsSensitivity` — the normalized 0–100 range. */
10395
+ sensitivity: NormalizedRangeSchema$1.optional(),
10396
+ supportsSwitchDelay: boolean(),
10397
+ /** Present when `supportsSwitchDelay` — the allowed delay range in seconds. */
10398
+ switchDelaySec: NormalizedRangeSchema$1.optional()
10399
+ });
10400
+ /**
10401
+ * Partial change to the day/night config — every field optional. A
10402
+ * provider ignores fields it does not support.
10403
+ */
10404
+ var DayNightSettingsPatchSchema = object({
10405
+ mode: DayNightModeSchema.optional(),
10406
+ sensitivity: number().optional(),
10407
+ switchDelaySec: number().optional()
10408
+ });
10409
+ var dayNightCapability = {
10410
+ name: "day-night",
10411
+ scope: "device",
10412
+ deviceNative: true,
10413
+ mode: "singleton",
10414
+ deviceTypes: [DeviceType.Camera],
10415
+ deviceConfig: { ui: {
10416
+ kind: "derived-form",
10417
+ builderId: "day-night",
10418
+ tab: "image"
10419
+ } },
10420
+ methods: {
10421
+ getOptions: method(object({ deviceId: number() }), DayNightOptionsSchema),
10422
+ setSettings: method(object({
10423
+ deviceId: number(),
10424
+ settings: DayNightSettingsPatchSchema
10425
+ }), _void(), {
10426
+ kind: "mutation",
10427
+ auth: "admin"
10428
+ })
10429
+ },
10430
+ status: {
10431
+ schema: DayNightStatusSchema,
10432
+ kind: "poll"
10433
+ },
10434
+ runtimeState: DayNightStatusSchema
10435
+ };
10436
+ /**
10326
10437
  * Identity envelope for a device's upstream-system metadata.
10327
10438
  *
10328
10439
  * Two jobs:
@@ -10981,6 +11092,155 @@ var imageCapability = {
10981
11092
  runtimeState: ImageStatusSchema
10982
11093
  };
10983
11094
  /**
11095
+ * Vendor-neutral image / picture-adjustment cap — the per-camera config
11096
+ * cap shared by reolink / hikvision / amcrest. Models the common ISP
11097
+ * surface: the four picture sliders (brightness / contrast / saturation /
11098
+ * sharpness), orientation (mirror / flip / rotate), white-balance,
11099
+ * exposure and backlight-compensation modes.
11100
+ *
11101
+ * NORMALIZATION: every slider is a normalized int 0–100. Vendors expose
11102
+ * these natively as 0–100 or 0–255 (or other ranges); each provider maps
11103
+ * its native range to/from this normalized 0–100 space so the cap surface
11104
+ * (and the derived form) is identical across cameras. `warmth` (manual
11105
+ * white-balance) is likewise normalized 0–100.
11106
+ *
11107
+ * Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
11108
+ * `getOptions` advertises per-camera availability, `getStatus` (auto-
11109
+ * injected from `status`) reports the live values, and a single
11110
+ * `setSettings` mutation applies a partial change. No hand-written
11111
+ * settings-contribution methods — the framework derives the UI + save
11112
+ * routing from this surface.
11113
+ */
11114
+ /** Sensor/image rotation, degrees clockwise. */
11115
+ var ImageRotateSchema = _enum([
11116
+ "0",
11117
+ "90",
11118
+ "180",
11119
+ "270"
11120
+ ]);
11121
+ /** White-balance mode. `manual` unlocks the normalized `warmth` knob. */
11122
+ var WhiteBalanceModeSchema = _enum(["auto", "manual"]);
11123
+ /** Exposure mode. */
11124
+ var ExposureModeSchema = _enum(["auto", "manual"]);
11125
+ /**
11126
+ * Backlight-compensation mode:
11127
+ * - `off` — disabled
11128
+ * - `blc` — backlight compensation
11129
+ * - `wdr` — wide dynamic range
11130
+ * - `hlc` — highlight compensation
11131
+ */
11132
+ var BacklightModeSchema = _enum([
11133
+ "off",
11134
+ "blc",
11135
+ "wdr",
11136
+ "hlc"
11137
+ ]);
11138
+ /** Normalized numeric range descriptor — `{ min, max, step }` per the
11139
+ * getOptions availability convention. Slider values are normalized 0–100. */
11140
+ var NormalizedRangeSchema = object({
11141
+ min: number(),
11142
+ max: number(),
11143
+ step: number()
11144
+ });
11145
+ /**
11146
+ * Current image-adjustment state. Every field optional — absent when the
11147
+ * camera does not expose that control. Slider values are NORMALIZED 0–100.
11148
+ * `lastFetchedAt` feeds the runtime-state bridge.
11149
+ */
11150
+ var ImageSettingsStatusSchema = object({
11151
+ /** Normalized 0–100. */
11152
+ brightness: number().optional(),
11153
+ /** Normalized 0–100. */
11154
+ contrast: number().optional(),
11155
+ /** Normalized 0–100. */
11156
+ saturation: number().optional(),
11157
+ /** Normalized 0–100. */
11158
+ sharpness: number().optional(),
11159
+ mirror: boolean().optional(),
11160
+ flip: boolean().optional(),
11161
+ rotate: ImageRotateSchema.optional(),
11162
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11163
+ /** Manual white-balance warmth, NORMALIZED 0–100. Meaningful only when `whiteBalance === 'manual'`. */
11164
+ warmth: number().optional(),
11165
+ exposureMode: ExposureModeSchema.optional(),
11166
+ backlightMode: BacklightModeSchema.optional(),
11167
+ lastFetchedAt: number()
11168
+ });
11169
+ /**
11170
+ * Per-camera availability descriptor — drives which controls the admin UI
11171
+ * renders. Booleans as `supportsX`; numeric ranges as `{ min, max, step }`
11172
+ * (the normalized 0–100 range); enums as arrays of supported values (empty
11173
+ * array → control hidden). A provider returns honest, camera-probed values
11174
+ * — never hardcoded.
11175
+ */
11176
+ var ImageSettingsOptionsSchema = object({
11177
+ supportsBrightness: boolean(),
11178
+ brightness: NormalizedRangeSchema.optional(),
11179
+ supportsContrast: boolean(),
11180
+ contrast: NormalizedRangeSchema.optional(),
11181
+ supportsSaturation: boolean(),
11182
+ saturation: NormalizedRangeSchema.optional(),
11183
+ supportsSharpness: boolean(),
11184
+ sharpness: NormalizedRangeSchema.optional(),
11185
+ supportsMirror: boolean(),
11186
+ supportsFlip: boolean(),
11187
+ /** Supported rotation values. Empty → rotation not configurable. */
11188
+ rotateOptions: array(ImageRotateSchema),
11189
+ /** Supported white-balance modes. Empty → white-balance not configurable. */
11190
+ whiteBalanceModes: array(WhiteBalanceModeSchema),
11191
+ supportsWarmth: boolean(),
11192
+ /** Present when `supportsWarmth` — the normalized 0–100 range. */
11193
+ warmth: NormalizedRangeSchema.optional(),
11194
+ /** Supported exposure modes. Empty → exposure not configurable. */
11195
+ exposureModes: array(ExposureModeSchema),
11196
+ /** Supported backlight modes. Empty → backlight-compensation not configurable. */
11197
+ backlightModes: array(BacklightModeSchema)
11198
+ });
11199
+ /**
11200
+ * Partial change to the image config — every field optional. Slider values
11201
+ * are normalized 0–100. A provider ignores fields it does not support.
11202
+ */
11203
+ var ImageSettingsPatchSchema = object({
11204
+ brightness: number().optional(),
11205
+ contrast: number().optional(),
11206
+ saturation: number().optional(),
11207
+ sharpness: number().optional(),
11208
+ mirror: boolean().optional(),
11209
+ flip: boolean().optional(),
11210
+ rotate: ImageRotateSchema.optional(),
11211
+ whiteBalance: WhiteBalanceModeSchema.optional(),
11212
+ warmth: number().optional(),
11213
+ exposureMode: ExposureModeSchema.optional(),
11214
+ backlightMode: BacklightModeSchema.optional()
11215
+ });
11216
+ var imageSettingsCapability = {
11217
+ name: "image-settings",
11218
+ scope: "device",
11219
+ deviceNative: true,
11220
+ mode: "singleton",
11221
+ deviceTypes: [DeviceType.Camera],
11222
+ deviceConfig: { ui: {
11223
+ kind: "derived-form",
11224
+ builderId: "image-settings",
11225
+ tab: "image"
11226
+ } },
11227
+ methods: {
11228
+ getOptions: method(object({ deviceId: number() }), ImageSettingsOptionsSchema),
11229
+ setSettings: method(object({
11230
+ deviceId: number(),
11231
+ settings: ImageSettingsPatchSchema
11232
+ }), _void(), {
11233
+ kind: "mutation",
11234
+ auth: "admin"
11235
+ })
11236
+ },
11237
+ status: {
11238
+ schema: ImageSettingsStatusSchema,
11239
+ kind: "poll"
11240
+ },
11241
+ runtimeState: ImageSettingsStatusSchema
11242
+ };
11243
+ /**
10984
11244
  * Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
10985
11245
  * with a mowing lifecycle plus a dock action.
10986
11246
  *
@@ -11979,6 +12239,16 @@ var RunnerCameraConfigSchema = object({
11979
12239
  * this gate is bypassed.
11980
12240
  */
11981
12241
  onboardMotionDrivesAnalyzer: boolean().default(true),
12242
+ /**
12243
+ * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
12244
+ * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
12245
+ * this is off by default because the recheck re-subscribes a detection session
12246
+ * every N seconds while `watching`, a major source of pull-decoder re-dial
12247
+ * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
12248
+ * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
12249
+ * (and only render) when this is enabled.
12250
+ */
12251
+ occupancyRecheckEnabled: boolean().default(false),
11982
12252
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
11983
12253
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
11984
12254
  /**
@@ -13984,6 +14254,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13984
14254
  contact: contactCapability,
13985
14255
  control: controlCapability,
13986
14256
  cover: coverCapability,
14257
+ dayNight: dayNightCapability,
13987
14258
  deviceDiscovery: deviceDiscoveryCapability,
13988
14259
  deviceStatus: deviceStatusCapability,
13989
14260
  doorbell: doorbellCapability,
@@ -13996,6 +14267,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
13996
14267
  humidifier: humidifierCapability,
13997
14268
  humiditySensor: humiditySensorCapability,
13998
14269
  image: imageCapability,
14270
+ imageSettings: imageSettingsCapability,
13999
14271
  lawnMowerControl: lawnMowerControlCapability,
14000
14272
  lockControl: lockControlCapability,
14001
14273
  mediaPlayer: mediaPlayerCapability,
@@ -15910,7 +16182,9 @@ method(object({ codec: string() }), boolean()), method(_void(), object({
15910
16182
  id: string(),
15911
16183
  name: string(),
15912
16184
  isPullMode: boolean().optional(),
15913
- priority: number().optional()
16185
+ priority: number().optional(),
16186
+ hwaccel: string().optional(),
16187
+ probedBestHwaccel: string().optional()
15914
16188
  })), method(DecoderSessionConfigSchema, object({
15915
16189
  sessionId: string(),
15916
16190
  nodeId: string()
@@ -21919,6 +22193,18 @@ Object.freeze({
21919
22193
  addonId: null,
21920
22194
  access: "view"
21921
22195
  },
22196
+ "dayNight.getOptions": {
22197
+ capName: "day-night",
22198
+ capScope: "device",
22199
+ addonId: null,
22200
+ access: "view"
22201
+ },
22202
+ "dayNight.setSettings": {
22203
+ capName: "day-night",
22204
+ capScope: "device",
22205
+ addonId: null,
22206
+ access: "create"
22207
+ },
21922
22208
  "decoder.createSession": {
21923
22209
  capName: "decoder",
21924
22210
  capScope: "system",
@@ -22849,6 +23135,18 @@ Object.freeze({
22849
23135
  addonId: null,
22850
23136
  access: "create"
22851
23137
  },
23138
+ "imageSettings.getOptions": {
23139
+ capName: "image-settings",
23140
+ capScope: "device",
23141
+ addonId: null,
23142
+ access: "view"
23143
+ },
23144
+ "imageSettings.setSettings": {
23145
+ capName: "image-settings",
23146
+ capScope: "device",
23147
+ addonId: null,
23148
+ access: "create"
23149
+ },
22852
23150
  "integrations.create": {
22853
23151
  capName: "integrations",
22854
23152
  capScope: "system",
package/dist/addon.mjs 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()
@@ -21918,6 +22192,18 @@ Object.freeze({
21918
22192
  addonId: null,
21919
22193
  access: "view"
21920
22194
  },
22195
+ "dayNight.getOptions": {
22196
+ capName: "day-night",
22197
+ capScope: "device",
22198
+ addonId: null,
22199
+ access: "view"
22200
+ },
22201
+ "dayNight.setSettings": {
22202
+ capName: "day-night",
22203
+ capScope: "device",
22204
+ addonId: null,
22205
+ access: "create"
22206
+ },
21921
22207
  "decoder.createSession": {
21922
22208
  capName: "decoder",
21923
22209
  capScope: "system",
@@ -22848,6 +23134,18 @@ Object.freeze({
22848
23134
  addonId: null,
22849
23135
  access: "create"
22850
23136
  },
23137
+ "imageSettings.getOptions": {
23138
+ capName: "image-settings",
23139
+ capScope: "device",
23140
+ addonId: null,
23141
+ access: "view"
23142
+ },
23143
+ "imageSettings.setSettings": {
23144
+ capName: "image-settings",
23145
+ capScope: "device",
23146
+ addonId: null,
23147
+ access: "create"
23148
+ },
22851
23149
  "integrations.create": {
22852
23150
  capName: "integrations",
22853
23151
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",