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