@camstack/addon-provider-bosch 0.1.47 → 0.1.49
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/CHANGELOG.md +12 -0
- package/dist/{account-integration-offline-Bie4aS5e.mjs → account-integration-offline-BKDol6kz.mjs} +1 -1
- package/dist/{account-integration-offline-C6tzFB-H.js → account-integration-offline-Dcx0sq_v.js} +1 -1
- package/dist/{bosch-instances-DAqkAsRO.mjs → bosch-instances-B2e4DAI1.mjs} +753 -561
- package/dist/{bosch-instances-D0eF-Jjy.js → bosch-instances-BHFcR1TK.js} +753 -561
- package/dist/home-connect/addon.js +2 -2
- package/dist/home-connect/addon.mjs +2 -2
- package/dist/homecom/addon.js +113 -18
- package/dist/homecom/addon.mjs +113 -18
- package/dist/shc/addon.js +1 -1
- package/dist/shc/addon.mjs +1 -1
- package/package.json +2 -2
|
@@ -802,7 +802,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
802
802
|
return EventCategory;
|
|
803
803
|
}({});
|
|
804
804
|
//#endregion
|
|
805
|
-
//#region ../types/dist/composed-stable-id-
|
|
805
|
+
//#region ../types/dist/composed-stable-id-DFNyOFzz.mjs
|
|
806
806
|
/**
|
|
807
807
|
import { errMsg } from '@camstack/types'
|
|
808
808
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -815,6 +815,7 @@ function errMsg(err) {
|
|
|
815
815
|
}
|
|
816
816
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
817
817
|
DeviceType["Camera"] = "camera";
|
|
818
|
+
/** Legacy stored value, read only by the hub-to-integration migrations; no live device carries it. */
|
|
818
819
|
DeviceType["Hub"] = "hub";
|
|
819
820
|
DeviceType["Light"] = "light";
|
|
820
821
|
DeviceType["Siren"] = "siren";
|
|
@@ -1090,6 +1091,10 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
1090
1091
|
/** Robot mower exposes targeted mowing (all-area / zones / edges /
|
|
1091
1092
|
* spots) — gates the Mow action + map selectors. */
|
|
1092
1093
|
DeviceFeature["MowerHasTargetedMowing"] = "mower-has-targeted-mowing";
|
|
1094
|
+
/** The device has a drive/navigation surface (`navigation` cap): a robot camera. */
|
|
1095
|
+
DeviceFeature["Navigation"] = "navigation";
|
|
1096
|
+
/** The device has a network-link reading (`network-link` cap). */
|
|
1097
|
+
DeviceFeature["NetworkLink"] = "network-link";
|
|
1093
1098
|
return DeviceFeature;
|
|
1094
1099
|
}({});
|
|
1095
1100
|
/**
|
|
@@ -6022,7 +6027,7 @@ var ZodIssueCode = {
|
|
|
6022
6027
|
var ZodFirstPartyTypeKind;
|
|
6023
6028
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6024
6029
|
//#endregion
|
|
6025
|
-
//#region ../types/dist/sleep-
|
|
6030
|
+
//#region ../types/dist/sleep-D_NpiLFP.mjs
|
|
6026
6031
|
/**
|
|
6027
6032
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6028
6033
|
* window to float samples (D455).
|
|
@@ -10109,15 +10114,52 @@ var PeerBytesTicketSchema = object({
|
|
|
10109
10114
|
*/
|
|
10110
10115
|
declaredBytes: number$1().int().nonnegative().nullable()
|
|
10111
10116
|
});
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10117
|
+
/**
|
|
10118
|
+
* The match a notification rule fired on (D705). Carried as a command origin so an
|
|
10119
|
+
* Action the rule starts can press `alarm-panel.trigger` as that match, not as an
|
|
10120
|
+
* anonymous press (D735). The same fields a rule fire ref freezes.
|
|
10121
|
+
*/
|
|
10122
|
+
var RuleFireOriginSchema = object({
|
|
10123
|
+
ruleId: string(),
|
|
10124
|
+
ruleName: string(),
|
|
10125
|
+
deviceId: number$1().int(),
|
|
10126
|
+
sourceDeviceId: number$1().int().optional(),
|
|
10127
|
+
recordId: string(),
|
|
10128
|
+
timestamp: number$1(),
|
|
10129
|
+
trackId: string().optional(),
|
|
10130
|
+
eventId: string().optional(),
|
|
10131
|
+
className: string().optional(),
|
|
10132
|
+
label: string().optional(),
|
|
10133
|
+
zones: array(string()).optional(),
|
|
10134
|
+
confidence: number$1().optional(),
|
|
10135
|
+
sensorChange: object({
|
|
10136
|
+
name: string(),
|
|
10137
|
+
kind: string(),
|
|
10138
|
+
state: string()
|
|
10139
|
+
}).optional(),
|
|
10140
|
+
extraStills: array(object({
|
|
10141
|
+
ownerId: string(),
|
|
10142
|
+
cameraId: number$1().int()
|
|
10143
|
+
})).optional()
|
|
10144
|
+
});
|
|
10145
|
+
discriminatedUnion("kind", [
|
|
10146
|
+
object({
|
|
10147
|
+
kind: literal("action"),
|
|
10148
|
+
actionId: string(),
|
|
10149
|
+
runId: string(),
|
|
10150
|
+
automationId: string().optional(),
|
|
10151
|
+
/** The rule fire that started this run, when one did (D705). */
|
|
10152
|
+
ruleFire: RuleFireOriginSchema.optional()
|
|
10153
|
+
}),
|
|
10154
|
+
object({
|
|
10155
|
+
kind: literal("scheduler"),
|
|
10156
|
+
schedulerId: string()
|
|
10157
|
+
}),
|
|
10158
|
+
object({
|
|
10159
|
+
kind: literal("rule"),
|
|
10160
|
+
fire: RuleFireOriginSchema
|
|
10161
|
+
})
|
|
10162
|
+
]);
|
|
10121
10163
|
/**
|
|
10122
10164
|
* One recorded device transition (D1022): a status field of a device went from
|
|
10123
10165
|
* one value to another, with who or what asked for it.
|
|
@@ -13851,10 +13893,6 @@ var CAMERA_CAP_VOCABULARY = {
|
|
|
13851
13893
|
scope: "device",
|
|
13852
13894
|
noun: t("Admin link", "Link di amministrazione")
|
|
13853
13895
|
},
|
|
13854
|
-
"device-discovery": {
|
|
13855
|
-
scope: "device",
|
|
13856
|
-
noun: t("Discovery", "Rilevamento dispositivi")
|
|
13857
|
-
},
|
|
13858
13896
|
"device-extension": {
|
|
13859
13897
|
scope: "device",
|
|
13860
13898
|
noun: t("Device extension", "Estensione del dispositivo")
|
|
@@ -15026,6 +15064,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
15026
15064
|
backup: system("system backups — run and restored from the Backups page"),
|
|
15027
15065
|
broker: system("message-broker connections — configured, not actuated"),
|
|
15028
15066
|
"calendar-source": system(INTERNAL),
|
|
15067
|
+
"cluster-update": system(CLUSTER),
|
|
15029
15068
|
calendars: system("calendars feed schedules and conditions, not device actions"),
|
|
15030
15069
|
composer: system("device composition — an authoring tool, not an action"),
|
|
15031
15070
|
"core-blocks": system(INTERNAL),
|
|
@@ -15315,6 +15354,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
15315
15354
|
"camera-streams",
|
|
15316
15355
|
"carbon-monoxide",
|
|
15317
15356
|
"climate-control",
|
|
15357
|
+
"cluster-update",
|
|
15318
15358
|
"color",
|
|
15319
15359
|
"composer",
|
|
15320
15360
|
"connectivity",
|
|
@@ -15332,7 +15372,6 @@ var CAP_NAMES = Object.freeze([
|
|
|
15332
15372
|
"device-admin-link",
|
|
15333
15373
|
"device-adoption",
|
|
15334
15374
|
"device-credentials",
|
|
15335
|
-
"device-discovery",
|
|
15336
15375
|
"device-export",
|
|
15337
15376
|
"device-extension",
|
|
15338
15377
|
"device-history",
|
|
@@ -15954,13 +15993,6 @@ Object.freeze({
|
|
|
15954
15993
|
"valueType": "string"
|
|
15955
15994
|
}
|
|
15956
15995
|
],
|
|
15957
|
-
"device-discovery": [{
|
|
15958
|
-
"path": "lastDiscoveryAt",
|
|
15959
|
-
"valueType": "number"
|
|
15960
|
-
}, {
|
|
15961
|
-
"path": "lastError",
|
|
15962
|
-
"valueType": "string"
|
|
15963
|
-
}],
|
|
15964
15996
|
"device-export": [
|
|
15965
15997
|
{
|
|
15966
15998
|
"path": "linkState",
|
|
@@ -17412,7 +17444,7 @@ Object.freeze({
|
|
|
17412
17444
|
}
|
|
17413
17445
|
});
|
|
17414
17446
|
//#endregion
|
|
17415
|
-
//#region ../types/dist/
|
|
17447
|
+
//#region ../types/dist/implemented-methods-M5aguGon.mjs
|
|
17416
17448
|
/**
|
|
17417
17449
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
17418
17450
|
*
|
|
@@ -19352,18 +19384,43 @@ var TargetKindLevelSchema = object({
|
|
|
19352
19384
|
requires: array(string()).optional(),
|
|
19353
19385
|
description: string().optional()
|
|
19354
19386
|
});
|
|
19387
|
+
/** Attachment capabilities for a kind (drives the degrade engine + test panel). */
|
|
19388
|
+
var TargetKindAttachmentsCapsSchema = object({
|
|
19389
|
+
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
19390
|
+
mode: _enum([
|
|
19391
|
+
"url",
|
|
19392
|
+
"bytes",
|
|
19393
|
+
"both"
|
|
19394
|
+
]),
|
|
19395
|
+
max: number$1().int().nonnegative(),
|
|
19396
|
+
maxBytes: number$1().int().positive().optional()
|
|
19397
|
+
});
|
|
19398
|
+
/**
|
|
19399
|
+
* Which TEXT fields a kind delivers (#483). Alexa speaks a title and nothing
|
|
19400
|
+
* else; a push service shows both.
|
|
19401
|
+
*
|
|
19402
|
+
* `.optional()` on the caps block, never defaulted: absent = both, which is
|
|
19403
|
+
* what every kind declared before this field meant (D938's rule for a Zod
|
|
19404
|
+
* default on the addon cap path).
|
|
19405
|
+
*/
|
|
19406
|
+
var TargetKindTextCapsSchema = object({
|
|
19407
|
+
title: boolean(),
|
|
19408
|
+
body: boolean()
|
|
19409
|
+
});
|
|
19410
|
+
_enum([
|
|
19411
|
+
"title",
|
|
19412
|
+
"body",
|
|
19413
|
+
"attachments",
|
|
19414
|
+
"actions",
|
|
19415
|
+
"priority",
|
|
19416
|
+
"sound",
|
|
19417
|
+
"clickUrl"
|
|
19418
|
+
]);
|
|
19355
19419
|
/** The full capability block consulted before dispatch. */
|
|
19356
19420
|
var TargetKindCapsSchema = object({
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
"url",
|
|
19361
|
-
"bytes",
|
|
19362
|
-
"both"
|
|
19363
|
-
]),
|
|
19364
|
-
max: number$1().int().nonnegative(),
|
|
19365
|
-
maxBytes: number$1().int().positive().optional()
|
|
19366
|
-
}),
|
|
19421
|
+
/** Text fields this kind delivers (#483). Absent = title AND body. */
|
|
19422
|
+
text: TargetKindTextCapsSchema.optional(),
|
|
19423
|
+
attachments: TargetKindAttachmentsCapsSchema,
|
|
19367
19424
|
/** Max action buttons (0 = none). */
|
|
19368
19425
|
actions: number$1().int().nonnegative(),
|
|
19369
19426
|
/**
|
|
@@ -44027,6 +44084,62 @@ var WeekdayKeySchema = _enum([
|
|
|
44027
44084
|
"sat",
|
|
44028
44085
|
"sun"
|
|
44029
44086
|
]);
|
|
44087
|
+
/**
|
|
44088
|
+
* Hold semantics — "for N seconds" on a leaf of the `when` tree (#498).
|
|
44089
|
+
*
|
|
44090
|
+
* ONE primitive, `for: { ms, mode, tolerance? }`, shared by `device-becomes`,
|
|
44091
|
+
* `device-is` and `expression`:
|
|
44092
|
+
*
|
|
44093
|
+
* - `held`: the condition stays true for `ms`;
|
|
44094
|
+
* - `stable`: the value does not move by more than `tolerance` (absolute, in
|
|
44095
|
+
* the field's base unit) for `ms` while the condition holds.
|
|
44096
|
+
*
|
|
44097
|
+
* {@link HoldCore} is the pure state machine (an input observation → a reading).
|
|
44098
|
+
* {@link HoldTracker} keys cores by a leaf path for the STATE leaves the tree
|
|
44099
|
+
* evaluator judges. {@link BecomesWatch} wraps a core with a timer for the
|
|
44100
|
+
* `device-becomes` EVENT leaf: the deadline is armed when the hold starts and
|
|
44101
|
+
* cancelled when it breaks, and the leaf fires ONCE per episode.
|
|
44102
|
+
*
|
|
44103
|
+
* Hold state is memory only. A hold that is already running when the watcher
|
|
44104
|
+
* first looks (a restart) is INHERITED: nobody knows when it began, so it never
|
|
44105
|
+
* fires for that episode and a state leaf reads it as unknown until the window
|
|
44106
|
+
* has elapsed from the moment the watcher started (D49: not-known is not false).
|
|
44107
|
+
*/
|
|
44108
|
+
var HOLD_MAX_MS = 864e5;
|
|
44109
|
+
var HoldModeSchema = _enum(["held", "stable"]);
|
|
44110
|
+
var HoldSpecSchema = object({
|
|
44111
|
+
/** How long the condition (or the value) must hold. */
|
|
44112
|
+
ms: number$1().int().min(1).max(HOLD_MAX_MS),
|
|
44113
|
+
mode: HoldModeSchema,
|
|
44114
|
+
/** `stable` only: the largest move of the value that still counts as unchanged (absolute, base unit). */
|
|
44115
|
+
tolerance: number$1().min(0).optional()
|
|
44116
|
+
});
|
|
44117
|
+
/** What a trace says about a hold. */
|
|
44118
|
+
var HoldTraceSchema = object({
|
|
44119
|
+
phase: _enum([
|
|
44120
|
+
"pending",
|
|
44121
|
+
"cancelled",
|
|
44122
|
+
"fired",
|
|
44123
|
+
"reseeded"
|
|
44124
|
+
]),
|
|
44125
|
+
ms: number$1().int(),
|
|
44126
|
+
mode: HoldModeSchema,
|
|
44127
|
+
/** When the hold started (ms epoch). */
|
|
44128
|
+
since: number$1().optional(),
|
|
44129
|
+
/** When it completes (ms epoch), for a pending hold. */
|
|
44130
|
+
deadline: number$1().optional()
|
|
44131
|
+
});
|
|
44132
|
+
/** The operators a `device-becomes` leaf may carry: a threshold or a range. */
|
|
44133
|
+
var BecomesOperatorSchema = _enum([
|
|
44134
|
+
"eq",
|
|
44135
|
+
"ne",
|
|
44136
|
+
"gt",
|
|
44137
|
+
"gte",
|
|
44138
|
+
"lt",
|
|
44139
|
+
"lte",
|
|
44140
|
+
"between",
|
|
44141
|
+
"outside"
|
|
44142
|
+
]);
|
|
44030
44143
|
/** How a state leaf compares a device field to a value. Derived from the
|
|
44031
44144
|
* field's `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
44032
44145
|
var AutomationConditionOperatorSchema = _enum([
|
|
@@ -44050,18 +44163,52 @@ var DeviceBecomesLeafSchema = object({
|
|
|
44050
44163
|
deviceId: number$1().int().nonnegative(),
|
|
44051
44164
|
cap: string().min(1),
|
|
44052
44165
|
fieldPath: string().min(1),
|
|
44053
|
-
/** Fire when the field takes this value. Omit to fire on any change. */
|
|
44166
|
+
/** Fire when the field takes this value. Omit (with no `operator`) to fire on any change. */
|
|
44054
44167
|
becomes: union([
|
|
44055
44168
|
string(),
|
|
44056
44169
|
number$1(),
|
|
44057
44170
|
boolean()
|
|
44058
44171
|
]).optional(),
|
|
44059
|
-
/**
|
|
44172
|
+
/**
|
|
44173
|
+
* A threshold or a range instead of an equality: "crosses above 3000", "enters
|
|
44174
|
+
* 18..24". The leaf fires on the TRANSITION into the predicate, never on a re-report.
|
|
44175
|
+
* `value` is in the field's base unit; `between` / `outside` take `[low, high]`.
|
|
44176
|
+
*/
|
|
44177
|
+
operator: BecomesOperatorSchema.optional(),
|
|
44178
|
+
value: union([
|
|
44179
|
+
number$1(),
|
|
44180
|
+
string(),
|
|
44181
|
+
boolean(),
|
|
44182
|
+
array(number$1()).length(2)
|
|
44183
|
+
]).optional(),
|
|
44184
|
+
/**
|
|
44185
|
+
* Hold: the transition (or, with no predicate, the new value) must stay for
|
|
44186
|
+
* `for.ms` before the leaf fires, ONCE per episode. See `hold.ts`.
|
|
44187
|
+
*/
|
|
44188
|
+
for: HoldSpecSchema.optional(),
|
|
44189
|
+
/** @deprecated every leaf fires on a transition now; read as always on. */
|
|
44060
44190
|
edge: boolean().optional(),
|
|
44061
|
-
/**
|
|
44062
|
-
forMs: number$1().int().min(0).max(
|
|
44191
|
+
/** @deprecated legacy `held` window — read through `holdOf` as `for: { ms, mode: 'held' }`. */
|
|
44192
|
+
forMs: number$1().int().min(0).max(HOLD_MAX_MS).optional(),
|
|
44063
44193
|
/** Collapse a burst into one occurrence. */
|
|
44064
44194
|
debounceMs: number$1().int().min(0).max(6e5).optional()
|
|
44195
|
+
}).superRefine((leaf, ctx) => {
|
|
44196
|
+
if (leaf.becomes !== void 0 && leaf.operator !== void 0) ctx.addIssue({
|
|
44197
|
+
code: "custom",
|
|
44198
|
+
message: "a leaf names `becomes` or `operator`, not both",
|
|
44199
|
+
path: ["operator"]
|
|
44200
|
+
});
|
|
44201
|
+
if (leaf.operator !== void 0 && leaf.value === void 0) ctx.addIssue({
|
|
44202
|
+
code: "custom",
|
|
44203
|
+
message: "an operator needs the value to compare to",
|
|
44204
|
+
path: ["value"]
|
|
44205
|
+
});
|
|
44206
|
+
const range = leaf.operator === "between" || leaf.operator === "outside";
|
|
44207
|
+
if (leaf.operator !== void 0 && range !== Array.isArray(leaf.value)) ctx.addIssue({
|
|
44208
|
+
code: "custom",
|
|
44209
|
+
message: range ? "a range takes [low, high]" : "only a range takes [low, high]",
|
|
44210
|
+
path: ["value"]
|
|
44211
|
+
});
|
|
44065
44212
|
});
|
|
44066
44213
|
var DeviceEventLeafSchema = object({
|
|
44067
44214
|
kind: literal("device-event"),
|
|
@@ -44126,7 +44273,9 @@ var DeviceIsLeafSchema = object({
|
|
|
44126
44273
|
QuantityValueSchema
|
|
44127
44274
|
]),
|
|
44128
44275
|
/** The unit the person picked for `value` (display only; `value` is in the base unit). */
|
|
44129
|
-
unit: string().min(1).optional()
|
|
44276
|
+
unit: string().min(1).optional(),
|
|
44277
|
+
/** The comparison must hold (`held`) or the value stay put (`stable`) this long. */
|
|
44278
|
+
for: HoldSpecSchema.optional()
|
|
44130
44279
|
});
|
|
44131
44280
|
/**
|
|
44132
44281
|
* True when the camera currently has a PARKED object matching `subjects` in at
|
|
@@ -44149,7 +44298,9 @@ var StationaryPresentLeafSchema = object({
|
|
|
44149
44298
|
var ExpressionLeafSchema = object({
|
|
44150
44299
|
kind: literal("expression"),
|
|
44151
44300
|
expr: string().min(1).max(MAX_EXPRESSION_SOURCE_LENGTH),
|
|
44152
|
-
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema)
|
|
44301
|
+
bindings: record(string().regex(EXPRESSION_IDENTIFIER_RE), ExpressionBindingSourceSchema),
|
|
44302
|
+
/** The expression must stay true this long. An expression has no single value, so only `held`. */
|
|
44303
|
+
for: HoldSpecSchema.optional()
|
|
44153
44304
|
}).superRefine((src, ctx) => {
|
|
44154
44305
|
const err = validateExpressionSource(src);
|
|
44155
44306
|
if (err !== null) ctx.addIssue({
|
|
@@ -44157,6 +44308,11 @@ var ExpressionLeafSchema = object({
|
|
|
44157
44308
|
message: err,
|
|
44158
44309
|
path: ["expr"]
|
|
44159
44310
|
});
|
|
44311
|
+
if (src.for?.mode === "stable") ctx.addIssue({
|
|
44312
|
+
code: "custom",
|
|
44313
|
+
message: "an expression is held, not stable: it has no single value to keep still",
|
|
44314
|
+
path: ["for", "mode"]
|
|
44315
|
+
});
|
|
44160
44316
|
});
|
|
44161
44317
|
var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
|
|
44162
44318
|
object({
|
|
@@ -44487,30 +44643,21 @@ function convertLegacyWhen(half) {
|
|
|
44487
44643
|
* (instants) and state leaves (durations). It replaces the flat trigger list
|
|
44488
44644
|
* plus the separate condition tree; the firing rule is in that file and in
|
|
44489
44645
|
* ADR "one tree".
|
|
44490
|
-
* - **Actions** — `
|
|
44491
|
-
* fragment of §3.2.2. See {@link AutomationActionSchema}
|
|
44492
|
-
* this had to diverge from "verbatim", and why.
|
|
44646
|
+
* - **Actions** — the `wait` and `cap` steps, plus the `{kind:'code'}`
|
|
44647
|
+
* fragment of §3.2.2. See {@link AutomationActionSchema}.
|
|
44493
44648
|
*
|
|
44494
44649
|
* A recipe stored in the old shape (`triggers` + `conditions`) still LOADS:
|
|
44495
44650
|
* {@link AutomationRecipeSchema} (the parse-anywhere schema) converts it on parse. Nothing writes it.
|
|
44496
44651
|
*/
|
|
44497
44652
|
/**
|
|
44498
|
-
* One action step.
|
|
44653
|
+
* One action step: `wait`, or a `cap` call.
|
|
44499
44654
|
*
|
|
44500
|
-
*
|
|
44501
|
-
*
|
|
44502
|
-
*
|
|
44503
|
-
*
|
|
44504
|
-
*
|
|
44505
|
-
*
|
|
44506
|
-
* a literal `z.number().int()`, and the NC runner's own `RunSequencesInput`
|
|
44507
|
-
* documents its subject device as *"for the log tag, never for routing"*. So an
|
|
44508
|
-
* NC action can never target the device that triggered it — which is fine for
|
|
44509
|
-
* the NC (its rules already scope to a device) and fatal for an automation
|
|
44510
|
-
* ("sound the siren of the camera that saw the person"). `deviceId` therefore
|
|
44511
|
-
* also accepts `{ $var }`, resolved from the run's `vars` bag BEFORE the runner
|
|
44512
|
-
* is called. The runner still receives a number and is untouched; the
|
|
44513
|
-
* resolution is the recipe's job, not the runner's.
|
|
44655
|
+
* A cap step's target is who it acts on (D983: `devices`, a `domain`, or a
|
|
44656
|
+
* `{ $var }` resolved from the run's variables); the legacy `deviceId` is still
|
|
44657
|
+
* READ, never written. The step runner (`runSteps`) owns the device-scope
|
|
44658
|
+
* check, the stop-at-first-failure and the variable substitution, once, for
|
|
44659
|
+
* every caller — automations, Actions, and the notification centre, which runs
|
|
44660
|
+
* only Actions (planning#473).
|
|
44514
44661
|
*/
|
|
44515
44662
|
var AutomationWaitStepSchema = object({
|
|
44516
44663
|
kind: literal("wait"),
|
|
@@ -44925,7 +45072,9 @@ var AutomationTriggerTraceSchema = object({
|
|
|
44925
45072
|
/** Why an event was rejected ("class person not in [dog]") or what fired. */
|
|
44926
45073
|
reason: string(),
|
|
44927
45074
|
/** deviceId, className, trackId, score … — only what the trigger exposes. */
|
|
44928
|
-
vars: record(string(), TraceValueSchema)
|
|
45075
|
+
vars: record(string(), TraceValueSchema),
|
|
45076
|
+
/** A hold (`for`) this occurrence went through: pending, cancelled, fired or re-seeded. */
|
|
45077
|
+
hold: HoldTraceSchema.optional()
|
|
44929
45078
|
});
|
|
44930
45079
|
var AutomationConditionTraceNodeSchema = object({
|
|
44931
45080
|
/** `when` for the root, `when.<i>` for its i-th child, … (`conditions…` on an old trace). */
|
|
@@ -45128,6 +45277,8 @@ var ActionStatusSchema = object({
|
|
|
45128
45277
|
/** The latest run's failure; null on success or when it never ran. */
|
|
45129
45278
|
lastError: string().nullable()
|
|
45130
45279
|
});
|
|
45280
|
+
/** The throttle window of an action, in seconds; absent or 0 = no throttle. */
|
|
45281
|
+
var ActionMinDelaySecSchema = number$1().int().min(0).max(86400);
|
|
45131
45282
|
var ActionEntrySchema = object({
|
|
45132
45283
|
/** `internal:<uuid>` or `<addonId>:<localId>`. */
|
|
45133
45284
|
id: string().min(3),
|
|
@@ -45140,6 +45291,14 @@ var ActionEntrySchema = object({
|
|
|
45140
45291
|
/** Internal only: cap and wait steps. No action-in-action, so no cycles. */
|
|
45141
45292
|
steps: array(ActionStepSchema).min(1).max(50).optional(),
|
|
45142
45293
|
variables: array(ActionVariableSchema).max(20).optional(),
|
|
45294
|
+
/**
|
|
45295
|
+
* Internal only: the least time between two run STARTS. A run that begins
|
|
45296
|
+
* inside the window is skipped (`skipped-cooldown`), traced and logged. It
|
|
45297
|
+
* is an actuator's budget — "how often may this gate physically open" —
|
|
45298
|
+
* not a notification cooldown, and it is shared by every caller of the
|
|
45299
|
+
* action (two rules, a button, an automation).
|
|
45300
|
+
*/
|
|
45301
|
+
minDelaySec: ActionMinDelaySecSchema.optional(),
|
|
45143
45302
|
status: ActionStatusSchema
|
|
45144
45303
|
}).superRefine((entry, ctx) => {
|
|
45145
45304
|
if (entry.source === "internal") {
|
|
@@ -45170,7 +45329,8 @@ var ActionEntrySchema = object({
|
|
|
45170
45329
|
var ActionInputSchema = object({
|
|
45171
45330
|
name: string().min(1).max(120),
|
|
45172
45331
|
steps: array(ActionStepSchema).min(1).max(50),
|
|
45173
|
-
variables: array(ActionVariableSchema).max(20).optional()
|
|
45332
|
+
variables: array(ActionVariableSchema).max(20).optional(),
|
|
45333
|
+
minDelaySec: ActionMinDelaySecSchema.optional()
|
|
45174
45334
|
});
|
|
45175
45335
|
/** Who started a run. Absent = the operator pressed it. */
|
|
45176
45336
|
var ActionRunOriginSchema = object({
|
|
@@ -45260,7 +45420,7 @@ object({
|
|
|
45260
45420
|
* is irrelevant; the array is treated as a set by consumers. */
|
|
45261
45421
|
hiddenChildIds: array(number$1()).readonly()
|
|
45262
45422
|
});
|
|
45263
|
-
DeviceType.Camera, DeviceType.
|
|
45423
|
+
DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Cover, DeviceType.Lock, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Generic, method(object({
|
|
45264
45424
|
deviceId: number$1().int().nonnegative(),
|
|
45265
45425
|
childDeviceId: number$1().int().nonnegative(),
|
|
45266
45426
|
hidden: boolean()
|
|
@@ -49330,14 +49490,14 @@ var climateControlCapability = {
|
|
|
49330
49490
|
kind: "mutation",
|
|
49331
49491
|
auth: "protected"
|
|
49332
49492
|
}),
|
|
49333
|
-
setFanMode:
|
|
49493
|
+
setFanMode: optionalMethod(object({
|
|
49334
49494
|
deviceId: number$1().int().nonnegative(),
|
|
49335
49495
|
fanMode: string().min(1)
|
|
49336
49496
|
}), _void(), {
|
|
49337
49497
|
kind: "mutation",
|
|
49338
49498
|
auth: "protected"
|
|
49339
49499
|
}),
|
|
49340
|
-
setPreset:
|
|
49500
|
+
setPreset: optionalMethod(object({
|
|
49341
49501
|
deviceId: number$1().int().nonnegative(),
|
|
49342
49502
|
preset: string().min(1)
|
|
49343
49503
|
}), _void(), {
|
|
@@ -49351,7 +49511,7 @@ var climateControlCapability = {
|
|
|
49351
49511
|
kind: "mutation",
|
|
49352
49512
|
auth: "protected"
|
|
49353
49513
|
}),
|
|
49354
|
-
setTargetRange:
|
|
49514
|
+
setTargetRange: optionalMethod(object({
|
|
49355
49515
|
deviceId: number$1().int().nonnegative(),
|
|
49356
49516
|
targetLow: number$1(),
|
|
49357
49517
|
targetHigh: number$1()
|
|
@@ -49359,21 +49519,21 @@ var climateControlCapability = {
|
|
|
49359
49519
|
kind: "mutation",
|
|
49360
49520
|
auth: "protected"
|
|
49361
49521
|
}),
|
|
49362
|
-
setTargetHumidity:
|
|
49522
|
+
setTargetHumidity: optionalMethod(object({
|
|
49363
49523
|
deviceId: number$1().int().nonnegative(),
|
|
49364
49524
|
targetHumidity: number$1().min(0).max(100)
|
|
49365
49525
|
}), _void(), {
|
|
49366
49526
|
kind: "mutation",
|
|
49367
49527
|
auth: "protected"
|
|
49368
49528
|
}),
|
|
49369
|
-
setSwingVertical:
|
|
49529
|
+
setSwingVertical: optionalMethod(object({
|
|
49370
49530
|
deviceId: number$1().int().nonnegative(),
|
|
49371
49531
|
on: boolean()
|
|
49372
49532
|
}), _void(), {
|
|
49373
49533
|
kind: "mutation",
|
|
49374
49534
|
auth: "protected"
|
|
49375
49535
|
}),
|
|
49376
|
-
setSwingHorizontal:
|
|
49536
|
+
setSwingHorizontal: optionalMethod(object({
|
|
49377
49537
|
deviceId: number$1().int().nonnegative(),
|
|
49378
49538
|
on: boolean()
|
|
49379
49539
|
}), _void(), {
|
|
@@ -49431,6 +49591,140 @@ var climateControlCapability = {
|
|
|
49431
49591
|
} }
|
|
49432
49592
|
};
|
|
49433
49593
|
/**
|
|
49594
|
+
* cluster-update — the ONE flow that brings the whole cluster to a release
|
|
49595
|
+
* (planning#493). Hub-provided (`server-provided`), hub-only: the hub runs
|
|
49596
|
+
* the sequence itself, so the admin UI, the MCP and the CLI all start the same
|
|
49597
|
+
* job and read the same report instead of each driving their own loop.
|
|
49598
|
+
*
|
|
49599
|
+
* 1. backup (`backup.trigger`) — skipped only when the caller says so
|
|
49600
|
+
* 2. the hub's server closure (`applyServerUpdate`); the hub restarts and the
|
|
49601
|
+
* job RESUMES on the new boot, verified against the hub's running version
|
|
49602
|
+
* 3. every online agent behind the target, one at a time, verified: runs the
|
|
49603
|
+
* target, settled, online, and its capabilities registered (D848) — an
|
|
49604
|
+
* agent that comes back capless is a FAILED step, never a done one
|
|
49605
|
+
* 4. every stale addon on the hub (`addons.updatePackage`); agents follow by
|
|
49606
|
+
* reconciliation, which is verified, never pushed
|
|
49607
|
+
*
|
|
49608
|
+
* The job stops on the first failed step with a typed reason (D877). Its state
|
|
49609
|
+
* is durable on the hub and read by RPC (`getClusterUpdateJob`) — events are
|
|
49610
|
+
* telemetry and never carry it (D8, D11).
|
|
49611
|
+
*/
|
|
49612
|
+
/** The steps, in the order they run. */
|
|
49613
|
+
var ClusterUpdateStepKindSchema = _enum([
|
|
49614
|
+
"backup",
|
|
49615
|
+
"hub-server",
|
|
49616
|
+
"agent-server",
|
|
49617
|
+
"addons"
|
|
49618
|
+
]);
|
|
49619
|
+
/**
|
|
49620
|
+
* - `pending` — not reached yet.
|
|
49621
|
+
* - `running` — in progress (for `hub-server`: possibly across the restart).
|
|
49622
|
+
* - `ok` — done AND verified.
|
|
49623
|
+
* - `failed` — did not land; `reason` + `detail` say why. Stops the job.
|
|
49624
|
+
* - `skipped` — not run: nothing to do, opted out, the node is offline, or a
|
|
49625
|
+
* step before it failed. `detail` says which.
|
|
49626
|
+
*/
|
|
49627
|
+
var ClusterUpdateStepStatusSchema = _enum([
|
|
49628
|
+
"pending",
|
|
49629
|
+
"running",
|
|
49630
|
+
"ok",
|
|
49631
|
+
"failed",
|
|
49632
|
+
"skipped"
|
|
49633
|
+
]);
|
|
49634
|
+
/**
|
|
49635
|
+
* Why a step (and with it the job) failed. Stable, greppable; `detail` carries
|
|
49636
|
+
* the prose.
|
|
49637
|
+
*/
|
|
49638
|
+
var ClusterUpdateFailureReasonSchema = _enum([
|
|
49639
|
+
"backup-unavailable",
|
|
49640
|
+
"backup-failed",
|
|
49641
|
+
"server-refused",
|
|
49642
|
+
"server-not-on-target",
|
|
49643
|
+
"node-capless",
|
|
49644
|
+
"status-unreadable",
|
|
49645
|
+
"addon-update-failed",
|
|
49646
|
+
"addons-not-converged",
|
|
49647
|
+
"interrupted"
|
|
49648
|
+
]);
|
|
49649
|
+
var ClusterUpdateStepSchema = object({
|
|
49650
|
+
kind: ClusterUpdateStepKindSchema,
|
|
49651
|
+
/** The node the step acts on; absent for `backup` and `addons`. */
|
|
49652
|
+
nodeId: string().optional(),
|
|
49653
|
+
status: ClusterUpdateStepStatusSchema,
|
|
49654
|
+
/** One line for the operator: what happened, or why not. */
|
|
49655
|
+
detail: string(),
|
|
49656
|
+
reason: ClusterUpdateFailureReasonSchema.optional(),
|
|
49657
|
+
/** `hub-server` / `agent-server`: the version the node ran before. */
|
|
49658
|
+
fromVersion: string().nullable().optional(),
|
|
49659
|
+
/** `addons`: the packages this step updates, `name from -> to`. */
|
|
49660
|
+
packages: array(string()).readonly().optional(),
|
|
49661
|
+
startedAt: number$1().optional(),
|
|
49662
|
+
finishedAt: number$1().optional()
|
|
49663
|
+
});
|
|
49664
|
+
var ClusterUpdateJobStateSchema = _enum([
|
|
49665
|
+
"running",
|
|
49666
|
+
"succeeded",
|
|
49667
|
+
"failed"
|
|
49668
|
+
]);
|
|
49669
|
+
var ClusterUpdateJobSchema = object({
|
|
49670
|
+
id: string(),
|
|
49671
|
+
state: ClusterUpdateJobStateSchema,
|
|
49672
|
+
/** The server version every node is brought to. */
|
|
49673
|
+
targetVersion: string(),
|
|
49674
|
+
/** Who started it (the user name, or `system`). */
|
|
49675
|
+
requestedBy: string(),
|
|
49676
|
+
startedAt: number$1(),
|
|
49677
|
+
finishedAt: number$1().optional(),
|
|
49678
|
+
/** Every step, in run order; later steps stay `pending` while it runs. */
|
|
49679
|
+
steps: array(ClusterUpdateStepSchema).readonly(),
|
|
49680
|
+
/** On `failed`: the step that stopped it (`nodeId` or the step kind). */
|
|
49681
|
+
stoppedAt: string().optional(),
|
|
49682
|
+
reason: ClusterUpdateFailureReasonSchema.optional(),
|
|
49683
|
+
/** Agents offline when the plan was read: never touched. */
|
|
49684
|
+
skippedOffline: array(string()).readonly()
|
|
49685
|
+
});
|
|
49686
|
+
var ClusterUpdateOptionsSchema = object({
|
|
49687
|
+
/** Explicit server target; omitted = the hub's latest registry check. */
|
|
49688
|
+
version: string().optional(),
|
|
49689
|
+
/** Update the addons too (default true). */
|
|
49690
|
+
addons: boolean().optional(),
|
|
49691
|
+
/**
|
|
49692
|
+
* Back up before touching anything (default true). `false` is an explicit
|
|
49693
|
+
* operator opt-out; a missing backup provider is otherwise a failure.
|
|
49694
|
+
*/
|
|
49695
|
+
backup: boolean().optional()
|
|
49696
|
+
});
|
|
49697
|
+
/** Why a plan cannot start. */
|
|
49698
|
+
var ClusterUpdateBlockerSchema = _enum([
|
|
49699
|
+
"no-target",
|
|
49700
|
+
"node-busy",
|
|
49701
|
+
"job-running",
|
|
49702
|
+
"nothing-to-do",
|
|
49703
|
+
"status-unreadable"
|
|
49704
|
+
]);
|
|
49705
|
+
var ClusterUpdatePlanSchema = object({
|
|
49706
|
+
/** `null` when no target could be resolved (`blocker: 'no-target'`). */
|
|
49707
|
+
targetVersion: string().nullable(),
|
|
49708
|
+
/** The steps the job WOULD run, all `pending` (or `skipped` with a reason). */
|
|
49709
|
+
steps: array(ClusterUpdateStepSchema).readonly(),
|
|
49710
|
+
skippedOffline: array(string()).readonly(),
|
|
49711
|
+
/** `null` = the plan can start. */
|
|
49712
|
+
blocker: ClusterUpdateBlockerSchema.nullable(),
|
|
49713
|
+
/** Prose for `blocker`. */
|
|
49714
|
+
blockerDetail: string().nullable()
|
|
49715
|
+
});
|
|
49716
|
+
var StartClusterUpdateResultSchema = object({
|
|
49717
|
+
accepted: boolean(),
|
|
49718
|
+
/** The job to follow with `getClusterUpdateJob`; `null` when refused. */
|
|
49719
|
+
jobId: string().nullable(),
|
|
49720
|
+
blocker: ClusterUpdateBlockerSchema.nullable(),
|
|
49721
|
+
message: string()
|
|
49722
|
+
});
|
|
49723
|
+
method(ClusterUpdateOptionsSchema, ClusterUpdatePlanSchema, { auth: "admin" }), method(ClusterUpdateOptionsSchema, StartClusterUpdateResultSchema, {
|
|
49724
|
+
kind: "mutation",
|
|
49725
|
+
auth: "admin"
|
|
49726
|
+
}), method(object({ jobId: string().optional() }), ClusterUpdateJobSchema.nullable(), { auth: "admin" });
|
|
49727
|
+
/**
|
|
49434
49728
|
* Color-light cap. Coexists with `switch` (on/off) and `brightness`
|
|
49435
49729
|
* (level) on the same device — `switch` toggles the bulb, `brightness`
|
|
49436
49730
|
* sets the dim level, this cap sets the chromaticity.
|
|
@@ -50632,27 +50926,27 @@ var mediaPlayerCapability = {
|
|
|
50632
50926
|
mode: "singleton",
|
|
50633
50927
|
deviceTypes: [DeviceType.MediaPlayer],
|
|
50634
50928
|
methods: {
|
|
50635
|
-
turnOn:
|
|
50929
|
+
turnOn: optionalMethod(deviceOnly, _void(), {
|
|
50636
50930
|
kind: "mutation",
|
|
50637
50931
|
auth: "protected"
|
|
50638
50932
|
}),
|
|
50639
|
-
turnOff:
|
|
50933
|
+
turnOff: optionalMethod(deviceOnly, _void(), {
|
|
50640
50934
|
kind: "mutation",
|
|
50641
50935
|
auth: "protected"
|
|
50642
50936
|
}),
|
|
50643
|
-
volumeUp:
|
|
50937
|
+
volumeUp: optionalMethod(stepInput, _void(), {
|
|
50644
50938
|
kind: "mutation",
|
|
50645
50939
|
auth: "protected"
|
|
50646
50940
|
}),
|
|
50647
|
-
volumeDown:
|
|
50941
|
+
volumeDown: optionalMethod(stepInput, _void(), {
|
|
50648
50942
|
kind: "mutation",
|
|
50649
50943
|
auth: "protected"
|
|
50650
50944
|
}),
|
|
50651
|
-
channelUp:
|
|
50945
|
+
channelUp: optionalMethod(stepInput, _void(), {
|
|
50652
50946
|
kind: "mutation",
|
|
50653
50947
|
auth: "protected"
|
|
50654
50948
|
}),
|
|
50655
|
-
channelDown:
|
|
50949
|
+
channelDown: optionalMethod(stepInput, _void(), {
|
|
50656
50950
|
kind: "mutation",
|
|
50657
50951
|
auth: "protected"
|
|
50658
50952
|
}),
|
|
@@ -50664,61 +50958,61 @@ var mediaPlayerCapability = {
|
|
|
50664
50958
|
kind: "mutation",
|
|
50665
50959
|
auth: "protected"
|
|
50666
50960
|
}),
|
|
50667
|
-
stop:
|
|
50961
|
+
stop: optionalMethod(object({ deviceId: number$1().int().nonnegative() }), _void(), {
|
|
50668
50962
|
kind: "mutation",
|
|
50669
50963
|
auth: "protected"
|
|
50670
50964
|
}),
|
|
50671
|
-
next:
|
|
50965
|
+
next: optionalMethod(object({ deviceId: number$1().int().nonnegative() }), _void(), {
|
|
50672
50966
|
kind: "mutation",
|
|
50673
50967
|
auth: "protected"
|
|
50674
50968
|
}),
|
|
50675
|
-
previous:
|
|
50969
|
+
previous: optionalMethod(object({ deviceId: number$1().int().nonnegative() }), _void(), {
|
|
50676
50970
|
kind: "mutation",
|
|
50677
50971
|
auth: "protected"
|
|
50678
50972
|
}),
|
|
50679
|
-
seek:
|
|
50973
|
+
seek: optionalMethod(object({
|
|
50680
50974
|
deviceId: number$1().int().nonnegative(),
|
|
50681
50975
|
position: number$1().int().nonnegative()
|
|
50682
50976
|
}), _void(), {
|
|
50683
50977
|
kind: "mutation",
|
|
50684
50978
|
auth: "protected"
|
|
50685
50979
|
}),
|
|
50686
|
-
setVolume:
|
|
50980
|
+
setVolume: optionalMethod(object({
|
|
50687
50981
|
deviceId: number$1().int().nonnegative(),
|
|
50688
50982
|
volumeLevel: number$1().min(0).max(100)
|
|
50689
50983
|
}), _void(), {
|
|
50690
50984
|
kind: "mutation",
|
|
50691
50985
|
auth: "protected"
|
|
50692
50986
|
}),
|
|
50693
|
-
setMute:
|
|
50987
|
+
setMute: optionalMethod(object({
|
|
50694
50988
|
deviceId: number$1().int().nonnegative(),
|
|
50695
50989
|
muted: boolean()
|
|
50696
50990
|
}), _void(), {
|
|
50697
50991
|
kind: "mutation",
|
|
50698
50992
|
auth: "protected"
|
|
50699
50993
|
}),
|
|
50700
|
-
setShuffle:
|
|
50994
|
+
setShuffle: optionalMethod(object({
|
|
50701
50995
|
deviceId: number$1().int().nonnegative(),
|
|
50702
50996
|
shuffle: boolean()
|
|
50703
50997
|
}), _void(), {
|
|
50704
50998
|
kind: "mutation",
|
|
50705
50999
|
auth: "protected"
|
|
50706
51000
|
}),
|
|
50707
|
-
setRepeat:
|
|
51001
|
+
setRepeat: optionalMethod(object({
|
|
50708
51002
|
deviceId: number$1().int().nonnegative(),
|
|
50709
51003
|
repeat: MediaPlayerRepeatSchema
|
|
50710
51004
|
}), _void(), {
|
|
50711
51005
|
kind: "mutation",
|
|
50712
51006
|
auth: "protected"
|
|
50713
51007
|
}),
|
|
50714
|
-
selectSource:
|
|
51008
|
+
selectSource: optionalMethod(object({
|
|
50715
51009
|
deviceId: number$1().int().nonnegative(),
|
|
50716
51010
|
source: string().min(1)
|
|
50717
51011
|
}), _void(), {
|
|
50718
51012
|
kind: "mutation",
|
|
50719
51013
|
auth: "protected"
|
|
50720
51014
|
}),
|
|
50721
|
-
playMedia:
|
|
51015
|
+
playMedia: optionalMethod(object({
|
|
50722
51016
|
deviceId: number$1().int().nonnegative(),
|
|
50723
51017
|
/** Media identifier / URL. */
|
|
50724
51018
|
mediaId: string().min(1),
|
|
@@ -50761,7 +51055,7 @@ var mediaPlayerCapability = {
|
|
|
50761
51055
|
isMuted: { kind: "boolean" }
|
|
50762
51056
|
} }
|
|
50763
51057
|
};
|
|
50764
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.HeatPump, DeviceType.Camera, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Gateway, DeviceType.
|
|
51058
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.HeatPump, DeviceType.Camera, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Gateway, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.MediaPlayer;
|
|
50765
51059
|
var NUMBER = {
|
|
50766
51060
|
kind: "fixed",
|
|
50767
51061
|
result: ["number"]
|
|
@@ -51740,18 +52034,18 @@ var coverCapability = {
|
|
|
51740
52034
|
kind: "mutation",
|
|
51741
52035
|
auth: "protected"
|
|
51742
52036
|
}),
|
|
51743
|
-
stop:
|
|
52037
|
+
stop: optionalMethod(object({ deviceId: number$1().int().nonnegative() }), _void(), {
|
|
51744
52038
|
kind: "mutation",
|
|
51745
52039
|
auth: "protected"
|
|
51746
52040
|
}),
|
|
51747
|
-
setPosition:
|
|
52041
|
+
setPosition: optionalMethod(object({
|
|
51748
52042
|
deviceId: number$1().int().nonnegative(),
|
|
51749
52043
|
position: number$1().min(0).max(100)
|
|
51750
52044
|
}), _void(), {
|
|
51751
52045
|
kind: "mutation",
|
|
51752
52046
|
auth: "protected"
|
|
51753
52047
|
}),
|
|
51754
|
-
setTiltPosition:
|
|
52048
|
+
setTiltPosition: optionalMethod(object({
|
|
51755
52049
|
deviceId: number$1().int().nonnegative(),
|
|
51756
52050
|
tiltPosition: number$1().min(0).max(100)
|
|
51757
52051
|
}), _void(), {
|
|
@@ -52233,27 +52527,35 @@ var DeviceAdminLinkSchema = object({
|
|
|
52233
52527
|
});
|
|
52234
52528
|
method(object({ deviceId: number$1().int().nonnegative() }), DeviceAdminLinkSchema.nullable(), { auth: "admin" });
|
|
52235
52529
|
/**
|
|
52236
|
-
* device-
|
|
52237
|
-
*
|
|
52238
|
-
*
|
|
52239
|
-
*
|
|
52240
|
-
*
|
|
52241
|
-
*
|
|
52242
|
-
*
|
|
52243
|
-
*
|
|
52244
|
-
*
|
|
52245
|
-
*
|
|
52246
|
-
*
|
|
52247
|
-
*
|
|
52248
|
-
*
|
|
52249
|
-
*
|
|
52250
|
-
*
|
|
52251
|
-
*
|
|
52252
|
-
*
|
|
52253
|
-
|
|
52254
|
-
|
|
52255
|
-
*
|
|
52256
|
-
*
|
|
52530
|
+
* `device-adoption` — generic discovery + adoption surface,
|
|
52531
|
+
* system-scoped collection (one provider per integration addon), routed
|
|
52532
|
+
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
52533
|
+
* pin model as `connection-test`. The admin UI keeps using
|
|
52534
|
+
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
52535
|
+
* successor to `ha-discovery`:
|
|
52536
|
+
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
52537
|
+
* internally) rather than a connection-specific `brokerId`, and it
|
|
52538
|
+
* OWNS the shared `DiscoveredChildDevice` candidate type
|
|
52539
|
+
* (declared below) so a single shared adoption modal renders any integration's
|
|
52540
|
+
* candidate tree.
|
|
52541
|
+
*
|
|
52542
|
+
* UI flow (Integrations page → integration detail):
|
|
52543
|
+
* 1. `listCandidates({integrationId, page, pageSize, filter})` →
|
|
52544
|
+
* paginated candidate list, each row collapsed.
|
|
52545
|
+
* 2. User expands a row → `getCandidate({integrationId,
|
|
52546
|
+
* childNativeId})` returns the single candidate (with its nested
|
|
52547
|
+
* `children`) for the accordion render.
|
|
52548
|
+
* 3. User clicks "Adopt" on one or more candidates →
|
|
52549
|
+
* `adopt({integrationId, childNativeIds, perCandidate?})`
|
|
52550
|
+
* materialises one parent CamStack device per candidate plus its
|
|
52551
|
+
* accessory children. `perCandidate[childNativeId]` carries an
|
|
52552
|
+
* optional display-name override + a `hiddenChildIds` pre-hide set
|
|
52553
|
+
* (the parent's `accessories.hiddenChildIds` gates UI visibility).
|
|
52554
|
+
* 4. User clicks "Release" → `release({integrationId, camDeviceId})`
|
|
52555
|
+
* removes the parent + every child from the kernel registry.
|
|
52556
|
+
*/
|
|
52557
|
+
/**
|
|
52558
|
+
* Status enum for a discovered device. Generic enough for
|
|
52257
52559
|
* battery cams, awake cams, and unreachable cams alike.
|
|
52258
52560
|
*/
|
|
52259
52561
|
var DiscoveredChildStatusSchema = _enum([
|
|
@@ -52270,12 +52572,12 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
52270
52572
|
/** DeviceType the child should be created with on adopt. */
|
|
52271
52573
|
type: _enum(DeviceType),
|
|
52272
52574
|
status: DiscoveredChildStatusSchema,
|
|
52273
|
-
/** Free-form integration-specific metadata surfaced in the
|
|
52575
|
+
/** Free-form integration-specific metadata surfaced in the adoption modal. */
|
|
52274
52576
|
metadata: object({
|
|
52275
52577
|
model: string().optional(),
|
|
52276
52578
|
serialNumber: string().optional(),
|
|
52277
52579
|
uid: string().optional(),
|
|
52278
|
-
/** Reolink: 0-based channel index inside the parent NVR
|
|
52580
|
+
/** Reolink: 0-based channel index inside the parent NVR. */
|
|
52279
52581
|
rtspChannel: number$1().int().nonnegative().optional(),
|
|
52280
52582
|
isBattery: boolean().optional(),
|
|
52281
52583
|
isDoorbell: boolean().optional(),
|
|
@@ -52291,137 +52593,24 @@ var DiscoveredChildDeviceSchema = lazy(() => object({
|
|
|
52291
52593
|
}).default({}),
|
|
52292
52594
|
/**
|
|
52293
52595
|
* `true` when the framework already created a child device for this
|
|
52294
|
-
* `childNativeId` under the current parent. The
|
|
52596
|
+
* `childNativeId` under the current parent. The adoption modal uses it to
|
|
52295
52597
|
* gate the Add/Remove button and surface the existing `deviceId`.
|
|
52296
52598
|
*/
|
|
52297
52599
|
alreadyAdopted: boolean(),
|
|
52298
52600
|
/** When `alreadyAdopted=true`, the framework-assigned child device id. */
|
|
52299
52601
|
adoptedDeviceId: number$1().int().nonnegative().nullable(),
|
|
52300
|
-
/** Capability names the candidate advertises — integrations populate,
|
|
52602
|
+
/** Capability names the candidate advertises — integrations populate, flat enumerations omit. */
|
|
52301
52603
|
capabilities: array(string()).readonly().optional(),
|
|
52302
|
-
/** Feature flags the candidate advertises — integrations populate,
|
|
52604
|
+
/** Feature flags the candidate advertises — integrations populate, flat enumerations omit. */
|
|
52303
52605
|
features: array(string()).readonly().optional(),
|
|
52304
52606
|
/** Upstream-system identity + rendering hints for the candidate. */
|
|
52305
52607
|
sourceInfo: SourceInfoSchema.optional(),
|
|
52306
|
-
/** Nested entity-children for accordion preview — integrations populate,
|
|
52608
|
+
/** Nested entity-children for accordion preview — integrations populate, flat enumerations omit. */
|
|
52307
52609
|
children: array(DiscoveredChildDeviceSchema).readonly().optional(),
|
|
52308
52610
|
/** `childNativeId` of the gateway candidate in the same list this device sits behind. */
|
|
52309
52611
|
parentStableId: string().optional()
|
|
52310
52612
|
}));
|
|
52311
52613
|
/**
|
|
52312
|
-
* Status block — populated by the integration after each
|
|
52313
|
-
* `refreshDiscovery` (or push-driven update). The runtime-state slice
|
|
52314
|
-
* is what the panel reads via the per-device proxy; `getStatus`
|
|
52315
|
-
* returns the same payload via the codegen'd auto-injection.
|
|
52316
|
-
*/
|
|
52317
|
-
var DeviceDiscoveryStatusSchema = object({
|
|
52318
|
-
discovered: array(DiscoveredChildDeviceSchema),
|
|
52319
|
-
/** Wall-clock ms of the last successful enumeration. */
|
|
52320
|
-
lastDiscoveryAt: number$1().int().nonnegative().nullable(),
|
|
52321
|
-
/** Last error surfaced from the source (rendered as a banner). */
|
|
52322
|
-
lastError: string().nullable()
|
|
52323
|
-
});
|
|
52324
|
-
var deviceDiscoveryCapability = {
|
|
52325
|
-
name: "device-discovery",
|
|
52326
|
-
scope: "device",
|
|
52327
|
-
deviceNative: true,
|
|
52328
|
-
mode: "singleton",
|
|
52329
|
-
deviceTypes: [DeviceType.Hub],
|
|
52330
|
-
status: {
|
|
52331
|
-
schema: DeviceDiscoveryStatusSchema,
|
|
52332
|
-
kind: "poll"
|
|
52333
|
-
},
|
|
52334
|
-
runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: number$1().int().nonnegative() }),
|
|
52335
|
-
/**
|
|
52336
|
-
* Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
|
|
52337
|
-
*
|
|
52338
|
-
* See `RuntimeStateDurability`. Enforced by
|
|
52339
|
-
* `scripts/check-runtime-state-durability.ts`.
|
|
52340
|
-
*/
|
|
52341
|
-
durability: "session",
|
|
52342
|
-
/**
|
|
52343
|
-
* History (D850): none — inventory.
|
|
52344
|
-
*/
|
|
52345
|
-
history: "none",
|
|
52346
|
-
methods: {
|
|
52347
|
-
/**
|
|
52348
|
-
* Snapshot of the current `discovered` list. Returns the
|
|
52349
|
-
* runtime-state cache — call `refreshDiscovery` first if a
|
|
52350
|
-
* fresh round-trip to the source is required.
|
|
52351
|
-
*/
|
|
52352
|
-
listDiscovered: method(object({ deviceId: number$1().int().nonnegative() }), array(DiscoveredChildDeviceSchema).readonly()),
|
|
52353
|
-
/**
|
|
52354
|
-
* Force the integration to re-enumerate and update the
|
|
52355
|
-
* runtime-state slice. Returns the freshly-enumerated list (also
|
|
52356
|
-
* available via `listDiscovered` post-call).
|
|
52357
|
-
*/
|
|
52358
|
-
refreshDiscovery: method(object({ deviceId: number$1().int().nonnegative() }), array(DiscoveredChildDeviceSchema).readonly(), {
|
|
52359
|
-
kind: "mutation",
|
|
52360
|
-
auth: "admin"
|
|
52361
|
-
}),
|
|
52362
|
-
/**
|
|
52363
|
-
* Promote a discovered entry to a real child device. The framework
|
|
52364
|
-
* creates the child via `kernel.devices.create()` with
|
|
52365
|
-
* `parentDeviceId = parent.id` and seeds the child's config from
|
|
52366
|
-
* `childInitialConfig` (driver-defined; usually carries channel +
|
|
52367
|
-
* uid + parent reference). Returns the kernel-assigned numeric id.
|
|
52368
|
-
*/
|
|
52369
|
-
adoptDevice: method(object({
|
|
52370
|
-
deviceId: number$1().int().nonnegative(),
|
|
52371
|
-
childNativeId: string(),
|
|
52372
|
-
/** Optional override for the child's display name. */
|
|
52373
|
-
name: string().optional()
|
|
52374
|
-
}), object({
|
|
52375
|
-
deviceId: number$1().int().nonnegative(),
|
|
52376
|
-
stableId: string()
|
|
52377
|
-
}), {
|
|
52378
|
-
kind: "mutation",
|
|
52379
|
-
auth: "admin"
|
|
52380
|
-
}),
|
|
52381
|
-
/**
|
|
52382
|
-
* Inverse of `adoptDevice`: removes the child device from the
|
|
52383
|
-
* kernel registry. The discovered entry remains in the
|
|
52384
|
-
* enumeration (status updates resume) so the operator can re-adopt
|
|
52385
|
-
* it later without a fresh refresh.
|
|
52386
|
-
*/
|
|
52387
|
-
releaseDevice: method(object({
|
|
52388
|
-
deviceId: number$1().int().nonnegative(),
|
|
52389
|
-
childDeviceId: number$1().int().nonnegative()
|
|
52390
|
-
}), _void(), {
|
|
52391
|
-
kind: "mutation",
|
|
52392
|
-
auth: "admin"
|
|
52393
|
-
})
|
|
52394
|
-
}
|
|
52395
|
-
};
|
|
52396
|
-
/**
|
|
52397
|
-
* `device-adoption` — generic discovery + adoption surface,
|
|
52398
|
-
* system-scoped collection (one provider per integration addon), routed
|
|
52399
|
-
* by explicit `{ addonId }` on direct `deviceAdoption.*` calls — the same
|
|
52400
|
-
* pin model as `connection-test`. The admin UI keeps using
|
|
52401
|
-
* `deviceManager.adoption*` (which already threads `addonId`). The de-HA-ified
|
|
52402
|
-
* successor to `ha-discovery`:
|
|
52403
|
-
* keyed by `integrationId` (the addon resolves integrationId → broker
|
|
52404
|
-
* internally) rather than a connection-specific `brokerId`, and it
|
|
52405
|
-
* REUSES the shared `DiscoveredChildDevice` candidate type from
|
|
52406
|
-
* `device-discovery.cap.ts` so a single shared adoption panel renders
|
|
52407
|
-
* any integration's candidate tree.
|
|
52408
|
-
*
|
|
52409
|
-
* UI flow (Integrations page → integration detail):
|
|
52410
|
-
* 1. `listCandidates({integrationId, page, pageSize, filter})` →
|
|
52411
|
-
* paginated candidate list, each row collapsed.
|
|
52412
|
-
* 2. User expands a row → `getCandidate({integrationId,
|
|
52413
|
-
* childNativeId})` returns the single candidate (with its nested
|
|
52414
|
-
* `children`) for the accordion render.
|
|
52415
|
-
* 3. User clicks "Adopt" on one or more candidates →
|
|
52416
|
-
* `adopt({integrationId, childNativeIds, perCandidate?})`
|
|
52417
|
-
* materialises one parent CamStack device per candidate plus its
|
|
52418
|
-
* accessory children. `perCandidate[childNativeId]` carries an
|
|
52419
|
-
* optional display-name override + a `hiddenChildIds` pre-hide set
|
|
52420
|
-
* (the parent's `accessories.hiddenChildIds` gates UI visibility).
|
|
52421
|
-
* 4. User clicks "Release" → `release({integrationId, camDeviceId})`
|
|
52422
|
-
* removes the parent + every child from the kernel registry.
|
|
52423
|
-
*/
|
|
52424
|
-
/**
|
|
52425
52614
|
* Provider-declared discovery *granularity* filter (the keystone of the
|
|
52426
52615
|
* single-entity-import design). A provider advertises which discovery
|
|
52427
52616
|
* granularities it supports via `listCandidateFilters`; the operator picks
|
|
@@ -52781,6 +52970,22 @@ method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(Expor
|
|
|
52781
52970
|
});
|
|
52782
52971
|
var DeviceAliasSchema = string().max(64).regex(/^[a-z][a-z0-9_]*$/);
|
|
52783
52972
|
var DeviceTemplateSchema = string().min(1).max(4096);
|
|
52973
|
+
/** One value a caller hands the renderer for `thisDevice`. */
|
|
52974
|
+
var DeviceTemplateValueSchema = union([
|
|
52975
|
+
string(),
|
|
52976
|
+
number$1(),
|
|
52977
|
+
boolean()
|
|
52978
|
+
]);
|
|
52979
|
+
/**
|
|
52980
|
+
* The device a render is FOR (`camera` in the text) and the values the caller
|
|
52981
|
+
* knows about it that no capability carries, for example `lastPerson` and
|
|
52982
|
+
* `lastPlate`. `values` read as `camera.<name>`; a name a capability also carries
|
|
52983
|
+
* is `ambiguous` and is written `camera.values.<name>`.
|
|
52984
|
+
*/
|
|
52985
|
+
var DeviceTemplateThisDeviceSchema = object({
|
|
52986
|
+
deviceId: number$1().int(),
|
|
52987
|
+
values: record(string().min(1).max(64), DeviceTemplateValueSchema).optional()
|
|
52988
|
+
});
|
|
52784
52989
|
var DeviceTemplateRefusalSchema = object({
|
|
52785
52990
|
reason: _enum([
|
|
52786
52991
|
"too-long",
|
|
@@ -52866,6 +53071,90 @@ var SiteZoneSchema = object({
|
|
|
52866
53071
|
* the ones that most want grouping. */
|
|
52867
53072
|
locationKeys: array(string())
|
|
52868
53073
|
});
|
|
53074
|
+
var DeviceSearchRequiresSchema = object({
|
|
53075
|
+
/** Capability names the field wants a value of. */
|
|
53076
|
+
caps: array(string()).readonly(),
|
|
53077
|
+
/** `any` (default): a device with one of them is compatible. `all`: it must hold every one. */
|
|
53078
|
+
mode: _enum(["any", "all"]).optional()
|
|
53079
|
+
});
|
|
53080
|
+
var DeviceSearchFiltersSchema = object({
|
|
53081
|
+
locations: array(string()).readonly().optional(),
|
|
53082
|
+
integrationIds: array(string()).readonly().optional(),
|
|
53083
|
+
types: array(string()).readonly().optional()
|
|
53084
|
+
});
|
|
53085
|
+
var DeviceSearchInputSchema = object({
|
|
53086
|
+
/** Matches name, location, type, integration (id and label) and id. Case-insensitive. */
|
|
53087
|
+
text: string().optional(),
|
|
53088
|
+
requires: DeviceSearchRequiresSchema.optional(),
|
|
53089
|
+
filters: DeviceSearchFiltersSchema.optional(),
|
|
53090
|
+
/** List the devices that do not provide the required cap too (greyed, not pickable). */
|
|
53091
|
+
includeIncompatible: boolean().optional(),
|
|
53092
|
+
/** The device the field belongs to: its location drives `suggested`. */
|
|
53093
|
+
contextDeviceId: number$1().optional(),
|
|
53094
|
+
/**
|
|
53095
|
+
* Resolve exactly these devices, regardless of every filter, so a picked
|
|
53096
|
+
* value can be rendered. When given, `items` is these devices in the order
|
|
53097
|
+
* asked (no paging, `nextCursor` null) and the ones that do not exist are
|
|
53098
|
+
* listed in `missingIds`.
|
|
53099
|
+
*/
|
|
53100
|
+
ids: array(number$1()).readonly().optional(),
|
|
53101
|
+
cursor: string().nullable().optional(),
|
|
53102
|
+
limit: number$1().int().min(1).max(200).optional()
|
|
53103
|
+
});
|
|
53104
|
+
var DeviceValueOptionSchema = object({
|
|
53105
|
+
cap: string(),
|
|
53106
|
+
/** Status-schema field path inside the cap (same paths as `getWireableFields`). */
|
|
53107
|
+
path: string(),
|
|
53108
|
+
label: string(),
|
|
53109
|
+
/** The current value as text; `null` when it is unknown or the read FAILED — never `0`. */
|
|
53110
|
+
reading: string().nullable(),
|
|
53111
|
+
unit: string().nullable().optional(),
|
|
53112
|
+
/** The field's measured quantity, when the cap declares one, so a client can format the reading. */
|
|
53113
|
+
quantity: ReadingQuantitySchema.optional()
|
|
53114
|
+
});
|
|
53115
|
+
var DeviceSearchItemSchema = object({
|
|
53116
|
+
id: number$1(),
|
|
53117
|
+
name: string(),
|
|
53118
|
+
type: _enum(DeviceType),
|
|
53119
|
+
location: string().nullable(),
|
|
53120
|
+
integrationId: string().nullable(),
|
|
53121
|
+
integrationLabel: string().nullable(),
|
|
53122
|
+
online: boolean().nullable(),
|
|
53123
|
+
disabled: boolean(),
|
|
53124
|
+
compatible: boolean(),
|
|
53125
|
+
/** Only the required caps' fields; empty when nothing was required or the device is incompatible. */
|
|
53126
|
+
values: array(DeviceValueOptionSchema).readonly()
|
|
53127
|
+
});
|
|
53128
|
+
var DeviceSearchFacetValueSchema = object({
|
|
53129
|
+
value: string(),
|
|
53130
|
+
count: number$1()
|
|
53131
|
+
});
|
|
53132
|
+
var DeviceSearchFacetIntegrationSchema = object({
|
|
53133
|
+
id: string(),
|
|
53134
|
+
label: string(),
|
|
53135
|
+
count: number$1()
|
|
53136
|
+
});
|
|
53137
|
+
var DeviceSearchFacetsSchema = object({
|
|
53138
|
+
locations: array(DeviceSearchFacetValueSchema).readonly(),
|
|
53139
|
+
integrations: array(DeviceSearchFacetIntegrationSchema).readonly(),
|
|
53140
|
+
types: array(DeviceSearchFacetValueSchema).readonly()
|
|
53141
|
+
});
|
|
53142
|
+
var DeviceSearchResultSchema = object({
|
|
53143
|
+
items: array(DeviceSearchItemSchema).readonly(),
|
|
53144
|
+
nextCursor: string().nullable(),
|
|
53145
|
+
/** Devices listed by this query across all pages (filters + text applied; incompatible counted only when `includeIncompatible`). */
|
|
53146
|
+
total: number$1(),
|
|
53147
|
+
/** Compatible devices after filters + text. */
|
|
53148
|
+
compatibleTotal: number$1(),
|
|
53149
|
+
/** Every device the caller's fleet holds, before anything is applied. */
|
|
53150
|
+
fleetTotal: number$1(),
|
|
53151
|
+
/** Incompatible devices after filters + text — the K of "show the K that don't". */
|
|
53152
|
+
hiddenIncompatible: number$1(),
|
|
53153
|
+
facets: DeviceSearchFacetsSchema,
|
|
53154
|
+
/** Same location as `contextDeviceId`; first page only. */
|
|
53155
|
+
suggested: array(DeviceSearchItemSchema).readonly(),
|
|
53156
|
+
missingIds: array(number$1()).readonly()
|
|
53157
|
+
});
|
|
52869
53158
|
var ProviderStatusSchema = object({
|
|
52870
53159
|
connected: boolean(),
|
|
52871
53160
|
deviceCount: number$1(),
|
|
@@ -53351,6 +53640,9 @@ var DeviceInfoSchema = object({
|
|
|
53351
53640
|
* named accordion sections (with optional intra-section order). See
|
|
53352
53641
|
* `DeviceMeta.childLayout`. Absent ⇒ no layout declared. */
|
|
53353
53642
|
childLayout: array(ChildLayoutEntrySchema).readonly().optional(),
|
|
53643
|
+
/** The children a container stands for, most preferred first, by accessory
|
|
53644
|
+
* `childKey`. Provider-declared. See `DeviceMeta.primaryChildPreference`. */
|
|
53645
|
+
primaryChildPreference: array(string()).readonly().optional(),
|
|
53354
53646
|
/** Operator-authored per-device display override. See `DeviceMeta.display`. */
|
|
53355
53647
|
display: DeviceDisplayOverrideSchema.optional()
|
|
53356
53648
|
});
|
|
@@ -53412,7 +53704,9 @@ var DeviceBindingsForDeviceSchema = object({
|
|
|
53412
53704
|
kind: _enum(["native", "wrapped"]),
|
|
53413
53705
|
providerAddonId: string(),
|
|
53414
53706
|
providerNodeId: string(),
|
|
53415
|
-
nativeAddonId: string()
|
|
53707
|
+
nativeAddonId: string(),
|
|
53708
|
+
/** The cap's methods the native provider implements; absent = all. */
|
|
53709
|
+
implementedMethods: array(string()).optional()
|
|
53416
53710
|
}))
|
|
53417
53711
|
});
|
|
53418
53712
|
/**
|
|
@@ -53497,6 +53791,9 @@ var DeviceMetaSchema = object({
|
|
|
53497
53791
|
* accordion sections (with optional intra-section order). See
|
|
53498
53792
|
* `DeviceMeta.childLayout`. Absent ⇒ no layout declared. */
|
|
53499
53793
|
childLayout: array(ChildLayoutEntrySchema).readonly().optional(),
|
|
53794
|
+
/** The children a container stands for, most preferred first, by accessory
|
|
53795
|
+
* `childKey`. Provider-declared. See `DeviceMeta.primaryChildPreference`. */
|
|
53796
|
+
primaryChildPreference: array(string()).readonly().optional(),
|
|
53500
53797
|
/** Semantic role string (`DeviceRole`) — propagated from the spawn pre-seed.
|
|
53501
53798
|
* Optional: only present for accessory children that carry a known role. */
|
|
53502
53799
|
role: string().nullable().optional(),
|
|
@@ -53655,17 +53952,24 @@ method(object({
|
|
|
53655
53952
|
auth: "admin"
|
|
53656
53953
|
}), method(object({
|
|
53657
53954
|
templates: array(DeviceTemplateSchema).max(64),
|
|
53658
|
-
allowedDeviceIds: array(number$1().int()).optional()
|
|
53955
|
+
allowedDeviceIds: array(number$1().int()).optional(),
|
|
53956
|
+
/** The device `camera` names in the texts, and the values the caller knows of it. */
|
|
53957
|
+
thisDevice: DeviceTemplateThisDeviceSchema.optional()
|
|
53659
53958
|
}), object({ results: array(DeviceTemplateRenderSchema) }), { auth: "admin" }), method(object({
|
|
53660
53959
|
templates: array(string()).max(64),
|
|
53661
|
-
allowedDeviceIds: array(number$1().int()).optional()
|
|
53960
|
+
allowedDeviceIds: array(number$1().int()).optional(),
|
|
53961
|
+
thisDevice: DeviceTemplateThisDeviceSchema.optional()
|
|
53662
53962
|
}), object({ results: array(discriminatedUnion("ok", [object({
|
|
53663
53963
|
ok: literal(true),
|
|
53664
53964
|
aliases: array(object({
|
|
53665
53965
|
alias: string(),
|
|
53666
53966
|
deviceId: number$1().int().nullable(),
|
|
53667
|
-
allowed: boolean()
|
|
53668
|
-
|
|
53967
|
+
allowed: boolean(),
|
|
53968
|
+
/** The fields the text reads on this alias, as written (`temperature`, `cap.field`). */
|
|
53969
|
+
reads: array(string())
|
|
53970
|
+
})),
|
|
53971
|
+
/** Whether the text reads the clock (`now`): it changes every minute. */
|
|
53972
|
+
readsClock: boolean()
|
|
53669
53973
|
}), object({
|
|
53670
53974
|
ok: literal(false),
|
|
53671
53975
|
refusal: DeviceTemplateRefusalSchema
|
|
@@ -53705,6 +54009,12 @@ method(object({
|
|
|
53705
54009
|
}), _void(), {
|
|
53706
54010
|
kind: "mutation",
|
|
53707
54011
|
auth: "admin"
|
|
54012
|
+
}), method(object({
|
|
54013
|
+
deviceId: number$1(),
|
|
54014
|
+
primaryChildPreference: array(string()).readonly()
|
|
54015
|
+
}), _void(), {
|
|
54016
|
+
kind: "mutation",
|
|
54017
|
+
auth: "admin"
|
|
53708
54018
|
}), method(object({
|
|
53709
54019
|
deviceId: number$1(),
|
|
53710
54020
|
display: DeviceDisplayOverrideSchema.nullable()
|
|
@@ -53842,7 +54152,7 @@ method(object({
|
|
|
53842
54152
|
* it answers today and the caller filters as it already does.
|
|
53843
54153
|
*/
|
|
53844
54154
|
deviceIds: array(number$1()).optional()
|
|
53845
|
-
}), array(DeviceInfoSchema), { role: "viewer" }), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema), { role: "viewer" }), method(object({ parentDeviceIds: array(number$1()).max(256) }), record(string(), array(DeviceInfoSchema))), method(object({ deviceId: number$1() }), object({
|
|
54155
|
+
}), array(DeviceInfoSchema), { role: "viewer" }), method(DeviceSearchInputSchema, DeviceSearchResultSchema, { role: "viewer" }), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema), { role: "viewer" }), method(object({ parentDeviceIds: array(number$1()).max(256) }), record(string(), array(DeviceInfoSchema))), method(object({ deviceId: number$1() }), object({
|
|
53846
54156
|
mode: LinkedDevicesModeSchema,
|
|
53847
54157
|
devices: array(LinkedDeviceSchema)
|
|
53848
54158
|
}), { role: "viewer" }), method(object({ deviceIds: array(number$1()) }), array(LinkedDevicesForDeviceSchema), { role: "viewer" }), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
|
|
@@ -56387,28 +56697,28 @@ var fanControlCapability = {
|
|
|
56387
56697
|
mode: "singleton",
|
|
56388
56698
|
deviceTypes: [DeviceType.Fan],
|
|
56389
56699
|
methods: {
|
|
56390
|
-
setPercentage:
|
|
56700
|
+
setPercentage: optionalMethod(object({
|
|
56391
56701
|
deviceId: number$1().int().nonnegative(),
|
|
56392
56702
|
speed: number$1().min(0).max(100)
|
|
56393
56703
|
}), _void(), {
|
|
56394
56704
|
kind: "mutation",
|
|
56395
56705
|
auth: "protected"
|
|
56396
56706
|
}),
|
|
56397
|
-
setPreset:
|
|
56707
|
+
setPreset: optionalMethod(object({
|
|
56398
56708
|
deviceId: number$1().int().nonnegative(),
|
|
56399
56709
|
preset: string().min(1)
|
|
56400
56710
|
}), _void(), {
|
|
56401
56711
|
kind: "mutation",
|
|
56402
56712
|
auth: "protected"
|
|
56403
56713
|
}),
|
|
56404
|
-
setDirection:
|
|
56714
|
+
setDirection: optionalMethod(object({
|
|
56405
56715
|
deviceId: number$1().int().nonnegative(),
|
|
56406
56716
|
direction: FanDirectionSchema
|
|
56407
56717
|
}), _void(), {
|
|
56408
56718
|
kind: "mutation",
|
|
56409
56719
|
auth: "protected"
|
|
56410
56720
|
}),
|
|
56411
|
-
setOscillating:
|
|
56721
|
+
setOscillating: optionalMethod(object({
|
|
56412
56722
|
deviceId: number$1().int().nonnegative(),
|
|
56413
56723
|
oscillating: boolean()
|
|
56414
56724
|
}), _void(), {
|
|
@@ -57510,13 +57820,11 @@ var HeroConfirmSchema = _enum([
|
|
|
57510
57820
|
"press"
|
|
57511
57821
|
]);
|
|
57512
57822
|
var HeroActionSchema = object({
|
|
57513
|
-
/** Unique within the model; the `gated` list and the specs name it. */
|
|
57514
57823
|
id: string(),
|
|
57515
57824
|
label: HeroTextSchema,
|
|
57516
57825
|
icon: IconKeySchema,
|
|
57517
57826
|
call: HeroCallSchema,
|
|
57518
57827
|
emphasis: _enum(["primary", "normal"]),
|
|
57519
|
-
/** Ask before running it. */
|
|
57520
57828
|
confirm: HeroConfirmSchema.nullable()
|
|
57521
57829
|
});
|
|
57522
57830
|
var HeroControlSchema = discriminatedUnion("kind", [
|
|
@@ -57567,6 +57875,8 @@ var HeroPillSchema = object({
|
|
|
57567
57875
|
});
|
|
57568
57876
|
var HeroRowSchema = object({
|
|
57569
57877
|
id: HeroRowIdSchema,
|
|
57878
|
+
/** `scene`: the row's action and slider controls are drawn on the scene. Absent: an ordinary row. */
|
|
57879
|
+
placement: _enum(["row", "scene"]).optional(),
|
|
57570
57880
|
/** The row's own name when the kind's label would not tell rows of one kind apart (a circuit's label). */
|
|
57571
57881
|
label: HeroTextSchema.optional(),
|
|
57572
57882
|
/** A group header drawn above the row when it differs from the previous row's ("System"). */
|
|
@@ -57597,9 +57907,16 @@ var HeroBadgeSchema = object({
|
|
|
57597
57907
|
value: number$1().nullable(),
|
|
57598
57908
|
label: HeroTextSchema
|
|
57599
57909
|
});
|
|
57600
|
-
var HeroRemoteSlotSchema = object({
|
|
57601
|
-
/** Saved commands; `null` = not known yet (the button still shows). */
|
|
57602
|
-
commands: number$1().int().nullable()
|
|
57910
|
+
var HeroRemoteSlotSchema = object({
|
|
57911
|
+
/** Saved commands; `null` = not known yet (the button still shows). */
|
|
57912
|
+
commands: number$1().int().nullable(),
|
|
57913
|
+
/**
|
|
57914
|
+
* The control a list row draws as the "open the remote" icon. Recognised by its id
|
|
57915
|
+
* ({@link REMOTE_OPEN_ACTION_ID}); it changes no state, so a client opens the remote
|
|
57916
|
+
* instead of running `call`. Absent on a model from an older server.
|
|
57917
|
+
*/
|
|
57918
|
+
open: HeroActionSchema.optional()
|
|
57919
|
+
});
|
|
57603
57920
|
var HeroConsumablesSlotSchema = object({
|
|
57604
57921
|
items: array(object({
|
|
57605
57922
|
key: string(),
|
|
@@ -57767,6 +58084,8 @@ var HeroModelSchema = object({
|
|
|
57767
58084
|
* the FIRST row that has any (a later row's control is never promoted). When
|
|
57768
58085
|
* the model lists that part in `gated`, the row has no inline control: the
|
|
57769
58086
|
* projection never falls through to another control the caller could use.
|
|
58087
|
+
* - a climate or thermostat row's primary is its `climate.mode` control (no power
|
|
58088
|
+
* toggle: "off" is a mode); when the model gates it the rule above applies as before;
|
|
57770
58089
|
* - a timed run, when the model carries the slot, sits beside that primary:
|
|
57771
58090
|
* Run while idle, Stop while armed. Gating the slot hides the control.
|
|
57772
58091
|
* - the status line is the head (what plays, else the state) plus at most
|
|
@@ -57774,6 +58093,13 @@ var HeroModelSchema = object({
|
|
|
57774
58093
|
* time left on an armed timed run;
|
|
57775
58094
|
* - the trailing fact is the first of power, battery, consumables.
|
|
57776
58095
|
*
|
|
58096
|
+
* - `extras` are the further inline controls of the types that carry more than one
|
|
58097
|
+
* ({@link ROW_EXTRAS_BY_TYPE}): climate setpoint, a robot's return to base,
|
|
58098
|
+
* a player's volume and remote. Each is a control the model already has, named by id,
|
|
58099
|
+
* in that order and at most {@link ROW_EXTRAS_MAX}; one the model lacks, or lists in
|
|
58100
|
+
* `gated`, is absent, and the one `primary` already is never repeats. Empty = the
|
|
58101
|
+
* row of an older server: `primary` alone.
|
|
58102
|
+
*
|
|
57777
58103
|
* `projectDeviceRow` is pure and computes nothing: it selects from a
|
|
57778
58104
|
* {@link HeroModel}. A row that needed a value the hero lacks would mean the
|
|
57779
58105
|
* model is missing it, so the fix goes in the model.
|
|
@@ -57805,8 +58131,16 @@ var HeroRowModelSchema = object({
|
|
|
57805
58131
|
* while armed. `null` when there is no slot, or the caller may not act.
|
|
57806
58132
|
*/
|
|
57807
58133
|
timedRun: HeroRowTimedRunSchema.nullable(),
|
|
58134
|
+
/**
|
|
58135
|
+
* The further inline controls after `primary`, in order (see the header). The remote
|
|
58136
|
+
* is an `action` with id `remote.open`: the client opens the remote, it does not run
|
|
58137
|
+
* the call. Absent or empty = `primary` alone.
|
|
58138
|
+
*/
|
|
58139
|
+
extras: array(HeroControlSchema).max(2).optional(),
|
|
57808
58140
|
trailing: HeroFactSchema.nullable()
|
|
57809
58141
|
});
|
|
58142
|
+
DeviceType.Climate, DeviceType.Thermostat;
|
|
58143
|
+
DeviceType.Climate, DeviceType.Thermostat, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer;
|
|
57810
58144
|
/**
|
|
57811
58145
|
* hero-layout — what a device's hero says (D1023). Read-only: the FIXED
|
|
57812
58146
|
* layouts live in `@camstack/types` and nothing here stores or edits one.
|
|
@@ -60513,7 +60847,7 @@ var lockControlCapability = {
|
|
|
60513
60847
|
kind: "mutation",
|
|
60514
60848
|
auth: "protected"
|
|
60515
60849
|
}),
|
|
60516
|
-
open:
|
|
60850
|
+
open: optionalMethod(object({ deviceId: number$1().int().nonnegative() }), _void(), {
|
|
60517
60851
|
kind: "mutation",
|
|
60518
60852
|
auth: "protected"
|
|
60519
60853
|
})
|
|
@@ -61710,7 +62044,7 @@ object({
|
|
|
61710
62044
|
deviceId: number$1().int().optional(),
|
|
61711
62045
|
atBefore: number$1().optional(),
|
|
61712
62046
|
where: RecordWhereSchema.optional()
|
|
61713
|
-
}), object({ count: number$1().int().nonnegative() }), object({}), object({ store: Rows }), object({ patch: Rows }), object({}), object({ keys: array(string().min(1)) }), object({ removed: array(string()) }), object({ refs: array(string()) }), object({ values: record(string(), string().nullable()) }), object({
|
|
62047
|
+
}), object({ count: number$1().int().nonnegative() }), object({}), object({ store: Rows }), object({ patch: Rows }), object({}), object({ keys: array(string().min(1)) }), object({ removed: array(string()) }), object({}), object({ deviceIds: array(number$1().int()) }), object({ deviceIds: array(number$1().int()) }), object({ blobs: record(string(), Rows) }), object({ refs: array(string()) }), object({ values: record(string(), string().nullable()) }), object({
|
|
61714
62048
|
ref: string().min(1),
|
|
61715
62049
|
value: string()
|
|
61716
62050
|
}), object({}), object({ refs: array(string()) }), object({ deleted: number$1().int().nonnegative() }), object({}), object({ integrations: array(MigrationIntegrationSchema) }), object({ id: string().min(1) }), MigrationIntegrationSchema.nullable(), object({
|
|
@@ -61721,7 +62055,7 @@ object({
|
|
|
61721
62055
|
integrationId: string().nullable(),
|
|
61722
62056
|
/** Whether the device carries any stored config; its content is not offered. */
|
|
61723
62057
|
hasConfig: boolean()
|
|
61724
|
-
}).nullable(), object({
|
|
62058
|
+
}).nullable(), object({ deviceIds: array(number$1().int()) }), object({ aliases: record(string(), string()) }), object({
|
|
61725
62059
|
deviceId: number$1().int(),
|
|
61726
62060
|
integrationId: string().min(1)
|
|
61727
62061
|
}), object({}), object({}), object({ nodeId: string() }), object({}), object({});
|
|
@@ -68999,92 +69333,21 @@ var NcZoneConditionSchema = object({
|
|
|
68999
69333
|
* membership lists are OR within the list (spec §2.3).
|
|
69000
69334
|
*/
|
|
69001
69335
|
/**
|
|
69002
|
-
* What a rule
|
|
69336
|
+
* What a rule or a button runs: an **Action** of the `actions` surface
|
|
69337
|
+
* (`internal:<uuid>` or an addon's), by id, and nothing else (planning#473).
|
|
69003
69338
|
*
|
|
69004
|
-
*
|
|
69005
|
-
*
|
|
69006
|
-
*
|
|
69007
|
-
*
|
|
69008
|
-
*
|
|
69009
|
-
*
|
|
69010
|
-
* That is not decoration. A rule can be authored by a NON-ADMIN — personal
|
|
69011
|
-
* rules are a supported flow — and the executor runs with the addon's
|
|
69012
|
-
* privileges, so an unbounded action is an arbitrary RPC channel with a
|
|
69013
|
-
* privilege escalation attached. Restricting to device scope excludes the
|
|
69014
|
-
* system caps (`device-manager.removeDevice` and friends) by construction,
|
|
69015
|
-
* costs nothing to maintain, and cannot rot: a cap that stops being
|
|
69016
|
-
* device-scoped stops being actuatable in the same change.
|
|
69017
|
-
*
|
|
69018
|
-
* The executor enforces it; {@link NcRuleActionSchema} carries the intent.
|
|
69339
|
+
* The notification centre has no step vocabulary of its own. The steps, the
|
|
69340
|
+
* device-scope boundary, the stop-at-first-failure, the throttle
|
|
69341
|
+
* (`minDelaySec`), the variables and the runs ledger all belong to the Action;
|
|
69342
|
+
* an operator edits them in ONE place (the Actions page) and a rule points at
|
|
69343
|
+
* the result. A rule can be authored by a non-admin (personal rules), which is
|
|
69344
|
+
* safe for the same reason: it can only name an Action an admin already wrote.
|
|
69019
69345
|
*/
|
|
69346
|
+
var NcActionIdSchema = string().min(1);
|
|
69347
|
+
/** Action ids one hook edge runs, in order. Capped so a slot never becomes a second editor. */
|
|
69348
|
+
var NcHookActionIdsSchema = array(NcActionIdSchema).max(4);
|
|
69020
69349
|
/**
|
|
69021
|
-
* One
|
|
69022
|
-
*
|
|
69023
|
-
* `wait` is a first-class step rather than a property of the next action: it is
|
|
69024
|
-
* what makes a sequence a SEQUENCE and not a list — "unlock, wait 5s, open"
|
|
69025
|
-
* cannot be expressed otherwise.
|
|
69026
|
-
*/
|
|
69027
|
-
var NcRuleActionSchema = discriminatedUnion("kind", [object({
|
|
69028
|
-
kind: literal("wait"),
|
|
69029
|
-
seconds: number$1().min(0).max(300)
|
|
69030
|
-
}), object({
|
|
69031
|
-
kind: literal("cap"),
|
|
69032
|
-
/**
|
|
69033
|
-
* WHO the step acts on (D983) — the only shape that is written. A sequence
|
|
69034
|
-
* stored before D983 carries `deviceId`; the sequence store reads it as a
|
|
69035
|
-
* `devices` target.
|
|
69036
|
-
*/
|
|
69037
|
-
target: ActionTargetSchema.optional(),
|
|
69038
|
-
/** The vocabulary action the step performs; required for a `domain` target. */
|
|
69039
|
-
actionId: string().min(1).optional(),
|
|
69040
|
-
/** @deprecated The pre-D983 single device. Read, never written. */
|
|
69041
|
-
deviceId: number$1().int().optional(),
|
|
69042
|
-
/** Capability name, e.g. `alarm-panel`. */
|
|
69043
|
-
cap: string().min(1),
|
|
69044
|
-
/** Method on it. The executor refuses a non-device-scoped cap. */
|
|
69045
|
-
method: string().min(1),
|
|
69046
|
-
/** Method arguments, minus `deviceId` (the executor injects it). */
|
|
69047
|
-
args: record(string(), unknown()).optional()
|
|
69048
|
-
}).refine((step) => step.target !== void 0 || step.deviceId !== void 0, {
|
|
69049
|
-
message: "a cap step needs a target",
|
|
69050
|
-
path: ["target"]
|
|
69051
|
-
}).refine((step) => step.target?.kind !== "domain" || step.actionId !== void 0, {
|
|
69052
|
-
message: "a domain target needs the vocabulary action it applies to (actionId)",
|
|
69053
|
-
path: ["actionId"]
|
|
69054
|
-
})]);
|
|
69055
|
-
/**
|
|
69056
|
-
* A named, ordered run of steps shared across rules, with its own throttle.
|
|
69057
|
-
*
|
|
69058
|
-
* Sequences live in the notification centre's sequence store — never inline on
|
|
69059
|
-
* a rule. A rule binds to one by id ({@link NcActionBindingSchema}), and a
|
|
69060
|
-
* button names one the same way. `minDelaySec` exists because a noisy rule
|
|
69061
|
-
* otherwise hammers a physical actuator — the rule's own cooldown governs
|
|
69062
|
-
* NOTIFICATIONS, which is a different budget from "how often may this gate
|
|
69063
|
-
* actually open". The throttle key is the sequence id, so two rules sharing
|
|
69064
|
-
* one sequence share its budget.
|
|
69065
|
-
*/
|
|
69066
|
-
var NcSharedSequenceSchema = object({
|
|
69067
|
-
id: string().min(1),
|
|
69068
|
-
name: string().min(1).max(120),
|
|
69069
|
-
minDelaySec: number$1().int().min(0).max(86400).optional(),
|
|
69070
|
-
actions: array(NcRuleActionSchema).min(1)
|
|
69071
|
-
});
|
|
69072
|
-
/** Create / update body — the id is minted by the provider. */
|
|
69073
|
-
var NcSharedSequenceInputSchema = object({
|
|
69074
|
-
name: string().min(1).max(120),
|
|
69075
|
-
minDelaySec: number$1().int().min(0).max(86400).optional(),
|
|
69076
|
-
actions: array(NcRuleActionSchema).min(1)
|
|
69077
|
-
});
|
|
69078
|
-
/** Bindings on one hook edge. Cap keeps a slot from becoming a second sequence editor. */
|
|
69079
|
-
var NcHookBindingsSchema = array(discriminatedUnion("kind", [object({
|
|
69080
|
-
kind: literal("sequence"),
|
|
69081
|
-
sequenceId: string().min(1)
|
|
69082
|
-
}), object({
|
|
69083
|
-
kind: literal("do"),
|
|
69084
|
-
action: NcRuleActionSchema
|
|
69085
|
-
})])).max(4);
|
|
69086
|
-
/**
|
|
69087
|
-
* One button carried by the notification, running a shared sequence on tap.
|
|
69350
|
+
* One button carried by the notification, running an Action on tap.
|
|
69088
69351
|
*
|
|
69089
69352
|
* **Read this before adding a button that does something physical.** The tap
|
|
69090
69353
|
* arrives over a link that travelled through third-party infrastructure — ntfy,
|
|
@@ -69099,9 +69362,9 @@ var NcRuleNotificationButtonSchema = object({
|
|
|
69099
69362
|
/** Stable id — travels in the callback and identifies the button in logs. */
|
|
69100
69363
|
id: string().min(1).max(64),
|
|
69101
69364
|
label: string().min(1).max(40),
|
|
69102
|
-
/**
|
|
69103
|
-
*
|
|
69104
|
-
|
|
69365
|
+
/** The Action the tap runs. The dispatcher drops a button whose Action does
|
|
69366
|
+
* not exist rather than minting a token for nothing. */
|
|
69367
|
+
actionId: NcActionIdSchema,
|
|
69105
69368
|
icon: NotificationActionIconSchema.optional(),
|
|
69106
69369
|
destructive: boolean().optional()
|
|
69107
69370
|
});
|
|
@@ -69116,25 +69379,19 @@ var NcRuleNotificationButtonSchema = object({
|
|
|
69116
69379
|
* leave). A delivery with no clear edge never produces this hook.
|
|
69117
69380
|
*/
|
|
69118
69381
|
var NcRuleActionsSchema = object({
|
|
69119
|
-
onActivation:
|
|
69120
|
-
onDeactivation:
|
|
69382
|
+
onActivation: NcHookActionIdsSchema.optional(),
|
|
69383
|
+
onDeactivation: NcHookActionIdsSchema.optional(),
|
|
69121
69384
|
/** Runs on a positive / raised match. */
|
|
69122
|
-
onTrigger:
|
|
69385
|
+
onTrigger: NcHookActionIdsSchema.optional(),
|
|
69123
69386
|
/** Runs on a clear / leave match, when the subject carries one. */
|
|
69124
|
-
onTriggerOff:
|
|
69387
|
+
onTriggerOff: NcHookActionIdsSchema.optional(),
|
|
69125
69388
|
/**
|
|
69126
|
-
* Buttons the NOTIFICATION carries, each running one
|
|
69127
|
-
*
|
|
69128
|
-
*
|
|
69389
|
+
* Buttons the NOTIFICATION carries, each running one Action when tapped.
|
|
69390
|
+
* Deliberately a REFERENCE — a button that could define its own steps would
|
|
69391
|
+
* be a parallel actuation vocabulary.
|
|
69129
69392
|
*/
|
|
69130
69393
|
buttons: array(NcRuleNotificationButtonSchema).max(8).optional()
|
|
69131
69394
|
});
|
|
69132
|
-
object({
|
|
69133
|
-
name: string().min(1).max(120),
|
|
69134
|
-
enabled: boolean(),
|
|
69135
|
-
minDelaySec: number$1().int().min(0).max(86400).optional(),
|
|
69136
|
-
actions: array(NcRuleActionSchema).min(1)
|
|
69137
|
-
});
|
|
69138
69395
|
/**
|
|
69139
69396
|
* "This rule applies only while `deviceId` is in one of `states`."
|
|
69140
69397
|
*
|
|
@@ -69433,6 +69690,26 @@ var NcRuleTargetSchema = object({
|
|
|
69433
69690
|
*/
|
|
69434
69691
|
params: record(string(), unknown()).optional()
|
|
69435
69692
|
});
|
|
69693
|
+
/** Which picture kind one target receives (#487). */
|
|
69694
|
+
var NcTargetAttachmentSchema = _enum([
|
|
69695
|
+
"none",
|
|
69696
|
+
"image",
|
|
69697
|
+
"clip",
|
|
69698
|
+
"gif"
|
|
69699
|
+
]);
|
|
69700
|
+
var NcTargetOverrideSchema = object({
|
|
69701
|
+
template: object({
|
|
69702
|
+
title: string().max(500).optional(),
|
|
69703
|
+
body: string().max(2e3).optional()
|
|
69704
|
+
}).optional(),
|
|
69705
|
+
schedule: NcScheduleSchema.optional(),
|
|
69706
|
+
priority: number$1().int().min(1).max(5).optional(),
|
|
69707
|
+
attachment: NcTargetAttachmentSchema.optional(),
|
|
69708
|
+
/** `false` = no buttons for this target; `true` is the same as absent. */
|
|
69709
|
+
actions: boolean().optional()
|
|
69710
|
+
});
|
|
69711
|
+
/** Per-target settings keyed by target id (#487). */
|
|
69712
|
+
var NcTargetOverridesSchema = record(string(), NcTargetOverrideSchema);
|
|
69436
69713
|
/**
|
|
69437
69714
|
* WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
|
|
69438
69715
|
*
|
|
@@ -69714,6 +69991,13 @@ var NcRuleInputSchema = object({
|
|
|
69714
69991
|
* targets.
|
|
69715
69992
|
*/
|
|
69716
69993
|
targetUsers: array(string()).optional(),
|
|
69994
|
+
/**
|
|
69995
|
+
* Per-target settings keyed by target id (#487): texts, schedule, priority.
|
|
69996
|
+
* Absent (and an absent entry) = the rule's own values. A patch that omits
|
|
69997
|
+
* the key keeps the stored map; a patch that names it REPLACES it whole —
|
|
69998
|
+
* `{}` empties it.
|
|
69999
|
+
*/
|
|
70000
|
+
targetOverrides: NcTargetOverridesSchema.optional(),
|
|
69717
70001
|
/** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
|
|
69718
70002
|
* detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
|
|
69719
70003
|
media: NcMediaPolicySchema.default({}),
|
|
@@ -70815,18 +71099,6 @@ method(object({}), object({ rules: array(NcRuleSchema) }), { auth: "admin" }), m
|
|
|
70815
71099
|
}), object({ success: literal(true) }), {
|
|
70816
71100
|
kind: "mutation",
|
|
70817
71101
|
auth: "admin"
|
|
70818
|
-
}), method(object({}), object({ sequences: array(NcSharedSequenceSchema) }), { auth: "admin" }), method(object({ sequenceId: string().min(1) }), object({ sequence: NcSharedSequenceSchema.nullable() }), { auth: "admin" }), method(object({ sequence: NcSharedSequenceInputSchema }), object({ sequence: NcSharedSequenceSchema }), {
|
|
70819
|
-
kind: "mutation",
|
|
70820
|
-
auth: "admin"
|
|
70821
|
-
}), method(object({
|
|
70822
|
-
sequenceId: string().min(1),
|
|
70823
|
-
sequence: NcSharedSequenceInputSchema
|
|
70824
|
-
}), object({ sequence: NcSharedSequenceSchema }), {
|
|
70825
|
-
kind: "mutation",
|
|
70826
|
-
auth: "admin"
|
|
70827
|
-
}), method(object({ sequenceId: string().min(1) }), object({ success: literal(true) }), {
|
|
70828
|
-
kind: "mutation",
|
|
70829
|
-
auth: "admin"
|
|
70830
71102
|
}), method(object({}), NcClipRetentionPlanSchema, { auth: "admin" }), method(object({}), object({ mutedDeviceIds: array(number$1().int()).readonly() }), { auth: "admin" }), method(object({
|
|
70831
71103
|
deviceId: number$1().int(),
|
|
70832
71104
|
muted: boolean()
|
|
@@ -71265,53 +71537,41 @@ DeviceType.Camera, method(object({
|
|
|
71265
71537
|
deviceId: number$1(),
|
|
71266
71538
|
status: OsdStatusSchema
|
|
71267
71539
|
});
|
|
71268
|
-
_enum([
|
|
71269
|
-
"value",
|
|
71270
|
-
"unit",
|
|
71271
|
-
"full"
|
|
71272
|
-
]);
|
|
71273
|
-
_enum([
|
|
71274
|
-
"value+unit",
|
|
71275
|
-
"value",
|
|
71276
|
-
"unit"
|
|
71277
|
-
]);
|
|
71278
71540
|
/**
|
|
71279
|
-
*
|
|
71280
|
-
*
|
|
71281
|
-
*
|
|
71541
|
+
* `osd-manager` — the ORCHESTRATOR over the device-scope `osd` cap.
|
|
71542
|
+
*
|
|
71543
|
+
* The `osd` cap is the firmware contract: it probes a camera's overlay
|
|
71544
|
+
* SLOTS and writes literal text into one. It has no idea WHERE that text
|
|
71545
|
+
* comes from, and it must not — a driver that grew a "show the temperature
|
|
71546
|
+
* here" feature would grow it once per vendor.
|
|
71547
|
+
*
|
|
71548
|
+
* This cap owns the other half: a per-(camera, slot) BINDING that says
|
|
71549
|
+
* which value feeds the slot, how it is formatted, and under which
|
|
71550
|
+
* conditions it is shown at all. Named TEMPLATES combine many device
|
|
71551
|
+
* fields into one overlay string (plugin catalog OSD Manager parity).
|
|
71282
71552
|
*/
|
|
71283
|
-
var OsdTemplatePickSchema = object({
|
|
71284
|
-
containerId: number$1().int().optional(),
|
|
71285
|
-
deviceId: number$1().int()
|
|
71286
|
-
});
|
|
71287
71553
|
/**
|
|
71288
|
-
*
|
|
71289
|
-
*
|
|
71290
|
-
* `{
|
|
71291
|
-
*
|
|
71554
|
+
* The text of a named template: a device template (D1021) —
|
|
71555
|
+
* `{{ camera.temperature | round(1) }}`, `{{ now | time('HH:mm') }}`,
|
|
71556
|
+
* `{% if camera.motion %}MOTION{% endif %}` — rendered by the ONE hub renderer
|
|
71557
|
+
* (`device-manager.renderDeviceTemplates`), never by this addon.
|
|
71558
|
+
*
|
|
71559
|
+
* Two names belong to the render rather than to a device:
|
|
71560
|
+
* - `now` is the clock; `time('HH:mm')` prints it in the server's zone.
|
|
71561
|
+
* - `camera` is the camera the overlay is on, so one template serves every
|
|
71562
|
+
* camera. `camera.lastPerson` and `camera.lastPlate` are the most recent
|
|
71563
|
+
* recognition persisted for it (empty text until there is one, with
|
|
71564
|
+
* `| default('')`).
|
|
71292
71565
|
*/
|
|
71293
|
-
var
|
|
71294
|
-
/** Token stem in the parser, e.g. `t` → `{t}` / `{t.value}`. Unique within the template. */
|
|
71295
|
-
alias: string().min(1).max(32).regex(/^[A-Za-z][A-Za-z0-9_-]*$/, "alias must start with a letter"),
|
|
71296
|
-
pick: OsdTemplatePickSchema,
|
|
71297
|
-
capName: string().min(1).max(64),
|
|
71298
|
-
valuePath: string().min(1).max(64),
|
|
71299
|
-
/** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
|
|
71300
|
-
displayUnit: string().max(16).optional(),
|
|
71301
|
-
maxDecimals: number$1().int().min(0).max(4).default(1),
|
|
71302
|
-
/** Raw value → display text (same shape as slot binding). Empty string hides. */
|
|
71303
|
-
valueMap: record(string(), string()).optional()
|
|
71304
|
-
});
|
|
71566
|
+
var OSD_TEMPLATE_TEXT_MAX = 1024;
|
|
71305
71567
|
/**
|
|
71306
|
-
* A named template:
|
|
71307
|
-
*
|
|
71568
|
+
* A named template: the unit of reuse. A slot points at one by id; editing it
|
|
71569
|
+
* changes every slot that points at it, on every camera.
|
|
71308
71570
|
*/
|
|
71309
71571
|
var OsdNamedTemplateSchema = object({
|
|
71310
71572
|
id: string().min(1).max(64),
|
|
71311
71573
|
name: string().min(1).max(64),
|
|
71312
|
-
|
|
71313
|
-
/** Parser with alias placeholders, e.g. `{t.value} {t.unit} / {h}`. */
|
|
71314
|
-
parser: string().max(256).default("")
|
|
71574
|
+
text: string().max(OSD_TEMPLATE_TEXT_MAX).default("")
|
|
71315
71575
|
});
|
|
71316
71576
|
/** Where a slot's value comes from. */
|
|
71317
71577
|
var OsdSourceSchema = discriminatedUnion("kind", [
|
|
@@ -71320,26 +71580,6 @@ var OsdSourceSchema = discriminatedUnion("kind", [
|
|
|
71320
71580
|
kind: literal("static"),
|
|
71321
71581
|
text: string().max(64)
|
|
71322
71582
|
}),
|
|
71323
|
-
object({
|
|
71324
|
-
kind: literal("clock"),
|
|
71325
|
-
/** Token pattern: `YYYY MM DD HH mm ss`. Everything else is literal. */
|
|
71326
|
-
pattern: string().min(1).max(32).default("HH:mm"),
|
|
71327
|
-
/** IANA zone. Omitted = the server's zone. */
|
|
71328
|
-
timezone: string().min(1).max(64).optional()
|
|
71329
|
-
}),
|
|
71330
|
-
object({
|
|
71331
|
-
kind: literal("device-state"),
|
|
71332
|
-
deviceId: number$1().int().optional(),
|
|
71333
|
-
capName: string().min(1).max(64),
|
|
71334
|
-
/** Dot path inside the slice, e.g. `detected`, `value`, `mode`. */
|
|
71335
|
-
valuePath: string().min(1).max(64),
|
|
71336
|
-
/** Convert TO this unit at render. Absent = no conversion. */
|
|
71337
|
-
displayUnit: string().max(16).optional()
|
|
71338
|
-
}),
|
|
71339
|
-
object({
|
|
71340
|
-
kind: literal("latest-recognition"),
|
|
71341
|
-
recognition: _enum(["person", "plate"])
|
|
71342
|
-
}),
|
|
71343
71583
|
object({
|
|
71344
71584
|
kind: literal("template"),
|
|
71345
71585
|
templateId: string().min(1).max(64)
|
|
@@ -71349,15 +71589,6 @@ var OsdSlotBindingSchema = object({
|
|
|
71349
71589
|
/** Off = the manager stops driving this slot. It does NOT clear it. */
|
|
71350
71590
|
enabled: boolean().default(true),
|
|
71351
71591
|
source: OsdSourceSchema,
|
|
71352
|
-
/** `${value}` and `${unit}` are substituted; every occurrence. */
|
|
71353
|
-
template: string().max(96).default("${value}"),
|
|
71354
|
-
/**
|
|
71355
|
-
* Decimal places for a numeric value. `0` yields an integer — the
|
|
71356
|
-
* documented workaround for firmwares that reject `.` in overlay text.
|
|
71357
|
-
*/
|
|
71358
|
-
maxDecimals: number$1().int().min(0).max(4).default(1),
|
|
71359
|
-
/** Raw value → display text, e.g. `{"true":"MOTION","false":""}`. */
|
|
71360
|
-
valueMap: record(string(), string()).optional(),
|
|
71361
71592
|
/** Time windows in which the slot is shown. Absent = always. */
|
|
71362
71593
|
schedule: NcScheduleSchema.optional(),
|
|
71363
71594
|
/**
|
|
@@ -71399,31 +71630,21 @@ var OsdRenderResultSchema = object({
|
|
|
71399
71630
|
/** Why, whenever the outcome is not a plain write. Never silent. */
|
|
71400
71631
|
reason: string().optional()
|
|
71401
71632
|
});
|
|
71402
|
-
var OsdSourceValueTypeEnum = _enum([
|
|
71403
|
-
"number",
|
|
71404
|
-
"boolean",
|
|
71405
|
-
"string",
|
|
71406
|
-
"enum"
|
|
71407
|
-
]);
|
|
71408
71633
|
/**
|
|
71409
|
-
*
|
|
71410
|
-
*
|
|
71411
|
-
*
|
|
71634
|
+
* A template rendered for one camera without being saved: what the editor
|
|
71635
|
+
* previews. `text` is what the overlay would carry; a refused render has a
|
|
71636
|
+
* `reason` and an empty text.
|
|
71412
71637
|
*/
|
|
71413
|
-
var
|
|
71414
|
-
|
|
71415
|
-
|
|
71416
|
-
|
|
71417
|
-
|
|
71418
|
-
label: string(),
|
|
71419
|
-
valueType: OsdSourceValueTypeEnum,
|
|
71420
|
-
/** Present for `enum`; the editor offers these as `valueMap` keys. */
|
|
71421
|
-
enumValues: array(string()).readonly().optional()
|
|
71638
|
+
var OsdTemplatePreviewSchema = object({
|
|
71639
|
+
ok: boolean(),
|
|
71640
|
+
text: string(),
|
|
71641
|
+
/** The refusal, or `ref: reason` per value that printed `—`. */
|
|
71642
|
+
notes: array(string())
|
|
71422
71643
|
});
|
|
71423
71644
|
method(object({ deviceId: number$1().int() }), object({
|
|
71424
71645
|
supported: boolean(),
|
|
71425
71646
|
slots: array(OsdSlotViewSchema)
|
|
71426
|
-
}), { auth: "admin" }), method(object({
|
|
71647
|
+
}), { auth: "admin" }), method(object({}), object({
|
|
71427
71648
|
supported: array(string()),
|
|
71428
71649
|
catalog: array(NcConditionDescriptorSchema)
|
|
71429
71650
|
}), { auth: "admin" }), method(object({
|
|
@@ -71465,6 +71686,12 @@ method(object({ deviceId: number$1().int() }), object({
|
|
|
71465
71686
|
}), OsdRenderResultSchema, {
|
|
71466
71687
|
kind: "mutation",
|
|
71467
71688
|
auth: "admin"
|
|
71689
|
+
}), method(object({
|
|
71690
|
+
deviceId: number$1().int(),
|
|
71691
|
+
text: string().max(OSD_TEMPLATE_TEXT_MAX)
|
|
71692
|
+
}), OsdTemplatePreviewSchema, {
|
|
71693
|
+
kind: "mutation",
|
|
71694
|
+
auth: "admin"
|
|
71468
71695
|
}), method(object({ deviceId: number$1().int() }), object({ results: array(OsdRenderResultSchema) }), {
|
|
71469
71696
|
kind: "mutation",
|
|
71470
71697
|
auth: "admin"
|
|
@@ -71670,9 +71897,13 @@ var petFeederCapability = {
|
|
|
71670
71897
|
*/
|
|
71671
71898
|
durability: "session",
|
|
71672
71899
|
/**
|
|
71673
|
-
* History (D850): recorded series.
|
|
71900
|
+
* History (D850): recorded series. `feeding` / `eating` are the meals the
|
|
71901
|
+
* device hero's "Meals" button names — change-only booleans, so a dispense
|
|
71902
|
+
* or a pet at the bowl is one span on the history.
|
|
71674
71903
|
*/
|
|
71675
71904
|
history: { fields: {
|
|
71905
|
+
feeding: { kind: "boolean" },
|
|
71906
|
+
eating: { kind: "boolean" },
|
|
71676
71907
|
foodLevel: { kind: "gauge" },
|
|
71677
71908
|
bowlFood: { kind: "gauge" },
|
|
71678
71909
|
food1: { kind: "gauge" },
|
|
@@ -73465,7 +73696,6 @@ var PowerSourceStateSchema = object({
|
|
|
73465
73696
|
});
|
|
73466
73697
|
var POWER_SOURCE_DEVICE_TYPES = [
|
|
73467
73698
|
DeviceType.Gateway,
|
|
73468
|
-
DeviceType.Hub,
|
|
73469
73699
|
DeviceType.Camera,
|
|
73470
73700
|
DeviceType.Sensor,
|
|
73471
73701
|
DeviceType.MediaPlayer,
|
|
@@ -73517,18 +73747,18 @@ var powerSourceCapability = {
|
|
|
73517
73747
|
mode: "singleton",
|
|
73518
73748
|
deviceTypes: POWER_SOURCE_DEVICE_TYPES,
|
|
73519
73749
|
methods: {
|
|
73520
|
-
getStatus: systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "
|
|
73750
|
+
getStatus: systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "protected" }),
|
|
73521
73751
|
powerOn: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73522
73752
|
kind: "mutation",
|
|
73523
|
-
auth: "
|
|
73753
|
+
auth: "protected"
|
|
73524
73754
|
}),
|
|
73525
73755
|
powerOff: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73526
73756
|
kind: "mutation",
|
|
73527
|
-
auth: "
|
|
73757
|
+
auth: "protected"
|
|
73528
73758
|
}),
|
|
73529
73759
|
forceRestart: systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
73530
73760
|
kind: "mutation",
|
|
73531
|
-
auth: "
|
|
73761
|
+
auth: "protected"
|
|
73532
73762
|
})
|
|
73533
73763
|
},
|
|
73534
73764
|
runtimeState: PowerSourceStateSchema,
|
|
@@ -81064,7 +81294,7 @@ var valveCapability = {
|
|
|
81064
81294
|
kind: "mutation",
|
|
81065
81295
|
auth: "protected"
|
|
81066
81296
|
}),
|
|
81067
|
-
setPosition:
|
|
81297
|
+
setPosition: optionalMethod(object({
|
|
81068
81298
|
deviceId: number$1().int().nonnegative(),
|
|
81069
81299
|
position: number$1().min(0).max(100)
|
|
81070
81300
|
}), _void(), {
|
|
@@ -83046,7 +83276,6 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
83046
83276
|
control: controlCapability,
|
|
83047
83277
|
cover: coverCapability,
|
|
83048
83278
|
dayNight: dayNightCapability,
|
|
83049
|
-
deviceDiscovery: deviceDiscoveryCapability,
|
|
83050
83279
|
deviceStatus: deviceStatusCapability,
|
|
83051
83280
|
dishwasher: dishwasherCapability,
|
|
83052
83281
|
doNotDisturb: doNotDisturbCapability,
|
|
@@ -88225,6 +88454,27 @@ Object.freeze({
|
|
|
88225
88454
|
access: "create",
|
|
88226
88455
|
role: "viewer"
|
|
88227
88456
|
},
|
|
88457
|
+
"clusterUpdate.getClusterUpdateJob": {
|
|
88458
|
+
capName: "cluster-update",
|
|
88459
|
+
capScope: "system",
|
|
88460
|
+
addonId: null,
|
|
88461
|
+
access: "view",
|
|
88462
|
+
role: "admin"
|
|
88463
|
+
},
|
|
88464
|
+
"clusterUpdate.previewClusterUpdate": {
|
|
88465
|
+
capName: "cluster-update",
|
|
88466
|
+
capScope: "system",
|
|
88467
|
+
addonId: null,
|
|
88468
|
+
access: "view",
|
|
88469
|
+
role: "admin"
|
|
88470
|
+
},
|
|
88471
|
+
"clusterUpdate.startClusterUpdate": {
|
|
88472
|
+
capName: "cluster-update",
|
|
88473
|
+
capScope: "system",
|
|
88474
|
+
addonId: null,
|
|
88475
|
+
access: "create",
|
|
88476
|
+
role: "admin"
|
|
88477
|
+
},
|
|
88228
88478
|
"color.getStatus": {
|
|
88229
88479
|
capName: "color",
|
|
88230
88480
|
capScope: "device",
|
|
@@ -88827,41 +89077,6 @@ Object.freeze({
|
|
|
88827
89077
|
access: "create",
|
|
88828
89078
|
role: "admin"
|
|
88829
89079
|
},
|
|
88830
|
-
"deviceDiscovery.adoptDevice": {
|
|
88831
|
-
capName: "device-discovery",
|
|
88832
|
-
capScope: "device",
|
|
88833
|
-
addonId: null,
|
|
88834
|
-
access: "create",
|
|
88835
|
-
role: "admin"
|
|
88836
|
-
},
|
|
88837
|
-
"deviceDiscovery.getStatus": {
|
|
88838
|
-
capName: "device-discovery",
|
|
88839
|
-
capScope: "device",
|
|
88840
|
-
addonId: null,
|
|
88841
|
-
access: "view",
|
|
88842
|
-
role: "viewer"
|
|
88843
|
-
},
|
|
88844
|
-
"deviceDiscovery.listDiscovered": {
|
|
88845
|
-
capName: "device-discovery",
|
|
88846
|
-
capScope: "device",
|
|
88847
|
-
addonId: null,
|
|
88848
|
-
access: "view",
|
|
88849
|
-
role: "viewer"
|
|
88850
|
-
},
|
|
88851
|
-
"deviceDiscovery.refreshDiscovery": {
|
|
88852
|
-
capName: "device-discovery",
|
|
88853
|
-
capScope: "device",
|
|
88854
|
-
addonId: null,
|
|
88855
|
-
access: "create",
|
|
88856
|
-
role: "admin"
|
|
88857
|
-
},
|
|
88858
|
-
"deviceDiscovery.releaseDevice": {
|
|
88859
|
-
capName: "device-discovery",
|
|
88860
|
-
capScope: "device",
|
|
88861
|
-
addonId: null,
|
|
88862
|
-
access: "create",
|
|
88863
|
-
role: "admin"
|
|
88864
|
-
},
|
|
88865
89080
|
"deviceExport.applyDeviceSettingsPatch": {
|
|
88866
89081
|
capName: "device-export",
|
|
88867
89082
|
capScope: "system",
|
|
@@ -89597,6 +89812,13 @@ Object.freeze({
|
|
|
89597
89812
|
access: "create",
|
|
89598
89813
|
role: "admin"
|
|
89599
89814
|
},
|
|
89815
|
+
"deviceManager.search": {
|
|
89816
|
+
capName: "device-manager",
|
|
89817
|
+
capScope: "system",
|
|
89818
|
+
addonId: null,
|
|
89819
|
+
access: "view",
|
|
89820
|
+
role: "viewer"
|
|
89821
|
+
},
|
|
89600
89822
|
"deviceManager.setAlias": {
|
|
89601
89823
|
capName: "device-manager",
|
|
89602
89824
|
capScope: "system",
|
|
@@ -89688,6 +89910,13 @@ Object.freeze({
|
|
|
89688
89910
|
access: "create",
|
|
89689
89911
|
role: "admin"
|
|
89690
89912
|
},
|
|
89913
|
+
"deviceManager.setPrimaryChildPreference": {
|
|
89914
|
+
capName: "device-manager",
|
|
89915
|
+
capScope: "system",
|
|
89916
|
+
addonId: null,
|
|
89917
|
+
access: "create",
|
|
89918
|
+
role: "admin"
|
|
89919
|
+
},
|
|
89691
89920
|
"deviceManager.setRole": {
|
|
89692
89921
|
capName: "device-manager",
|
|
89693
89922
|
capScope: "system",
|
|
@@ -92369,13 +92598,6 @@ Object.freeze({
|
|
|
92369
92598
|
access: "create",
|
|
92370
92599
|
role: "admin"
|
|
92371
92600
|
},
|
|
92372
|
-
"notificationRules.createSequence": {
|
|
92373
|
-
capName: "notification-rules",
|
|
92374
|
-
capScope: "system",
|
|
92375
|
-
addonId: null,
|
|
92376
|
-
access: "create",
|
|
92377
|
-
role: "admin"
|
|
92378
|
-
},
|
|
92379
92601
|
"notificationRules.createSnooze": {
|
|
92380
92602
|
capName: "notification-rules",
|
|
92381
92603
|
capScope: "system",
|
|
@@ -92397,13 +92619,6 @@ Object.freeze({
|
|
|
92397
92619
|
access: "delete",
|
|
92398
92620
|
role: "admin"
|
|
92399
92621
|
},
|
|
92400
|
-
"notificationRules.deleteSequence": {
|
|
92401
|
-
capName: "notification-rules",
|
|
92402
|
-
capScope: "system",
|
|
92403
|
-
addonId: null,
|
|
92404
|
-
access: "delete",
|
|
92405
|
-
role: "admin"
|
|
92406
|
-
},
|
|
92407
92622
|
"notificationRules.getAlarmConfig": {
|
|
92408
92623
|
capName: "notification-rules",
|
|
92409
92624
|
capScope: "system",
|
|
@@ -92453,13 +92668,6 @@ Object.freeze({
|
|
|
92453
92668
|
access: "view",
|
|
92454
92669
|
role: "admin"
|
|
92455
92670
|
},
|
|
92456
|
-
"notificationRules.getSequence": {
|
|
92457
|
-
capName: "notification-rules",
|
|
92458
|
-
capScope: "system",
|
|
92459
|
-
addonId: null,
|
|
92460
|
-
access: "view",
|
|
92461
|
-
role: "admin"
|
|
92462
|
-
},
|
|
92463
92671
|
"notificationRules.getTemplateCatalog": {
|
|
92464
92672
|
capName: "notification-rules",
|
|
92465
92673
|
capScope: "system",
|
|
@@ -92481,13 +92689,6 @@ Object.freeze({
|
|
|
92481
92689
|
access: "view",
|
|
92482
92690
|
role: "admin"
|
|
92483
92691
|
},
|
|
92484
|
-
"notificationRules.listSequences": {
|
|
92485
|
-
capName: "notification-rules",
|
|
92486
|
-
capScope: "system",
|
|
92487
|
-
addonId: null,
|
|
92488
|
-
access: "view",
|
|
92489
|
-
role: "admin"
|
|
92490
|
-
},
|
|
92491
92692
|
"notificationRules.listSnoozes": {
|
|
92492
92693
|
capName: "notification-rules",
|
|
92493
92694
|
capScope: "system",
|
|
@@ -92558,13 +92759,6 @@ Object.freeze({
|
|
|
92558
92759
|
access: "create",
|
|
92559
92760
|
role: "admin"
|
|
92560
92761
|
},
|
|
92561
|
-
"notificationRules.updateSequence": {
|
|
92562
|
-
capName: "notification-rules",
|
|
92563
|
-
capScope: "system",
|
|
92564
|
-
addonId: null,
|
|
92565
|
-
access: "create",
|
|
92566
|
-
role: "admin"
|
|
92567
|
-
},
|
|
92568
92762
|
"notifier.cancel": {
|
|
92569
92763
|
capName: "notifier",
|
|
92570
92764
|
capScope: "device",
|
|
@@ -92649,21 +92843,21 @@ Object.freeze({
|
|
|
92649
92843
|
access: "view",
|
|
92650
92844
|
role: "admin"
|
|
92651
92845
|
},
|
|
92652
|
-
"osdManager.
|
|
92846
|
+
"osdManager.listTemplates": {
|
|
92653
92847
|
capName: "osd-manager",
|
|
92654
92848
|
capScope: "system",
|
|
92655
92849
|
addonId: null,
|
|
92656
92850
|
access: "view",
|
|
92657
92851
|
role: "admin"
|
|
92658
92852
|
},
|
|
92659
|
-
"osdManager.
|
|
92853
|
+
"osdManager.previewSlot": {
|
|
92660
92854
|
capName: "osd-manager",
|
|
92661
92855
|
capScope: "system",
|
|
92662
92856
|
addonId: null,
|
|
92663
|
-
access: "
|
|
92857
|
+
access: "create",
|
|
92664
92858
|
role: "admin"
|
|
92665
92859
|
},
|
|
92666
|
-
"osdManager.
|
|
92860
|
+
"osdManager.previewTemplate": {
|
|
92667
92861
|
capName: "osd-manager",
|
|
92668
92862
|
capScope: "system",
|
|
92669
92863
|
addonId: null,
|
|
@@ -94362,28 +94556,28 @@ Object.freeze({
|
|
|
94362
94556
|
capScope: "device",
|
|
94363
94557
|
addonId: null,
|
|
94364
94558
|
access: "create",
|
|
94365
|
-
role: "
|
|
94559
|
+
role: "viewer"
|
|
94366
94560
|
},
|
|
94367
94561
|
"powerSource.getStatus": {
|
|
94368
94562
|
capName: "power-source",
|
|
94369
94563
|
capScope: "device",
|
|
94370
94564
|
addonId: null,
|
|
94371
94565
|
access: "view",
|
|
94372
|
-
role: "
|
|
94566
|
+
role: "viewer"
|
|
94373
94567
|
},
|
|
94374
94568
|
"powerSource.powerOff": {
|
|
94375
94569
|
capName: "power-source",
|
|
94376
94570
|
capScope: "device",
|
|
94377
94571
|
addonId: null,
|
|
94378
94572
|
access: "create",
|
|
94379
|
-
role: "
|
|
94573
|
+
role: "viewer"
|
|
94380
94574
|
},
|
|
94381
94575
|
"powerSource.powerOn": {
|
|
94382
94576
|
capName: "power-source",
|
|
94383
94577
|
capScope: "device",
|
|
94384
94578
|
addonId: null,
|
|
94385
94579
|
access: "create",
|
|
94386
|
-
role: "
|
|
94580
|
+
role: "viewer"
|
|
94387
94581
|
},
|
|
94388
94582
|
"presence.getStatus": {
|
|
94389
94583
|
capName: "presence",
|
|
@@ -97453,6 +97647,24 @@ function projectAction(cap, action) {
|
|
|
97453
97647
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
97454
97648
|
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.HeatPump, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Heater, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway;
|
|
97455
97649
|
DeviceFeature.BatteryOperated;
|
|
97650
|
+
function bound(cap, methods = [], authority = "reported") {
|
|
97651
|
+
return {
|
|
97652
|
+
kind: "cap",
|
|
97653
|
+
cap,
|
|
97654
|
+
methods,
|
|
97655
|
+
authority
|
|
97656
|
+
};
|
|
97657
|
+
}
|
|
97658
|
+
function derived(cap, methods = []) {
|
|
97659
|
+
return bound(cap, methods, "derived");
|
|
97660
|
+
}
|
|
97661
|
+
DeviceFeature.BatteryOperated, DeviceFeature.Rebootable, derived("reboot", ["reboot"]), DeviceFeature.Resyncable, DeviceFeature.NativeSnapshot, DeviceFeature.DoorbellButton, derived("doorbell"), DeviceFeature.TwoWayAudio, derived("intercom", [
|
|
97662
|
+
"startTalkSession",
|
|
97663
|
+
"pushTalkAudio",
|
|
97664
|
+
"endTalkSession"
|
|
97665
|
+
]), DeviceFeature.PanTiltZoom, derived("ptz"), DeviceFeature.PtzAutotrack, derived("ptz-autotrack"), DeviceFeature.MotionTrigger, derived("motion-trigger", ["setMotionTrigger"]), DeviceFeature.TimedRun, derived("timed-run", ["runFor"]), DeviceFeature.Switch, DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired, DeviceFeature.ClimateDualSetpoint, DeviceFeature.ClimateHumidity, DeviceFeature.ClimateFanMode, DeviceFeature.ClimatePreset, DeviceFeature.ClimateSwingVertical, DeviceFeature.ClimateSwingHorizontal, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.CoverStoppable, DeviceFeature.ValvePositionable, DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.LockPinRequired, DeviceFeature.LockOpen, DeviceFeature.MediaPlayerSeek, DeviceFeature.MediaPlayerVolume, DeviceFeature.MediaPlayerMute, DeviceFeature.MediaPlayerShuffle, DeviceFeature.MediaPlayerRepeat, DeviceFeature.MediaPlayerSelectSource, DeviceFeature.MediaPlayerPlayMedia, DeviceFeature.MediaPlayerNext, DeviceFeature.MediaPlayerPrevious, DeviceFeature.MediaPlayerStop, DeviceFeature.MediaPlayerVolumeStep, DeviceFeature.MediaPlayerChannelStep, DeviceFeature.MediaPlayerPower, DeviceFeature.AlarmPinRequired, DeviceFeature.PresenceGps, DeviceFeature.NotifierImage, DeviceFeature.NotifierPriority, DeviceFeature.NotifierData, DeviceFeature.NotifierActions, DeviceFeature.NotifierRecipients, DeviceFeature.ScriptVariables, DeviceFeature.AutomationSkipCondition, DeviceFeature.VacuumHasMap, DeviceFeature.VacuumHasAi, DeviceFeature.MowerHasMap, DeviceFeature.MowerHasTargetedMowing, DeviceFeature.Navigation, derived("navigation"), DeviceFeature.NetworkLink, derived("network-link");
|
|
97666
|
+
var ALL_FEATURES = Object.values(DeviceFeature);
|
|
97667
|
+
new Set(ALL_FEATURES);
|
|
97456
97668
|
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
97457
97669
|
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|
|
97458
97670
|
var HOMEKIT_REASON = "HomeKit has no laundry-appliance service. The export tab would pair an accessory with nothing on it: running-state is withheld until a null reading can be unavailable, and power is not a HomeKit service this export honours.";
|
|
@@ -97922,35 +98134,6 @@ Object.freeze({
|
|
|
97922
98134
|
form: "single",
|
|
97923
98135
|
optional: false
|
|
97924
98136
|
}],
|
|
97925
|
-
"deviceDiscovery.adoptDevice": [{
|
|
97926
|
-
name: "deviceId",
|
|
97927
|
-
form: "single",
|
|
97928
|
-
optional: false
|
|
97929
|
-
}],
|
|
97930
|
-
"deviceDiscovery.getStatus": [{
|
|
97931
|
-
name: "deviceId",
|
|
97932
|
-
form: "single",
|
|
97933
|
-
optional: false
|
|
97934
|
-
}],
|
|
97935
|
-
"deviceDiscovery.listDiscovered": [{
|
|
97936
|
-
name: "deviceId",
|
|
97937
|
-
form: "single",
|
|
97938
|
-
optional: false
|
|
97939
|
-
}],
|
|
97940
|
-
"deviceDiscovery.refreshDiscovery": [{
|
|
97941
|
-
name: "deviceId",
|
|
97942
|
-
form: "single",
|
|
97943
|
-
optional: false
|
|
97944
|
-
}],
|
|
97945
|
-
"deviceDiscovery.releaseDevice": [{
|
|
97946
|
-
name: "childDeviceId",
|
|
97947
|
-
form: "single",
|
|
97948
|
-
optional: false
|
|
97949
|
-
}, {
|
|
97950
|
-
name: "deviceId",
|
|
97951
|
-
form: "single",
|
|
97952
|
-
optional: false
|
|
97953
|
-
}],
|
|
97954
98137
|
"deviceExport.applyDeviceSettingsPatch": [{
|
|
97955
98138
|
name: "deviceId",
|
|
97956
98139
|
form: "single",
|
|
@@ -98229,6 +98412,11 @@ Object.freeze({
|
|
|
98229
98412
|
form: "single",
|
|
98230
98413
|
optional: false
|
|
98231
98414
|
}],
|
|
98415
|
+
"deviceManager.setPrimaryChildPreference": [{
|
|
98416
|
+
name: "deviceId",
|
|
98417
|
+
form: "single",
|
|
98418
|
+
optional: false
|
|
98419
|
+
}],
|
|
98232
98420
|
"deviceManager.setRole": [{
|
|
98233
98421
|
name: "deviceId",
|
|
98234
98422
|
form: "single",
|
|
@@ -99108,12 +99296,12 @@ Object.freeze({
|
|
|
99108
99296
|
form: "single",
|
|
99109
99297
|
optional: false
|
|
99110
99298
|
}],
|
|
99111
|
-
"osdManager.
|
|
99299
|
+
"osdManager.previewSlot": [{
|
|
99112
99300
|
name: "deviceId",
|
|
99113
99301
|
form: "single",
|
|
99114
99302
|
optional: false
|
|
99115
99303
|
}],
|
|
99116
|
-
"osdManager.
|
|
99304
|
+
"osdManager.previewTemplate": [{
|
|
99117
99305
|
name: "deviceId",
|
|
99118
99306
|
form: "single",
|
|
99119
99307
|
optional: false
|
|
@@ -101697,7 +101885,9 @@ var TimelapseRuleInputSchema = object({
|
|
|
101697
101885
|
/** Classes the notification counts — see {@link ReportClassesField}. */
|
|
101698
101886
|
reportClasses: ReportClassesField.optional(),
|
|
101699
101887
|
/** Canonical notification priority ordinal (1..5); per-target overridable. */
|
|
101700
|
-
priority: PriorityField.default(3)
|
|
101888
|
+
priority: PriorityField.default(3),
|
|
101889
|
+
/** Per-target settings keyed by target id (D1032) — absent = every target follows the rule. */
|
|
101890
|
+
targetOverrides: NcTargetOverridesSchema.optional()
|
|
101701
101891
|
});
|
|
101702
101892
|
object({
|
|
101703
101893
|
name: NameField.optional(),
|
|
@@ -101713,7 +101903,9 @@ object({
|
|
|
101713
101903
|
previewText: PreviewTextField.optional(),
|
|
101714
101904
|
previewMode: PreviewModeField.optional(),
|
|
101715
101905
|
reportClasses: ReportClassesField.optional(),
|
|
101716
|
-
priority: PriorityField.optional()
|
|
101906
|
+
priority: PriorityField.optional(),
|
|
101907
|
+
/** Per-target settings keyed by target id (D1032) — absent = every target follows the rule. */
|
|
101908
|
+
targetOverrides: NcTargetOverridesSchema.optional()
|
|
101717
101909
|
});
|
|
101718
101910
|
TimelapseRuleInputSchema.extend({
|
|
101719
101911
|
id: string(),
|