@camstack/addon-provider-homeassistant 1.2.632 → 1.2.634

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.
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-CT-hz5Rb.mjs
1
+ //#region ../types/dist/event-category-DmZDPDf_.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -625,7 +625,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
625
625
  * (a track was promoted to a stationary-registry entry) or departs (the
626
626
  * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
627
627
  * the dedicated "Stationary" section — never the live event feed. Payload:
628
- * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
628
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
629
629
  */
630
630
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
631
631
  /**
@@ -763,6 +763,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
763
763
  */
764
764
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
765
765
  /**
766
+ * An action run started or ended. Emitted by the `actions` surface.
767
+ * Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
768
+ */
769
+ EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
770
+ /**
766
771
  * Progress update from a running model conversion job.
767
772
  * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
768
773
  * Emitted by `addon-model-studio` on the converting node.
@@ -5574,7 +5579,7 @@ var ZodIssueCode = {
5574
5579
  var ZodFirstPartyTypeKind;
5575
5580
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5576
5581
  //#endregion
5577
- //#region ../types/dist/sleep--jXS9hWo.mjs
5582
+ //#region ../types/dist/sleep-Crlmu_tO.mjs
5578
5583
  /**
5579
5584
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5580
5585
  * window to float samples (D455).
@@ -8944,6 +8949,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
8944
8949
  /** Every capability name, so addon code can check a name without the schema graph. */
8945
8950
  var CAP_NAMES = Object.freeze([
8946
8951
  "accessories",
8952
+ "action-source",
8953
+ "actions",
8947
8954
  "addon-pages",
8948
8955
  "addon-pages-source",
8949
8956
  "addon-routes",
@@ -9132,11 +9139,11 @@ var CAP_NAMES = Object.freeze([
9132
9139
  Object.freeze({
9133
9140
  "air-quality-sensor": [
9134
9141
  {
9135
- "path": "co2Ppm",
9142
+ "path": "co2",
9136
9143
  "valueType": "number"
9137
9144
  },
9138
9145
  {
9139
- "path": "vocPpb",
9146
+ "path": "voc",
9140
9147
  "valueType": "number"
9141
9148
  },
9142
9149
  {
@@ -9186,7 +9193,7 @@ Object.freeze({
9186
9193
  }
9187
9194
  ],
9188
9195
  "ambient-light-sensor": [{
9189
- "path": "lux",
9196
+ "path": "illuminance",
9190
9197
  "valueType": "number"
9191
9198
  }],
9192
9199
  "audio-metrics": [
@@ -9247,7 +9254,7 @@ Object.freeze({
9247
9254
  ],
9248
9255
  "battery": [
9249
9256
  {
9250
- "path": "percentage",
9257
+ "path": "level",
9251
9258
  "valueType": "number"
9252
9259
  },
9253
9260
  {
@@ -9269,7 +9276,7 @@ Object.freeze({
9269
9276
  "valueType": "number"
9270
9277
  },
9271
9278
  {
9272
- "path": "volts",
9279
+ "path": "voltage",
9273
9280
  "valueType": "number"
9274
9281
  },
9275
9282
  {
@@ -9290,7 +9297,7 @@ Object.freeze({
9290
9297
  "valueType": "boolean"
9291
9298
  }],
9292
9299
  "brightness": [{
9293
- "path": "percentage",
9300
+ "path": "level",
9294
9301
  "valueType": "number"
9295
9302
  }],
9296
9303
  "broker": [{
@@ -9491,7 +9498,7 @@ Object.freeze({
9491
9498
  "valueType": "number"
9492
9499
  },
9493
9500
  {
9494
- "path": "mireds",
9501
+ "path": "colorTemperature",
9495
9502
  "valueType": "number"
9496
9503
  }
9497
9504
  ],
@@ -9670,15 +9677,15 @@ Object.freeze({
9670
9677
  "valueType": "string"
9671
9678
  },
9672
9679
  {
9673
- "path": "remainingSeconds",
9680
+ "path": "remaining",
9674
9681
  "valueType": "number"
9675
9682
  },
9676
9683
  {
9677
- "path": "delayedStartSeconds",
9684
+ "path": "delayedStart",
9678
9685
  "valueType": "number"
9679
9686
  },
9680
9687
  {
9681
- "path": "progressPercent",
9688
+ "path": "progress",
9682
9689
  "valueType": "number"
9683
9690
  },
9684
9691
  {
@@ -9792,7 +9799,7 @@ Object.freeze({
9792
9799
  ],
9793
9800
  "fan-control": [
9794
9801
  {
9795
- "path": "percentage",
9802
+ "path": "speed",
9796
9803
  "valueType": "number"
9797
9804
  },
9798
9805
  {
@@ -9892,7 +9899,7 @@ Object.freeze({
9892
9899
  }
9893
9900
  ],
9894
9901
  "humidity-sensor": [{
9895
- "path": "percent",
9902
+ "path": "humidity",
9896
9903
  "valueType": "number"
9897
9904
  }],
9898
9905
  "image": [{
@@ -10002,7 +10009,7 @@ Object.freeze({
10002
10009
  "valueType": "number"
10003
10010
  },
10004
10011
  {
10005
- "path": "progressPercent",
10012
+ "path": "progress",
10006
10013
  "valueType": "number"
10007
10014
  },
10008
10015
  {
@@ -10081,11 +10088,11 @@ Object.freeze({
10081
10088
  "valueType": "string"
10082
10089
  },
10083
10090
  {
10084
- "path": "positionMs",
10091
+ "path": "position",
10085
10092
  "valueType": "number"
10086
10093
  },
10087
10094
  {
10088
- "path": "durationMs",
10095
+ "path": "duration",
10089
10096
  "valueType": "number"
10090
10097
  },
10091
10098
  {
@@ -10187,11 +10194,11 @@ Object.freeze({
10187
10194
  ]
10188
10195
  },
10189
10196
  {
10190
- "path": "signalPercent",
10197
+ "path": "signal",
10191
10198
  "valueType": "number"
10192
10199
  },
10193
10200
  {
10194
- "path": "rssiDbm",
10201
+ "path": "rssi",
10195
10202
  "valueType": "number"
10196
10203
  },
10197
10204
  {
@@ -10246,6 +10253,18 @@ Object.freeze({
10246
10253
  "path": "foodLevel",
10247
10254
  "valueType": "number"
10248
10255
  },
10256
+ {
10257
+ "path": "bowlFood",
10258
+ "valueType": "number"
10259
+ },
10260
+ {
10261
+ "path": "eating",
10262
+ "valueType": "boolean"
10263
+ },
10264
+ {
10265
+ "path": "supportsMarkRefilled",
10266
+ "valueType": "boolean"
10267
+ },
10249
10268
  {
10250
10269
  "path": "food1",
10251
10270
  "valueType": "number"
@@ -10310,23 +10329,23 @@ Object.freeze({
10310
10329
  ],
10311
10330
  "power-meter": [
10312
10331
  {
10313
- "path": "watts",
10332
+ "path": "power",
10314
10333
  "valueType": "number"
10315
10334
  },
10316
10335
  {
10317
- "path": "kwhTotal",
10336
+ "path": "energy",
10318
10337
  "valueType": "number"
10319
10338
  },
10320
10339
  {
10321
- "path": "volts",
10340
+ "path": "voltage",
10322
10341
  "valueType": "number"
10323
10342
  },
10324
10343
  {
10325
- "path": "amps",
10344
+ "path": "current",
10326
10345
  "valueType": "number"
10327
10346
  },
10328
10347
  {
10329
- "path": "va",
10348
+ "path": "apparentPower",
10330
10349
  "valueType": "number"
10331
10350
  },
10332
10351
  {
@@ -10354,14 +10373,10 @@ Object.freeze({
10354
10373
  {
10355
10374
  "path": "gps.accuracyMeters",
10356
10375
  "valueType": "number"
10357
- },
10358
- {
10359
- "path": "batteryPercent",
10360
- "valueType": "number"
10361
10376
  }
10362
10377
  ],
10363
10378
  "pressure-sensor": [{
10364
- "path": "hpa",
10379
+ "path": "pressure",
10365
10380
  "valueType": "number"
10366
10381
  }],
10367
10382
  "privacy-mask": [{
@@ -10675,7 +10690,7 @@ Object.freeze({
10675
10690
  "valueType": "boolean"
10676
10691
  }],
10677
10692
  "temperature-sensor": [{
10678
- "path": "celsius",
10693
+ "path": "temperature",
10679
10694
  "valueType": "number"
10680
10695
  }],
10681
10696
  "update": [
@@ -10723,7 +10738,7 @@ Object.freeze({
10723
10738
  "valueType": "string"
10724
10739
  },
10725
10740
  {
10726
- "path": "progressPercent",
10741
+ "path": "progress",
10727
10742
  "valueType": "number"
10728
10743
  },
10729
10744
  {
@@ -11208,7 +11223,7 @@ function errMsg(err) {
11208
11223
  return String(err);
11209
11224
  }
11210
11225
  //#endregion
11211
- //#region ../types/dist/composition-Bb8iwHEJ.mjs
11226
+ //#region ../types/dist/composition-CZImLpOI.mjs
11212
11227
  /**
11213
11228
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11214
11229
  *
@@ -15872,6 +15887,14 @@ var AutomationConditionLeafSchema = object({
15872
15887
  array(union([string(), number()]))
15873
15888
  ])
15874
15889
  });
15890
+ var AutomationConditionStationaryPresentSchema = object({
15891
+ kind: literal("stationary-present"),
15892
+ deviceId: number().int().nonnegative(),
15893
+ /** Class names; a macro class matches every raw class that maps to it. */
15894
+ classes: array(string().min(1)).min(1).optional(),
15895
+ /** The parked object must be in at least one of these zones. */
15896
+ zones: array(string().min(1)).min(1).optional()
15897
+ });
15875
15898
  /**
15876
15899
  * The expression leaf, declared as a plain object rather than an intersection
15877
15900
  * with {@link ExpressionSourceSchema}: a discriminated union has to be able to
@@ -15905,7 +15928,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
15905
15928
  child: AutomationConditionSchema
15906
15929
  }),
15907
15930
  AutomationConditionLeafSchema,
15908
- AutomationConditionExpressionSchema
15931
+ AutomationConditionExpressionSchema,
15932
+ AutomationConditionStationaryPresentSchema
15909
15933
  ]));
15910
15934
  /**
15911
15935
  * What starts a run.
@@ -15946,7 +15970,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15946
15970
  kind: literal("schedule"),
15947
15971
  cron: string().min(1).max(120)
15948
15972
  }),
15949
- object({ kind: literal("manual") })
15973
+ object({ kind: literal("manual") }),
15974
+ object({
15975
+ kind: literal("detection"),
15976
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15977
+ * matches every raw class that maps to it; any other name matches
15978
+ * exactly. */
15979
+ classes: array(string().min(1)).min(1),
15980
+ deviceIds: array(number().int().nonnegative()).min(1),
15981
+ /** The track must have visited at least one of these zones. */
15982
+ zones: array(string().min(1)).min(1).optional(),
15983
+ /** Best-so-far confidence the track must reach. */
15984
+ minScore: number().min(0).max(1).optional()
15985
+ }),
15986
+ object({
15987
+ kind: literal("stationary"),
15988
+ deviceIds: array(number().int().nonnegative()).min(1),
15989
+ /** Class names; a macro class matches like the detection trigger. */
15990
+ classes: array(string().min(1)).min(1).optional(),
15991
+ /** The parked object must be in at least one of these zones. */
15992
+ zones: array(string().min(1)).min(1).optional(),
15993
+ /** `appeared`: it became parked. `departed`: the registry retired it.
15994
+ * The vocabulary of `PipelineAnalyticsStationaryChanged`. */
15995
+ phase: _enum(["appeared", "departed"])
15996
+ }),
15997
+ object({
15998
+ kind: literal("interval"),
15999
+ minutes: number().int().min(1).max(1440)
16000
+ })
15950
16001
  ]);
15951
16002
  /**
15952
16003
  * One action step.
@@ -15966,28 +16017,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15966
16017
  * is called. The runner still receives a number and is untouched; the
15967
16018
  * resolution is the recipe's job, not the runner's.
15968
16019
  */
16020
+ var AutomationWaitStepSchema = object({
16021
+ kind: literal("wait"),
16022
+ seconds: number().min(0).max(300)
16023
+ });
16024
+ var AutomationCapStepSchema = object({
16025
+ kind: literal("cap"),
16026
+ /**
16027
+ * One device, several same-family devices (locks / climate family / …),
16028
+ * or `{ $var }` for the device that triggered the run. An array is
16029
+ * fan-out at codegen — each id gets the same cap.method call.
16030
+ */
16031
+ deviceId: union([
16032
+ number().int(),
16033
+ array(number().int()).min(1),
16034
+ object({ $var: string().min(1) })
16035
+ ]),
16036
+ cap: string().min(1),
16037
+ method: string().min(1),
16038
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16039
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16040
+ * the expression leaf. */
16041
+ args: record(string(), unknown()).optional()
16042
+ });
16043
+ /**
16044
+ * The steps an internal Action may contain: cap and wait, and nothing that can
16045
+ * call back into an Action — so an Action can never reach itself (no cycles).
16046
+ */
16047
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15969
16048
  var AutomationActionSchema = discriminatedUnion("kind", [
16049
+ AutomationWaitStepSchema,
16050
+ AutomationCapStepSchema,
15970
16051
  object({
15971
- kind: literal("wait"),
15972
- seconds: number().min(0).max(300)
15973
- }),
15974
- object({
15975
- kind: literal("cap"),
15976
- /**
15977
- * One device, several same-family devices (locks / climate family / …),
15978
- * or `{ $var }` for the device that triggered the run. An array is
15979
- * fan-out at codegen — each id gets the same cap.method call.
15980
- */
15981
- deviceId: union([
15982
- number().int(),
15983
- array(number().int()).min(1),
15984
- object({ $var: string().min(1) })
15985
- ]),
15986
- cap: string().min(1),
15987
- method: string().min(1),
15988
- /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
15989
- * evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
15990
- args: record(string(), unknown()).optional()
16052
+ kind: literal("action"),
16053
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
16054
+ actionId: string().min(1),
16055
+ /** Values for the action's declared variables; the others take their default. */
16056
+ variables: record(string(), union([
16057
+ string(),
16058
+ number(),
16059
+ boolean()
16060
+ ])).optional()
15991
16061
  }),
15992
16062
  object({
15993
16063
  kind: literal("code"),
@@ -15996,10 +16066,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15996
16066
  code: string().min(1).max(2e4)
15997
16067
  })
15998
16068
  ]);
16069
+ /**
16070
+ * How a trigger that arrives while the automation is busy (or cooling down) is
16071
+ * handled. One of the automation's execution modes, never a property of its
16072
+ * actions. Absent means `single`.
16073
+ *
16074
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
16075
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
16076
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
16077
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
16078
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
16079
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
16080
+ * wait, never the single/queued limits.
16081
+ */
16082
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
16083
+ object({ mode: literal("single") }),
16084
+ object({ mode: literal("restart") }),
16085
+ object({
16086
+ mode: literal("queued"),
16087
+ max: number().int().min(1).max(10)
16088
+ }),
16089
+ object({
16090
+ mode: literal("parallel"),
16091
+ max: number().int().min(1).max(10)
16092
+ }),
16093
+ object({
16094
+ mode: literal("cooldown"),
16095
+ minutes: number().int().min(1).max(1440)
16096
+ })
16097
+ ]);
15999
16098
  var AutomationRecipeSchema = object({
16000
16099
  triggers: array(AutomationTriggerSchema),
16001
16100
  conditions: AutomationConditionSchema.optional(),
16002
- actions: array(AutomationActionSchema)
16101
+ actions: array(AutomationActionSchema),
16102
+ runMode: AutomationRunModeSchema.optional(),
16103
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
16104
+ keepTraces: number().int().min(1).max(100).optional()
16105
+ });
16106
+ new Set([
16107
+ {
16108
+ id: "person",
16109
+ name: "Person"
16110
+ },
16111
+ {
16112
+ id: "vehicle",
16113
+ name: "Vehicle"
16114
+ },
16115
+ {
16116
+ id: "animal",
16117
+ name: "Animal"
16118
+ },
16119
+ {
16120
+ id: "package",
16121
+ name: "Package"
16122
+ }
16123
+ ].map((l) => l.id));
16124
+ var COCO_TO_MACRO = {
16125
+ mapping: {
16126
+ person: "person",
16127
+ bicycle: "vehicle",
16128
+ car: "vehicle",
16129
+ motorcycle: "vehicle",
16130
+ airplane: "vehicle",
16131
+ bus: "vehicle",
16132
+ train: "vehicle",
16133
+ truck: "vehicle",
16134
+ boat: "vehicle",
16135
+ bird: "animal",
16136
+ cat: "animal",
16137
+ dog: "animal",
16138
+ horse: "animal",
16139
+ sheep: "animal",
16140
+ cow: "animal",
16141
+ elephant: "animal",
16142
+ bear: "animal",
16143
+ zebra: "animal",
16144
+ giraffe: "animal",
16145
+ suitcase: "package",
16146
+ backpack: "package",
16147
+ handbag: "package"
16148
+ },
16149
+ preserveOriginal: false
16150
+ };
16151
+ new Set(Object.values(COCO_TO_MACRO.mapping));
16152
+ /**
16153
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
16154
+ * so the editor can paint every block green or red with its reason.
16155
+ *
16156
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
16157
+ * every condition node (containers and leaves, including the ones a
16158
+ * short-circuit never reached), the run-mode verdict and every action step —
16159
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
16160
+ * for an Action run). Skipped
16161
+ * evaluations are traced too, and identical consecutive skips collapse into a
16162
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
16163
+ *
16164
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
16165
+ * vocabulary so an Action run records the same step shape.
16166
+ */
16167
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
16168
+ var TraceValueSchema = union([
16169
+ string(),
16170
+ number(),
16171
+ boolean(),
16172
+ _null(),
16173
+ array(union([string(), number()]))
16174
+ ]);
16175
+ var AutomationRunOutcomeSchema = _enum([
16176
+ "ran",
16177
+ "skipped-trigger",
16178
+ "skipped-conditions",
16179
+ "skipped-cooldown",
16180
+ "skipped-overlap",
16181
+ "failed",
16182
+ "aborted"
16183
+ ]);
16184
+ /** `not-evaluated` = a short-circuit never reached the node. */
16185
+ var TraceNodeOutcomeSchema = _enum([
16186
+ "pass",
16187
+ "fail",
16188
+ "not-evaluated"
16189
+ ]);
16190
+ var AutomationTriggerTraceSchema = object({
16191
+ kind: string().min(1),
16192
+ outcome: _enum(["pass", "fail"]),
16193
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
16194
+ reason: string(),
16195
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
16196
+ vars: record(string(), TraceValueSchema)
16197
+ });
16198
+ var AutomationConditionTraceNodeSchema = object({
16199
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
16200
+ path: string().min(1),
16201
+ kind: _enum([
16202
+ "all",
16203
+ "any",
16204
+ "not",
16205
+ "condition",
16206
+ "expression",
16207
+ "stationary-present"
16208
+ ]),
16209
+ outcome: TraceNodeOutcomeSchema,
16210
+ reason: string(),
16211
+ deviceId: number().int().optional(),
16212
+ cap: string().optional(),
16213
+ fieldPath: string().optional(),
16214
+ operator: string().optional(),
16215
+ expected: TraceValueSchema.optional(),
16216
+ /** What the mirror held; `null` when it held nothing (unknown). */
16217
+ observed: TraceValueSchema.optional()
16218
+ });
16219
+ var AutomationRunVerdictSchema = object({
16220
+ mode: AutomationRunModeSchema,
16221
+ decision: _enum([
16222
+ "run",
16223
+ "queued",
16224
+ "restart",
16225
+ "drop",
16226
+ "cooldown",
16227
+ "bypass"
16228
+ ]),
16229
+ reason: string()
16230
+ });
16231
+ /** One executed (or not-run) step — shared by automations and Action runs. */
16232
+ var AutomationStepTraceSchema = object({
16233
+ /** `actions.<i>` */
16234
+ path: string().min(1),
16235
+ kind: string().min(1),
16236
+ cap: string().optional(),
16237
+ method: string().optional(),
16238
+ deviceId: number().int().optional(),
16239
+ startedAt: number().optional(),
16240
+ endedAt: number().optional(),
16241
+ outcome: _enum([
16242
+ "ok",
16243
+ "error",
16244
+ "not-run"
16245
+ ]),
16246
+ message: string().optional()
16247
+ });
16248
+ var AutomationRunTraceSchema = object({
16249
+ runId: string().min(1),
16250
+ startedAt: number(),
16251
+ endedAt: number(),
16252
+ trigger: AutomationTriggerTraceSchema,
16253
+ conditions: array(AutomationConditionTraceNodeSchema),
16254
+ verdict: AutomationRunVerdictSchema.optional(),
16255
+ steps: array(AutomationStepTraceSchema),
16256
+ outcome: AutomationRunOutcomeSchema,
16257
+ /** How many identical consecutive skips this trace stands for (>= 1). */
16258
+ repeat: number().int().min(1),
16259
+ /** When the latest of those repeats happened. */
16260
+ lastAt: number()
16261
+ });
16262
+ /**
16263
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
16264
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
16265
+ */
16266
+ var AutomationStateDocSchema = object({
16267
+ version: literal(1),
16268
+ lastRunStartedAt: number().nullable(),
16269
+ traces: array(AutomationRunTraceSchema)
16270
+ });
16271
+ /**
16272
+ * Actions — named, runnable things an operator (or an automation) can start,
16273
+ * declared as LIST ENTRIES, never as devices.
16274
+ *
16275
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
16276
+ * hub's `actions` record kind) or declared by an addon through the
16277
+ * `action-source` collection (a Home Assistant script, a scene …). The one
16278
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
16279
+ * catalog of its own (D3) — every `list` asks the providers live.
16280
+ *
16281
+ * This file is the data half: the entry schema, the variables an entry may
16282
+ * declare, and the pure resolution of the values a run was given. It holds no
16283
+ * runtime.
16284
+ */
16285
+ /** What a variable's value is. `select` takes one of `options`. */
16286
+ var ActionVariableTypeSchema = _enum([
16287
+ "string",
16288
+ "number",
16289
+ "boolean",
16290
+ "select"
16291
+ ]);
16292
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
16293
+ var ActionVariableValueSchema = union([
16294
+ string(),
16295
+ number(),
16296
+ boolean()
16297
+ ]);
16298
+ /**
16299
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
16300
+ * value) or `{{vars.name}}` (inside a string) in their args.
16301
+ */
16302
+ var ActionVariableSchema = object({
16303
+ name: string().regex(ACTION_VARIABLE_NAME_RE),
16304
+ label: string().min(1).max(120).optional(),
16305
+ type: ActionVariableTypeSchema,
16306
+ required: boolean().optional(),
16307
+ default: ActionVariableValueSchema.optional(),
16308
+ /** The allowed values of a `select`. */
16309
+ options: array(string().min(1)).min(1).optional()
16310
+ }).superRefine((v, ctx) => {
16311
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
16312
+ code: "custom",
16313
+ message: "a select variable needs options",
16314
+ path: ["options"]
16315
+ });
16316
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
16317
+ code: "custom",
16318
+ message: variableValueError(v, v.default) ?? "invalid default",
16319
+ path: ["default"]
16320
+ });
16321
+ });
16322
+ /** Why `value` is not a legal value for the variable, or null when it is. */
16323
+ function variableValueError(variable, value) {
16324
+ switch (variable.type) {
16325
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
16326
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
16327
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
16328
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
16329
+ }
16330
+ }
16331
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
16332
+ function isInternalActionId(actionId) {
16333
+ return actionId.startsWith("internal:") && actionId.length > 9;
16334
+ }
16335
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
16336
+ function addonIdOfActionId(actionId) {
16337
+ if (isInternalActionId(actionId)) return null;
16338
+ const at = actionId.indexOf(":");
16339
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
16340
+ }
16341
+ var ActionStatusSchema = object({
16342
+ isRunning: boolean(),
16343
+ /** Ms epoch the latest run STARTED; null when it never ran. */
16344
+ lastRunAt: number().nullable(),
16345
+ /** The latest run's failure; null on success or when it never ran. */
16346
+ lastError: string().nullable()
16347
+ });
16348
+ var ActionEntrySchema = object({
16349
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
16350
+ id: string().min(3),
16351
+ name: string().min(1).max(120),
16352
+ /** The addon that declared it; `core-blocks` for an internal one. */
16353
+ addonId: string().min(1),
16354
+ source: ActionSourceKindSchema,
16355
+ /** An addon-declared entry is edited where it was declared. */
16356
+ readOnly: boolean(),
16357
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
16358
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
16359
+ variables: array(ActionVariableSchema).max(20).optional(),
16360
+ status: ActionStatusSchema
16361
+ }).superRefine((entry, ctx) => {
16362
+ if (entry.source === "internal") {
16363
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
16364
+ code: "custom",
16365
+ message: "an internal action id is internal:<uuid>",
16366
+ path: ["id"]
16367
+ });
16368
+ return;
16369
+ }
16370
+ if (entry.steps !== void 0) ctx.addIssue({
16371
+ code: "custom",
16372
+ message: "only an internal action carries steps",
16373
+ path: ["steps"]
16374
+ });
16375
+ if (!entry.readOnly) ctx.addIssue({
16376
+ code: "custom",
16377
+ message: "an addon action is read-only here",
16378
+ path: ["readOnly"]
16379
+ });
16380
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
16381
+ code: "custom",
16382
+ message: "an addon action id is <addonId>:<localId>",
16383
+ path: ["id"]
16384
+ });
16385
+ });
16386
+ /** What an operator writes for an internal action. */
16387
+ var ActionInputSchema = object({
16388
+ name: string().min(1).max(120),
16389
+ steps: array(ActionStepSchema).min(1).max(50),
16390
+ variables: array(ActionVariableSchema).max(20).optional()
16391
+ });
16392
+ /** Who started a run. Absent = the operator pressed it. */
16393
+ var ActionRunOriginSchema = object({
16394
+ /** The automation block whose step started it. */
16395
+ blockId: string().min(1).optional() });
16396
+ /** `started` = the caller did not ask to wait. */
16397
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
16398
+ var ActionRunResultSchema = object({
16399
+ runId: string().min(1),
16400
+ outcome: ActionRunOutcomeSchema,
16401
+ /** Why it did not run, or what failed. */
16402
+ message: string().optional()
16403
+ });
16404
+ _enum([
16405
+ "not-found",
16406
+ "read-only",
16407
+ "invalid-variables",
16408
+ "invalid-steps",
16409
+ "not-linked",
16410
+ "busy"
16411
+ ]);
16412
+ object({
16413
+ actionId: string(),
16414
+ runId: string(),
16415
+ isRunning: boolean(),
16416
+ /** Set when the run ended. */
16417
+ outcome: AutomationRunOutcomeSchema.optional(),
16418
+ lastRunAt: number().nullable(),
16419
+ lastError: string().nullable()
16003
16420
  });
16004
16421
  /**
16005
16422
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -18754,7 +19171,7 @@ var CompositionEventPlanSchema = object({
18754
19171
  stateField: string(),
18755
19172
  fieldKey: string()
18756
19173
  });
18757
- /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
19174
+ /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
18758
19175
  var CompositionProblemSchema = object({
18759
19176
  code: _enum([
18760
19177
  "reserved-variant",
@@ -19073,7 +19490,7 @@ var GROUP_TEMPLATES = [
19073
19490
  summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
19074
19491
  role: DeviceRole.TemperatureSensor,
19075
19492
  outputCap: "temperature-sensor",
19076
- outputField: "celsius",
19493
+ outputField: "temperature",
19077
19494
  quantity: "temperature",
19078
19495
  defaultAggregate: "mean",
19079
19496
  empty: "null",
@@ -19084,7 +19501,7 @@ var GROUP_TEMPLATES = [
19084
19501
  summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
19085
19502
  role: DeviceRole.HumiditySensor,
19086
19503
  outputCap: "humidity-sensor",
19087
- outputField: "percent",
19504
+ outputField: "humidity",
19088
19505
  quantity: "humidity",
19089
19506
  defaultAggregate: "mean",
19090
19507
  empty: "null",
@@ -19095,7 +19512,7 @@ var GROUP_TEMPLATES = [
19095
19512
  summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
19096
19513
  role: DeviceRole.PressureSensor,
19097
19514
  outputCap: "pressure-sensor",
19098
- outputField: "hpa",
19515
+ outputField: "pressure",
19099
19516
  quantity: "pressure",
19100
19517
  defaultAggregate: "mean",
19101
19518
  empty: "null",
@@ -19106,7 +19523,7 @@ var GROUP_TEMPLATES = [
19106
19523
  summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
19107
19524
  role: DeviceRole.AmbientLightSensor,
19108
19525
  outputCap: "ambient-light-sensor",
19109
- outputField: "lux",
19526
+ outputField: "illuminance",
19110
19527
  quantity: "illuminance",
19111
19528
  defaultAggregate: "mean",
19112
19529
  empty: "null",
@@ -19117,7 +19534,7 @@ var GROUP_TEMPLATES = [
19117
19534
  summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
19118
19535
  role: DeviceRole.PowerSensor,
19119
19536
  outputCap: "power-meter",
19120
- outputField: "watts",
19537
+ outputField: "power",
19121
19538
  quantity: "power",
19122
19539
  defaultAggregate: "sum",
19123
19540
  empty: "omit",
@@ -19128,7 +19545,7 @@ var GROUP_TEMPLATES = [
19128
19545
  summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
19129
19546
  role: DeviceRole.EnergySensor,
19130
19547
  outputCap: "power-meter",
19131
- outputField: "kwhTotal",
19548
+ outputField: "energy",
19132
19549
  quantity: "energy",
19133
19550
  defaultAggregate: "sum",
19134
19551
  empty: "omit",
@@ -19139,7 +19556,7 @@ var GROUP_TEMPLATES = [
19139
19556
  summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
19140
19557
  role: DeviceRole.BatterySensor,
19141
19558
  outputCap: "battery",
19142
- outputField: "percentage",
19559
+ outputField: "level",
19143
19560
  quantity: "percentage",
19144
19561
  defaultAggregate: "mean",
19145
19562
  empty: "null",
@@ -19717,7 +20134,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19717
20134
  kind: "mutation",
19718
20135
  auth: "admin",
19719
20136
  access: "view"
19720
- });
20137
+ }), method(object({
20138
+ blockId: string().min(1),
20139
+ trace: AutomationRunTraceSchema.optional(),
20140
+ runStartedAt: number().optional(),
20141
+ keepTraces: number().int().min(1).max(100).optional()
20142
+ }), _void(), {
20143
+ kind: "mutation",
20144
+ auth: "admin"
20145
+ }), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
20146
+ traces: array(AutomationRunTraceSchema),
20147
+ lastError: string().nullable()
20148
+ }), { auth: "admin" });
19721
20149
  /**
19722
20150
  * `custom-model-registry` — collection cap exposing operator-registered
19723
20151
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -44872,7 +45300,7 @@ var NetworkAccessStatusSchema = object({
44872
45300
  });
44873
45301
  /**
44874
45302
  * Optional, richer endpoint shape returned by providers that expose
44875
- * MORE than one ingress concurrently (Tailscale Ingress with mixed
45303
+ * MORE than one ingress concurrently (Tailscale Funnel with mixed
44876
45304
  * serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
44877
45305
  * the originating provider config (mode + sourcePort) so the
44878
45306
  * orchestrator UI can label rows distinctly. Providers that expose only
@@ -45287,51 +45715,6 @@ var notificationOutputCapability = {
45287
45715
  })
45288
45716
  }
45289
45717
  };
45290
- new Set([
45291
- {
45292
- id: "person",
45293
- name: "Person"
45294
- },
45295
- {
45296
- id: "vehicle",
45297
- name: "Vehicle"
45298
- },
45299
- {
45300
- id: "animal",
45301
- name: "Animal"
45302
- },
45303
- {
45304
- id: "package",
45305
- name: "Package"
45306
- }
45307
- ].map((l) => l.id));
45308
- var COCO_TO_MACRO = {
45309
- mapping: {
45310
- person: "person",
45311
- bicycle: "vehicle",
45312
- car: "vehicle",
45313
- motorcycle: "vehicle",
45314
- airplane: "vehicle",
45315
- bus: "vehicle",
45316
- train: "vehicle",
45317
- truck: "vehicle",
45318
- boat: "vehicle",
45319
- bird: "animal",
45320
- cat: "animal",
45321
- dog: "animal",
45322
- horse: "animal",
45323
- sheep: "animal",
45324
- cow: "animal",
45325
- elephant: "animal",
45326
- bear: "animal",
45327
- zebra: "animal",
45328
- giraffe: "animal",
45329
- suitcase: "package",
45330
- backpack: "package",
45331
- handbag: "package"
45332
- },
45333
- preserveOriginal: false
45334
- };
45335
45718
  var AUDIO_MACRO_LABELS = [
45336
45719
  {
45337
45720
  id: "speech",
@@ -57986,9 +58369,9 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
57986
58369
  */
57987
58370
  var AirQualitySensorStatusSchema = object({
57988
58371
  /** Carbon dioxide concentration in ppm. */
57989
- co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
58372
+ co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
57990
58373
  /** Total volatile organic compounds in ppb. */
57991
- vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
58374
+ voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57992
58375
  /** Particulate matter ≤ 2.5 μm in µg/m³. */
57993
58376
  pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
57994
58377
  /** Particulate matter ≤ 10 μm in µg/m³. */
@@ -58021,12 +58404,12 @@ var airQualitySensorCapability = {
58021
58404
  * History (D850): recorded series.
58022
58405
  */
58023
58406
  history: { fields: {
58024
- co2Ppm: {
58407
+ co2: {
58025
58408
  kind: "gauge",
58026
58409
  unit: "ppm",
58027
58410
  deadband: 5
58028
58411
  },
58029
- vocPpb: {
58412
+ voc: {
58030
58413
  kind: "gauge",
58031
58414
  unit: "ppb",
58032
58415
  deadband: 5
@@ -58057,7 +58440,7 @@ var airQualitySensorCapability = {
58057
58440
  */
58058
58441
  var AmbientLightSensorStatusSchema = object({
58059
58442
  /** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
58060
- lux: number().min(0).nullable().meta(readingMeta("illuminance", {
58443
+ illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
58061
58444
  precision: 0,
58062
58445
  label: "Illuminance"
58063
58446
  })),
@@ -58086,7 +58469,7 @@ var ambientLightSensorCapability = {
58086
58469
  /**
58087
58470
  * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
58088
58471
  */
58089
- history: { fields: { lux: {
58472
+ history: { fields: { illuminance: {
58090
58473
  kind: "gauge",
58091
58474
  unit: "lx",
58092
58475
  deadbandPct: 10,
@@ -58225,6 +58608,84 @@ var audioMetricsCapability = {
58225
58608
  */
58226
58609
  history: "none"
58227
58610
  };
58611
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58612
+ actionId: string().min(1),
58613
+ variables: record(string(), ActionVariableValueSchema).optional()
58614
+ }), _void(), {
58615
+ kind: "mutation",
58616
+ auth: "admin"
58617
+ }), method(object({ actionId: string().min(1) }), _void(), {
58618
+ kind: "mutation",
58619
+ auth: "admin"
58620
+ });
58621
+ /**
58622
+ * actions — the ONE surface for runnable actions, for the UI and for
58623
+ * automations. Provided by the core-blocks builtin on the hub.
58624
+ *
58625
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
58626
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
58627
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
58628
+ * the run status from the hub's `runs` ledger; there is no catalog here to
58629
+ * drift (D3).
58630
+ *
58631
+ * **Permissions follow the camera, as linked devices do.** An action is linked
58632
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
58633
+ * non-admin may `get` / `run` an action only through a camera they may see that
58634
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
58635
+ * gate sees it) and the provider refuses an action that camera does not link.
58636
+ * An admin, and an in-process caller (an automation block), may run any action.
58637
+ * Every refusal is typed (`[not-linked] …`) and logged.
58638
+ *
58639
+ * A second `run` of an action that is already running is REFUSED — traced and
58640
+ * logged — never queued.
58641
+ */
58642
+ var ActionIdInput = object({ actionId: string().min(1) });
58643
+ var ActionLinksSchema = object({
58644
+ deviceId: number().int().nonnegative(),
58645
+ actionIds: array(string().min(1)).max(100)
58646
+ });
58647
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58648
+ actionId: string().min(1),
58649
+ deviceId: number().int().nonnegative().optional()
58650
+ }), object({ action: ActionEntrySchema.nullable() }), {
58651
+ role: "viewer",
58652
+ auth: "protected",
58653
+ kind: "query",
58654
+ caller: "required"
58655
+ }), method(object({
58656
+ actionId: string().min(1),
58657
+ variables: record(string(), ActionVariableValueSchema).optional(),
58658
+ wait: boolean().optional(),
58659
+ origin: ActionRunOriginSchema.optional(),
58660
+ deviceId: number().int().nonnegative().optional()
58661
+ }), ActionRunResultSchema, {
58662
+ role: "viewer",
58663
+ auth: "protected",
58664
+ kind: "mutation",
58665
+ caller: "required"
58666
+ }), method(ActionIdInput, _void(), {
58667
+ kind: "mutation",
58668
+ auth: "admin"
58669
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58670
+ kind: "mutation",
58671
+ auth: "admin"
58672
+ }), method(object({
58673
+ actionId: string().min(1),
58674
+ action: ActionInputSchema.partial()
58675
+ }), object({ action: ActionEntrySchema }), {
58676
+ kind: "mutation",
58677
+ auth: "admin"
58678
+ }), method(ActionIdInput, _void(), {
58679
+ kind: "mutation",
58680
+ auth: "admin"
58681
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
58682
+ role: "viewer",
58683
+ auth: "protected",
58684
+ kind: "query"
58685
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
58686
+ kind: "mutation",
58687
+ auth: "admin"
58688
+ });
58228
58689
  /**
58229
58690
  * Automation-control cap. Models HA `automation.*` entities on
58230
58691
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -58321,7 +58782,7 @@ var BatteryStatusSchema = object({
58321
58782
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
58322
58783
  * declines to band a non-finite reading, which is the correct shape.
58323
58784
  */
58324
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58785
+ level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58325
58786
  /**
58326
58787
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
58327
58788
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -58331,7 +58792,7 @@ var BatteryStatusSchema = object({
58331
58792
  * `'unknown'` is the absence of an answer: the provider has not read the
58332
58793
  * power fields yet, or the firmware reported neither. Before it existed,
58333
58794
  * two unreadable fields produced `'none'`, and a camera nobody had reached
58334
- * was drawn "on battery alone" — the same D315 defect `percentage` closed
58795
+ * was drawn "on battery alone" — the same D315 defect `level` closed
58335
58796
  * by going nullable. Consumers SKIP it (no charger state published, no
58336
58797
  * glyph, no HomeKit ChargingState) rather than coerce it either way.
58337
58798
  */
@@ -58355,7 +58816,7 @@ var BatteryStatusSchema = object({
58355
58816
  * that only report charge. A second reading on this cap, not a second
58356
58817
  * `numeric-sensor` on the same device.
58357
58818
  */
58358
- volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58819
+ voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58359
58820
  /**
58360
58821
  * Ms epoch of the last time the device PROVED it was reachable — a
58361
58822
  * completed firmware round-trip, an observed wake, or an inbound push
@@ -58389,7 +58850,7 @@ var BatteryStatusSchema = object({
58389
58850
  /**
58390
58851
  * True when the source is a BINARY low-battery indicator (HA
58391
58852
  * `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
58392
- * charge level — `percentage` is then a coarse stand-in (100 = normal,
58853
+ * charge level — `level` is then a coarse stand-in (100 = normal,
58393
58854
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
58394
58855
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
58395
58856
  */
@@ -58402,21 +58863,22 @@ var BATTERY_DEVICE_TYPES = [
58402
58863
  DeviceType.Switch,
58403
58864
  DeviceType.PetFeeder,
58404
58865
  DeviceType.Container,
58405
- DeviceType.Thermostat
58866
+ DeviceType.Thermostat,
58867
+ DeviceType.EventEmitter
58406
58868
  ];
58407
58869
  /** Generic Customize target for the percentage reading (D936). */
58408
58870
  var batteryCustomize = {
58409
58871
  version: 1,
58410
58872
  targets: [{
58411
- id: "percentage",
58873
+ id: "level",
58412
58874
  cardinality: "scalar",
58413
58875
  vocabulary: {
58414
58876
  cap: "battery",
58415
- stateField: "percentage"
58877
+ stateField: "level"
58416
58878
  },
58417
58879
  deviceTypes: BATTERY_DEVICE_TYPES,
58418
58880
  apply: "add",
58419
- path: "percentage",
58881
+ path: "level",
58420
58882
  sources: [{
58421
58883
  kind: "field",
58422
58884
  valueKinds: ["number", "string"],
@@ -58510,7 +58972,7 @@ onStatusChanged: { data: object({
58510
58972
  schema: BatteryStatusSchema,
58511
58973
  kind: "push",
58512
58974
  empty: {
58513
- percentage: null,
58975
+ level: null,
58514
58976
  charging: "unknown",
58515
58977
  sleeping: false,
58516
58978
  lastUpdated: 0
@@ -58537,11 +58999,11 @@ onStatusChanged: { data: object({
58537
58999
  * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
58538
59000
  */
58539
59001
  history: { fields: {
58540
- percentage: {
59002
+ level: {
58541
59003
  kind: "gauge",
58542
59004
  unit: "%"
58543
59005
  },
58544
- volts: {
59006
+ voltage: {
58545
59007
  kind: "gauge",
58546
59008
  unit: "V"
58547
59009
  }
@@ -58601,14 +59063,14 @@ var binaryCapability = {
58601
59063
  * controls to this single-method surface.
58602
59064
  *
58603
59065
  * The cap is intentionally minimal: a single `setBrightness({deviceId,
58604
- * percentage})` mutation plus the auto-injected `getStatus`. Drivers
59066
+ * level})` mutation plus the auto-injected `getStatus`. Drivers
58605
59067
  * that expose richer controls (color temperature, scenes, schedules)
58606
59068
  * should surface those via the device's `getSettingsUISchema()`
58607
59069
  * instead of bloating this cap.
58608
59070
  */
58609
59071
  var BrightnessStatusSchema = object({
58610
59072
  /** Current level as 0..100 inclusive. Firmware-reported. */
58611
- percentage: number().min(0).max(100).meta(readingMeta("percentage")),
59073
+ level: number().min(0).max(100).meta(readingMeta("percentage")),
58612
59074
  /** Ms epoch of the last operator-driven change. Useful for UI freshness. */
58613
59075
  lastChangedAt: number()
58614
59076
  });
@@ -58620,7 +59082,7 @@ var brightnessCapability = {
58620
59082
  deviceTypes: [DeviceType.Light],
58621
59083
  methods: { setBrightness: method(object({
58622
59084
  deviceId: number().int().nonnegative(),
58623
- percentage: number().min(0).max(100)
59085
+ level: number().min(0).max(100)
58624
59086
  }), _void(), {
58625
59087
  kind: "mutation",
58626
59088
  auth: "protected"
@@ -58633,7 +59095,7 @@ var brightnessCapability = {
58633
59095
  */
58634
59096
  onBrightnessChanged: { data: object({
58635
59097
  deviceId: number(),
58636
- percentage: number().min(0).max(100),
59098
+ level: number().min(0).max(100),
58637
59099
  lastChangedAt: number()
58638
59100
  }) } },
58639
59101
  status: {
@@ -58656,7 +59118,7 @@ onBrightnessChanged: { data: object({
58656
59118
  /**
58657
59119
  * History (D850): recorded series. Actuator tier: level keeps every change.
58658
59120
  */
58659
- history: { fields: { percentage: {
59121
+ history: { fields: { level: {
58660
59122
  kind: "gauge",
58661
59123
  unit: "%",
58662
59124
  minIntervalMs: 0
@@ -59280,11 +59742,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
59280
59742
  }),
59281
59743
  object({
59282
59744
  mode: literal("mired"),
59283
- mireds: number().int().min(50).max(1e3)
59745
+ colorTemperature: number().int().min(50).max(1e3)
59284
59746
  })
59285
59747
  ]);
59286
59748
  var ColorStatusSchema = object({
59287
- /** Active color mode — which of `rgb` / `hsv` / `mireds` reflects
59749
+ /** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
59288
59750
  * the bulb's current state. */
59289
59751
  mode: _enum([
59290
59752
  "rgb",
@@ -59296,7 +59758,7 @@ var ColorStatusSchema = object({
59296
59758
  /** Populated when `mode === 'hsv'`. */
59297
59759
  hsv: HsvTripletSchema.optional(),
59298
59760
  /** Populated when `mode === 'mired'`. */
59299
- mireds: number().int().optional().meta(readingMeta("colour-temperature")),
59761
+ colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
59300
59762
  /** Ms epoch of the last operator-driven change. */
59301
59763
  lastChangedAt: number()
59302
59764
  });
@@ -59328,7 +59790,7 @@ onColorChanged: { data: object({
59328
59790
  ]),
59329
59791
  rgb: RgbTripletSchema.optional(),
59330
59792
  hsv: HsvTripletSchema.optional(),
59331
- mireds: number().int().optional(),
59793
+ colorTemperature: number().int().optional(),
59332
59794
  lastChangedAt: number()
59333
59795
  }) } },
59334
59796
  status: {
@@ -60219,11 +60681,11 @@ var DishwasherStatusSchema = object({
60219
60681
  /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
60220
60682
  availablePrograms: array(string()),
60221
60683
  /** Seconds remaining on the active cycle, or null when not running / not known. */
60222
- remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60684
+ remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60223
60685
  /** Seconds the delayed start is set to (time until the cycle starts), or null. */
60224
- delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60686
+ delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60225
60687
  /** Cycle completion 0..100, or null when not applicable. */
60226
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60688
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60227
60689
  /** True when the door is reported open; null when the door state is not known. */
60228
60690
  doorOpen: boolean().nullable(),
60229
60691
  /** True when the door is latched (locked) during a cycle; null when not reported. */
@@ -60442,14 +60904,14 @@ var dishwasherCapability = {
60442
60904
  runtimeState: DishwasherStatusSchema,
60443
60905
  durability: "session",
60444
60906
  history: { fields: {
60445
- progressPercent: {
60907
+ progress: {
60446
60908
  kind: "gauge",
60447
60909
  unit: "%",
60448
60910
  deadband: 2
60449
60911
  },
60450
60912
  state: { kind: "enum" },
60451
60913
  operationState: { kind: "enum" },
60452
- remainingSeconds: {
60914
+ remaining: {
60453
60915
  kind: "gauge",
60454
60916
  unit: "s",
60455
60917
  minIntervalMs: 6e4
@@ -61050,7 +61512,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
61050
61512
  var FanControlStatusSchema = object({
61051
61513
  /** Active speed as 0..100 inclusive. Null when the device has no
61052
61514
  * speed surface (single-speed fan). */
61053
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61515
+ speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61054
61516
  /** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
61055
61517
  * a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
61056
61518
  percentageStep: number().positive().optional().meta(readingMeta("percentage")),
@@ -61077,7 +61539,7 @@ var fanControlCapability = {
61077
61539
  methods: {
61078
61540
  setPercentage: method(object({
61079
61541
  deviceId: number().int().nonnegative(),
61080
- percentage: number().min(0).max(100)
61542
+ speed: number().min(0).max(100)
61081
61543
  }), _void(), {
61082
61544
  kind: "mutation",
61083
61545
  auth: "protected"
@@ -61110,7 +61572,7 @@ var fanControlCapability = {
61110
61572
  },
61111
61573
  /**
61112
61574
  * Runtime-state slice — mirrored by the kernel. UI fan speed
61113
- * sliders read `percentage` for live updates.
61575
+ * sliders read `speed` for live updates.
61114
61576
  */
61115
61577
  runtimeState: FanControlStatusSchema,
61116
61578
  /**
@@ -61124,7 +61586,7 @@ var fanControlCapability = {
61124
61586
  * History (D850): recorded series. Actuator tier: speed keeps every change.
61125
61587
  */
61126
61588
  history: { fields: {
61127
- percentage: {
61589
+ speed: {
61128
61590
  kind: "gauge",
61129
61591
  unit: "%",
61130
61592
  minIntervalMs: 0
@@ -61569,7 +62031,7 @@ var humidifierCapability = {
61569
62031
  */
61570
62032
  var HumiditySensorStatusSchema = object({
61571
62033
  /** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
61572
- percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
62034
+ humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
61573
62035
  precision: 0,
61574
62036
  label: "Humidity"
61575
62037
  })),
@@ -61598,7 +62060,7 @@ var humiditySensorCapability = {
61598
62060
  /**
61599
62061
  * History (D850): recorded series.
61600
62062
  */
61601
- history: { fields: { percent: {
62063
+ history: { fields: { humidity: {
61602
62064
  kind: "gauge",
61603
62065
  unit: "%",
61604
62066
  deadband: .5
@@ -62238,7 +62700,7 @@ var LawnMowerControlStatusSchema = object({
62238
62700
  batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62239
62701
  /** 0..100 mowing-completion percentage of the current task, or null when no
62240
62702
  * task is active / progress is unavailable. */
62241
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62703
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62242
62704
  /** Current device/event code (dynamic — mostly status, sometimes an error),
62243
62705
  * or null when unknown. */
62244
62706
  currentCode: number().nullable().meta(readingMeta("none")),
@@ -62738,7 +63200,7 @@ var lockControlCapability = {
62738
63200
  volatileStateFields: ["lastChangedAt"]
62739
63201
  };
62740
63202
  /**
62741
- * A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
63203
+ * A monotonic total between resets (D944). Energy uses `power-meter.energy`
62742
63204
  * so dashboards keep one series; every other instantaneous reading lands here.
62743
63205
  * `value` is the time integral in the source quantity's accumulated base
62744
63206
  * (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
@@ -62832,10 +63294,10 @@ var MediaPlayerStatusSchema = object({
62832
63294
  currentMedia: MediaInfoSchema.nullable(),
62833
63295
  /** Current playback position in ms. Null when not seekable or
62834
63296
  * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
62835
- positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63297
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62836
63298
  /** Total duration of the current media in ms. Null when unknown
62837
63299
  * (live stream) or nothing is playing. */
62838
- durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
63300
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62839
63301
  /** Shuffle toggle. Null when no shuffle surface.
62840
63302
  * Pair with `DeviceFeature.MediaPlayerShuffle`. */
62841
63303
  shuffle: boolean().nullable(),
@@ -62874,7 +63336,7 @@ var mediaPlayerCapability = {
62874
63336
  }),
62875
63337
  seek: method(object({
62876
63338
  deviceId: number().int().nonnegative(),
62877
- positionMs: number().int().nonnegative()
63339
+ position: number().int().nonnegative()
62878
63340
  }), _void(), {
62879
63341
  kind: "mutation",
62880
63342
  auth: "protected"
@@ -62946,7 +63408,7 @@ var mediaPlayerCapability = {
62946
63408
  /**
62947
63409
  * History (D850): volume (a level an operator or an automation sets; the
62948
63410
  * default 10 s floor folds a slider drag into its end value) and mute.
62949
- * `positionMs` is not recorded: it moves continuously while playing.
63411
+ * `position` is not recorded: it moves continuously while playing.
62950
63412
  */
62951
63413
  history: { fields: {
62952
63414
  volumeLevel: {
@@ -63908,9 +64370,9 @@ var NetworkLinkStatusSchema = object({
63908
64370
  * one whose reading has not landed must not be drawn at 0 %. Consumers
63909
64371
  * SKIP a null rather than coerce it.
63910
64372
  */
63911
- signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
64373
+ signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63912
64374
  /** Raw received signal strength in dBm, when the firmware reports one. */
63913
- rssiDbm: number().optional().meta(readingMeta("signal-level")),
64375
+ rssi: number().optional().meta(readingMeta("signal-level")),
63914
64376
  /** Network name of a wireless link, when the firmware reports it. */
63915
64377
  ssid: string().optional(),
63916
64378
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
@@ -63946,7 +64408,7 @@ onStatusChanged: { data: object({
63946
64408
  kind: "push",
63947
64409
  empty: {
63948
64410
  type: "unknown",
63949
- signalPercent: null,
64411
+ signal: null,
63950
64412
  lastUpdated: 0
63951
64413
  }
63952
64414
  },
@@ -63969,13 +64431,13 @@ onStatusChanged: { data: object({
63969
64431
  * History (D850): recorded series.
63970
64432
  */
63971
64433
  history: { fields: {
63972
- signalPercent: {
64434
+ signal: {
63973
64435
  kind: "gauge",
63974
64436
  unit: "%",
63975
64437
  deadband: 3,
63976
64438
  minIntervalMs: 6e4
63977
64439
  },
63978
- rssiDbm: {
64440
+ rssi: {
63979
64441
  kind: "gauge",
63980
64442
  unit: "dBm",
63981
64443
  deadband: 2,
@@ -64720,10 +65182,20 @@ var PetFeederDeviceStatusSchema = _enum([
64720
65182
  ]);
64721
65183
  var gramsPortion = number().int().min(4).max(200);
64722
65184
  var PetFeederStatusSchema = object({
64723
- /** Food currently in the bowl (grams). Null when the device has not
64724
- * reported a reading yet. On dual-hopper models this is the combined
64725
- * bowl reading; per-hopper levels live in `food1`/`food2`. */
65185
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
65186
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
65187
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
65188
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
65189
+ * the device has not reported yet. */
64726
65190
  foodLevel: number().nullable().meta(readingMeta("none")),
65191
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
65192
+ * feeder's own units. Null when the model reports none. */
65193
+ bowlFood: number().nullable().meta(readingMeta("none")),
65194
+ /** True while the pet is eating (`state.eating`). */
65195
+ eating: boolean(),
65196
+ /** Whether `markFoodReplenished` does anything on this model. When false
65197
+ * the client must not offer it. */
65198
+ supportsMarkRefilled: boolean(),
64727
65199
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
64728
65200
  * single-hopper models. */
64729
65201
  food1: number().nullable().meta(readingMeta("none")),
@@ -64731,8 +65203,8 @@ var PetFeederStatusSchema = object({
64731
65203
  * single-hopper models. */
64732
65204
  food2: number().nullable().meta(readingMeta("none")),
64733
65205
  /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
64734
- * (`device_class: problem`, on = low). True when the bowl is empty /
64735
- * below the feeder's low threshold. */
65206
+ * (`device_class: problem`, on = low). True when the tank reports empty,
65207
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
64736
65208
  lowFood: boolean(),
64737
65209
  /** Battery charge 0..100 (%). Null on mains-powered models or when the
64738
65210
  * device has no battery reading. */
@@ -64800,7 +65272,9 @@ var petFeederCapability = {
64800
65272
  kind: "mutation",
64801
65273
  auth: "protected"
64802
65274
  }),
64803
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
65275
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
65276
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
65277
+ * change any sensor reading. */
64804
65278
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
64805
65279
  kind: "mutation",
64806
65280
  auth: "protected"
@@ -64873,6 +65347,7 @@ var petFeederCapability = {
64873
65347
  */
64874
65348
  history: { fields: {
64875
65349
  foodLevel: { kind: "gauge" },
65350
+ bowlFood: { kind: "gauge" },
64876
65351
  food1: { kind: "gauge" },
64877
65352
  food2: { kind: "gauge" },
64878
65353
  batteryPower: {
@@ -65282,16 +65757,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
65282
65757
  * in real-world devices.
65283
65758
  */
65284
65759
  var PowerMeterStatusSchema = object({
65285
- /** Instantaneous power draw in watts. */
65286
- watts: number().optional().meta(readingMeta("power", { label: "Power" })),
65760
+ /** Instantaneous power draw (watts). */
65761
+ power: number().optional().meta(readingMeta("power", { label: "Power" })),
65287
65762
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
65288
- kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65289
- /** Voltage in volts. */
65290
- volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65763
+ energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65764
+ /** Voltage (volts). */
65765
+ voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65291
65766
  /** Current in amperes. */
65292
- amps: number().optional().meta(readingMeta("current", { label: "Current" })),
65767
+ current: number().optional().meta(readingMeta("current", { label: "Current" })),
65293
65768
  /** Apparent power in volt-amperes. */
65294
- va: number().optional().meta(readingMeta("apparent-power")),
65769
+ apparentPower: number().optional().meta(readingMeta("apparent-power")),
65295
65770
  /** Power factor (0..1) if reported. */
65296
65771
  powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
65297
65772
  /** Ms epoch when the slice was last updated. */
@@ -65349,14 +65824,14 @@ function powerTarget(id, unit) {
65349
65824
  advancedExpression: true
65350
65825
  };
65351
65826
  }
65352
- /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65827
+ /** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
65353
65828
  var powerMeterCustomize = {
65354
65829
  version: 1,
65355
65830
  targets: [
65356
- powerTarget("watts", "W"),
65357
- powerTarget("kwhTotal", "kWh"),
65358
- powerTarget("volts", "V"),
65359
- powerTarget("amps", "A")
65831
+ powerTarget("power", "W"),
65832
+ powerTarget("energy", "kWh"),
65833
+ powerTarget("voltage", "V"),
65834
+ powerTarget("current", "A")
65360
65835
  ]
65361
65836
  };
65362
65837
  var powerMeterCapability = {
@@ -65372,41 +65847,41 @@ var powerMeterCapability = {
65372
65847
  },
65373
65848
  runtimeState: PowerMeterStatusSchema,
65374
65849
  /**
65375
- * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
65850
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
65376
65851
  *
65377
65852
  * See `RuntimeStateDurability`. Enforced by
65378
65853
  * `scripts/check-runtime-state-durability.ts`.
65379
65854
  */
65380
65855
  durability: "restored",
65381
65856
  /**
65382
- * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
65857
+ * History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
65383
65858
  */
65384
65859
  history: { fields: {
65385
- watts: {
65860
+ power: {
65386
65861
  kind: "gauge",
65387
65862
  unit: "W",
65388
65863
  deadband: 1,
65389
65864
  minIntervalMs: 3e4
65390
65865
  },
65391
- kwhTotal: {
65866
+ energy: {
65392
65867
  kind: "counter",
65393
65868
  unit: "kWh",
65394
65869
  deadband: .01,
65395
65870
  minIntervalMs: 6e4
65396
65871
  },
65397
- volts: {
65872
+ voltage: {
65398
65873
  kind: "gauge",
65399
65874
  unit: "V",
65400
65875
  deadband: 1,
65401
65876
  minIntervalMs: 3e4
65402
65877
  },
65403
- amps: {
65878
+ current: {
65404
65879
  kind: "gauge",
65405
65880
  unit: "A",
65406
65881
  deadband: .05,
65407
65882
  minIntervalMs: 3e4
65408
65883
  },
65409
- va: {
65884
+ apparentPower: {
65410
65885
  kind: "gauge",
65411
65886
  unit: "VA",
65412
65887
  deadband: 1,
@@ -65456,9 +65931,6 @@ var PresenceStatusSchema = object({
65456
65931
  location: string().nullable(),
65457
65932
  /** GPS coordinates when available. Null otherwise. */
65458
65933
  gps: GpsLocationSchema.nullable(),
65459
- /** Optional battery level of the tracking device (0..100). Null
65460
- * when not reported. */
65461
- batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
65462
65934
  /** Ms epoch when the slice was last updated. */
65463
65935
  lastChangedAt: number()
65464
65936
  });
@@ -65487,14 +65959,7 @@ var presenceCapability = {
65487
65959
  * `scripts/check-runtime-state-durability.ts`.
65488
65960
  */
65489
65961
  durability: "restored",
65490
- /**
65491
- * History (D850): recorded series.
65492
- */
65493
- history: { fields: { batteryPercent: {
65494
- kind: "gauge",
65495
- unit: "%",
65496
- deadband: 1
65497
- } } },
65962
+ history: "none",
65498
65963
  /** Clock fields: written, but excluded from the compare that decides
65499
65964
  * whether persisting is worth a SQLite commit. */
65500
65965
  volatileStateFields: ["lastChangedAt"]
@@ -65509,7 +65974,7 @@ var presenceCapability = {
65509
65974
  */
65510
65975
  var PressureSensorStatusSchema = object({
65511
65976
  /** Current pressure in hPa. `null` when the sample was refused (D393). */
65512
- hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65977
+ pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65513
65978
  /** Ms epoch when the slice was last updated. */
65514
65979
  lastFetchedAt: number()
65515
65980
  });
@@ -65535,7 +66000,7 @@ var pressureSensorCapability = {
65535
66000
  /**
65536
66001
  * History (D850): recorded series.
65537
66002
  */
65538
- history: { fields: { hpa: {
66003
+ history: { fields: { pressure: {
65539
66004
  kind: "gauge",
65540
66005
  unit: "hPa",
65541
66006
  deadband: .1
@@ -69242,7 +69707,7 @@ var tamperCapability = {
69242
69707
  */
69243
69708
  var TemperatureSensorStatusSchema = object({
69244
69709
  /** Current temperature in Celsius. `null` when the sample was refused (D393). */
69245
- celsius: number().nullable().meta(readingMeta("temperature", {
69710
+ temperature: number().nullable().meta(readingMeta("temperature", {
69246
69711
  precision: 1,
69247
69712
  label: "Temperature"
69248
69713
  })),
@@ -69271,7 +69736,7 @@ var temperatureSensorCapability = {
69271
69736
  /**
69272
69737
  * History (D850): recorded series.
69273
69738
  */
69274
- history: { fields: { celsius: {
69739
+ history: { fields: { temperature: {
69275
69740
  kind: "gauge",
69276
69741
  unit: "°C",
69277
69742
  deadband: .1
@@ -69568,7 +70033,7 @@ var VacuumControlStatusSchema = object({
69568
70033
  /** Speed tokens the hardware accepts — drives the UI selector. */
69569
70034
  availableFanSpeeds: array(string()),
69570
70035
  /** 0..100 cleaning-completion percentage of the current task, or null. */
69571
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
70036
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
69572
70037
  /** Current error code (0 / null = no error). */
69573
70038
  errorCode: number().nullable().meta(readingMeta("none")),
69574
70039
  /** Human label for {@link errorCode}, or null when none / undecodable. */
@@ -71253,7 +71718,7 @@ function tryConvertDelta(value, from, to) {
71253
71718
  return shifted - origin;
71254
71719
  }
71255
71720
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
71256
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, 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.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, 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.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.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.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.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
71721
+ 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.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, 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.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.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.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.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
71257
71722
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
71258
71723
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
71259
71724
  new Set(CAP_NAMES);
@@ -71657,7 +72122,7 @@ var BaseDevice = class {
71657
72122
  * `device-local-state.ts`. Drivers access via:
71658
72123
  *
71659
72124
  * `this.state.battery.sleeping = true` // patches the battery slice
71660
- * `const pct = this.state.battery.percentage` // reads the battery slice
72125
+ * `const pct = this.state.battery.level` // reads the battery slice
71661
72126
  * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
71662
72127
  *
71663
72128
  * Adding a new cap with `runtimeState:` automatically extends this
@@ -71697,7 +72162,7 @@ var BaseDevice = class {
71697
72162
  * shape; drivers don't redeclare it, they just write through.
71698
72163
  *
71699
72164
  * Read: `this.runtimeState.getCapState('battery')` →
71700
- * `{percentage, charging, sleeping, lastUpdated}` for any
72165
+ * `{level, charging, sleeping, lastUpdated}` for any
71701
72166
  * provider that registers `batteryCapability`.
71702
72167
  * Write: `this.runtimeState.setCapState('battery', { … })`.
71703
72168
  *
@@ -72871,6 +73336,104 @@ Object.freeze({
72871
73336
  access: "create",
72872
73337
  role: "admin"
72873
73338
  },
73339
+ "actions.create": {
73340
+ capName: "actions",
73341
+ capScope: "system",
73342
+ addonId: null,
73343
+ access: "create",
73344
+ role: "admin"
73345
+ },
73346
+ "actions.delete": {
73347
+ capName: "actions",
73348
+ capScope: "system",
73349
+ addonId: null,
73350
+ access: "delete",
73351
+ role: "admin"
73352
+ },
73353
+ "actions.get": {
73354
+ capName: "actions",
73355
+ capScope: "system",
73356
+ addonId: null,
73357
+ access: "view",
73358
+ role: "viewer"
73359
+ },
73360
+ "actions.getLinks": {
73361
+ capName: "actions",
73362
+ capScope: "system",
73363
+ addonId: null,
73364
+ access: "view",
73365
+ role: "admin"
73366
+ },
73367
+ "actions.getTraces": {
73368
+ capName: "actions",
73369
+ capScope: "system",
73370
+ addonId: null,
73371
+ access: "view",
73372
+ role: "admin"
73373
+ },
73374
+ "actions.list": {
73375
+ capName: "actions",
73376
+ capScope: "system",
73377
+ addonId: null,
73378
+ access: "view",
73379
+ role: "admin"
73380
+ },
73381
+ "actions.listForCamera": {
73382
+ capName: "actions",
73383
+ capScope: "system",
73384
+ addonId: null,
73385
+ access: "view",
73386
+ role: "viewer"
73387
+ },
73388
+ "actions.run": {
73389
+ capName: "actions",
73390
+ capScope: "system",
73391
+ addonId: null,
73392
+ access: "create",
73393
+ role: "viewer"
73394
+ },
73395
+ "actions.setLinks": {
73396
+ capName: "actions",
73397
+ capScope: "system",
73398
+ addonId: null,
73399
+ access: "create",
73400
+ role: "admin"
73401
+ },
73402
+ "actions.stop": {
73403
+ capName: "actions",
73404
+ capScope: "system",
73405
+ addonId: null,
73406
+ access: "create",
73407
+ role: "admin"
73408
+ },
73409
+ "actions.update": {
73410
+ capName: "actions",
73411
+ capScope: "system",
73412
+ addonId: null,
73413
+ access: "create",
73414
+ role: "admin"
73415
+ },
73416
+ "actionSource.listActions": {
73417
+ capName: "action-source",
73418
+ capScope: "system",
73419
+ addonId: null,
73420
+ access: "view",
73421
+ role: "admin"
73422
+ },
73423
+ "actionSource.runAction": {
73424
+ capName: "action-source",
73425
+ capScope: "system",
73426
+ addonId: null,
73427
+ access: "create",
73428
+ role: "admin"
73429
+ },
73430
+ "actionSource.stopAction": {
73431
+ capName: "action-source",
73432
+ capScope: "system",
73433
+ addonId: null,
73434
+ access: "create",
73435
+ role: "admin"
73436
+ },
72874
73437
  "addonPages.listPages": {
72875
73438
  capName: "addon-pages",
72876
73439
  capScope: "system",
@@ -74152,6 +74715,13 @@ Object.freeze({
74152
74715
  access: "view",
74153
74716
  role: "admin"
74154
74717
  },
74718
+ "coreBlocks.getAutomationRunState": {
74719
+ capName: "core-blocks",
74720
+ capScope: "system",
74721
+ addonId: null,
74722
+ access: "view",
74723
+ role: "admin"
74724
+ },
74155
74725
  "coreBlocks.getBlockSettings": {
74156
74726
  capName: "core-blocks",
74157
74727
  capScope: "system",
@@ -74173,6 +74743,13 @@ Object.freeze({
74173
74743
  access: "view",
74174
74744
  role: "admin"
74175
74745
  },
74746
+ "coreBlocks.getTraces": {
74747
+ capName: "core-blocks",
74748
+ capScope: "system",
74749
+ addonId: null,
74750
+ access: "view",
74751
+ role: "admin"
74752
+ },
74176
74753
  "coreBlocks.getTypeDefs": {
74177
74754
  capName: "core-blocks",
74178
74755
  capScope: "system",
@@ -74208,6 +74785,13 @@ Object.freeze({
74208
74785
  access: "create",
74209
74786
  role: "admin"
74210
74787
  },
74788
+ "coreBlocks.reportAutomationRun": {
74789
+ capName: "core-blocks",
74790
+ capScope: "system",
74791
+ addonId: null,
74792
+ access: "create",
74793
+ role: "admin"
74794
+ },
74211
74795
  "coreBlocks.restart": {
74212
74796
  capName: "core-blocks",
74213
74797
  capScope: "system",
@@ -82781,7 +83365,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82781
83365
  label: t("Full brightness", "Luminosità massima"),
82782
83366
  phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
82783
83367
  icon: "sun",
82784
- args: { percentage: 100 }
83368
+ args: { level: 100 }
82785
83369
  },
82786
83370
  {
82787
83371
  id: "brightness.half",
@@ -82789,7 +83373,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82789
83373
  label: t("Half brightness", "Luminosità a metà"),
82790
83374
  phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
82791
83375
  icon: "sun-dim",
82792
- args: { percentage: 50 }
83376
+ args: { level: 50 }
82793
83377
  },
82794
83378
  {
82795
83379
  id: "brightness.off",
@@ -82797,16 +83381,16 @@ var ACTUATOR_CAP_VOCABULARY = {
82797
83381
  label: t("Brightness off", "Luminosità a zero"),
82798
83382
  phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
82799
83383
  icon: "lightbulb-off",
82800
- args: { percentage: 0 }
83384
+ args: { level: 0 }
82801
83385
  },
82802
83386
  {
82803
83387
  id: "brightness.set",
82804
83388
  method: "setBrightness",
82805
83389
  label: t("Set brightness", "Imposta la luminosità"),
82806
- phrase: t("Set the brightness of {device} to {percentage}", "Imposta la luminosità di {device} a {percentage}"),
83390
+ phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
82807
83391
  icon: "sun-medium",
82808
83392
  openArgs: [{
82809
- key: "percentage",
83393
+ key: "level",
82810
83394
  label: PERCENT,
82811
83395
  offer: {
82812
83396
  kind: "number",
@@ -82820,13 +83404,13 @@ var ACTUATOR_CAP_VOCABULARY = {
82820
83404
  ],
82821
83405
  state: [{
82822
83406
  kind: "numeric",
82823
- field: "percentage",
83407
+ field: "level",
82824
83408
  quantity: t("the brightness", "la luminosità"),
82825
83409
  label: t("Brightness", "Luminosità"),
82826
83410
  unit: "%",
82827
83411
  icon: "sun"
82828
83412
  }],
82829
- events: { onBrightnessChanged: { notOperatorFacing: "the `percentage` state trigger reads the same change" } }
83413
+ events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
82830
83414
  },
82831
83415
  color: {
82832
83416
  scope: "device",
@@ -82840,7 +83424,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82840
83424
  icon: "sun",
82841
83425
  args: { color: {
82842
83426
  mode: "mired",
82843
- mireds: 370
83427
+ colorTemperature: 370
82844
83428
  } }
82845
83429
  },
82846
83430
  {
@@ -82851,7 +83435,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82851
83435
  icon: "snowflake",
82852
83436
  args: { color: {
82853
83437
  mode: "mired",
82854
- mireds: 200
83438
+ colorTemperature: 200
82855
83439
  } }
82856
83440
  },
82857
83441
  {
@@ -83465,7 +84049,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83465
84049
  label: t("Fan off", "Ventilatore spento"),
83466
84050
  phrase: t("Stop {device}", "Ferma {device}"),
83467
84051
  icon: "power-off",
83468
- args: { percentage: 0 }
84052
+ args: { speed: 0 }
83469
84053
  },
83470
84054
  {
83471
84055
  id: "fan.full",
@@ -83473,16 +84057,16 @@ var ACTUATOR_CAP_VOCABULARY = {
83473
84057
  label: t("Fan full", "Ventilatore al massimo"),
83474
84058
  phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
83475
84059
  icon: "fan",
83476
- args: { percentage: 100 }
84060
+ args: { speed: 100 }
83477
84061
  },
83478
84062
  {
83479
84063
  id: "fan.speed",
83480
84064
  method: "setPercentage",
83481
84065
  label: t("Set speed", "Imposta la velocità"),
83482
- phrase: t("Set the speed of {device} to {percentage}", "Imposta la velocità di {device} al {percentage}"),
84066
+ phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
83483
84067
  icon: "fan",
83484
84068
  openArgs: [{
83485
- key: "percentage",
84069
+ key: "speed",
83486
84070
  label: t("Speed", "Velocità"),
83487
84071
  offer: {
83488
84072
  kind: "number",
@@ -83544,7 +84128,7 @@ var ACTUATOR_CAP_VOCABULARY = {
83544
84128
  ],
83545
84129
  state: [{
83546
84130
  kind: "numeric",
83547
- field: "percentage",
84131
+ field: "speed",
83548
84132
  quantity: t("the speed", "la velocità"),
83549
84133
  label: t("Speed", "Velocità"),
83550
84134
  unit: "%",
@@ -84342,7 +84926,7 @@ var APPLIANCE_CAP_VOCABULARY = {
84342
84926
  },
84343
84927
  {
84344
84928
  kind: "numeric",
84345
- field: "progressPercent",
84929
+ field: "progress",
84346
84930
  quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
84347
84931
  label: t("Progress", "Avanzamento"),
84348
84932
  unit: "%",
@@ -84700,10 +85284,10 @@ var APPLIANCE_CAP_VOCABULARY = {
84700
85284
  id: "media.seek",
84701
85285
  method: "seek",
84702
85286
  label: t("Seek", "Vai al punto"),
84703
- phrase: t("Move {device} to {positionMs}", "Porta {device} al punto {positionMs}"),
85287
+ phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
84704
85288
  icon: "fast-forward",
84705
85289
  openArgs: [{
84706
- key: "positionMs",
85290
+ key: "position",
84707
85291
  label: t("Position", "Posizione"),
84708
85292
  offer: {
84709
85293
  kind: "number",
@@ -85752,7 +86336,7 @@ var SENSOR_CAP_VOCABULARY = {
85752
86336
  state: [
85753
86337
  {
85754
86338
  kind: "numeric",
85755
- field: "co2Ppm",
86339
+ field: "co2",
85756
86340
  quantity: t("the CO₂", "la CO₂"),
85757
86341
  label: t("CO₂", "CO₂"),
85758
86342
  unit: "ppm",
@@ -85760,7 +86344,7 @@ var SENSOR_CAP_VOCABULARY = {
85760
86344
  },
85761
86345
  {
85762
86346
  kind: "numeric",
85763
- field: "vocPpb",
86347
+ field: "voc",
85764
86348
  quantity: t("the VOC level", "il livello di COV"),
85765
86349
  label: t("VOC", "COV"),
85766
86350
  unit: "ppb",
@@ -85796,7 +86380,7 @@ var SENSOR_CAP_VOCABULARY = {
85796
86380
  noun: t("Light level", "Luminosità ambiente"),
85797
86381
  state: [{
85798
86382
  kind: "numeric",
85799
- field: "lux",
86383
+ field: "illuminance",
85800
86384
  quantity: t("the light level", "la luminosità"),
85801
86385
  label: t("Illuminance", "Illuminamento"),
85802
86386
  unit: "lx",
@@ -85999,7 +86583,7 @@ var SENSOR_CAP_VOCABULARY = {
85999
86583
  noun: t("Humidity", "Umidità"),
86000
86584
  state: [{
86001
86585
  kind: "numeric",
86002
- field: "percent",
86586
+ field: "humidity",
86003
86587
  quantity: t("the humidity", "l’umidità"),
86004
86588
  label: t("Humidity", "Umidità"),
86005
86589
  unit: "%",
@@ -86047,7 +86631,7 @@ var SENSOR_CAP_VOCABULARY = {
86047
86631
  state: [
86048
86632
  {
86049
86633
  kind: "numeric",
86050
- field: "watts",
86634
+ field: "power",
86051
86635
  quantity: t("the power draw", "il consumo"),
86052
86636
  label: t("Power", "Potenza"),
86053
86637
  unit: "W",
@@ -86055,7 +86639,7 @@ var SENSOR_CAP_VOCABULARY = {
86055
86639
  },
86056
86640
  {
86057
86641
  kind: "numeric",
86058
- field: "kwhTotal",
86642
+ field: "energy",
86059
86643
  quantity: t("the energy used", "l’energia consumata"),
86060
86644
  label: t("Energy", "Energia"),
86061
86645
  unit: "kWh",
@@ -86063,7 +86647,7 @@ var SENSOR_CAP_VOCABULARY = {
86063
86647
  },
86064
86648
  {
86065
86649
  kind: "numeric",
86066
- field: "volts",
86650
+ field: "voltage",
86067
86651
  quantity: t("the voltage", "la tensione"),
86068
86652
  label: t("Voltage", "Tensione"),
86069
86653
  unit: "V",
@@ -86071,7 +86655,7 @@ var SENSOR_CAP_VOCABULARY = {
86071
86655
  },
86072
86656
  {
86073
86657
  kind: "numeric",
86074
- field: "amps",
86658
+ field: "current",
86075
86659
  quantity: t("the current", "la corrente"),
86076
86660
  label: t("Current", "Corrente"),
86077
86661
  unit: "A",
@@ -86088,13 +86672,6 @@ var SENSOR_CAP_VOCABULARY = {
86088
86672
  label: t("Where", "Posizione"),
86089
86673
  phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
86090
86674
  icon: "map-pin"
86091
- }, {
86092
- kind: "numeric",
86093
- field: "batteryPercent",
86094
- quantity: t("the phone battery", "la batteria del telefono"),
86095
- label: t("Battery", "Batteria"),
86096
- unit: "%",
86097
- icon: "battery"
86098
86675
  }]
86099
86676
  },
86100
86677
  "pressure-sensor": {
@@ -86102,7 +86679,7 @@ var SENSOR_CAP_VOCABULARY = {
86102
86679
  noun: t("Pressure", "Pressione"),
86103
86680
  state: [{
86104
86681
  kind: "numeric",
86105
- field: "hpa",
86682
+ field: "pressure",
86106
86683
  quantity: t("the pressure", "la pressione"),
86107
86684
  label: t("Pressure", "Pressione"),
86108
86685
  unit: "hPa",
@@ -86138,7 +86715,7 @@ var SENSOR_CAP_VOCABULARY = {
86138
86715
  noun: t("Temperature", "Temperatura"),
86139
86716
  state: [{
86140
86717
  kind: "numeric",
86141
- field: "celsius",
86718
+ field: "temperature",
86142
86719
  quantity: t("the temperature", "la temperatura"),
86143
86720
  label: t("Temperature", "Temperatura"),
86144
86721
  unit: "°C",
@@ -86209,7 +86786,7 @@ var SENSOR_CAP_VOCABULARY = {
86209
86786
  state: [
86210
86787
  {
86211
86788
  kind: "numeric",
86212
- field: "percentage",
86789
+ field: "level",
86213
86790
  quantity: t("the battery level", "il livello della batteria"),
86214
86791
  label: t("Battery", "Batteria"),
86215
86792
  unit: "%",
@@ -86251,7 +86828,7 @@ var SENSOR_CAP_VOCABULARY = {
86251
86828
  icon: "battery-charging"
86252
86829
  }
86253
86830
  ],
86254
- events: { onStatusChanged: { notOperatorFacing: "the percentage / sleeping / charging state triggers each read one field of this change" } },
86831
+ events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
86255
86832
  extraEvents: [{
86256
86833
  category: EventCategory.DeviceAwake,
86257
86834
  label: t("Woke up", "Risvegliato"),
@@ -86269,7 +86846,7 @@ var SENSOR_CAP_VOCABULARY = {
86269
86846
  noun: t("Network link", "Collegamento di rete"),
86270
86847
  state: [{
86271
86848
  kind: "numeric",
86272
- field: "signalPercent",
86849
+ field: "signal",
86273
86850
  quantity: t("the signal strength", "l’intensità del segnale"),
86274
86851
  label: t("Signal", "Segnale"),
86275
86852
  unit: "%",
@@ -86362,6 +86939,8 @@ var ML = "model and training machinery — no device action";
86362
86939
  var INTERNAL = "internal plumbing between addons — never operator-facing";
86363
86940
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
86364
86941
  var SYSTEM_CAP_VOCABULARY = {
86942
+ "action-source": system(INTERNAL),
86943
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
86365
86944
  "addon-pages": system(UI_PLUMBING),
86366
86945
  "addon-pages-source": system(UI_PLUMBING),
86367
86946
  "addon-routes": system(UI_PLUMBING),
@@ -86569,6 +87148,31 @@ Object.freeze({
86569
87148
  form: "single",
86570
87149
  optional: false
86571
87150
  }],
87151
+ "actions.get": [{
87152
+ name: "deviceId",
87153
+ form: "single",
87154
+ optional: true
87155
+ }],
87156
+ "actions.getLinks": [{
87157
+ name: "deviceId",
87158
+ form: "single",
87159
+ optional: false
87160
+ }],
87161
+ "actions.listForCamera": [{
87162
+ name: "deviceId",
87163
+ form: "single",
87164
+ optional: false
87165
+ }],
87166
+ "actions.run": [{
87167
+ name: "deviceId",
87168
+ form: "single",
87169
+ optional: true
87170
+ }],
87171
+ "actions.setLinks": [{
87172
+ name: "deviceId",
87173
+ form: "single",
87174
+ optional: false
87175
+ }],
86572
87176
  "addonSettings.getDeviceSettings": [{
86573
87177
  name: "deviceId",
86574
87178
  form: "single",
@@ -90999,6 +91603,7 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
90999
91603
  }
91000
91604
  return best;
91001
91605
  }
91606
+ String.raw`(?<=^|["'(\s>,\[{])`;
91002
91607
  var MB = 1024 * 1024;
91003
91608
  1024 * MB, 3072 * MB;
91004
91609
  //#endregion