@camstack/addon-matter-broker 0.2.151 → 0.2.152

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.mjs CHANGED
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
11
11
  import { finished } from "node:stream/promises";
12
12
  import { createConnection, createServer as createServer$2 } from "node:net";
13
13
  import * as dgram from "node:dgram";
14
- //#region ../types/dist/event-category-CT-hz5Rb.mjs
14
+ //#region ../types/dist/event-category-DmZDPDf_.mjs
15
15
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
16
16
  EventCategory["SystemBoot"] = "system.boot";
17
17
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -638,7 +638,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
638
638
  * (a track was promoted to a stationary-registry entry) or departs (the
639
639
  * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
640
640
  * the dedicated "Stationary" section — never the live event feed. Payload:
641
- * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
641
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
642
642
  */
643
643
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
644
644
  /**
@@ -776,6 +776,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
776
776
  */
777
777
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
778
778
  /**
779
+ * An action run started or ended. Emitted by the `actions` surface.
780
+ * Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
781
+ */
782
+ EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
783
+ /**
779
784
  * Progress update from a running model conversion job.
780
785
  * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
781
786
  * Emitted by `addon-model-studio` on the converting node.
@@ -5587,7 +5592,7 @@ var ZodIssueCode = {
5587
5592
  var ZodFirstPartyTypeKind;
5588
5593
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5589
5594
  //#endregion
5590
- //#region ../types/dist/sleep--jXS9hWo.mjs
5595
+ //#region ../types/dist/sleep-Crlmu_tO.mjs
5591
5596
  /**
5592
5597
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5593
5598
  * window to float samples (D455).
@@ -8895,6 +8900,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
8895
8900
  /** Every capability name, so addon code can check a name without the schema graph. */
8896
8901
  var CAP_NAMES = Object.freeze([
8897
8902
  "accessories",
8903
+ "action-source",
8904
+ "actions",
8898
8905
  "addon-pages",
8899
8906
  "addon-pages-source",
8900
8907
  "addon-routes",
@@ -9083,11 +9090,11 @@ var CAP_NAMES = Object.freeze([
9083
9090
  Object.freeze({
9084
9091
  "air-quality-sensor": [
9085
9092
  {
9086
- "path": "co2Ppm",
9093
+ "path": "co2",
9087
9094
  "valueType": "number"
9088
9095
  },
9089
9096
  {
9090
- "path": "vocPpb",
9097
+ "path": "voc",
9091
9098
  "valueType": "number"
9092
9099
  },
9093
9100
  {
@@ -9137,7 +9144,7 @@ Object.freeze({
9137
9144
  }
9138
9145
  ],
9139
9146
  "ambient-light-sensor": [{
9140
- "path": "lux",
9147
+ "path": "illuminance",
9141
9148
  "valueType": "number"
9142
9149
  }],
9143
9150
  "audio-metrics": [
@@ -9198,7 +9205,7 @@ Object.freeze({
9198
9205
  ],
9199
9206
  "battery": [
9200
9207
  {
9201
- "path": "percentage",
9208
+ "path": "level",
9202
9209
  "valueType": "number"
9203
9210
  },
9204
9211
  {
@@ -9220,7 +9227,7 @@ Object.freeze({
9220
9227
  "valueType": "number"
9221
9228
  },
9222
9229
  {
9223
- "path": "volts",
9230
+ "path": "voltage",
9224
9231
  "valueType": "number"
9225
9232
  },
9226
9233
  {
@@ -9241,7 +9248,7 @@ Object.freeze({
9241
9248
  "valueType": "boolean"
9242
9249
  }],
9243
9250
  "brightness": [{
9244
- "path": "percentage",
9251
+ "path": "level",
9245
9252
  "valueType": "number"
9246
9253
  }],
9247
9254
  "broker": [{
@@ -9442,7 +9449,7 @@ Object.freeze({
9442
9449
  "valueType": "number"
9443
9450
  },
9444
9451
  {
9445
- "path": "mireds",
9452
+ "path": "colorTemperature",
9446
9453
  "valueType": "number"
9447
9454
  }
9448
9455
  ],
@@ -9621,15 +9628,15 @@ Object.freeze({
9621
9628
  "valueType": "string"
9622
9629
  },
9623
9630
  {
9624
- "path": "remainingSeconds",
9631
+ "path": "remaining",
9625
9632
  "valueType": "number"
9626
9633
  },
9627
9634
  {
9628
- "path": "delayedStartSeconds",
9635
+ "path": "delayedStart",
9629
9636
  "valueType": "number"
9630
9637
  },
9631
9638
  {
9632
- "path": "progressPercent",
9639
+ "path": "progress",
9633
9640
  "valueType": "number"
9634
9641
  },
9635
9642
  {
@@ -9743,7 +9750,7 @@ Object.freeze({
9743
9750
  ],
9744
9751
  "fan-control": [
9745
9752
  {
9746
- "path": "percentage",
9753
+ "path": "speed",
9747
9754
  "valueType": "number"
9748
9755
  },
9749
9756
  {
@@ -9843,7 +9850,7 @@ Object.freeze({
9843
9850
  }
9844
9851
  ],
9845
9852
  "humidity-sensor": [{
9846
- "path": "percent",
9853
+ "path": "humidity",
9847
9854
  "valueType": "number"
9848
9855
  }],
9849
9856
  "image": [{
@@ -9953,7 +9960,7 @@ Object.freeze({
9953
9960
  "valueType": "number"
9954
9961
  },
9955
9962
  {
9956
- "path": "progressPercent",
9963
+ "path": "progress",
9957
9964
  "valueType": "number"
9958
9965
  },
9959
9966
  {
@@ -10032,11 +10039,11 @@ Object.freeze({
10032
10039
  "valueType": "string"
10033
10040
  },
10034
10041
  {
10035
- "path": "positionMs",
10042
+ "path": "position",
10036
10043
  "valueType": "number"
10037
10044
  },
10038
10045
  {
10039
- "path": "durationMs",
10046
+ "path": "duration",
10040
10047
  "valueType": "number"
10041
10048
  },
10042
10049
  {
@@ -10138,11 +10145,11 @@ Object.freeze({
10138
10145
  ]
10139
10146
  },
10140
10147
  {
10141
- "path": "signalPercent",
10148
+ "path": "signal",
10142
10149
  "valueType": "number"
10143
10150
  },
10144
10151
  {
10145
- "path": "rssiDbm",
10152
+ "path": "rssi",
10146
10153
  "valueType": "number"
10147
10154
  },
10148
10155
  {
@@ -10197,6 +10204,18 @@ Object.freeze({
10197
10204
  "path": "foodLevel",
10198
10205
  "valueType": "number"
10199
10206
  },
10207
+ {
10208
+ "path": "bowlFood",
10209
+ "valueType": "number"
10210
+ },
10211
+ {
10212
+ "path": "eating",
10213
+ "valueType": "boolean"
10214
+ },
10215
+ {
10216
+ "path": "supportsMarkRefilled",
10217
+ "valueType": "boolean"
10218
+ },
10200
10219
  {
10201
10220
  "path": "food1",
10202
10221
  "valueType": "number"
@@ -10261,23 +10280,23 @@ Object.freeze({
10261
10280
  ],
10262
10281
  "power-meter": [
10263
10282
  {
10264
- "path": "watts",
10283
+ "path": "power",
10265
10284
  "valueType": "number"
10266
10285
  },
10267
10286
  {
10268
- "path": "kwhTotal",
10287
+ "path": "energy",
10269
10288
  "valueType": "number"
10270
10289
  },
10271
10290
  {
10272
- "path": "volts",
10291
+ "path": "voltage",
10273
10292
  "valueType": "number"
10274
10293
  },
10275
10294
  {
10276
- "path": "amps",
10295
+ "path": "current",
10277
10296
  "valueType": "number"
10278
10297
  },
10279
10298
  {
10280
- "path": "va",
10299
+ "path": "apparentPower",
10281
10300
  "valueType": "number"
10282
10301
  },
10283
10302
  {
@@ -10305,14 +10324,10 @@ Object.freeze({
10305
10324
  {
10306
10325
  "path": "gps.accuracyMeters",
10307
10326
  "valueType": "number"
10308
- },
10309
- {
10310
- "path": "batteryPercent",
10311
- "valueType": "number"
10312
10327
  }
10313
10328
  ],
10314
10329
  "pressure-sensor": [{
10315
- "path": "hpa",
10330
+ "path": "pressure",
10316
10331
  "valueType": "number"
10317
10332
  }],
10318
10333
  "privacy-mask": [{
@@ -10626,7 +10641,7 @@ Object.freeze({
10626
10641
  "valueType": "boolean"
10627
10642
  }],
10628
10643
  "temperature-sensor": [{
10629
- "path": "celsius",
10644
+ "path": "temperature",
10630
10645
  "valueType": "number"
10631
10646
  }],
10632
10647
  "update": [
@@ -10674,7 +10689,7 @@ Object.freeze({
10674
10689
  "valueType": "string"
10675
10690
  },
10676
10691
  {
10677
- "path": "progressPercent",
10692
+ "path": "progress",
10678
10693
  "valueType": "number"
10679
10694
  },
10680
10695
  {
@@ -11159,7 +11174,7 @@ function errMsg(err) {
11159
11174
  return String(err);
11160
11175
  }
11161
11176
  //#endregion
11162
- //#region ../types/dist/composition-Bb8iwHEJ.mjs
11177
+ //#region ../types/dist/composition-CZImLpOI.mjs
11163
11178
  /**
11164
11179
  * The ffmpeg build every CamStack node downloads, per platform and arch.
11165
11180
  *
@@ -15679,6 +15694,14 @@ var AutomationConditionLeafSchema = object({
15679
15694
  array(union([string$2(), number()]))
15680
15695
  ])
15681
15696
  });
15697
+ var AutomationConditionStationaryPresentSchema = object({
15698
+ kind: literal("stationary-present"),
15699
+ deviceId: number().int().nonnegative(),
15700
+ /** Class names; a macro class matches every raw class that maps to it. */
15701
+ classes: array(string$2().min(1)).min(1).optional(),
15702
+ /** The parked object must be in at least one of these zones. */
15703
+ zones: array(string$2().min(1)).min(1).optional()
15704
+ });
15682
15705
  /**
15683
15706
  * The expression leaf, declared as a plain object rather than an intersection
15684
15707
  * with {@link ExpressionSourceSchema}: a discriminated union has to be able to
@@ -15712,7 +15735,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
15712
15735
  child: AutomationConditionSchema
15713
15736
  }),
15714
15737
  AutomationConditionLeafSchema,
15715
- AutomationConditionExpressionSchema
15738
+ AutomationConditionExpressionSchema,
15739
+ AutomationConditionStationaryPresentSchema
15716
15740
  ]));
15717
15741
  /**
15718
15742
  * What starts a run.
@@ -15753,7 +15777,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15753
15777
  kind: literal("schedule"),
15754
15778
  cron: string$2().min(1).max(120)
15755
15779
  }),
15756
- object({ kind: literal("manual") })
15780
+ object({ kind: literal("manual") }),
15781
+ object({
15782
+ kind: literal("detection"),
15783
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15784
+ * matches every raw class that maps to it; any other name matches
15785
+ * exactly. */
15786
+ classes: array(string$2().min(1)).min(1),
15787
+ deviceIds: array(number().int().nonnegative()).min(1),
15788
+ /** The track must have visited at least one of these zones. */
15789
+ zones: array(string$2().min(1)).min(1).optional(),
15790
+ /** Best-so-far confidence the track must reach. */
15791
+ minScore: number().min(0).max(1).optional()
15792
+ }),
15793
+ object({
15794
+ kind: literal("stationary"),
15795
+ deviceIds: array(number().int().nonnegative()).min(1),
15796
+ /** Class names; a macro class matches like the detection trigger. */
15797
+ classes: array(string$2().min(1)).min(1).optional(),
15798
+ /** The parked object must be in at least one of these zones. */
15799
+ zones: array(string$2().min(1)).min(1).optional(),
15800
+ /** `appeared`: it became parked. `departed`: the registry retired it.
15801
+ * The vocabulary of `PipelineAnalyticsStationaryChanged`. */
15802
+ phase: _enum(["appeared", "departed"])
15803
+ }),
15804
+ object({
15805
+ kind: literal("interval"),
15806
+ minutes: number().int().min(1).max(1440)
15807
+ })
15757
15808
  ]);
15758
15809
  /**
15759
15810
  * One action step.
@@ -15773,28 +15824,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15773
15824
  * is called. The runner still receives a number and is untouched; the
15774
15825
  * resolution is the recipe's job, not the runner's.
15775
15826
  */
15827
+ var AutomationWaitStepSchema = object({
15828
+ kind: literal("wait"),
15829
+ seconds: number().min(0).max(300)
15830
+ });
15831
+ var AutomationCapStepSchema = object({
15832
+ kind: literal("cap"),
15833
+ /**
15834
+ * One device, several same-family devices (locks / climate family / …),
15835
+ * or `{ $var }` for the device that triggered the run. An array is
15836
+ * fan-out at codegen — each id gets the same cap.method call.
15837
+ */
15838
+ deviceId: union([
15839
+ number().int(),
15840
+ array(number().int()).min(1),
15841
+ object({ $var: string$2().min(1) })
15842
+ ]),
15843
+ cap: string$2().min(1),
15844
+ method: string$2().min(1),
15845
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
15846
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
15847
+ * the expression leaf. */
15848
+ args: record(string$2(), unknown()).optional()
15849
+ });
15850
+ /**
15851
+ * The steps an internal Action may contain: cap and wait, and nothing that can
15852
+ * call back into an Action — so an Action can never reach itself (no cycles).
15853
+ */
15854
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15776
15855
  var AutomationActionSchema = discriminatedUnion("kind", [
15856
+ AutomationWaitStepSchema,
15857
+ AutomationCapStepSchema,
15777
15858
  object({
15778
- kind: literal("wait"),
15779
- seconds: number().min(0).max(300)
15780
- }),
15781
- object({
15782
- kind: literal("cap"),
15783
- /**
15784
- * One device, several same-family devices (locks / climate family / …),
15785
- * or `{ $var }` for the device that triggered the run. An array is
15786
- * fan-out at codegen — each id gets the same cap.method call.
15787
- */
15788
- deviceId: union([
15789
- number().int(),
15790
- array(number().int()).min(1),
15791
- object({ $var: string$2().min(1) })
15792
- ]),
15793
- cap: string$2().min(1),
15794
- method: string$2().min(1),
15795
- /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
15796
- * evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
15797
- args: record(string$2(), unknown()).optional()
15859
+ kind: literal("action"),
15860
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
15861
+ actionId: string$2().min(1),
15862
+ /** Values for the action's declared variables; the others take their default. */
15863
+ variables: record(string$2(), union([
15864
+ string$2(),
15865
+ number(),
15866
+ boolean()
15867
+ ])).optional()
15798
15868
  }),
15799
15869
  object({
15800
15870
  kind: literal("code"),
@@ -15803,10 +15873,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15803
15873
  code: string$2().min(1).max(2e4)
15804
15874
  })
15805
15875
  ]);
15876
+ /**
15877
+ * How a trigger that arrives while the automation is busy (or cooling down) is
15878
+ * handled. One of the automation's execution modes, never a property of its
15879
+ * actions. Absent means `single`.
15880
+ *
15881
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
15882
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
15883
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
15884
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
15885
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
15886
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
15887
+ * wait, never the single/queued limits.
15888
+ */
15889
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
15890
+ object({ mode: literal("single") }),
15891
+ object({ mode: literal("restart") }),
15892
+ object({
15893
+ mode: literal("queued"),
15894
+ max: number().int().min(1).max(10)
15895
+ }),
15896
+ object({
15897
+ mode: literal("parallel"),
15898
+ max: number().int().min(1).max(10)
15899
+ }),
15900
+ object({
15901
+ mode: literal("cooldown"),
15902
+ minutes: number().int().min(1).max(1440)
15903
+ })
15904
+ ]);
15806
15905
  var AutomationRecipeSchema = object({
15807
15906
  triggers: array(AutomationTriggerSchema),
15808
15907
  conditions: AutomationConditionSchema.optional(),
15809
- actions: array(AutomationActionSchema)
15908
+ actions: array(AutomationActionSchema),
15909
+ runMode: AutomationRunModeSchema.optional(),
15910
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
15911
+ keepTraces: number().int().min(1).max(100).optional()
15912
+ });
15913
+ new Set([
15914
+ {
15915
+ id: "person",
15916
+ name: "Person"
15917
+ },
15918
+ {
15919
+ id: "vehicle",
15920
+ name: "Vehicle"
15921
+ },
15922
+ {
15923
+ id: "animal",
15924
+ name: "Animal"
15925
+ },
15926
+ {
15927
+ id: "package",
15928
+ name: "Package"
15929
+ }
15930
+ ].map((l) => l.id));
15931
+ var COCO_TO_MACRO = {
15932
+ mapping: {
15933
+ person: "person",
15934
+ bicycle: "vehicle",
15935
+ car: "vehicle",
15936
+ motorcycle: "vehicle",
15937
+ airplane: "vehicle",
15938
+ bus: "vehicle",
15939
+ train: "vehicle",
15940
+ truck: "vehicle",
15941
+ boat: "vehicle",
15942
+ bird: "animal",
15943
+ cat: "animal",
15944
+ dog: "animal",
15945
+ horse: "animal",
15946
+ sheep: "animal",
15947
+ cow: "animal",
15948
+ elephant: "animal",
15949
+ bear: "animal",
15950
+ zebra: "animal",
15951
+ giraffe: "animal",
15952
+ suitcase: "package",
15953
+ backpack: "package",
15954
+ handbag: "package"
15955
+ },
15956
+ preserveOriginal: false
15957
+ };
15958
+ new Set(Object.values(COCO_TO_MACRO.mapping));
15959
+ /**
15960
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
15961
+ * so the editor can paint every block green or red with its reason.
15962
+ *
15963
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
15964
+ * every condition node (containers and leaves, including the ones a
15965
+ * short-circuit never reached), the run-mode verdict and every action step —
15966
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
15967
+ * for an Action run). Skipped
15968
+ * evaluations are traced too, and identical consecutive skips collapse into a
15969
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
15970
+ *
15971
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
15972
+ * vocabulary so an Action run records the same step shape.
15973
+ */
15974
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
15975
+ var TraceValueSchema = union([
15976
+ string$2(),
15977
+ number(),
15978
+ boolean(),
15979
+ _null(),
15980
+ array(union([string$2(), number()]))
15981
+ ]);
15982
+ var AutomationRunOutcomeSchema = _enum([
15983
+ "ran",
15984
+ "skipped-trigger",
15985
+ "skipped-conditions",
15986
+ "skipped-cooldown",
15987
+ "skipped-overlap",
15988
+ "failed",
15989
+ "aborted"
15990
+ ]);
15991
+ /** `not-evaluated` = a short-circuit never reached the node. */
15992
+ var TraceNodeOutcomeSchema = _enum([
15993
+ "pass",
15994
+ "fail",
15995
+ "not-evaluated"
15996
+ ]);
15997
+ var AutomationTriggerTraceSchema = object({
15998
+ kind: string$2().min(1),
15999
+ outcome: _enum(["pass", "fail"]),
16000
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
16001
+ reason: string$2(),
16002
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
16003
+ vars: record(string$2(), TraceValueSchema)
16004
+ });
16005
+ var AutomationConditionTraceNodeSchema = object({
16006
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
16007
+ path: string$2().min(1),
16008
+ kind: _enum([
16009
+ "all",
16010
+ "any",
16011
+ "not",
16012
+ "condition",
16013
+ "expression",
16014
+ "stationary-present"
16015
+ ]),
16016
+ outcome: TraceNodeOutcomeSchema,
16017
+ reason: string$2(),
16018
+ deviceId: number().int().optional(),
16019
+ cap: string$2().optional(),
16020
+ fieldPath: string$2().optional(),
16021
+ operator: string$2().optional(),
16022
+ expected: TraceValueSchema.optional(),
16023
+ /** What the mirror held; `null` when it held nothing (unknown). */
16024
+ observed: TraceValueSchema.optional()
16025
+ });
16026
+ var AutomationRunVerdictSchema = object({
16027
+ mode: AutomationRunModeSchema,
16028
+ decision: _enum([
16029
+ "run",
16030
+ "queued",
16031
+ "restart",
16032
+ "drop",
16033
+ "cooldown",
16034
+ "bypass"
16035
+ ]),
16036
+ reason: string$2()
16037
+ });
16038
+ /** One executed (or not-run) step — shared by automations and Action runs. */
16039
+ var AutomationStepTraceSchema = object({
16040
+ /** `actions.<i>` */
16041
+ path: string$2().min(1),
16042
+ kind: string$2().min(1),
16043
+ cap: string$2().optional(),
16044
+ method: string$2().optional(),
16045
+ deviceId: number().int().optional(),
16046
+ startedAt: number().optional(),
16047
+ endedAt: number().optional(),
16048
+ outcome: _enum([
16049
+ "ok",
16050
+ "error",
16051
+ "not-run"
16052
+ ]),
16053
+ message: string$2().optional()
16054
+ });
16055
+ var AutomationRunTraceSchema = object({
16056
+ runId: string$2().min(1),
16057
+ startedAt: number(),
16058
+ endedAt: number(),
16059
+ trigger: AutomationTriggerTraceSchema,
16060
+ conditions: array(AutomationConditionTraceNodeSchema),
16061
+ verdict: AutomationRunVerdictSchema.optional(),
16062
+ steps: array(AutomationStepTraceSchema),
16063
+ outcome: AutomationRunOutcomeSchema,
16064
+ /** How many identical consecutive skips this trace stands for (>= 1). */
16065
+ repeat: number().int().min(1),
16066
+ /** When the latest of those repeats happened. */
16067
+ lastAt: number()
16068
+ });
16069
+ /**
16070
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
16071
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
16072
+ */
16073
+ var AutomationStateDocSchema = object({
16074
+ version: literal(1),
16075
+ lastRunStartedAt: number().nullable(),
16076
+ traces: array(AutomationRunTraceSchema)
16077
+ });
16078
+ /**
16079
+ * Actions — named, runnable things an operator (or an automation) can start,
16080
+ * declared as LIST ENTRIES, never as devices.
16081
+ *
16082
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
16083
+ * hub's `actions` record kind) or declared by an addon through the
16084
+ * `action-source` collection (a Home Assistant script, a scene …). The one
16085
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
16086
+ * catalog of its own (D3) — every `list` asks the providers live.
16087
+ *
16088
+ * This file is the data half: the entry schema, the variables an entry may
16089
+ * declare, and the pure resolution of the values a run was given. It holds no
16090
+ * runtime.
16091
+ */
16092
+ /** What a variable's value is. `select` takes one of `options`. */
16093
+ var ActionVariableTypeSchema = _enum([
16094
+ "string",
16095
+ "number",
16096
+ "boolean",
16097
+ "select"
16098
+ ]);
16099
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
16100
+ var ActionVariableValueSchema = union([
16101
+ string$2(),
16102
+ number(),
16103
+ boolean()
16104
+ ]);
16105
+ /**
16106
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
16107
+ * value) or `{{vars.name}}` (inside a string) in their args.
16108
+ */
16109
+ var ActionVariableSchema = object({
16110
+ name: string$2().regex(ACTION_VARIABLE_NAME_RE),
16111
+ label: string$2().min(1).max(120).optional(),
16112
+ type: ActionVariableTypeSchema,
16113
+ required: boolean().optional(),
16114
+ default: ActionVariableValueSchema.optional(),
16115
+ /** The allowed values of a `select`. */
16116
+ options: array(string$2().min(1)).min(1).optional()
16117
+ }).superRefine((v, ctx) => {
16118
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
16119
+ code: "custom",
16120
+ message: "a select variable needs options",
16121
+ path: ["options"]
16122
+ });
16123
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
16124
+ code: "custom",
16125
+ message: variableValueError(v, v.default) ?? "invalid default",
16126
+ path: ["default"]
16127
+ });
16128
+ });
16129
+ /** Why `value` is not a legal value for the variable, or null when it is. */
16130
+ function variableValueError(variable, value) {
16131
+ switch (variable.type) {
16132
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
16133
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
16134
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
16135
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
16136
+ }
16137
+ }
16138
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
16139
+ function isInternalActionId(actionId) {
16140
+ return actionId.startsWith("internal:") && actionId.length > 9;
16141
+ }
16142
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
16143
+ function addonIdOfActionId(actionId) {
16144
+ if (isInternalActionId(actionId)) return null;
16145
+ const at = actionId.indexOf(":");
16146
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
16147
+ }
16148
+ var ActionStatusSchema = object({
16149
+ isRunning: boolean(),
16150
+ /** Ms epoch the latest run STARTED; null when it never ran. */
16151
+ lastRunAt: number().nullable(),
16152
+ /** The latest run's failure; null on success or when it never ran. */
16153
+ lastError: string$2().nullable()
16154
+ });
16155
+ var ActionEntrySchema = object({
16156
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
16157
+ id: string$2().min(3),
16158
+ name: string$2().min(1).max(120),
16159
+ /** The addon that declared it; `core-blocks` for an internal one. */
16160
+ addonId: string$2().min(1),
16161
+ source: ActionSourceKindSchema,
16162
+ /** An addon-declared entry is edited where it was declared. */
16163
+ readOnly: boolean(),
16164
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
16165
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
16166
+ variables: array(ActionVariableSchema).max(20).optional(),
16167
+ status: ActionStatusSchema
16168
+ }).superRefine((entry, ctx) => {
16169
+ if (entry.source === "internal") {
16170
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
16171
+ code: "custom",
16172
+ message: "an internal action id is internal:<uuid>",
16173
+ path: ["id"]
16174
+ });
16175
+ return;
16176
+ }
16177
+ if (entry.steps !== void 0) ctx.addIssue({
16178
+ code: "custom",
16179
+ message: "only an internal action carries steps",
16180
+ path: ["steps"]
16181
+ });
16182
+ if (!entry.readOnly) ctx.addIssue({
16183
+ code: "custom",
16184
+ message: "an addon action is read-only here",
16185
+ path: ["readOnly"]
16186
+ });
16187
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
16188
+ code: "custom",
16189
+ message: "an addon action id is <addonId>:<localId>",
16190
+ path: ["id"]
16191
+ });
16192
+ });
16193
+ /** What an operator writes for an internal action. */
16194
+ var ActionInputSchema = object({
16195
+ name: string$2().min(1).max(120),
16196
+ steps: array(ActionStepSchema).min(1).max(50),
16197
+ variables: array(ActionVariableSchema).max(20).optional()
16198
+ });
16199
+ /** Who started a run. Absent = the operator pressed it. */
16200
+ var ActionRunOriginSchema = object({
16201
+ /** The automation block whose step started it. */
16202
+ blockId: string$2().min(1).optional() });
16203
+ /** `started` = the caller did not ask to wait. */
16204
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
16205
+ var ActionRunResultSchema = object({
16206
+ runId: string$2().min(1),
16207
+ outcome: ActionRunOutcomeSchema,
16208
+ /** Why it did not run, or what failed. */
16209
+ message: string$2().optional()
16210
+ });
16211
+ _enum([
16212
+ "not-found",
16213
+ "read-only",
16214
+ "invalid-variables",
16215
+ "invalid-steps",
16216
+ "not-linked",
16217
+ "busy"
16218
+ ]);
16219
+ object({
16220
+ actionId: string$2(),
16221
+ runId: string$2(),
16222
+ isRunning: boolean(),
16223
+ /** Set when the run ended. */
16224
+ outcome: AutomationRunOutcomeSchema.optional(),
16225
+ lastRunAt: number().nullable(),
16226
+ lastError: string$2().nullable()
15810
16227
  });
15811
16228
  /**
15812
16229
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -18542,7 +18959,7 @@ var CompositionEventPlanSchema = object({
18542
18959
  stateField: string$2(),
18543
18960
  fieldKey: string$2()
18544
18961
  });
18545
- /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
18962
+ /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
18546
18963
  var CompositionProblemSchema = object({
18547
18964
  code: _enum([
18548
18965
  "reserved-variant",
@@ -18861,7 +19278,7 @@ var GROUP_TEMPLATES = [
18861
19278
  summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
18862
19279
  role: DeviceRole.TemperatureSensor,
18863
19280
  outputCap: "temperature-sensor",
18864
- outputField: "celsius",
19281
+ outputField: "temperature",
18865
19282
  quantity: "temperature",
18866
19283
  defaultAggregate: "mean",
18867
19284
  empty: "null",
@@ -18872,7 +19289,7 @@ var GROUP_TEMPLATES = [
18872
19289
  summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
18873
19290
  role: DeviceRole.HumiditySensor,
18874
19291
  outputCap: "humidity-sensor",
18875
- outputField: "percent",
19292
+ outputField: "humidity",
18876
19293
  quantity: "humidity",
18877
19294
  defaultAggregate: "mean",
18878
19295
  empty: "null",
@@ -18883,7 +19300,7 @@ var GROUP_TEMPLATES = [
18883
19300
  summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
18884
19301
  role: DeviceRole.PressureSensor,
18885
19302
  outputCap: "pressure-sensor",
18886
- outputField: "hpa",
19303
+ outputField: "pressure",
18887
19304
  quantity: "pressure",
18888
19305
  defaultAggregate: "mean",
18889
19306
  empty: "null",
@@ -18894,7 +19311,7 @@ var GROUP_TEMPLATES = [
18894
19311
  summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
18895
19312
  role: DeviceRole.AmbientLightSensor,
18896
19313
  outputCap: "ambient-light-sensor",
18897
- outputField: "lux",
19314
+ outputField: "illuminance",
18898
19315
  quantity: "illuminance",
18899
19316
  defaultAggregate: "mean",
18900
19317
  empty: "null",
@@ -18905,7 +19322,7 @@ var GROUP_TEMPLATES = [
18905
19322
  summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
18906
19323
  role: DeviceRole.PowerSensor,
18907
19324
  outputCap: "power-meter",
18908
- outputField: "watts",
19325
+ outputField: "power",
18909
19326
  quantity: "power",
18910
19327
  defaultAggregate: "sum",
18911
19328
  empty: "omit",
@@ -18916,7 +19333,7 @@ var GROUP_TEMPLATES = [
18916
19333
  summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
18917
19334
  role: DeviceRole.EnergySensor,
18918
19335
  outputCap: "power-meter",
18919
- outputField: "kwhTotal",
19336
+ outputField: "energy",
18920
19337
  quantity: "energy",
18921
19338
  defaultAggregate: "sum",
18922
19339
  empty: "omit",
@@ -18927,7 +19344,7 @@ var GROUP_TEMPLATES = [
18927
19344
  summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
18928
19345
  role: DeviceRole.BatterySensor,
18929
19346
  outputCap: "battery",
18930
- outputField: "percentage",
19347
+ outputField: "level",
18931
19348
  quantity: "percentage",
18932
19349
  defaultAggregate: "mean",
18933
19350
  empty: "null",
@@ -19505,7 +19922,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19505
19922
  kind: "mutation",
19506
19923
  auth: "admin",
19507
19924
  access: "view"
19508
- });
19925
+ }), method(object({
19926
+ blockId: string$2().min(1),
19927
+ trace: AutomationRunTraceSchema.optional(),
19928
+ runStartedAt: number().optional(),
19929
+ keepTraces: number().int().min(1).max(100).optional()
19930
+ }), _void(), {
19931
+ kind: "mutation",
19932
+ auth: "admin"
19933
+ }), method(object({ blockId: string$2().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string$2().min(1) }), object({
19934
+ traces: array(AutomationRunTraceSchema),
19935
+ lastError: string$2().nullable()
19936
+ }), { auth: "admin" });
19509
19937
  /**
19510
19938
  * `custom-model-registry` — collection cap exposing operator-registered
19511
19939
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -44807,51 +45235,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
44807
45235
  kind: "mutation",
44808
45236
  auth: "admin"
44809
45237
  });
44810
- new Set([
44811
- {
44812
- id: "person",
44813
- name: "Person"
44814
- },
44815
- {
44816
- id: "vehicle",
44817
- name: "Vehicle"
44818
- },
44819
- {
44820
- id: "animal",
44821
- name: "Animal"
44822
- },
44823
- {
44824
- id: "package",
44825
- name: "Package"
44826
- }
44827
- ].map((l) => l.id));
44828
- var COCO_TO_MACRO = {
44829
- mapping: {
44830
- person: "person",
44831
- bicycle: "vehicle",
44832
- car: "vehicle",
44833
- motorcycle: "vehicle",
44834
- airplane: "vehicle",
44835
- bus: "vehicle",
44836
- train: "vehicle",
44837
- truck: "vehicle",
44838
- boat: "vehicle",
44839
- bird: "animal",
44840
- cat: "animal",
44841
- dog: "animal",
44842
- horse: "animal",
44843
- sheep: "animal",
44844
- cow: "animal",
44845
- elephant: "animal",
44846
- bear: "animal",
44847
- zebra: "animal",
44848
- giraffe: "animal",
44849
- suitcase: "package",
44850
- backpack: "package",
44851
- handbag: "package"
44852
- },
44853
- preserveOriginal: false
44854
- };
44855
45238
  var AUDIO_MACRO_LABELS = [
44856
45239
  {
44857
45240
  id: "speech",
@@ -57418,9 +57801,9 @@ method(object({ nodeId: string$2().optional() }).optional(), array(AddonListItem
57418
57801
  */
57419
57802
  var AirQualitySensorStatusSchema = object({
57420
57803
  /** Carbon dioxide concentration in ppm. */
57421
- co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
57804
+ co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
57422
57805
  /** Total volatile organic compounds in ppb. */
57423
- vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57806
+ voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57424
57807
  /** Particulate matter ≤ 2.5 μm in µg/m³. */
57425
57808
  pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
57426
57809
  /** Particulate matter ≤ 10 μm in µg/m³. */
@@ -57453,12 +57836,12 @@ var airQualitySensorCapability = {
57453
57836
  * History (D850): recorded series.
57454
57837
  */
57455
57838
  history: { fields: {
57456
- co2Ppm: {
57839
+ co2: {
57457
57840
  kind: "gauge",
57458
57841
  unit: "ppm",
57459
57842
  deadband: 5
57460
57843
  },
57461
- vocPpb: {
57844
+ voc: {
57462
57845
  kind: "gauge",
57463
57846
  unit: "ppb",
57464
57847
  deadband: 5
@@ -57489,7 +57872,7 @@ var airQualitySensorCapability = {
57489
57872
  */
57490
57873
  var AmbientLightSensorStatusSchema = object({
57491
57874
  /** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
57492
- lux: number().min(0).nullable().meta(readingMeta("illuminance", {
57875
+ illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
57493
57876
  precision: 0,
57494
57877
  label: "Illuminance"
57495
57878
  })),
@@ -57518,7 +57901,7 @@ var ambientLightSensorCapability = {
57518
57901
  /**
57519
57902
  * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
57520
57903
  */
57521
- history: { fields: { lux: {
57904
+ history: { fields: { illuminance: {
57522
57905
  kind: "gauge",
57523
57906
  unit: "lx",
57524
57907
  deadbandPct: 10,
@@ -57657,6 +58040,84 @@ var audioMetricsCapability = {
57657
58040
  */
57658
58041
  history: "none"
57659
58042
  };
58043
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58044
+ actionId: string$2().min(1),
58045
+ variables: record(string$2(), ActionVariableValueSchema).optional()
58046
+ }), _void(), {
58047
+ kind: "mutation",
58048
+ auth: "admin"
58049
+ }), method(object({ actionId: string$2().min(1) }), _void(), {
58050
+ kind: "mutation",
58051
+ auth: "admin"
58052
+ });
58053
+ /**
58054
+ * actions — the ONE surface for runnable actions, for the UI and for
58055
+ * automations. Provided by the core-blocks builtin on the hub.
58056
+ *
58057
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
58058
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
58059
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
58060
+ * the run status from the hub's `runs` ledger; there is no catalog here to
58061
+ * drift (D3).
58062
+ *
58063
+ * **Permissions follow the camera, as linked devices do.** An action is linked
58064
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
58065
+ * non-admin may `get` / `run` an action only through a camera they may see that
58066
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
58067
+ * gate sees it) and the provider refuses an action that camera does not link.
58068
+ * An admin, and an in-process caller (an automation block), may run any action.
58069
+ * Every refusal is typed (`[not-linked] …`) and logged.
58070
+ *
58071
+ * A second `run` of an action that is already running is REFUSED — traced and
58072
+ * logged — never queued.
58073
+ */
58074
+ var ActionIdInput = object({ actionId: string$2().min(1) });
58075
+ var ActionLinksSchema = object({
58076
+ deviceId: number().int().nonnegative(),
58077
+ actionIds: array(string$2().min(1)).max(100)
58078
+ });
58079
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58080
+ actionId: string$2().min(1),
58081
+ deviceId: number().int().nonnegative().optional()
58082
+ }), object({ action: ActionEntrySchema.nullable() }), {
58083
+ role: "viewer",
58084
+ auth: "protected",
58085
+ kind: "query",
58086
+ caller: "required"
58087
+ }), method(object({
58088
+ actionId: string$2().min(1),
58089
+ variables: record(string$2(), ActionVariableValueSchema).optional(),
58090
+ wait: boolean().optional(),
58091
+ origin: ActionRunOriginSchema.optional(),
58092
+ deviceId: number().int().nonnegative().optional()
58093
+ }), ActionRunResultSchema, {
58094
+ role: "viewer",
58095
+ auth: "protected",
58096
+ kind: "mutation",
58097
+ caller: "required"
58098
+ }), method(ActionIdInput, _void(), {
58099
+ kind: "mutation",
58100
+ auth: "admin"
58101
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58102
+ kind: "mutation",
58103
+ auth: "admin"
58104
+ }), method(object({
58105
+ actionId: string$2().min(1),
58106
+ action: ActionInputSchema.partial()
58107
+ }), object({ action: ActionEntrySchema }), {
58108
+ kind: "mutation",
58109
+ auth: "admin"
58110
+ }), method(ActionIdInput, _void(), {
58111
+ kind: "mutation",
58112
+ auth: "admin"
58113
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
58114
+ role: "viewer",
58115
+ auth: "protected",
58116
+ kind: "query"
58117
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
58118
+ kind: "mutation",
58119
+ auth: "admin"
58120
+ });
57660
58121
  /**
57661
58122
  * Automation-control cap. Models HA `automation.*` entities on
57662
58123
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -57753,7 +58214,7 @@ var BatteryStatusSchema = object({
57753
58214
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
57754
58215
  * declines to band a non-finite reading, which is the correct shape.
57755
58216
  */
57756
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58217
+ level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
57757
58218
  /**
57758
58219
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
57759
58220
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -57763,7 +58224,7 @@ var BatteryStatusSchema = object({
57763
58224
  * `'unknown'` is the absence of an answer: the provider has not read the
57764
58225
  * power fields yet, or the firmware reported neither. Before it existed,
57765
58226
  * two unreadable fields produced `'none'`, and a camera nobody had reached
57766
- * was drawn "on battery alone" — the same D315 defect `percentage` closed
58227
+ * was drawn "on battery alone" — the same D315 defect `level` closed
57767
58228
  * by going nullable. Consumers SKIP it (no charger state published, no
57768
58229
  * glyph, no HomeKit ChargingState) rather than coerce it either way.
57769
58230
  */
@@ -57787,7 +58248,7 @@ var BatteryStatusSchema = object({
57787
58248
  * that only report charge. A second reading on this cap, not a second
57788
58249
  * `numeric-sensor` on the same device.
57789
58250
  */
57790
- volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58251
+ voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
57791
58252
  /**
57792
58253
  * Ms epoch of the last time the device PROVED it was reachable — a
57793
58254
  * completed firmware round-trip, an observed wake, or an inbound push
@@ -57821,7 +58282,7 @@ var BatteryStatusSchema = object({
57821
58282
  /**
57822
58283
  * True when the source is a BINARY low-battery indicator (HA
57823
58284
  * `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
57824
- * charge level — `percentage` is then a coarse stand-in (100 = normal,
58285
+ * charge level — `level` is then a coarse stand-in (100 = normal,
57825
58286
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
57826
58287
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
57827
58288
  */
@@ -57841,15 +58302,15 @@ var BATTERY_DEVICE_TYPES = [
57841
58302
  var batteryCustomize = {
57842
58303
  version: 1,
57843
58304
  targets: [{
57844
- id: "percentage",
58305
+ id: "level",
57845
58306
  cardinality: "scalar",
57846
58307
  vocabulary: {
57847
58308
  cap: "battery",
57848
- stateField: "percentage"
58309
+ stateField: "level"
57849
58310
  },
57850
58311
  deviceTypes: BATTERY_DEVICE_TYPES,
57851
58312
  apply: "add",
57852
- path: "percentage",
58313
+ path: "level",
57853
58314
  sources: [{
57854
58315
  kind: "field",
57855
58316
  valueKinds: ["number", "string"],
@@ -57943,7 +58404,7 @@ onStatusChanged: { data: object({
57943
58404
  schema: BatteryStatusSchema,
57944
58405
  kind: "push",
57945
58406
  empty: {
57946
- percentage: null,
58407
+ level: null,
57947
58408
  charging: "unknown",
57948
58409
  sleeping: false,
57949
58410
  lastUpdated: 0
@@ -57970,11 +58431,11 @@ onStatusChanged: { data: object({
57970
58431
  * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
57971
58432
  */
57972
58433
  history: { fields: {
57973
- percentage: {
58434
+ level: {
57974
58435
  kind: "gauge",
57975
58436
  unit: "%"
57976
58437
  },
57977
- volts: {
58438
+ voltage: {
57978
58439
  kind: "gauge",
57979
58440
  unit: "V"
57980
58441
  }
@@ -58034,14 +58495,14 @@ var binaryCapability = {
58034
58495
  * controls to this single-method surface.
58035
58496
  *
58036
58497
  * The cap is intentionally minimal: a single `setBrightness({deviceId,
58037
- * percentage})` mutation plus the auto-injected `getStatus`. Drivers
58498
+ * level})` mutation plus the auto-injected `getStatus`. Drivers
58038
58499
  * that expose richer controls (color temperature, scenes, schedules)
58039
58500
  * should surface those via the device's `getSettingsUISchema()`
58040
58501
  * instead of bloating this cap.
58041
58502
  */
58042
58503
  var BrightnessStatusSchema = object({
58043
58504
  /** Current level as 0..100 inclusive. Firmware-reported. */
58044
- percentage: number().min(0).max(100).meta(readingMeta("percentage")),
58505
+ level: number().min(0).max(100).meta(readingMeta("percentage")),
58045
58506
  /** Ms epoch of the last operator-driven change. Useful for UI freshness. */
58046
58507
  lastChangedAt: number()
58047
58508
  });
@@ -58053,7 +58514,7 @@ var brightnessCapability = {
58053
58514
  deviceTypes: [DeviceType.Light],
58054
58515
  methods: { setBrightness: method(object({
58055
58516
  deviceId: number().int().nonnegative(),
58056
- percentage: number().min(0).max(100)
58517
+ level: number().min(0).max(100)
58057
58518
  }), _void(), {
58058
58519
  kind: "mutation",
58059
58520
  auth: "protected"
@@ -58066,7 +58527,7 @@ var brightnessCapability = {
58066
58527
  */
58067
58528
  onBrightnessChanged: { data: object({
58068
58529
  deviceId: number(),
58069
- percentage: number().min(0).max(100),
58530
+ level: number().min(0).max(100),
58070
58531
  lastChangedAt: number()
58071
58532
  }) } },
58072
58533
  status: {
@@ -58089,7 +58550,7 @@ onBrightnessChanged: { data: object({
58089
58550
  /**
58090
58551
  * History (D850): recorded series. Actuator tier: level keeps every change.
58091
58552
  */
58092
- history: { fields: { percentage: {
58553
+ history: { fields: { level: {
58093
58554
  kind: "gauge",
58094
58555
  unit: "%",
58095
58556
  minIntervalMs: 0
@@ -58703,11 +59164,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
58703
59164
  }),
58704
59165
  object({
58705
59166
  mode: literal("mired"),
58706
- mireds: number().int().min(50).max(1e3)
59167
+ colorTemperature: number().int().min(50).max(1e3)
58707
59168
  })
58708
59169
  ]);
58709
59170
  var ColorStatusSchema = object({
58710
- /** Active color mode — which of `rgb` / `hsv` / `mireds` reflects
59171
+ /** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
58711
59172
  * the bulb's current state. */
58712
59173
  mode: _enum([
58713
59174
  "rgb",
@@ -58719,7 +59180,7 @@ var ColorStatusSchema = object({
58719
59180
  /** Populated when `mode === 'hsv'`. */
58720
59181
  hsv: HsvTripletSchema.optional(),
58721
59182
  /** Populated when `mode === 'mired'`. */
58722
- mireds: number().int().optional().meta(readingMeta("colour-temperature")),
59183
+ colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
58723
59184
  /** Ms epoch of the last operator-driven change. */
58724
59185
  lastChangedAt: number()
58725
59186
  });
@@ -58751,7 +59212,7 @@ onColorChanged: { data: object({
58751
59212
  ]),
58752
59213
  rgb: RgbTripletSchema.optional(),
58753
59214
  hsv: HsvTripletSchema.optional(),
58754
- mireds: number().int().optional(),
59215
+ colorTemperature: number().int().optional(),
58755
59216
  lastChangedAt: number()
58756
59217
  }) } },
58757
59218
  status: {
@@ -59628,11 +60089,11 @@ var DishwasherStatusSchema = object({
59628
60089
  /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
59629
60090
  availablePrograms: array(string$2()),
59630
60091
  /** Seconds remaining on the active cycle, or null when not running / not known. */
59631
- remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60092
+ remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59632
60093
  /** Seconds the delayed start is set to (time until the cycle starts), or null. */
59633
- delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
60094
+ delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59634
60095
  /** Cycle completion 0..100, or null when not applicable. */
59635
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60096
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
59636
60097
  /** True when the door is reported open; null when the door state is not known. */
59637
60098
  doorOpen: boolean().nullable(),
59638
60099
  /** True when the door is latched (locked) during a cycle; null when not reported. */
@@ -59851,14 +60312,14 @@ var dishwasherCapability = {
59851
60312
  runtimeState: DishwasherStatusSchema,
59852
60313
  durability: "session",
59853
60314
  history: { fields: {
59854
- progressPercent: {
60315
+ progress: {
59855
60316
  kind: "gauge",
59856
60317
  unit: "%",
59857
60318
  deadband: 2
59858
60319
  },
59859
60320
  state: { kind: "enum" },
59860
60321
  operationState: { kind: "enum" },
59861
- remainingSeconds: {
60322
+ remaining: {
59862
60323
  kind: "gauge",
59863
60324
  unit: "s",
59864
60325
  minIntervalMs: 6e4
@@ -60449,7 +60910,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
60449
60910
  var FanControlStatusSchema = object({
60450
60911
  /** Active speed as 0..100 inclusive. Null when the device has no
60451
60912
  * speed surface (single-speed fan). */
60452
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60913
+ speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60453
60914
  /** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
60454
60915
  * a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
60455
60916
  percentageStep: number().positive().optional().meta(readingMeta("percentage")),
@@ -60476,7 +60937,7 @@ var fanControlCapability = {
60476
60937
  methods: {
60477
60938
  setPercentage: method(object({
60478
60939
  deviceId: number().int().nonnegative(),
60479
- percentage: number().min(0).max(100)
60940
+ speed: number().min(0).max(100)
60480
60941
  }), _void(), {
60481
60942
  kind: "mutation",
60482
60943
  auth: "protected"
@@ -60509,7 +60970,7 @@ var fanControlCapability = {
60509
60970
  },
60510
60971
  /**
60511
60972
  * Runtime-state slice — mirrored by the kernel. UI fan speed
60512
- * sliders read `percentage` for live updates.
60973
+ * sliders read `speed` for live updates.
60513
60974
  */
60514
60975
  runtimeState: FanControlStatusSchema,
60515
60976
  /**
@@ -60523,7 +60984,7 @@ var fanControlCapability = {
60523
60984
  * History (D850): recorded series. Actuator tier: speed keeps every change.
60524
60985
  */
60525
60986
  history: { fields: {
60526
- percentage: {
60987
+ speed: {
60527
60988
  kind: "gauge",
60528
60989
  unit: "%",
60529
60990
  minIntervalMs: 0
@@ -60968,7 +61429,7 @@ var humidifierCapability = {
60968
61429
  */
60969
61430
  var HumiditySensorStatusSchema = object({
60970
61431
  /** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
60971
- percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
61432
+ humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
60972
61433
  precision: 0,
60973
61434
  label: "Humidity"
60974
61435
  })),
@@ -60997,7 +61458,7 @@ var humiditySensorCapability = {
60997
61458
  /**
60998
61459
  * History (D850): recorded series.
60999
61460
  */
61000
- history: { fields: { percent: {
61461
+ history: { fields: { humidity: {
61001
61462
  kind: "gauge",
61002
61463
  unit: "%",
61003
61464
  deadband: .5
@@ -61637,7 +62098,7 @@ var LawnMowerControlStatusSchema = object({
61637
62098
  batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61638
62099
  /** 0..100 mowing-completion percentage of the current task, or null when no
61639
62100
  * task is active / progress is unavailable. */
61640
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
62101
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61641
62102
  /** Current device/event code (dynamic — mostly status, sometimes an error),
61642
62103
  * or null when unknown. */
61643
62104
  currentCode: number().nullable().meta(readingMeta("none")),
@@ -62137,7 +62598,7 @@ var lockControlCapability = {
62137
62598
  volatileStateFields: ["lastChangedAt"]
62138
62599
  };
62139
62600
  /**
62140
- * A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
62601
+ * A monotonic total between resets (D944). Energy uses `power-meter.energy`
62141
62602
  * so dashboards keep one series; every other instantaneous reading lands here.
62142
62603
  * `value` is the time integral in the source quantity's accumulated base
62143
62604
  * (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
@@ -62231,10 +62692,10 @@ var MediaPlayerStatusSchema = object({
62231
62692
  currentMedia: MediaInfoSchema.nullable(),
62232
62693
  /** Current playback position in ms. Null when not seekable or
62233
62694
  * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
62234
- positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62695
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62235
62696
  /** Total duration of the current media in ms. Null when unknown
62236
62697
  * (live stream) or nothing is playing. */
62237
- durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62698
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62238
62699
  /** Shuffle toggle. Null when no shuffle surface.
62239
62700
  * Pair with `DeviceFeature.MediaPlayerShuffle`. */
62240
62701
  shuffle: boolean().nullable(),
@@ -62273,7 +62734,7 @@ var mediaPlayerCapability = {
62273
62734
  }),
62274
62735
  seek: method(object({
62275
62736
  deviceId: number().int().nonnegative(),
62276
- positionMs: number().int().nonnegative()
62737
+ position: number().int().nonnegative()
62277
62738
  }), _void(), {
62278
62739
  kind: "mutation",
62279
62740
  auth: "protected"
@@ -62345,7 +62806,7 @@ var mediaPlayerCapability = {
62345
62806
  /**
62346
62807
  * History (D850): volume (a level an operator or an automation sets; the
62347
62808
  * default 10 s floor folds a slider drag into its end value) and mute.
62348
- * `positionMs` is not recorded: it moves continuously while playing.
62809
+ * `position` is not recorded: it moves continuously while playing.
62349
62810
  */
62350
62811
  history: { fields: {
62351
62812
  volumeLevel: {
@@ -63307,9 +63768,9 @@ var NetworkLinkStatusSchema = object({
63307
63768
  * one whose reading has not landed must not be drawn at 0 %. Consumers
63308
63769
  * SKIP a null rather than coerce it.
63309
63770
  */
63310
- signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63771
+ signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63311
63772
  /** Raw received signal strength in dBm, when the firmware reports one. */
63312
- rssiDbm: number().optional().meta(readingMeta("signal-level")),
63773
+ rssi: number().optional().meta(readingMeta("signal-level")),
63313
63774
  /** Network name of a wireless link, when the firmware reports it. */
63314
63775
  ssid: string$2().optional(),
63315
63776
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
@@ -63345,7 +63806,7 @@ onStatusChanged: { data: object({
63345
63806
  kind: "push",
63346
63807
  empty: {
63347
63808
  type: "unknown",
63348
- signalPercent: null,
63809
+ signal: null,
63349
63810
  lastUpdated: 0
63350
63811
  }
63351
63812
  },
@@ -63368,13 +63829,13 @@ onStatusChanged: { data: object({
63368
63829
  * History (D850): recorded series.
63369
63830
  */
63370
63831
  history: { fields: {
63371
- signalPercent: {
63832
+ signal: {
63372
63833
  kind: "gauge",
63373
63834
  unit: "%",
63374
63835
  deadband: 3,
63375
63836
  minIntervalMs: 6e4
63376
63837
  },
63377
- rssiDbm: {
63838
+ rssi: {
63378
63839
  kind: "gauge",
63379
63840
  unit: "dBm",
63380
63841
  deadband: 2,
@@ -64119,10 +64580,20 @@ var PetFeederDeviceStatusSchema = _enum([
64119
64580
  ]);
64120
64581
  var gramsPortion = number().int().min(4).max(200);
64121
64582
  var PetFeederStatusSchema = object({
64122
- /** Food currently in the bowl (grams). Null when the device has not
64123
- * reported a reading yet. On dual-hopper models this is the combined
64124
- * bowl reading; per-hopper levels live in `food1`/`food2`. */
64583
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
64584
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
64585
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
64586
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
64587
+ * the device has not reported yet. */
64125
64588
  foodLevel: number().nullable().meta(readingMeta("none")),
64589
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
64590
+ * feeder's own units. Null when the model reports none. */
64591
+ bowlFood: number().nullable().meta(readingMeta("none")),
64592
+ /** True while the pet is eating (`state.eating`). */
64593
+ eating: boolean(),
64594
+ /** Whether `markFoodReplenished` does anything on this model. When false
64595
+ * the client must not offer it. */
64596
+ supportsMarkRefilled: boolean(),
64126
64597
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
64127
64598
  * single-hopper models. */
64128
64599
  food1: number().nullable().meta(readingMeta("none")),
@@ -64130,8 +64601,8 @@ var PetFeederStatusSchema = object({
64130
64601
  * single-hopper models. */
64131
64602
  food2: number().nullable().meta(readingMeta("none")),
64132
64603
  /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
64133
- * (`device_class: problem`, on = low). True when the bowl is empty /
64134
- * below the feeder's low threshold. */
64604
+ * (`device_class: problem`, on = low). True when the tank reports empty,
64605
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
64135
64606
  lowFood: boolean(),
64136
64607
  /** Battery charge 0..100 (%). Null on mains-powered models or when the
64137
64608
  * device has no battery reading. */
@@ -64199,7 +64670,9 @@ var petFeederCapability = {
64199
64670
  kind: "mutation",
64200
64671
  auth: "protected"
64201
64672
  }),
64202
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
64673
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
64674
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
64675
+ * change any sensor reading. */
64203
64676
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
64204
64677
  kind: "mutation",
64205
64678
  auth: "protected"
@@ -64272,6 +64745,7 @@ var petFeederCapability = {
64272
64745
  */
64273
64746
  history: { fields: {
64274
64747
  foodLevel: { kind: "gauge" },
64748
+ bowlFood: { kind: "gauge" },
64275
64749
  food1: { kind: "gauge" },
64276
64750
  food2: { kind: "gauge" },
64277
64751
  batteryPower: {
@@ -64681,16 +65155,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
64681
65155
  * in real-world devices.
64682
65156
  */
64683
65157
  var PowerMeterStatusSchema = object({
64684
- /** Instantaneous power draw in watts. */
64685
- watts: number().optional().meta(readingMeta("power", { label: "Power" })),
65158
+ /** Instantaneous power draw (watts). */
65159
+ power: number().optional().meta(readingMeta("power", { label: "Power" })),
64686
65160
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
64687
- kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
64688
- /** Voltage in volts. */
64689
- volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
65161
+ energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
65162
+ /** Voltage (volts). */
65163
+ voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
64690
65164
  /** Current in amperes. */
64691
- amps: number().optional().meta(readingMeta("current", { label: "Current" })),
65165
+ current: number().optional().meta(readingMeta("current", { label: "Current" })),
64692
65166
  /** Apparent power in volt-amperes. */
64693
- va: number().optional().meta(readingMeta("apparent-power")),
65167
+ apparentPower: number().optional().meta(readingMeta("apparent-power")),
64694
65168
  /** Power factor (0..1) if reported. */
64695
65169
  powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
64696
65170
  /** Ms epoch when the slice was last updated. */
@@ -64748,14 +65222,14 @@ function powerTarget(id, unit) {
64748
65222
  advancedExpression: true
64749
65223
  };
64750
65224
  }
64751
- /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65225
+ /** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
64752
65226
  var powerMeterCustomize = {
64753
65227
  version: 1,
64754
65228
  targets: [
64755
- powerTarget("watts", "W"),
64756
- powerTarget("kwhTotal", "kWh"),
64757
- powerTarget("volts", "V"),
64758
- powerTarget("amps", "A")
65229
+ powerTarget("power", "W"),
65230
+ powerTarget("energy", "kWh"),
65231
+ powerTarget("voltage", "V"),
65232
+ powerTarget("current", "A")
64759
65233
  ]
64760
65234
  };
64761
65235
  var powerMeterCapability = {
@@ -64771,41 +65245,41 @@ var powerMeterCapability = {
64771
65245
  },
64772
65246
  runtimeState: PowerMeterStatusSchema,
64773
65247
  /**
64774
- * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
65248
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
64775
65249
  *
64776
65250
  * See `RuntimeStateDurability`. Enforced by
64777
65251
  * `scripts/check-runtime-state-durability.ts`.
64778
65252
  */
64779
65253
  durability: "restored",
64780
65254
  /**
64781
- * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
65255
+ * History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
64782
65256
  */
64783
65257
  history: { fields: {
64784
- watts: {
65258
+ power: {
64785
65259
  kind: "gauge",
64786
65260
  unit: "W",
64787
65261
  deadband: 1,
64788
65262
  minIntervalMs: 3e4
64789
65263
  },
64790
- kwhTotal: {
65264
+ energy: {
64791
65265
  kind: "counter",
64792
65266
  unit: "kWh",
64793
65267
  deadband: .01,
64794
65268
  minIntervalMs: 6e4
64795
65269
  },
64796
- volts: {
65270
+ voltage: {
64797
65271
  kind: "gauge",
64798
65272
  unit: "V",
64799
65273
  deadband: 1,
64800
65274
  minIntervalMs: 3e4
64801
65275
  },
64802
- amps: {
65276
+ current: {
64803
65277
  kind: "gauge",
64804
65278
  unit: "A",
64805
65279
  deadband: .05,
64806
65280
  minIntervalMs: 3e4
64807
65281
  },
64808
- va: {
65282
+ apparentPower: {
64809
65283
  kind: "gauge",
64810
65284
  unit: "VA",
64811
65285
  deadband: 1,
@@ -64855,9 +65329,6 @@ var PresenceStatusSchema = object({
64855
65329
  location: string$2().nullable(),
64856
65330
  /** GPS coordinates when available. Null otherwise. */
64857
65331
  gps: GpsLocationSchema.nullable(),
64858
- /** Optional battery level of the tracking device (0..100). Null
64859
- * when not reported. */
64860
- batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
64861
65332
  /** Ms epoch when the slice was last updated. */
64862
65333
  lastChangedAt: number()
64863
65334
  });
@@ -64886,14 +65357,7 @@ var presenceCapability = {
64886
65357
  * `scripts/check-runtime-state-durability.ts`.
64887
65358
  */
64888
65359
  durability: "restored",
64889
- /**
64890
- * History (D850): recorded series.
64891
- */
64892
- history: { fields: { batteryPercent: {
64893
- kind: "gauge",
64894
- unit: "%",
64895
- deadband: 1
64896
- } } },
65360
+ history: "none",
64897
65361
  /** Clock fields: written, but excluded from the compare that decides
64898
65362
  * whether persisting is worth a SQLite commit. */
64899
65363
  volatileStateFields: ["lastChangedAt"]
@@ -64908,7 +65372,7 @@ var presenceCapability = {
64908
65372
  */
64909
65373
  var PressureSensorStatusSchema = object({
64910
65374
  /** Current pressure in hPa. `null` when the sample was refused (D393). */
64911
- hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65375
+ pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
64912
65376
  /** Ms epoch when the slice was last updated. */
64913
65377
  lastFetchedAt: number()
64914
65378
  });
@@ -64934,7 +65398,7 @@ var pressureSensorCapability = {
64934
65398
  /**
64935
65399
  * History (D850): recorded series.
64936
65400
  */
64937
- history: { fields: { hpa: {
65401
+ history: { fields: { pressure: {
64938
65402
  kind: "gauge",
64939
65403
  unit: "hPa",
64940
65404
  deadband: .1
@@ -68633,7 +69097,7 @@ var tamperCapability = {
68633
69097
  */
68634
69098
  var TemperatureSensorStatusSchema = object({
68635
69099
  /** Current temperature in Celsius. `null` when the sample was refused (D393). */
68636
- celsius: number().nullable().meta(readingMeta("temperature", {
69100
+ temperature: number().nullable().meta(readingMeta("temperature", {
68637
69101
  precision: 1,
68638
69102
  label: "Temperature"
68639
69103
  })),
@@ -68662,7 +69126,7 @@ var temperatureSensorCapability = {
68662
69126
  /**
68663
69127
  * History (D850): recorded series.
68664
69128
  */
68665
- history: { fields: { celsius: {
69129
+ history: { fields: { temperature: {
68666
69130
  kind: "gauge",
68667
69131
  unit: "°C",
68668
69132
  deadband: .1
@@ -68959,7 +69423,7 @@ var VacuumControlStatusSchema = object({
68959
69423
  /** Speed tokens the hardware accepts — drives the UI selector. */
68960
69424
  availableFanSpeeds: array(string$2()),
68961
69425
  /** 0..100 cleaning-completion percentage of the current task, or null. */
68962
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
69426
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
68963
69427
  /** Current error code (0 / null = no error). */
68964
69428
  errorCode: number().nullable().meta(readingMeta("none")),
68965
69429
  /** Human label for {@link errorCode}, or null when none / undecodable. */
@@ -70613,7 +71077,7 @@ var BaseDevice = class {
70613
71077
  * `device-local-state.ts`. Drivers access via:
70614
71078
  *
70615
71079
  * `this.state.battery.sleeping = true` // patches the battery slice
70616
- * `const pct = this.state.battery.percentage` // reads the battery slice
71080
+ * `const pct = this.state.battery.level` // reads the battery slice
70617
71081
  * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
70618
71082
  *
70619
71083
  * Adding a new cap with `runtimeState:` automatically extends this
@@ -70653,7 +71117,7 @@ var BaseDevice = class {
70653
71117
  * shape; drivers don't redeclare it, they just write through.
70654
71118
  *
70655
71119
  * Read: `this.runtimeState.getCapState('battery')` →
70656
- * `{percentage, charging, sleeping, lastUpdated}` for any
71120
+ * `{level, charging, sleeping, lastUpdated}` for any
70657
71121
  * provider that registers `batteryCapability`.
70658
71122
  * Write: `this.runtimeState.setCapState('battery', { … })`.
70659
71123
  *
@@ -71827,6 +72291,104 @@ Object.freeze({
71827
72291
  access: "create",
71828
72292
  role: "admin"
71829
72293
  },
72294
+ "actions.create": {
72295
+ capName: "actions",
72296
+ capScope: "system",
72297
+ addonId: null,
72298
+ access: "create",
72299
+ role: "admin"
72300
+ },
72301
+ "actions.delete": {
72302
+ capName: "actions",
72303
+ capScope: "system",
72304
+ addonId: null,
72305
+ access: "delete",
72306
+ role: "admin"
72307
+ },
72308
+ "actions.get": {
72309
+ capName: "actions",
72310
+ capScope: "system",
72311
+ addonId: null,
72312
+ access: "view",
72313
+ role: "viewer"
72314
+ },
72315
+ "actions.getLinks": {
72316
+ capName: "actions",
72317
+ capScope: "system",
72318
+ addonId: null,
72319
+ access: "view",
72320
+ role: "admin"
72321
+ },
72322
+ "actions.getTraces": {
72323
+ capName: "actions",
72324
+ capScope: "system",
72325
+ addonId: null,
72326
+ access: "view",
72327
+ role: "admin"
72328
+ },
72329
+ "actions.list": {
72330
+ capName: "actions",
72331
+ capScope: "system",
72332
+ addonId: null,
72333
+ access: "view",
72334
+ role: "admin"
72335
+ },
72336
+ "actions.listForCamera": {
72337
+ capName: "actions",
72338
+ capScope: "system",
72339
+ addonId: null,
72340
+ access: "view",
72341
+ role: "viewer"
72342
+ },
72343
+ "actions.run": {
72344
+ capName: "actions",
72345
+ capScope: "system",
72346
+ addonId: null,
72347
+ access: "create",
72348
+ role: "viewer"
72349
+ },
72350
+ "actions.setLinks": {
72351
+ capName: "actions",
72352
+ capScope: "system",
72353
+ addonId: null,
72354
+ access: "create",
72355
+ role: "admin"
72356
+ },
72357
+ "actions.stop": {
72358
+ capName: "actions",
72359
+ capScope: "system",
72360
+ addonId: null,
72361
+ access: "create",
72362
+ role: "admin"
72363
+ },
72364
+ "actions.update": {
72365
+ capName: "actions",
72366
+ capScope: "system",
72367
+ addonId: null,
72368
+ access: "create",
72369
+ role: "admin"
72370
+ },
72371
+ "actionSource.listActions": {
72372
+ capName: "action-source",
72373
+ capScope: "system",
72374
+ addonId: null,
72375
+ access: "view",
72376
+ role: "admin"
72377
+ },
72378
+ "actionSource.runAction": {
72379
+ capName: "action-source",
72380
+ capScope: "system",
72381
+ addonId: null,
72382
+ access: "create",
72383
+ role: "admin"
72384
+ },
72385
+ "actionSource.stopAction": {
72386
+ capName: "action-source",
72387
+ capScope: "system",
72388
+ addonId: null,
72389
+ access: "create",
72390
+ role: "admin"
72391
+ },
71830
72392
  "addonPages.listPages": {
71831
72393
  capName: "addon-pages",
71832
72394
  capScope: "system",
@@ -73108,6 +73670,13 @@ Object.freeze({
73108
73670
  access: "view",
73109
73671
  role: "admin"
73110
73672
  },
73673
+ "coreBlocks.getAutomationRunState": {
73674
+ capName: "core-blocks",
73675
+ capScope: "system",
73676
+ addonId: null,
73677
+ access: "view",
73678
+ role: "admin"
73679
+ },
73111
73680
  "coreBlocks.getBlockSettings": {
73112
73681
  capName: "core-blocks",
73113
73682
  capScope: "system",
@@ -73129,6 +73698,13 @@ Object.freeze({
73129
73698
  access: "view",
73130
73699
  role: "admin"
73131
73700
  },
73701
+ "coreBlocks.getTraces": {
73702
+ capName: "core-blocks",
73703
+ capScope: "system",
73704
+ addonId: null,
73705
+ access: "view",
73706
+ role: "admin"
73707
+ },
73132
73708
  "coreBlocks.getTypeDefs": {
73133
73709
  capName: "core-blocks",
73134
73710
  capScope: "system",
@@ -73164,6 +73740,13 @@ Object.freeze({
73164
73740
  access: "create",
73165
73741
  role: "admin"
73166
73742
  },
73743
+ "coreBlocks.reportAutomationRun": {
73744
+ capName: "core-blocks",
73745
+ capScope: "system",
73746
+ addonId: null,
73747
+ access: "create",
73748
+ role: "admin"
73749
+ },
73167
73750
  "coreBlocks.restart": {
73168
73751
  capName: "core-blocks",
73169
73752
  capScope: "system",
@@ -81737,7 +82320,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81737
82320
  label: t("Full brightness", "Luminosità massima"),
81738
82321
  phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
81739
82322
  icon: "sun",
81740
- args: { percentage: 100 }
82323
+ args: { level: 100 }
81741
82324
  },
81742
82325
  {
81743
82326
  id: "brightness.half",
@@ -81745,7 +82328,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81745
82328
  label: t("Half brightness", "Luminosità a metà"),
81746
82329
  phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
81747
82330
  icon: "sun-dim",
81748
- args: { percentage: 50 }
82331
+ args: { level: 50 }
81749
82332
  },
81750
82333
  {
81751
82334
  id: "brightness.off",
@@ -81753,16 +82336,16 @@ var ACTUATOR_CAP_VOCABULARY = {
81753
82336
  label: t("Brightness off", "Luminosità a zero"),
81754
82337
  phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
81755
82338
  icon: "lightbulb-off",
81756
- args: { percentage: 0 }
82339
+ args: { level: 0 }
81757
82340
  },
81758
82341
  {
81759
82342
  id: "brightness.set",
81760
82343
  method: "setBrightness",
81761
82344
  label: t("Set brightness", "Imposta la luminosità"),
81762
- phrase: t("Set the brightness of {device} to {percentage}", "Imposta la luminosità di {device} a {percentage}"),
82345
+ phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
81763
82346
  icon: "sun-medium",
81764
82347
  openArgs: [{
81765
- key: "percentage",
82348
+ key: "level",
81766
82349
  label: PERCENT,
81767
82350
  offer: {
81768
82351
  kind: "number",
@@ -81776,13 +82359,13 @@ var ACTUATOR_CAP_VOCABULARY = {
81776
82359
  ],
81777
82360
  state: [{
81778
82361
  kind: "numeric",
81779
- field: "percentage",
82362
+ field: "level",
81780
82363
  quantity: t("the brightness", "la luminosità"),
81781
82364
  label: t("Brightness", "Luminosità"),
81782
82365
  unit: "%",
81783
82366
  icon: "sun"
81784
82367
  }],
81785
- events: { onBrightnessChanged: { notOperatorFacing: "the `percentage` state trigger reads the same change" } }
82368
+ events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
81786
82369
  },
81787
82370
  color: {
81788
82371
  scope: "device",
@@ -81796,7 +82379,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81796
82379
  icon: "sun",
81797
82380
  args: { color: {
81798
82381
  mode: "mired",
81799
- mireds: 370
82382
+ colorTemperature: 370
81800
82383
  } }
81801
82384
  },
81802
82385
  {
@@ -81807,7 +82390,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81807
82390
  icon: "snowflake",
81808
82391
  args: { color: {
81809
82392
  mode: "mired",
81810
- mireds: 200
82393
+ colorTemperature: 200
81811
82394
  } }
81812
82395
  },
81813
82396
  {
@@ -82421,7 +83004,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82421
83004
  label: t("Fan off", "Ventilatore spento"),
82422
83005
  phrase: t("Stop {device}", "Ferma {device}"),
82423
83006
  icon: "power-off",
82424
- args: { percentage: 0 }
83007
+ args: { speed: 0 }
82425
83008
  },
82426
83009
  {
82427
83010
  id: "fan.full",
@@ -82429,16 +83012,16 @@ var ACTUATOR_CAP_VOCABULARY = {
82429
83012
  label: t("Fan full", "Ventilatore al massimo"),
82430
83013
  phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
82431
83014
  icon: "fan",
82432
- args: { percentage: 100 }
83015
+ args: { speed: 100 }
82433
83016
  },
82434
83017
  {
82435
83018
  id: "fan.speed",
82436
83019
  method: "setPercentage",
82437
83020
  label: t("Set speed", "Imposta la velocità"),
82438
- phrase: t("Set the speed of {device} to {percentage}", "Imposta la velocità di {device} al {percentage}"),
83021
+ phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
82439
83022
  icon: "fan",
82440
83023
  openArgs: [{
82441
- key: "percentage",
83024
+ key: "speed",
82442
83025
  label: t("Speed", "Velocità"),
82443
83026
  offer: {
82444
83027
  kind: "number",
@@ -82500,7 +83083,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82500
83083
  ],
82501
83084
  state: [{
82502
83085
  kind: "numeric",
82503
- field: "percentage",
83086
+ field: "speed",
82504
83087
  quantity: t("the speed", "la velocità"),
82505
83088
  label: t("Speed", "Velocità"),
82506
83089
  unit: "%",
@@ -83298,7 +83881,7 @@ var APPLIANCE_CAP_VOCABULARY = {
83298
83881
  },
83299
83882
  {
83300
83883
  kind: "numeric",
83301
- field: "progressPercent",
83884
+ field: "progress",
83302
83885
  quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
83303
83886
  label: t("Progress", "Avanzamento"),
83304
83887
  unit: "%",
@@ -83656,10 +84239,10 @@ var APPLIANCE_CAP_VOCABULARY = {
83656
84239
  id: "media.seek",
83657
84240
  method: "seek",
83658
84241
  label: t("Seek", "Vai al punto"),
83659
- phrase: t("Move {device} to {positionMs}", "Porta {device} al punto {positionMs}"),
84242
+ phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
83660
84243
  icon: "fast-forward",
83661
84244
  openArgs: [{
83662
- key: "positionMs",
84245
+ key: "position",
83663
84246
  label: t("Position", "Posizione"),
83664
84247
  offer: {
83665
84248
  kind: "number",
@@ -84708,7 +85291,7 @@ var SENSOR_CAP_VOCABULARY = {
84708
85291
  state: [
84709
85292
  {
84710
85293
  kind: "numeric",
84711
- field: "co2Ppm",
85294
+ field: "co2",
84712
85295
  quantity: t("the CO₂", "la CO₂"),
84713
85296
  label: t("CO₂", "CO₂"),
84714
85297
  unit: "ppm",
@@ -84716,7 +85299,7 @@ var SENSOR_CAP_VOCABULARY = {
84716
85299
  },
84717
85300
  {
84718
85301
  kind: "numeric",
84719
- field: "vocPpb",
85302
+ field: "voc",
84720
85303
  quantity: t("the VOC level", "il livello di COV"),
84721
85304
  label: t("VOC", "COV"),
84722
85305
  unit: "ppb",
@@ -84752,7 +85335,7 @@ var SENSOR_CAP_VOCABULARY = {
84752
85335
  noun: t("Light level", "Luminosità ambiente"),
84753
85336
  state: [{
84754
85337
  kind: "numeric",
84755
- field: "lux",
85338
+ field: "illuminance",
84756
85339
  quantity: t("the light level", "la luminosità"),
84757
85340
  label: t("Illuminance", "Illuminamento"),
84758
85341
  unit: "lx",
@@ -84955,7 +85538,7 @@ var SENSOR_CAP_VOCABULARY = {
84955
85538
  noun: t("Humidity", "Umidità"),
84956
85539
  state: [{
84957
85540
  kind: "numeric",
84958
- field: "percent",
85541
+ field: "humidity",
84959
85542
  quantity: t("the humidity", "l’umidità"),
84960
85543
  label: t("Humidity", "Umidità"),
84961
85544
  unit: "%",
@@ -85003,7 +85586,7 @@ var SENSOR_CAP_VOCABULARY = {
85003
85586
  state: [
85004
85587
  {
85005
85588
  kind: "numeric",
85006
- field: "watts",
85589
+ field: "power",
85007
85590
  quantity: t("the power draw", "il consumo"),
85008
85591
  label: t("Power", "Potenza"),
85009
85592
  unit: "W",
@@ -85011,7 +85594,7 @@ var SENSOR_CAP_VOCABULARY = {
85011
85594
  },
85012
85595
  {
85013
85596
  kind: "numeric",
85014
- field: "kwhTotal",
85597
+ field: "energy",
85015
85598
  quantity: t("the energy used", "l’energia consumata"),
85016
85599
  label: t("Energy", "Energia"),
85017
85600
  unit: "kWh",
@@ -85019,7 +85602,7 @@ var SENSOR_CAP_VOCABULARY = {
85019
85602
  },
85020
85603
  {
85021
85604
  kind: "numeric",
85022
- field: "volts",
85605
+ field: "voltage",
85023
85606
  quantity: t("the voltage", "la tensione"),
85024
85607
  label: t("Voltage", "Tensione"),
85025
85608
  unit: "V",
@@ -85027,7 +85610,7 @@ var SENSOR_CAP_VOCABULARY = {
85027
85610
  },
85028
85611
  {
85029
85612
  kind: "numeric",
85030
- field: "amps",
85613
+ field: "current",
85031
85614
  quantity: t("the current", "la corrente"),
85032
85615
  label: t("Current", "Corrente"),
85033
85616
  unit: "A",
@@ -85044,13 +85627,6 @@ var SENSOR_CAP_VOCABULARY = {
85044
85627
  label: t("Where", "Posizione"),
85045
85628
  phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
85046
85629
  icon: "map-pin"
85047
- }, {
85048
- kind: "numeric",
85049
- field: "batteryPercent",
85050
- quantity: t("the phone battery", "la batteria del telefono"),
85051
- label: t("Battery", "Batteria"),
85052
- unit: "%",
85053
- icon: "battery"
85054
85630
  }]
85055
85631
  },
85056
85632
  "pressure-sensor": {
@@ -85058,7 +85634,7 @@ var SENSOR_CAP_VOCABULARY = {
85058
85634
  noun: t("Pressure", "Pressione"),
85059
85635
  state: [{
85060
85636
  kind: "numeric",
85061
- field: "hpa",
85637
+ field: "pressure",
85062
85638
  quantity: t("the pressure", "la pressione"),
85063
85639
  label: t("Pressure", "Pressione"),
85064
85640
  unit: "hPa",
@@ -85094,7 +85670,7 @@ var SENSOR_CAP_VOCABULARY = {
85094
85670
  noun: t("Temperature", "Temperatura"),
85095
85671
  state: [{
85096
85672
  kind: "numeric",
85097
- field: "celsius",
85673
+ field: "temperature",
85098
85674
  quantity: t("the temperature", "la temperatura"),
85099
85675
  label: t("Temperature", "Temperatura"),
85100
85676
  unit: "°C",
@@ -85165,7 +85741,7 @@ var SENSOR_CAP_VOCABULARY = {
85165
85741
  state: [
85166
85742
  {
85167
85743
  kind: "numeric",
85168
- field: "percentage",
85744
+ field: "level",
85169
85745
  quantity: t("the battery level", "il livello della batteria"),
85170
85746
  label: t("Battery", "Batteria"),
85171
85747
  unit: "%",
@@ -85207,7 +85783,7 @@ var SENSOR_CAP_VOCABULARY = {
85207
85783
  icon: "battery-charging"
85208
85784
  }
85209
85785
  ],
85210
- events: { onStatusChanged: { notOperatorFacing: "the percentage / sleeping / charging state triggers each read one field of this change" } },
85786
+ events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
85211
85787
  extraEvents: [{
85212
85788
  category: EventCategory.DeviceAwake,
85213
85789
  label: t("Woke up", "Risvegliato"),
@@ -85225,7 +85801,7 @@ var SENSOR_CAP_VOCABULARY = {
85225
85801
  noun: t("Network link", "Collegamento di rete"),
85226
85802
  state: [{
85227
85803
  kind: "numeric",
85228
- field: "signalPercent",
85804
+ field: "signal",
85229
85805
  quantity: t("the signal strength", "l’intensità del segnale"),
85230
85806
  label: t("Signal", "Segnale"),
85231
85807
  unit: "%",
@@ -85318,6 +85894,8 @@ var ML = "model and training machinery — no device action";
85318
85894
  var INTERNAL$1 = "internal plumbing between addons — never operator-facing";
85319
85895
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
85320
85896
  var SYSTEM_CAP_VOCABULARY = {
85897
+ "action-source": system(INTERNAL$1),
85898
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
85321
85899
  "addon-pages": system(UI_PLUMBING),
85322
85900
  "addon-pages-source": system(UI_PLUMBING),
85323
85901
  "addon-routes": system(UI_PLUMBING),
@@ -85514,6 +86092,31 @@ Object.freeze({
85514
86092
  form: "single",
85515
86093
  optional: false
85516
86094
  }],
86095
+ "actions.get": [{
86096
+ name: "deviceId",
86097
+ form: "single",
86098
+ optional: true
86099
+ }],
86100
+ "actions.getLinks": [{
86101
+ name: "deviceId",
86102
+ form: "single",
86103
+ optional: false
86104
+ }],
86105
+ "actions.listForCamera": [{
86106
+ name: "deviceId",
86107
+ form: "single",
86108
+ optional: false
86109
+ }],
86110
+ "actions.run": [{
86111
+ name: "deviceId",
86112
+ form: "single",
86113
+ optional: true
86114
+ }],
86115
+ "actions.setLinks": [{
86116
+ name: "deviceId",
86117
+ form: "single",
86118
+ optional: false
86119
+ }],
85517
86120
  "addonSettings.getDeviceSettings": [{
85518
86121
  name: "deviceId",
85519
86122
  form: "single",
@@ -89595,6 +90198,7 @@ DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
89595
90198
  DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
89596
90199
  DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb;
89597
90200
  DEFAULT_NATIVE_LEASE_SETTINGS.admission;
90201
+ String.raw`(?<=^|["'(\s>,\[{])`;
89598
90202
  var MB = 1024 * 1024;
89599
90203
  1024 * MB, 3072 * MB;
89600
90204
  //#endregion
@@ -198378,9 +198982,9 @@ function decodeMatterAttribute(input) {
198378
198982
  case MatterClusterId.LevelControl: return decodeLevel(attributeId, value);
198379
198983
  case MatterClusterId.BooleanState: return decodeContact(attributeId, value);
198380
198984
  case MatterClusterId.OccupancySensing: return decodeOccupancy(attributeId, value);
198381
- case MatterClusterId.TemperatureMeasurement: return decodeScaledMeasurement(attributeId, value, "temperature-sensor", "celsius", .01);
198382
- case MatterClusterId.RelativeHumidityMeasurement: return decodeScaledMeasurement(attributeId, value, "humidity-sensor", "percent", .01);
198383
- case MatterClusterId.PressureMeasurement: return decodeScaledMeasurement(attributeId, value, "pressure-sensor", "hpa", 1);
198985
+ case MatterClusterId.TemperatureMeasurement: return decodeScaledMeasurement(attributeId, value, "temperature-sensor", "temperature", .01);
198986
+ case MatterClusterId.RelativeHumidityMeasurement: return decodeScaledMeasurement(attributeId, value, "humidity-sensor", "humidity", .01);
198987
+ case MatterClusterId.PressureMeasurement: return decodeScaledMeasurement(attributeId, value, "pressure-sensor", "pressure", 1);
198384
198988
  case MatterClusterId.IlluminanceMeasurement: return decodeIlluminance(attributeId, value);
198385
198989
  case MatterClusterId.PowerSource: return decodeBattery(attributeId, value);
198386
198990
  case MatterClusterId.Thermostat: return decodeThermostat(attributeId, value);
@@ -198475,7 +199079,7 @@ function decodeLevel(attributeId, value) {
198475
199079
  return {
198476
199080
  cap: "brightness",
198477
199081
  patch: {
198478
- percentage: Math.round(Math.max(0, Math.min(254, level)) / 254 * 100),
199082
+ level: Math.round(Math.max(0, Math.min(254, level)) / 254 * 100),
198479
199083
  lastChangedAt: Date.now()
198480
199084
  }
198481
199085
  };
@@ -198524,7 +199128,7 @@ function decodeIlluminance(attributeId, value) {
198524
199128
  return {
198525
199129
  cap: "ambient-light-sensor",
198526
199130
  patch: {
198527
- lux: Math.round(10 ** ((raw - 1) / 1e4)),
199131
+ illuminance: Math.round(10 ** ((raw - 1) / 1e4)),
198528
199132
  lastFetchedAt: Date.now()
198529
199133
  }
198530
199134
  };
@@ -198536,7 +199140,7 @@ function decodeBattery(attributeId, value) {
198536
199140
  return {
198537
199141
  cap: "battery",
198538
199142
  patch: {
198539
- percentage: Math.max(0, Math.min(100, Math.round(half / 2))),
199143
+ level: Math.max(0, Math.min(100, Math.round(half / 2))),
198540
199144
  lastUpdated: Date.now()
198541
199145
  }
198542
199146
  };
@@ -198599,7 +199203,7 @@ function decodeElectricalPower(attributeId, value) {
198599
199203
  return mw === null ? null : {
198600
199204
  cap: "power-meter",
198601
199205
  patch: {
198602
- watts: mw / 1e3,
199206
+ power: mw / 1e3,
198603
199207
  lastFetchedAt: Date.now()
198604
199208
  }
198605
199209
  };
@@ -198609,7 +199213,7 @@ function decodeElectricalPower(attributeId, value) {
198609
199213
  return mv === null ? null : {
198610
199214
  cap: "power-meter",
198611
199215
  patch: {
198612
- volts: mv / 1e3,
199216
+ voltage: mv / 1e3,
198613
199217
  lastFetchedAt: Date.now()
198614
199218
  }
198615
199219
  };
@@ -198619,7 +199223,7 @@ function decodeElectricalPower(attributeId, value) {
198619
199223
  return ma === null ? null : {
198620
199224
  cap: "power-meter",
198621
199225
  patch: {
198622
- amps: ma / 1e3,
199226
+ current: ma / 1e3,
198623
199227
  lastFetchedAt: Date.now()
198624
199228
  }
198625
199229
  };
@@ -198634,7 +199238,7 @@ function decodeElectricalEnergy(attributeId, value) {
198634
199238
  return {
198635
199239
  cap: "power-meter",
198636
199240
  patch: {
198637
- kwhTotal: mwh / 1e6,
199241
+ energy: mwh / 1e6,
198638
199242
  lastFetchedAt: Date.now()
198639
199243
  }
198640
199244
  };
@@ -200858,16 +201462,16 @@ var MatterEndpointDevice = class extends BaseDevice {
200858
201462
  }
200859
201463
  registerBrightness() {
200860
201464
  const COLD = {
200861
- percentage: 0,
201465
+ level: 0,
200862
201466
  lastChangedAt: 0
200863
201467
  };
200864
201468
  this.ctx.registerNativeCap(brightnessCapability, {
200865
201469
  getStatus: async () => this.runtimeState.getCapState("brightness") ?? COLD,
200866
- setBrightness: async ({ percentage }) => {
201470
+ setBrightness: async ({ level: percentage }) => {
200867
201471
  const level = Math.round(Math.max(0, Math.min(100, percentage)) / 100 * 254);
200868
201472
  await this.invoke(MatterClusterId.LevelControl, "moveToLevel", { level });
200869
201473
  this.runtimeState.setCapState("brightness", {
200870
- percentage,
201474
+ level: percentage,
200871
201475
  lastChangedAt: Date.now()
200872
201476
  });
200873
201477
  }
@@ -201078,7 +201682,7 @@ var MatterEndpointDevice = class extends BaseDevice {
201078
201682
  }
201079
201683
  registerTemperatureSensor() {
201080
201684
  const COLD = {
201081
- celsius: 0,
201685
+ temperature: 0,
201082
201686
  lastFetchedAt: 0
201083
201687
  };
201084
201688
  this.ctx.registerNativeCap(temperatureSensorCapability, { getStatus: async () => this.runtimeState.getCapState("temperature-sensor") ?? COLD });
@@ -201086,7 +201690,7 @@ var MatterEndpointDevice = class extends BaseDevice {
201086
201690
  }
201087
201691
  registerHumiditySensor() {
201088
201692
  const COLD = {
201089
- percent: 0,
201693
+ humidity: 0,
201090
201694
  lastFetchedAt: 0
201091
201695
  };
201092
201696
  this.ctx.registerNativeCap(humiditySensorCapability, { getStatus: async () => this.runtimeState.getCapState("humidity-sensor") ?? COLD });
@@ -201094,7 +201698,7 @@ var MatterEndpointDevice = class extends BaseDevice {
201094
201698
  }
201095
201699
  registerPressureSensor() {
201096
201700
  const COLD = {
201097
- hpa: 0,
201701
+ pressure: 0,
201098
201702
  lastFetchedAt: 0
201099
201703
  };
201100
201704
  this.ctx.registerNativeCap(pressureSensorCapability, { getStatus: async () => this.runtimeState.getCapState("pressure-sensor") ?? COLD });
@@ -201102,7 +201706,7 @@ var MatterEndpointDevice = class extends BaseDevice {
201102
201706
  }
201103
201707
  registerAmbientLightSensor() {
201104
201708
  const COLD = {
201105
- lux: 0,
201709
+ illuminance: 0,
201106
201710
  lastFetchedAt: 0
201107
201711
  };
201108
201712
  this.ctx.registerNativeCap(ambientLightSensorCapability, { getStatus: async () => this.runtimeState.getCapState("ambient-light-sensor") ?? COLD });
@@ -201110,7 +201714,7 @@ var MatterEndpointDevice = class extends BaseDevice {
201110
201714
  }
201111
201715
  registerBattery() {
201112
201716
  const COLD = {
201113
- percentage: 0,
201717
+ level: 0,
201114
201718
  charging: "unknown",
201115
201719
  sleeping: false,
201116
201720
  lastUpdated: 0