@camstack/addon-provider-ecowitt 0.2.149 → 0.2.150

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
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let http = require("http");
3
3
  let events = require("events");
4
4
  let dgram = require("dgram");
5
- //#region ../types/dist/event-category-CT-hz5Rb.mjs
5
+ //#region ../types/dist/event-category-DmZDPDf_.mjs
6
6
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
7
7
  EventCategory["SystemBoot"] = "system.boot";
8
8
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -629,7 +629,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
629
629
  * (a track was promoted to a stationary-registry entry) or departs (the
630
630
  * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
631
631
  * the dedicated "Stationary" section — never the live event feed. Payload:
632
- * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
632
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp, observedAt, zones }`.
633
633
  */
634
634
  EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
635
635
  /**
@@ -767,6 +767,11 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
767
767
  */
768
768
  EventCategory["AccessoriesChanged"] = "accessories.onAccessoriesChanged";
769
769
  /**
770
+ * An action run started or ended. Emitted by the `actions` surface.
771
+ * Payload: `ActionRunChanged` (`{ actionId, runId, isRunning, outcome?, lastRunAt, lastError }`).
772
+ */
773
+ EventCategory["ActionsRunChanged"] = "actions.onRunChanged";
774
+ /**
770
775
  * Progress update from a running model conversion job.
771
776
  * Payload: `{ kind: 'model-convert', phase, sessionId?, pct?, detail? }`.
772
777
  * Emitted by `addon-model-studio` on the converting node.
@@ -5445,7 +5450,7 @@ var ZodIssueCode$1 = {
5445
5450
  var ZodFirstPartyTypeKind$1;
5446
5451
  ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
5447
5452
  //#endregion
5448
- //#region ../types/dist/sleep--jXS9hWo.mjs
5453
+ //#region ../types/dist/sleep-Crlmu_tO.mjs
5449
5454
  /**
5450
5455
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5451
5456
  * window to float samples (D455).
@@ -8565,6 +8570,8 @@ Object.freeze({ "doorbell": "lastPressedAt" });
8565
8570
  /** Every capability name, so addon code can check a name without the schema graph. */
8566
8571
  var CAP_NAMES = Object.freeze([
8567
8572
  "accessories",
8573
+ "action-source",
8574
+ "actions",
8568
8575
  "addon-pages",
8569
8576
  "addon-pages-source",
8570
8577
  "addon-routes",
@@ -8753,11 +8760,11 @@ var CAP_NAMES = Object.freeze([
8753
8760
  Object.freeze({
8754
8761
  "air-quality-sensor": [
8755
8762
  {
8756
- "path": "co2Ppm",
8763
+ "path": "co2",
8757
8764
  "valueType": "number"
8758
8765
  },
8759
8766
  {
8760
- "path": "vocPpb",
8767
+ "path": "voc",
8761
8768
  "valueType": "number"
8762
8769
  },
8763
8770
  {
@@ -8807,7 +8814,7 @@ Object.freeze({
8807
8814
  }
8808
8815
  ],
8809
8816
  "ambient-light-sensor": [{
8810
- "path": "lux",
8817
+ "path": "illuminance",
8811
8818
  "valueType": "number"
8812
8819
  }],
8813
8820
  "audio-metrics": [
@@ -8868,7 +8875,7 @@ Object.freeze({
8868
8875
  ],
8869
8876
  "battery": [
8870
8877
  {
8871
- "path": "percentage",
8878
+ "path": "level",
8872
8879
  "valueType": "number"
8873
8880
  },
8874
8881
  {
@@ -8890,7 +8897,7 @@ Object.freeze({
8890
8897
  "valueType": "number"
8891
8898
  },
8892
8899
  {
8893
- "path": "volts",
8900
+ "path": "voltage",
8894
8901
  "valueType": "number"
8895
8902
  },
8896
8903
  {
@@ -8911,7 +8918,7 @@ Object.freeze({
8911
8918
  "valueType": "boolean"
8912
8919
  }],
8913
8920
  "brightness": [{
8914
- "path": "percentage",
8921
+ "path": "level",
8915
8922
  "valueType": "number"
8916
8923
  }],
8917
8924
  "broker": [{
@@ -9112,7 +9119,7 @@ Object.freeze({
9112
9119
  "valueType": "number"
9113
9120
  },
9114
9121
  {
9115
- "path": "mireds",
9122
+ "path": "colorTemperature",
9116
9123
  "valueType": "number"
9117
9124
  }
9118
9125
  ],
@@ -9291,15 +9298,15 @@ Object.freeze({
9291
9298
  "valueType": "string"
9292
9299
  },
9293
9300
  {
9294
- "path": "remainingSeconds",
9301
+ "path": "remaining",
9295
9302
  "valueType": "number"
9296
9303
  },
9297
9304
  {
9298
- "path": "delayedStartSeconds",
9305
+ "path": "delayedStart",
9299
9306
  "valueType": "number"
9300
9307
  },
9301
9308
  {
9302
- "path": "progressPercent",
9309
+ "path": "progress",
9303
9310
  "valueType": "number"
9304
9311
  },
9305
9312
  {
@@ -9413,7 +9420,7 @@ Object.freeze({
9413
9420
  ],
9414
9421
  "fan-control": [
9415
9422
  {
9416
- "path": "percentage",
9423
+ "path": "speed",
9417
9424
  "valueType": "number"
9418
9425
  },
9419
9426
  {
@@ -9513,7 +9520,7 @@ Object.freeze({
9513
9520
  }
9514
9521
  ],
9515
9522
  "humidity-sensor": [{
9516
- "path": "percent",
9523
+ "path": "humidity",
9517
9524
  "valueType": "number"
9518
9525
  }],
9519
9526
  "image": [{
@@ -9623,7 +9630,7 @@ Object.freeze({
9623
9630
  "valueType": "number"
9624
9631
  },
9625
9632
  {
9626
- "path": "progressPercent",
9633
+ "path": "progress",
9627
9634
  "valueType": "number"
9628
9635
  },
9629
9636
  {
@@ -9702,11 +9709,11 @@ Object.freeze({
9702
9709
  "valueType": "string"
9703
9710
  },
9704
9711
  {
9705
- "path": "positionMs",
9712
+ "path": "position",
9706
9713
  "valueType": "number"
9707
9714
  },
9708
9715
  {
9709
- "path": "durationMs",
9716
+ "path": "duration",
9710
9717
  "valueType": "number"
9711
9718
  },
9712
9719
  {
@@ -9808,11 +9815,11 @@ Object.freeze({
9808
9815
  ]
9809
9816
  },
9810
9817
  {
9811
- "path": "signalPercent",
9818
+ "path": "signal",
9812
9819
  "valueType": "number"
9813
9820
  },
9814
9821
  {
9815
- "path": "rssiDbm",
9822
+ "path": "rssi",
9816
9823
  "valueType": "number"
9817
9824
  },
9818
9825
  {
@@ -9867,6 +9874,18 @@ Object.freeze({
9867
9874
  "path": "foodLevel",
9868
9875
  "valueType": "number"
9869
9876
  },
9877
+ {
9878
+ "path": "bowlFood",
9879
+ "valueType": "number"
9880
+ },
9881
+ {
9882
+ "path": "eating",
9883
+ "valueType": "boolean"
9884
+ },
9885
+ {
9886
+ "path": "supportsMarkRefilled",
9887
+ "valueType": "boolean"
9888
+ },
9870
9889
  {
9871
9890
  "path": "food1",
9872
9891
  "valueType": "number"
@@ -9931,23 +9950,23 @@ Object.freeze({
9931
9950
  ],
9932
9951
  "power-meter": [
9933
9952
  {
9934
- "path": "watts",
9953
+ "path": "power",
9935
9954
  "valueType": "number"
9936
9955
  },
9937
9956
  {
9938
- "path": "kwhTotal",
9957
+ "path": "energy",
9939
9958
  "valueType": "number"
9940
9959
  },
9941
9960
  {
9942
- "path": "volts",
9961
+ "path": "voltage",
9943
9962
  "valueType": "number"
9944
9963
  },
9945
9964
  {
9946
- "path": "amps",
9965
+ "path": "current",
9947
9966
  "valueType": "number"
9948
9967
  },
9949
9968
  {
9950
- "path": "va",
9969
+ "path": "apparentPower",
9951
9970
  "valueType": "number"
9952
9971
  },
9953
9972
  {
@@ -9975,14 +9994,10 @@ Object.freeze({
9975
9994
  {
9976
9995
  "path": "gps.accuracyMeters",
9977
9996
  "valueType": "number"
9978
- },
9979
- {
9980
- "path": "batteryPercent",
9981
- "valueType": "number"
9982
9997
  }
9983
9998
  ],
9984
9999
  "pressure-sensor": [{
9985
- "path": "hpa",
10000
+ "path": "pressure",
9986
10001
  "valueType": "number"
9987
10002
  }],
9988
10003
  "privacy-mask": [{
@@ -10296,7 +10311,7 @@ Object.freeze({
10296
10311
  "valueType": "boolean"
10297
10312
  }],
10298
10313
  "temperature-sensor": [{
10299
- "path": "celsius",
10314
+ "path": "temperature",
10300
10315
  "valueType": "number"
10301
10316
  }],
10302
10317
  "update": [
@@ -10344,7 +10359,7 @@ Object.freeze({
10344
10359
  "valueType": "string"
10345
10360
  },
10346
10361
  {
10347
- "path": "progressPercent",
10362
+ "path": "progress",
10348
10363
  "valueType": "number"
10349
10364
  },
10350
10365
  {
@@ -10843,7 +10858,7 @@ function errMsg(err) {
10843
10858
  return String(err);
10844
10859
  }
10845
10860
  //#endregion
10846
- //#region ../types/dist/composition-Bb8iwHEJ.mjs
10861
+ //#region ../types/dist/composition-CZImLpOI.mjs
10847
10862
  /**
10848
10863
  * The ffmpeg build every CamStack node downloads, per platform and arch.
10849
10864
  *
@@ -15363,6 +15378,14 @@ var AutomationConditionLeafSchema = object({
15363
15378
  array(union([string(), number()]))
15364
15379
  ])
15365
15380
  });
15381
+ var AutomationConditionStationaryPresentSchema = object({
15382
+ kind: literal("stationary-present"),
15383
+ deviceId: number().int().nonnegative(),
15384
+ /** Class names; a macro class matches every raw class that maps to it. */
15385
+ classes: array(string().min(1)).min(1).optional(),
15386
+ /** The parked object must be in at least one of these zones. */
15387
+ zones: array(string().min(1)).min(1).optional()
15388
+ });
15366
15389
  /**
15367
15390
  * The expression leaf, declared as a plain object rather than an intersection
15368
15391
  * with {@link ExpressionSourceSchema}: a discriminated union has to be able to
@@ -15396,7 +15419,8 @@ var AutomationConditionSchema = lazy(() => discriminatedUnion("kind", [
15396
15419
  child: AutomationConditionSchema
15397
15420
  }),
15398
15421
  AutomationConditionLeafSchema,
15399
- AutomationConditionExpressionSchema
15422
+ AutomationConditionExpressionSchema,
15423
+ AutomationConditionStationaryPresentSchema
15400
15424
  ]));
15401
15425
  /**
15402
15426
  * What starts a run.
@@ -15437,7 +15461,34 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15437
15461
  kind: literal("schedule"),
15438
15462
  cron: string().min(1).max(120)
15439
15463
  }),
15440
- object({ kind: literal("manual") })
15464
+ object({ kind: literal("manual") }),
15465
+ object({
15466
+ kind: literal("detection"),
15467
+ /** Class names. A macro class (`animal`, `vehicle`, `person`, `package`)
15468
+ * matches every raw class that maps to it; any other name matches
15469
+ * exactly. */
15470
+ classes: array(string().min(1)).min(1),
15471
+ deviceIds: array(number().int().nonnegative()).min(1),
15472
+ /** The track must have visited at least one of these zones. */
15473
+ zones: array(string().min(1)).min(1).optional(),
15474
+ /** Best-so-far confidence the track must reach. */
15475
+ minScore: number().min(0).max(1).optional()
15476
+ }),
15477
+ object({
15478
+ kind: literal("stationary"),
15479
+ deviceIds: array(number().int().nonnegative()).min(1),
15480
+ /** Class names; a macro class matches like the detection trigger. */
15481
+ classes: array(string().min(1)).min(1).optional(),
15482
+ /** The parked object must be in at least one of these zones. */
15483
+ zones: array(string().min(1)).min(1).optional(),
15484
+ /** `appeared`: it became parked. `departed`: the registry retired it.
15485
+ * The vocabulary of `PipelineAnalyticsStationaryChanged`. */
15486
+ phase: _enum(["appeared", "departed"])
15487
+ }),
15488
+ object({
15489
+ kind: literal("interval"),
15490
+ minutes: number().int().min(1).max(1440)
15491
+ })
15441
15492
  ]);
15442
15493
  /**
15443
15494
  * One action step.
@@ -15457,28 +15508,47 @@ var AutomationTriggerSchema = discriminatedUnion("kind", [
15457
15508
  * is called. The runner still receives a number and is untouched; the
15458
15509
  * resolution is the recipe's job, not the runner's.
15459
15510
  */
15511
+ var AutomationWaitStepSchema = object({
15512
+ kind: literal("wait"),
15513
+ seconds: number().min(0).max(300)
15514
+ });
15515
+ var AutomationCapStepSchema = object({
15516
+ kind: literal("cap"),
15517
+ /**
15518
+ * One device, several same-family devices (locks / climate family / …),
15519
+ * or `{ $var }` for the device that triggered the run. An array is
15520
+ * fan-out at codegen — each id gets the same cap.method call.
15521
+ */
15522
+ deviceId: union([
15523
+ number().int(),
15524
+ array(number().int()).min(1),
15525
+ object({ $var: string().min(1) })
15526
+ ]),
15527
+ cap: string().min(1),
15528
+ method: string().min(1),
15529
+ /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
15530
+ * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
15531
+ * the expression leaf. */
15532
+ args: record(string(), unknown()).optional()
15533
+ });
15534
+ /**
15535
+ * The steps an internal Action may contain: cap and wait, and nothing that can
15536
+ * call back into an Action — so an Action can never reach itself (no cycles).
15537
+ */
15538
+ var ActionStepSchema = discriminatedUnion("kind", [AutomationWaitStepSchema, AutomationCapStepSchema]);
15460
15539
  var AutomationActionSchema = discriminatedUnion("kind", [
15540
+ AutomationWaitStepSchema,
15541
+ AutomationCapStepSchema,
15461
15542
  object({
15462
- kind: literal("wait"),
15463
- seconds: number().min(0).max(300)
15464
- }),
15465
- object({
15466
- kind: literal("cap"),
15467
- /**
15468
- * One device, several same-family devices (locks / climate family / …),
15469
- * or `{ $var }` for the device that triggered the run. An array is
15470
- * fan-out at codegen — each id gets the same cap.method call.
15471
- */
15472
- deviceId: union([
15473
- number().int(),
15474
- array(number().int()).min(1),
15475
- object({ $var: string().min(1) })
15476
- ]),
15477
- cap: string().min(1),
15478
- method: string().min(1),
15479
- /** Values may carry `{{vars.x}}` slots, which SUBSTITUTE and do not
15480
- * evaluate (§3.2.3). Anything beyond substitution is the expression leaf. */
15481
- args: record(string(), unknown()).optional()
15543
+ kind: literal("action"),
15544
+ /** An entry of the `actions` surface (`internal:<uuid>` or `<addonId>:<localId>`). */
15545
+ actionId: string().min(1),
15546
+ /** Values for the action's declared variables; the others take their default. */
15547
+ variables: record(string(), union([
15548
+ string(),
15549
+ number(),
15550
+ boolean()
15551
+ ])).optional()
15482
15552
  }),
15483
15553
  object({
15484
15554
  kind: literal("code"),
@@ -15487,10 +15557,357 @@ var AutomationActionSchema = discriminatedUnion("kind", [
15487
15557
  code: string().min(1).max(2e4)
15488
15558
  })
15489
15559
  ]);
15560
+ /**
15561
+ * How a trigger that arrives while the automation is busy (or cooling down) is
15562
+ * handled. One of the automation's execution modes, never a property of its
15563
+ * actions. Absent means `single`.
15564
+ *
15565
+ * - `single` — drop the trigger while a run is in progress (traced + logged).
15566
+ * - `restart` — abort the run in progress (at its next step boundary), start fresh.
15567
+ * - `queued` — queue up to `max` triggers, drop the rest (traced).
15568
+ * - `parallel` — up to `max` runs at once, drop the rest (traced).
15569
+ * - `cooldown` — `single`, and no new run until `minutes` after the last run
15570
+ * STARTED; persisted across a restart. A manual trigger bypasses only this
15571
+ * wait, never the single/queued limits.
15572
+ */
15573
+ var AutomationRunModeSchema = discriminatedUnion("mode", [
15574
+ object({ mode: literal("single") }),
15575
+ object({ mode: literal("restart") }),
15576
+ object({
15577
+ mode: literal("queued"),
15578
+ max: number().int().min(1).max(10)
15579
+ }),
15580
+ object({
15581
+ mode: literal("parallel"),
15582
+ max: number().int().min(1).max(10)
15583
+ }),
15584
+ object({
15585
+ mode: literal("cooldown"),
15586
+ minutes: number().int().min(1).max(1440)
15587
+ })
15588
+ ]);
15490
15589
  var AutomationRecipeSchema = object({
15491
15590
  triggers: array(AutomationTriggerSchema),
15492
15591
  conditions: AutomationConditionSchema.optional(),
15493
- actions: array(AutomationActionSchema)
15592
+ actions: array(AutomationActionSchema),
15593
+ runMode: AutomationRunModeSchema.optional(),
15594
+ /** How many run traces the automation keeps (default {@link DEFAULT_TRACE_KEEP}). */
15595
+ keepTraces: number().int().min(1).max(100).optional()
15596
+ });
15597
+ new Set([
15598
+ {
15599
+ id: "person",
15600
+ name: "Person"
15601
+ },
15602
+ {
15603
+ id: "vehicle",
15604
+ name: "Vehicle"
15605
+ },
15606
+ {
15607
+ id: "animal",
15608
+ name: "Animal"
15609
+ },
15610
+ {
15611
+ id: "package",
15612
+ name: "Package"
15613
+ }
15614
+ ].map((l) => l.id));
15615
+ var COCO_TO_MACRO = {
15616
+ mapping: {
15617
+ person: "person",
15618
+ bicycle: "vehicle",
15619
+ car: "vehicle",
15620
+ motorcycle: "vehicle",
15621
+ airplane: "vehicle",
15622
+ bus: "vehicle",
15623
+ train: "vehicle",
15624
+ truck: "vehicle",
15625
+ boat: "vehicle",
15626
+ bird: "animal",
15627
+ cat: "animal",
15628
+ dog: "animal",
15629
+ horse: "animal",
15630
+ sheep: "animal",
15631
+ cow: "animal",
15632
+ elephant: "animal",
15633
+ bear: "animal",
15634
+ zebra: "animal",
15635
+ giraffe: "animal",
15636
+ suitcase: "package",
15637
+ backpack: "package",
15638
+ handbag: "package"
15639
+ },
15640
+ preserveOriginal: false
15641
+ };
15642
+ new Set(Object.values(COCO_TO_MACRO.mapping));
15643
+ /**
15644
+ * Run traces — what an automation (or, later, an Action run) DID, node by node,
15645
+ * so the editor can paint every block green or red with its reason.
15646
+ *
15647
+ * A trace is data, not a log: it covers the WHOLE tree — the trigger stage,
15648
+ * every condition node (containers and leaves, including the ones a
15649
+ * short-circuit never reached), the run-mode verdict and every action step —
15650
+ * each addressed by a stable path (`conditions.0.1`, `actions.2`, or `steps.N`
15651
+ * for an Action run). Skipped
15652
+ * evaluations are traced too, and identical consecutive skips collapse into a
15653
+ * repeat count so a trigger that fails every 5 minutes cannot flush real runs.
15654
+ *
15655
+ * {@link AutomationStepTraceSchema} is deliberately free of automation
15656
+ * vocabulary so an Action run records the same step shape.
15657
+ */
15658
+ /** A value a trace may show: JSON primitives and short lists, nothing deeper. */
15659
+ var TraceValueSchema = union([
15660
+ string(),
15661
+ number(),
15662
+ boolean(),
15663
+ _null(),
15664
+ array(union([string(), number()]))
15665
+ ]);
15666
+ var AutomationRunOutcomeSchema = _enum([
15667
+ "ran",
15668
+ "skipped-trigger",
15669
+ "skipped-conditions",
15670
+ "skipped-cooldown",
15671
+ "skipped-overlap",
15672
+ "failed",
15673
+ "aborted"
15674
+ ]);
15675
+ /** `not-evaluated` = a short-circuit never reached the node. */
15676
+ var TraceNodeOutcomeSchema = _enum([
15677
+ "pass",
15678
+ "fail",
15679
+ "not-evaluated"
15680
+ ]);
15681
+ var AutomationTriggerTraceSchema = object({
15682
+ kind: string().min(1),
15683
+ outcome: _enum(["pass", "fail"]),
15684
+ /** Why an event was rejected ("class person not in [dog]") or what fired. */
15685
+ reason: string(),
15686
+ /** deviceId, className, trackId, score … — only what the trigger exposes. */
15687
+ vars: record(string(), TraceValueSchema)
15688
+ });
15689
+ var AutomationConditionTraceNodeSchema = object({
15690
+ /** `conditions` for the root, `conditions.<i>` for its i-th child, … */
15691
+ path: string().min(1),
15692
+ kind: _enum([
15693
+ "all",
15694
+ "any",
15695
+ "not",
15696
+ "condition",
15697
+ "expression",
15698
+ "stationary-present"
15699
+ ]),
15700
+ outcome: TraceNodeOutcomeSchema,
15701
+ reason: string(),
15702
+ deviceId: number().int().optional(),
15703
+ cap: string().optional(),
15704
+ fieldPath: string().optional(),
15705
+ operator: string().optional(),
15706
+ expected: TraceValueSchema.optional(),
15707
+ /** What the mirror held; `null` when it held nothing (unknown). */
15708
+ observed: TraceValueSchema.optional()
15709
+ });
15710
+ var AutomationRunVerdictSchema = object({
15711
+ mode: AutomationRunModeSchema,
15712
+ decision: _enum([
15713
+ "run",
15714
+ "queued",
15715
+ "restart",
15716
+ "drop",
15717
+ "cooldown",
15718
+ "bypass"
15719
+ ]),
15720
+ reason: string()
15721
+ });
15722
+ /** One executed (or not-run) step — shared by automations and Action runs. */
15723
+ var AutomationStepTraceSchema = object({
15724
+ /** `actions.<i>` */
15725
+ path: string().min(1),
15726
+ kind: string().min(1),
15727
+ cap: string().optional(),
15728
+ method: string().optional(),
15729
+ deviceId: number().int().optional(),
15730
+ startedAt: number().optional(),
15731
+ endedAt: number().optional(),
15732
+ outcome: _enum([
15733
+ "ok",
15734
+ "error",
15735
+ "not-run"
15736
+ ]),
15737
+ message: string().optional()
15738
+ });
15739
+ var AutomationRunTraceSchema = object({
15740
+ runId: string().min(1),
15741
+ startedAt: number(),
15742
+ endedAt: number(),
15743
+ trigger: AutomationTriggerTraceSchema,
15744
+ conditions: array(AutomationConditionTraceNodeSchema),
15745
+ verdict: AutomationRunVerdictSchema.optional(),
15746
+ steps: array(AutomationStepTraceSchema),
15747
+ outcome: AutomationRunOutcomeSchema,
15748
+ /** How many identical consecutive skips this trace stands for (>= 1). */
15749
+ repeat: number().int().min(1),
15750
+ /** When the latest of those repeats happened. */
15751
+ lastAt: number()
15752
+ });
15753
+ /**
15754
+ * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
15755
+ * `action:<actionId>`): the cooldown stamp and the trace ring.
15756
+ */
15757
+ var AutomationStateDocSchema = object({
15758
+ version: literal(1),
15759
+ lastRunStartedAt: number().nullable(),
15760
+ traces: array(AutomationRunTraceSchema)
15761
+ });
15762
+ /**
15763
+ * Actions — named, runnable things an operator (or an automation) can start,
15764
+ * declared as LIST ENTRIES, never as devices.
15765
+ *
15766
+ * An entry is either **internal** (a short list of cap/wait steps kept in the
15767
+ * hub's `actions` record kind) or declared by an addon through the
15768
+ * `action-source` collection (a Home Assistant script, a scene …). The one
15769
+ * surface the UI and automations talk to is the `actions` cap; it keeps no
15770
+ * catalog of its own (D3) — every `list` asks the providers live.
15771
+ *
15772
+ * This file is the data half: the entry schema, the variables an entry may
15773
+ * declare, and the pure resolution of the values a run was given. It holds no
15774
+ * runtime.
15775
+ */
15776
+ /** What a variable's value is. `select` takes one of `options`. */
15777
+ var ActionVariableTypeSchema = _enum([
15778
+ "string",
15779
+ "number",
15780
+ "boolean",
15781
+ "select"
15782
+ ]);
15783
+ var ACTION_VARIABLE_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
15784
+ var ActionVariableValueSchema = union([
15785
+ string(),
15786
+ number(),
15787
+ boolean()
15788
+ ]);
15789
+ /**
15790
+ * One declared variable. Steps reference it as `{ $var: 'name' }` (the whole
15791
+ * value) or `{{vars.name}}` (inside a string) in their args.
15792
+ */
15793
+ var ActionVariableSchema = object({
15794
+ name: string().regex(ACTION_VARIABLE_NAME_RE),
15795
+ label: string().min(1).max(120).optional(),
15796
+ type: ActionVariableTypeSchema,
15797
+ required: boolean().optional(),
15798
+ default: ActionVariableValueSchema.optional(),
15799
+ /** The allowed values of a `select`. */
15800
+ options: array(string().min(1)).min(1).optional()
15801
+ }).superRefine((v, ctx) => {
15802
+ if (v.type === "select" && v.options === void 0) ctx.addIssue({
15803
+ code: "custom",
15804
+ message: "a select variable needs options",
15805
+ path: ["options"]
15806
+ });
15807
+ if (v.default !== void 0 && variableValueError(v, v.default) !== null) ctx.addIssue({
15808
+ code: "custom",
15809
+ message: variableValueError(v, v.default) ?? "invalid default",
15810
+ path: ["default"]
15811
+ });
15812
+ });
15813
+ /** Why `value` is not a legal value for the variable, or null when it is. */
15814
+ function variableValueError(variable, value) {
15815
+ switch (variable.type) {
15816
+ case "string": return typeof value === "string" ? null : `variable "${variable.name}" must be a string`;
15817
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : `variable "${variable.name}" must be a number`;
15818
+ case "boolean": return typeof value === "boolean" ? null : `variable "${variable.name}" must be true or false`;
15819
+ case "select": return typeof value === "string" && (variable.options ?? []).includes(value) ? null : `variable "${variable.name}" must be one of ${(variable.options ?? []).join(", ")}`;
15820
+ }
15821
+ }
15822
+ var ActionSourceKindSchema = _enum(["internal", "addon"]);
15823
+ function isInternalActionId(actionId) {
15824
+ return actionId.startsWith("internal:") && actionId.length > 9;
15825
+ }
15826
+ /** The addon behind a `<addonId>:<localId>` id, or null for anything else (internal included). */
15827
+ function addonIdOfActionId(actionId) {
15828
+ if (isInternalActionId(actionId)) return null;
15829
+ const at = actionId.indexOf(":");
15830
+ return at > 0 && at < actionId.length - 1 ? actionId.slice(0, at) : null;
15831
+ }
15832
+ var ActionStatusSchema = object({
15833
+ isRunning: boolean(),
15834
+ /** Ms epoch the latest run STARTED; null when it never ran. */
15835
+ lastRunAt: number().nullable(),
15836
+ /** The latest run's failure; null on success or when it never ran. */
15837
+ lastError: string().nullable()
15838
+ });
15839
+ var ActionEntrySchema = object({
15840
+ /** `internal:<uuid>` or `<addonId>:<localId>`. */
15841
+ id: string().min(3),
15842
+ name: string().min(1).max(120),
15843
+ /** The addon that declared it; `core-blocks` for an internal one. */
15844
+ addonId: string().min(1),
15845
+ source: ActionSourceKindSchema,
15846
+ /** An addon-declared entry is edited where it was declared. */
15847
+ readOnly: boolean(),
15848
+ /** Internal only: cap and wait steps. No action-in-action, so no cycles. */
15849
+ steps: array(ActionStepSchema).min(1).max(50).optional(),
15850
+ variables: array(ActionVariableSchema).max(20).optional(),
15851
+ status: ActionStatusSchema
15852
+ }).superRefine((entry, ctx) => {
15853
+ if (entry.source === "internal") {
15854
+ if (!isInternalActionId(entry.id)) ctx.addIssue({
15855
+ code: "custom",
15856
+ message: "an internal action id is internal:<uuid>",
15857
+ path: ["id"]
15858
+ });
15859
+ return;
15860
+ }
15861
+ if (entry.steps !== void 0) ctx.addIssue({
15862
+ code: "custom",
15863
+ message: "only an internal action carries steps",
15864
+ path: ["steps"]
15865
+ });
15866
+ if (!entry.readOnly) ctx.addIssue({
15867
+ code: "custom",
15868
+ message: "an addon action is read-only here",
15869
+ path: ["readOnly"]
15870
+ });
15871
+ if (addonIdOfActionId(entry.id) === null) ctx.addIssue({
15872
+ code: "custom",
15873
+ message: "an addon action id is <addonId>:<localId>",
15874
+ path: ["id"]
15875
+ });
15876
+ });
15877
+ /** What an operator writes for an internal action. */
15878
+ var ActionInputSchema = object({
15879
+ name: string().min(1).max(120),
15880
+ steps: array(ActionStepSchema).min(1).max(50),
15881
+ variables: array(ActionVariableSchema).max(20).optional()
15882
+ });
15883
+ /** Who started a run. Absent = the operator pressed it. */
15884
+ var ActionRunOriginSchema = object({
15885
+ /** The automation block whose step started it. */
15886
+ blockId: string().min(1).optional() });
15887
+ /** `started` = the caller did not ask to wait. */
15888
+ var ActionRunOutcomeSchema = union([AutomationRunOutcomeSchema, literal("started")]);
15889
+ var ActionRunResultSchema = object({
15890
+ runId: string().min(1),
15891
+ outcome: ActionRunOutcomeSchema,
15892
+ /** Why it did not run, or what failed. */
15893
+ message: string().optional()
15894
+ });
15895
+ _enum([
15896
+ "not-found",
15897
+ "read-only",
15898
+ "invalid-variables",
15899
+ "invalid-steps",
15900
+ "not-linked",
15901
+ "busy"
15902
+ ]);
15903
+ object({
15904
+ actionId: string(),
15905
+ runId: string(),
15906
+ isRunning: boolean(),
15907
+ /** Set when the run ended. */
15908
+ outcome: AutomationRunOutcomeSchema.optional(),
15909
+ lastRunAt: number().nullable(),
15910
+ lastError: string().nullable()
15494
15911
  });
15495
15912
  /**
15496
15913
  * `addon-pages` — system-scoped singleton aggregator cap. Public-facing
@@ -18177,7 +18594,7 @@ var CompositionEventPlanSchema = object({
18177
18594
  stateField: string(),
18178
18595
  fieldKey: string()
18179
18596
  });
18180
- /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
18597
+ /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
18181
18598
  var CompositionProblemSchema = object({
18182
18599
  code: _enum([
18183
18600
  "reserved-variant",
@@ -18496,7 +18913,7 @@ var GROUP_TEMPLATES = [
18496
18913
  summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
18497
18914
  role: DeviceRole.TemperatureSensor,
18498
18915
  outputCap: "temperature-sensor",
18499
- outputField: "celsius",
18916
+ outputField: "temperature",
18500
18917
  quantity: "temperature",
18501
18918
  defaultAggregate: "mean",
18502
18919
  empty: "null",
@@ -18507,7 +18924,7 @@ var GROUP_TEMPLATES = [
18507
18924
  summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
18508
18925
  role: DeviceRole.HumiditySensor,
18509
18926
  outputCap: "humidity-sensor",
18510
- outputField: "percent",
18927
+ outputField: "humidity",
18511
18928
  quantity: "humidity",
18512
18929
  defaultAggregate: "mean",
18513
18930
  empty: "null",
@@ -18518,7 +18935,7 @@ var GROUP_TEMPLATES = [
18518
18935
  summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
18519
18936
  role: DeviceRole.PressureSensor,
18520
18937
  outputCap: "pressure-sensor",
18521
- outputField: "hpa",
18938
+ outputField: "pressure",
18522
18939
  quantity: "pressure",
18523
18940
  defaultAggregate: "mean",
18524
18941
  empty: "null",
@@ -18529,7 +18946,7 @@ var GROUP_TEMPLATES = [
18529
18946
  summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
18530
18947
  role: DeviceRole.AmbientLightSensor,
18531
18948
  outputCap: "ambient-light-sensor",
18532
- outputField: "lux",
18949
+ outputField: "illuminance",
18533
18950
  quantity: "illuminance",
18534
18951
  defaultAggregate: "mean",
18535
18952
  empty: "null",
@@ -18540,7 +18957,7 @@ var GROUP_TEMPLATES = [
18540
18957
  summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
18541
18958
  role: DeviceRole.PowerSensor,
18542
18959
  outputCap: "power-meter",
18543
- outputField: "watts",
18960
+ outputField: "power",
18544
18961
  quantity: "power",
18545
18962
  defaultAggregate: "sum",
18546
18963
  empty: "omit",
@@ -18551,7 +18968,7 @@ var GROUP_TEMPLATES = [
18551
18968
  summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
18552
18969
  role: DeviceRole.EnergySensor,
18553
18970
  outputCap: "power-meter",
18554
- outputField: "kwhTotal",
18971
+ outputField: "energy",
18555
18972
  quantity: "energy",
18556
18973
  defaultAggregate: "sum",
18557
18974
  empty: "omit",
@@ -18562,7 +18979,7 @@ var GROUP_TEMPLATES = [
18562
18979
  summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
18563
18980
  role: DeviceRole.BatterySensor,
18564
18981
  outputCap: "battery",
18565
- outputField: "percentage",
18982
+ outputField: "level",
18566
18983
  quantity: "percentage",
18567
18984
  defaultAggregate: "mean",
18568
18985
  empty: "null",
@@ -19140,7 +19557,18 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
19140
19557
  kind: "mutation",
19141
19558
  auth: "admin",
19142
19559
  access: "view"
19143
- });
19560
+ }), method(object({
19561
+ blockId: string().min(1),
19562
+ trace: AutomationRunTraceSchema.optional(),
19563
+ runStartedAt: number().optional(),
19564
+ keepTraces: number().int().min(1).max(100).optional()
19565
+ }), _void(), {
19566
+ kind: "mutation",
19567
+ auth: "admin"
19568
+ }), method(object({ blockId: string().min(1) }), AutomationStateDocSchema, { auth: "admin" }), method(object({ blockId: string().min(1) }), object({
19569
+ traces: array(AutomationRunTraceSchema),
19570
+ lastError: string().nullable()
19571
+ }), { auth: "admin" });
19144
19572
  /**
19145
19573
  * `custom-model-registry` — collection cap exposing operator-registered
19146
19574
  * custom detection models. Each provider (today: `addon-model-studio`)
@@ -44612,51 +45040,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
44612
45040
  kind: "mutation",
44613
45041
  auth: "admin"
44614
45042
  });
44615
- new Set([
44616
- {
44617
- id: "person",
44618
- name: "Person"
44619
- },
44620
- {
44621
- id: "vehicle",
44622
- name: "Vehicle"
44623
- },
44624
- {
44625
- id: "animal",
44626
- name: "Animal"
44627
- },
44628
- {
44629
- id: "package",
44630
- name: "Package"
44631
- }
44632
- ].map((l) => l.id));
44633
- var COCO_TO_MACRO = {
44634
- mapping: {
44635
- person: "person",
44636
- bicycle: "vehicle",
44637
- car: "vehicle",
44638
- motorcycle: "vehicle",
44639
- airplane: "vehicle",
44640
- bus: "vehicle",
44641
- train: "vehicle",
44642
- truck: "vehicle",
44643
- boat: "vehicle",
44644
- bird: "animal",
44645
- cat: "animal",
44646
- dog: "animal",
44647
- horse: "animal",
44648
- sheep: "animal",
44649
- cow: "animal",
44650
- elephant: "animal",
44651
- bear: "animal",
44652
- zebra: "animal",
44653
- giraffe: "animal",
44654
- suitcase: "package",
44655
- backpack: "package",
44656
- handbag: "package"
44657
- },
44658
- preserveOriginal: false
44659
- };
44660
45043
  var AUDIO_MACRO_LABELS = [
44661
45044
  {
44662
45045
  id: "speech",
@@ -57223,9 +57606,9 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
57223
57606
  */
57224
57607
  var AirQualitySensorStatusSchema = object({
57225
57608
  /** Carbon dioxide concentration in ppm. */
57226
- co2Ppm: number().min(0).optional().meta(readingMeta("concentration-volume")),
57609
+ co2: number().min(0).optional().meta(readingMeta("concentration-volume")),
57227
57610
  /** Total volatile organic compounds in ppb. */
57228
- vocPpb: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57611
+ voc: number().min(0).optional().meta(readingMeta("concentration-ppb")),
57229
57612
  /** Particulate matter ≤ 2.5 μm in µg/m³. */
57230
57613
  pm25: number().min(0).optional().meta(readingMeta("concentration-mass")),
57231
57614
  /** Particulate matter ≤ 10 μm in µg/m³. */
@@ -57258,12 +57641,12 @@ var airQualitySensorCapability = {
57258
57641
  * History (D850): recorded series.
57259
57642
  */
57260
57643
  history: { fields: {
57261
- co2Ppm: {
57644
+ co2: {
57262
57645
  kind: "gauge",
57263
57646
  unit: "ppm",
57264
57647
  deadband: 5
57265
57648
  },
57266
- vocPpb: {
57649
+ voc: {
57267
57650
  kind: "gauge",
57268
57651
  unit: "ppb",
57269
57652
  deadband: 5
@@ -57294,7 +57677,7 @@ var airQualitySensorCapability = {
57294
57677
  */
57295
57678
  var AmbientLightSensorStatusSchema = object({
57296
57679
  /** Current illuminance in lux (lx). `null` when the sample was refused (D393). */
57297
- lux: number().min(0).nullable().meta(readingMeta("illuminance", {
57680
+ illuminance: number().min(0).nullable().meta(readingMeta("illuminance", {
57298
57681
  precision: 0,
57299
57682
  label: "Illuminance"
57300
57683
  })),
@@ -57323,7 +57706,7 @@ var ambientLightSensorCapability = {
57323
57706
  /**
57324
57707
  * History (D850): recorded series. Wide range, so a RELATIVE deadband (10 %).
57325
57708
  */
57326
- history: { fields: { lux: {
57709
+ history: { fields: { illuminance: {
57327
57710
  kind: "gauge",
57328
57711
  unit: "lx",
57329
57712
  deadbandPct: 10,
@@ -57462,6 +57845,84 @@ var audioMetricsCapability = {
57462
57845
  */
57463
57846
  history: "none"
57464
57847
  };
57848
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
57849
+ actionId: string().min(1),
57850
+ variables: record(string(), ActionVariableValueSchema).optional()
57851
+ }), _void(), {
57852
+ kind: "mutation",
57853
+ auth: "admin"
57854
+ }), method(object({ actionId: string().min(1) }), _void(), {
57855
+ kind: "mutation",
57856
+ auth: "admin"
57857
+ });
57858
+ /**
57859
+ * actions — the ONE surface for runnable actions, for the UI and for
57860
+ * automations. Provided by the core-blocks builtin on the hub.
57861
+ *
57862
+ * An action is a LIST ENTRY, not a device (D883): either internal (cap and wait
57863
+ * steps, kept in the hub's `actions` record kind) or declared by an addon over
57864
+ * `action-source`. `list` asks every `action-source` provider LIVE and overlays
57865
+ * the run status from the hub's `runs` ledger; there is no catalog here to
57866
+ * drift (D3).
57867
+ *
57868
+ * **Permissions follow the camera, as linked devices do.** An action is linked
57869
+ * to cameras by the operator (`setLinks`, D356: nothing links itself). A
57870
+ * non-admin may `get` / `run` an action only through a camera they may see that
57871
+ * links it: they name the camera (`deviceId`, a top-level field so the scope
57872
+ * gate sees it) and the provider refuses an action that camera does not link.
57873
+ * An admin, and an in-process caller (an automation block), may run any action.
57874
+ * Every refusal is typed (`[not-linked] …`) and logged.
57875
+ *
57876
+ * A second `run` of an action that is already running is REFUSED — traced and
57877
+ * logged — never queued.
57878
+ */
57879
+ var ActionIdInput = object({ actionId: string().min(1) });
57880
+ var ActionLinksSchema = object({
57881
+ deviceId: number().int().nonnegative(),
57882
+ actionIds: array(string().min(1)).max(100)
57883
+ });
57884
+ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
57885
+ actionId: string().min(1),
57886
+ deviceId: number().int().nonnegative().optional()
57887
+ }), object({ action: ActionEntrySchema.nullable() }), {
57888
+ role: "viewer",
57889
+ auth: "protected",
57890
+ kind: "query",
57891
+ caller: "required"
57892
+ }), method(object({
57893
+ actionId: string().min(1),
57894
+ variables: record(string(), ActionVariableValueSchema).optional(),
57895
+ wait: boolean().optional(),
57896
+ origin: ActionRunOriginSchema.optional(),
57897
+ deviceId: number().int().nonnegative().optional()
57898
+ }), ActionRunResultSchema, {
57899
+ role: "viewer",
57900
+ auth: "protected",
57901
+ kind: "mutation",
57902
+ caller: "required"
57903
+ }), method(ActionIdInput, _void(), {
57904
+ kind: "mutation",
57905
+ auth: "admin"
57906
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
57907
+ kind: "mutation",
57908
+ auth: "admin"
57909
+ }), method(object({
57910
+ actionId: string().min(1),
57911
+ action: ActionInputSchema.partial()
57912
+ }), object({ action: ActionEntrySchema }), {
57913
+ kind: "mutation",
57914
+ auth: "admin"
57915
+ }), method(ActionIdInput, _void(), {
57916
+ kind: "mutation",
57917
+ auth: "admin"
57918
+ }), method(object({ deviceId: number().int().nonnegative() }), array(ActionEntrySchema), {
57919
+ role: "viewer",
57920
+ auth: "protected",
57921
+ kind: "query"
57922
+ }), method(object({ deviceId: number().int().nonnegative() }), ActionLinksSchema, { auth: "admin" }), method(ActionLinksSchema, ActionLinksSchema, {
57923
+ kind: "mutation",
57924
+ auth: "admin"
57925
+ });
57465
57926
  /**
57466
57927
  * Automation-control cap. Models HA `automation.*` entities on
57467
57928
  * `DeviceType.Automation`. An automation is a trigger+condition+
@@ -57558,7 +58019,7 @@ var BatteryStatusSchema = object({
57558
58019
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
57559
58020
  * declines to band a non-finite reading, which is the correct shape.
57560
58021
  */
57561
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
58022
+ level: number().min(0).max(100).nullable().meta(readingMeta("percentage", { label: "Charge" })),
57562
58023
  /**
57563
58024
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
57564
58025
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -57568,7 +58029,7 @@ var BatteryStatusSchema = object({
57568
58029
  * `'unknown'` is the absence of an answer: the provider has not read the
57569
58030
  * power fields yet, or the firmware reported neither. Before it existed,
57570
58031
  * two unreadable fields produced `'none'`, and a camera nobody had reached
57571
- * was drawn "on battery alone" — the same D315 defect `percentage` closed
58032
+ * was drawn "on battery alone" — the same D315 defect `level` closed
57572
58033
  * by going nullable. Consumers SKIP it (no charger state published, no
57573
58034
  * glyph, no HomeKit ChargingState) rather than coerce it either way.
57574
58035
  */
@@ -57592,7 +58053,7 @@ var BatteryStatusSchema = object({
57592
58053
  * that only report charge. A second reading on this cap, not a second
57593
58054
  * `numeric-sensor` on the same device.
57594
58055
  */
57595
- volts: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
58056
+ voltage: number().nullable().optional().meta(readingMeta("voltage", { label: "Voltage" })),
57596
58057
  /**
57597
58058
  * Ms epoch of the last time the device PROVED it was reachable — a
57598
58059
  * completed firmware round-trip, an observed wake, or an inbound push
@@ -57626,7 +58087,7 @@ var BatteryStatusSchema = object({
57626
58087
  /**
57627
58088
  * True when the source is a BINARY low-battery indicator (HA
57628
58089
  * `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
57629
- * charge level — `percentage` is then a coarse stand-in (100 = normal,
58090
+ * charge level — `level` is then a coarse stand-in (100 = normal,
57630
58091
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
57631
58092
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
57632
58093
  */
@@ -57646,15 +58107,15 @@ var BATTERY_DEVICE_TYPES = [
57646
58107
  var batteryCustomize = {
57647
58108
  version: 1,
57648
58109
  targets: [{
57649
- id: "percentage",
58110
+ id: "level",
57650
58111
  cardinality: "scalar",
57651
58112
  vocabulary: {
57652
58113
  cap: "battery",
57653
- stateField: "percentage"
58114
+ stateField: "level"
57654
58115
  },
57655
58116
  deviceTypes: BATTERY_DEVICE_TYPES,
57656
58117
  apply: "add",
57657
- path: "percentage",
58118
+ path: "level",
57658
58119
  sources: [{
57659
58120
  kind: "field",
57660
58121
  valueKinds: ["number", "string"],
@@ -57748,7 +58209,7 @@ onStatusChanged: { data: object({
57748
58209
  schema: BatteryStatusSchema,
57749
58210
  kind: "push",
57750
58211
  empty: {
57751
- percentage: null,
58212
+ level: null,
57752
58213
  charging: "unknown",
57753
58214
  sleeping: false,
57754
58215
  lastUpdated: 0
@@ -57775,11 +58236,11 @@ onStatusChanged: { data: object({
57775
58236
  * History (D850): recorded series. The generic capture replaces the `battery` series of `pipeline-analytics:stats-5m`.
57776
58237
  */
57777
58238
  history: { fields: {
57778
- percentage: {
58239
+ level: {
57779
58240
  kind: "gauge",
57780
58241
  unit: "%"
57781
58242
  },
57782
- volts: {
58243
+ voltage: {
57783
58244
  kind: "gauge",
57784
58245
  unit: "V"
57785
58246
  }
@@ -57839,14 +58300,14 @@ var binaryCapability = {
57839
58300
  * controls to this single-method surface.
57840
58301
  *
57841
58302
  * The cap is intentionally minimal: a single `setBrightness({deviceId,
57842
- * percentage})` mutation plus the auto-injected `getStatus`. Drivers
58303
+ * level})` mutation plus the auto-injected `getStatus`. Drivers
57843
58304
  * that expose richer controls (color temperature, scenes, schedules)
57844
58305
  * should surface those via the device's `getSettingsUISchema()`
57845
58306
  * instead of bloating this cap.
57846
58307
  */
57847
58308
  var BrightnessStatusSchema = object({
57848
58309
  /** Current level as 0..100 inclusive. Firmware-reported. */
57849
- percentage: number().min(0).max(100).meta(readingMeta("percentage")),
58310
+ level: number().min(0).max(100).meta(readingMeta("percentage")),
57850
58311
  /** Ms epoch of the last operator-driven change. Useful for UI freshness. */
57851
58312
  lastChangedAt: number()
57852
58313
  });
@@ -57858,7 +58319,7 @@ var brightnessCapability = {
57858
58319
  deviceTypes: [DeviceType.Light],
57859
58320
  methods: { setBrightness: method(object({
57860
58321
  deviceId: number().int().nonnegative(),
57861
- percentage: number().min(0).max(100)
58322
+ level: number().min(0).max(100)
57862
58323
  }), _void(), {
57863
58324
  kind: "mutation",
57864
58325
  auth: "protected"
@@ -57871,7 +58332,7 @@ var brightnessCapability = {
57871
58332
  */
57872
58333
  onBrightnessChanged: { data: object({
57873
58334
  deviceId: number(),
57874
- percentage: number().min(0).max(100),
58335
+ level: number().min(0).max(100),
57875
58336
  lastChangedAt: number()
57876
58337
  }) } },
57877
58338
  status: {
@@ -57894,7 +58355,7 @@ onBrightnessChanged: { data: object({
57894
58355
  /**
57895
58356
  * History (D850): recorded series. Actuator tier: level keeps every change.
57896
58357
  */
57897
- history: { fields: { percentage: {
58358
+ history: { fields: { level: {
57898
58359
  kind: "gauge",
57899
58360
  unit: "%",
57900
58361
  minIntervalMs: 0
@@ -58491,11 +58952,11 @@ var ColorInputSchema = discriminatedUnion("mode", [
58491
58952
  }),
58492
58953
  object({
58493
58954
  mode: literal("mired"),
58494
- mireds: number().int().min(50).max(1e3)
58955
+ colorTemperature: number().int().min(50).max(1e3)
58495
58956
  })
58496
58957
  ]);
58497
58958
  var ColorStatusSchema = object({
58498
- /** Active color mode — which of `rgb` / `hsv` / `mireds` reflects
58959
+ /** Active color mode — which of `rgb` / `hsv` / `colorTemperature` reflects
58499
58960
  * the bulb's current state. */
58500
58961
  mode: _enum([
58501
58962
  "rgb",
@@ -58507,7 +58968,7 @@ var ColorStatusSchema = object({
58507
58968
  /** Populated when `mode === 'hsv'`. */
58508
58969
  hsv: HsvTripletSchema.optional(),
58509
58970
  /** Populated when `mode === 'mired'`. */
58510
- mireds: number().int().optional().meta(readingMeta("colour-temperature")),
58971
+ colorTemperature: number().int().optional().meta(readingMeta("colour-temperature")),
58511
58972
  /** Ms epoch of the last operator-driven change. */
58512
58973
  lastChangedAt: number()
58513
58974
  });
@@ -58539,7 +59000,7 @@ onColorChanged: { data: object({
58539
59000
  ]),
58540
59001
  rgb: RgbTripletSchema.optional(),
58541
59002
  hsv: HsvTripletSchema.optional(),
58542
- mireds: number().int().optional(),
59003
+ colorTemperature: number().int().optional(),
58543
59004
  lastChangedAt: number()
58544
59005
  }) } },
58545
59006
  status: {
@@ -59416,11 +59877,11 @@ var DishwasherStatusSchema = object({
59416
59877
  /** Feature keys of the programs the appliance currently offers — drives the UI selector. */
59417
59878
  availablePrograms: array(string()),
59418
59879
  /** Seconds remaining on the active cycle, or null when not running / not known. */
59419
- remainingSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59880
+ remaining: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59420
59881
  /** Seconds the delayed start is set to (time until the cycle starts), or null. */
59421
- delayedStartSeconds: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59882
+ delayedStart: number().int().nonnegative().nullable().meta(readingMeta("duration")),
59422
59883
  /** Cycle completion 0..100, or null when not applicable. */
59423
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
59884
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
59424
59885
  /** True when the door is reported open; null when the door state is not known. */
59425
59886
  doorOpen: boolean().nullable(),
59426
59887
  /** True when the door is latched (locked) during a cycle; null when not reported. */
@@ -59639,14 +60100,14 @@ var dishwasherCapability = {
59639
60100
  runtimeState: DishwasherStatusSchema,
59640
60101
  durability: "session",
59641
60102
  history: { fields: {
59642
- progressPercent: {
60103
+ progress: {
59643
60104
  kind: "gauge",
59644
60105
  unit: "%",
59645
60106
  deadband: 2
59646
60107
  },
59647
60108
  state: { kind: "enum" },
59648
60109
  operationState: { kind: "enum" },
59649
- remainingSeconds: {
60110
+ remaining: {
59650
60111
  kind: "gauge",
59651
60112
  unit: "s",
59652
60113
  minIntervalMs: 6e4
@@ -60237,7 +60698,7 @@ var FanDirectionSchema = _enum(["forward", "reverse"]);
60237
60698
  var FanControlStatusSchema = object({
60238
60699
  /** Active speed as 0..100 inclusive. Null when the device has no
60239
60700
  * speed surface (single-speed fan). */
60240
- percentage: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60701
+ speed: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
60241
60702
  /** Speed granularity the device accepts (HA `percentage_step`, e.g. 25 for
60242
60703
  * a 4-speed fan). Absent when unknown — the UI then falls back to step 1. */
60243
60704
  percentageStep: number().positive().optional().meta(readingMeta("percentage")),
@@ -60264,7 +60725,7 @@ var fanControlCapability = {
60264
60725
  methods: {
60265
60726
  setPercentage: method(object({
60266
60727
  deviceId: number().int().nonnegative(),
60267
- percentage: number().min(0).max(100)
60728
+ speed: number().min(0).max(100)
60268
60729
  }), _void(), {
60269
60730
  kind: "mutation",
60270
60731
  auth: "protected"
@@ -60297,7 +60758,7 @@ var fanControlCapability = {
60297
60758
  },
60298
60759
  /**
60299
60760
  * Runtime-state slice — mirrored by the kernel. UI fan speed
60300
- * sliders read `percentage` for live updates.
60761
+ * sliders read `speed` for live updates.
60301
60762
  */
60302
60763
  runtimeState: FanControlStatusSchema,
60303
60764
  /**
@@ -60311,7 +60772,7 @@ var fanControlCapability = {
60311
60772
  * History (D850): recorded series. Actuator tier: speed keeps every change.
60312
60773
  */
60313
60774
  history: { fields: {
60314
- percentage: {
60775
+ speed: {
60315
60776
  kind: "gauge",
60316
60777
  unit: "%",
60317
60778
  minIntervalMs: 0
@@ -60756,7 +61217,7 @@ var humidifierCapability = {
60756
61217
  */
60757
61218
  var HumiditySensorStatusSchema = object({
60758
61219
  /** Current relative humidity, 0..100. `null` when the sample was refused (D393). */
60759
- percent: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
61220
+ humidity: number().min(0).max(100).nullable().meta(readingMeta("humidity", {
60760
61221
  precision: 0,
60761
61222
  label: "Humidity"
60762
61223
  })),
@@ -60785,7 +61246,7 @@ var humiditySensorCapability = {
60785
61246
  /**
60786
61247
  * History (D850): recorded series.
60787
61248
  */
60788
- history: { fields: { percent: {
61249
+ history: { fields: { humidity: {
60789
61250
  kind: "gauge",
60790
61251
  unit: "%",
60791
61252
  deadband: .5
@@ -61425,7 +61886,7 @@ var LawnMowerControlStatusSchema = object({
61425
61886
  batteryLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61426
61887
  /** 0..100 mowing-completion percentage of the current task, or null when no
61427
61888
  * task is active / progress is unavailable. */
61428
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61889
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
61429
61890
  /** Current device/event code (dynamic — mostly status, sometimes an error),
61430
61891
  * or null when unknown. */
61431
61892
  currentCode: number().nullable().meta(readingMeta("none")),
@@ -61925,7 +62386,7 @@ var lockControlCapability = {
61925
62386
  volatileStateFields: ["lastChangedAt"]
61926
62387
  };
61927
62388
  /**
61928
- * A monotonic total between resets (D944). Energy uses `power-meter.kwhTotal`
62389
+ * A monotonic total between resets (D944). Energy uses `power-meter.energy`
61929
62390
  * so dashboards keep one series; every other instantaneous reading lands here.
61930
62391
  * `value` is the time integral in the source quantity's accumulated base
61931
62392
  * (base-unit seconds, or kWh on the power meter). `null` is a gap, never zero.
@@ -62019,10 +62480,10 @@ var MediaPlayerStatusSchema = object({
62019
62480
  currentMedia: MediaInfoSchema.nullable(),
62020
62481
  /** Current playback position in ms. Null when not seekable or
62021
62482
  * nothing is playing. Pair with `DeviceFeature.MediaPlayerSeek`. */
62022
- positionMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62483
+ position: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62023
62484
  /** Total duration of the current media in ms. Null when unknown
62024
62485
  * (live stream) or nothing is playing. */
62025
- durationMs: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62486
+ duration: number().int().nonnegative().nullable().meta(readingMeta("duration-ms")),
62026
62487
  /** Shuffle toggle. Null when no shuffle surface.
62027
62488
  * Pair with `DeviceFeature.MediaPlayerShuffle`. */
62028
62489
  shuffle: boolean().nullable(),
@@ -62061,7 +62522,7 @@ var mediaPlayerCapability = {
62061
62522
  }),
62062
62523
  seek: method(object({
62063
62524
  deviceId: number().int().nonnegative(),
62064
- positionMs: number().int().nonnegative()
62525
+ position: number().int().nonnegative()
62065
62526
  }), _void(), {
62066
62527
  kind: "mutation",
62067
62528
  auth: "protected"
@@ -62133,7 +62594,7 @@ var mediaPlayerCapability = {
62133
62594
  /**
62134
62595
  * History (D850): volume (a level an operator or an automation sets; the
62135
62596
  * default 10 s floor folds a slider drag into its end value) and mute.
62136
- * `positionMs` is not recorded: it moves continuously while playing.
62597
+ * `position` is not recorded: it moves continuously while playing.
62137
62598
  */
62138
62599
  history: { fields: {
62139
62600
  volumeLevel: {
@@ -63095,9 +63556,9 @@ var NetworkLinkStatusSchema = object({
63095
63556
  * one whose reading has not landed must not be drawn at 0 %. Consumers
63096
63557
  * SKIP a null rather than coerce it.
63097
63558
  */
63098
- signalPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63559
+ signal: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
63099
63560
  /** Raw received signal strength in dBm, when the firmware reports one. */
63100
- rssiDbm: number().optional().meta(readingMeta("signal-level")),
63561
+ rssi: number().optional().meta(readingMeta("signal-level")),
63101
63562
  /** Network name of a wireless link, when the firmware reports it. */
63102
63563
  ssid: string().optional(),
63103
63564
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
@@ -63133,7 +63594,7 @@ onStatusChanged: { data: object({
63133
63594
  kind: "push",
63134
63595
  empty: {
63135
63596
  type: "unknown",
63136
- signalPercent: null,
63597
+ signal: null,
63137
63598
  lastUpdated: 0
63138
63599
  }
63139
63600
  },
@@ -63156,13 +63617,13 @@ onStatusChanged: { data: object({
63156
63617
  * History (D850): recorded series.
63157
63618
  */
63158
63619
  history: { fields: {
63159
- signalPercent: {
63620
+ signal: {
63160
63621
  kind: "gauge",
63161
63622
  unit: "%",
63162
63623
  deadband: 3,
63163
63624
  minIntervalMs: 6e4
63164
63625
  },
63165
- rssiDbm: {
63626
+ rssi: {
63166
63627
  kind: "gauge",
63167
63628
  unit: "dBm",
63168
63629
  deadband: 2,
@@ -63907,10 +64368,20 @@ var PetFeederDeviceStatusSchema = _enum([
63907
64368
  ]);
63908
64369
  var gramsPortion = number().int().min(4).max(200);
63909
64370
  var PetFeederStatusSchema = object({
63910
- /** Food currently in the bowl (grams). Null when the device has not
63911
- * reported a reading yet. On dual-hopper models this is the combined
63912
- * bowl reading; per-hopper levels live in `food1`/`food2`. */
64371
+ /** Food in the TANK (hopper), as the feeder's own sensor reports it
64372
+ * (`state.food`). A coarse level code, not grams — `0` is empty. The
64373
+ * amount in the bowl is `bowlFood`. On dual-hopper models this is the
64374
+ * combined reading; per-hopper levels live in `food1`/`food2`. Null when
64375
+ * the device has not reported yet. */
63913
64376
  foodLevel: number().nullable().meta(readingMeta("none")),
64377
+ /** Food in the BOWL as the feeder reports it (`state.bowl`), in the
64378
+ * feeder's own units. Null when the model reports none. */
64379
+ bowlFood: number().nullable().meta(readingMeta("none")),
64380
+ /** True while the pet is eating (`state.eating`). */
64381
+ eating: boolean(),
64382
+ /** Whether `markFoodReplenished` does anything on this model. When false
64383
+ * the client must not offer it. */
64384
+ supportsMarkRefilled: boolean(),
63914
64385
  /** Hopper-1 food level (grams) on dual-hopper feeders; null on
63915
64386
  * single-hopper models. */
63916
64387
  food1: number().nullable().meta(readingMeta("none")),
@@ -63918,8 +64389,8 @@ var PetFeederStatusSchema = object({
63918
64389
  * single-hopper models. */
63919
64390
  food2: number().nullable().meta(readingMeta("none")),
63920
64391
  /** Derived low-food flag — mirrors the HA `food_level` binary_sensor
63921
- * (`device_class: problem`, on = low). True when the bowl is empty /
63922
- * below the feeder's low threshold. */
64392
+ * (`device_class: problem`, on = low). True when the tank reports empty,
64393
+ * or, on a dual-hopper model, when EITHER hopper is empty. */
63923
64394
  lowFood: boolean(),
63924
64395
  /** Battery charge 0..100 (%). Null on mains-powered models or when the
63925
64396
  * device has no battery reading. */
@@ -63987,7 +64458,9 @@ var petFeederCapability = {
63987
64458
  kind: "mutation",
63988
64459
  auth: "protected"
63989
64460
  }),
63990
- /** Mark a hopper as refilled (D4H/D4S/D4SH). */
64461
+ /** Tell the PetKit cloud a hopper was refilled so it stops its low-food
64462
+ * reminders (D4H/D4S/D4SH only — see `supportsMarkRefilled`). It does not
64463
+ * change any sensor reading. */
63991
64464
  markFoodReplenished: method(object({ deviceId: number().int().nonnegative() }), _void(), {
63992
64465
  kind: "mutation",
63993
64466
  auth: "protected"
@@ -64060,6 +64533,7 @@ var petFeederCapability = {
64060
64533
  */
64061
64534
  history: { fields: {
64062
64535
  foodLevel: { kind: "gauge" },
64536
+ bowlFood: { kind: "gauge" },
64063
64537
  food1: { kind: "gauge" },
64064
64538
  food2: { kind: "gauge" },
64065
64539
  batteryPower: {
@@ -64469,16 +64943,16 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
64469
64943
  * in real-world devices.
64470
64944
  */
64471
64945
  var PowerMeterStatusSchema = object({
64472
- /** Instantaneous power draw in watts. */
64473
- watts: number().optional().meta(readingMeta("power", { label: "Power" })),
64946
+ /** Instantaneous power draw (watts). */
64947
+ power: number().optional().meta(readingMeta("power", { label: "Power" })),
64474
64948
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
64475
- kwhTotal: number().optional().meta(readingMeta("energy", { label: "Energy" })),
64476
- /** Voltage in volts. */
64477
- volts: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
64949
+ energy: number().optional().meta(readingMeta("energy", { label: "Energy" })),
64950
+ /** Voltage (volts). */
64951
+ voltage: number().optional().meta(readingMeta("voltage", { label: "Voltage" })),
64478
64952
  /** Current in amperes. */
64479
- amps: number().optional().meta(readingMeta("current", { label: "Current" })),
64953
+ current: number().optional().meta(readingMeta("current", { label: "Current" })),
64480
64954
  /** Apparent power in volt-amperes. */
64481
- va: number().optional().meta(readingMeta("apparent-power")),
64955
+ apparentPower: number().optional().meta(readingMeta("apparent-power")),
64482
64956
  /** Power factor (0..1) if reported. */
64483
64957
  powerFactor: number().min(0).max(1).optional().meta(readingMeta("ratio")),
64484
64958
  /** Ms epoch when the slice was last updated. */
@@ -64536,14 +65010,14 @@ function powerTarget(id, unit) {
64536
65010
  advancedExpression: true
64537
65011
  };
64538
65012
  }
64539
- /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
65013
+ /** "Power and energy" extension: power, energy, voltage and current from other devices (D951). */
64540
65014
  var powerMeterCustomize = {
64541
65015
  version: 1,
64542
65016
  targets: [
64543
- powerTarget("watts", "W"),
64544
- powerTarget("kwhTotal", "kWh"),
64545
- powerTarget("volts", "V"),
64546
- powerTarget("amps", "A")
65017
+ powerTarget("power", "W"),
65018
+ powerTarget("energy", "kWh"),
65019
+ powerTarget("voltage", "V"),
65020
+ powerTarget("current", "A")
64547
65021
  ]
64548
65022
  };
64549
65023
  var powerMeterCapability = {
@@ -64559,41 +65033,41 @@ var powerMeterCapability = {
64559
65033
  },
64560
65034
  runtimeState: PowerMeterStatusSchema,
64561
65035
  /**
64562
- * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
65036
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `energy` is an accumulator whose restored value is the baseline.
64563
65037
  *
64564
65038
  * See `RuntimeStateDurability`. Enforced by
64565
65039
  * `scripts/check-runtime-state-durability.ts`.
64566
65040
  */
64567
65041
  durability: "restored",
64568
65042
  /**
64569
- * History (D850): recorded series. Gauges are floored at 30 s; `kwhTotal` is the one monotonic meter (counter).
65043
+ * History (D850): recorded series. Gauges are floored at 30 s; `energy` is the one monotonic meter (counter).
64570
65044
  */
64571
65045
  history: { fields: {
64572
- watts: {
65046
+ power: {
64573
65047
  kind: "gauge",
64574
65048
  unit: "W",
64575
65049
  deadband: 1,
64576
65050
  minIntervalMs: 3e4
64577
65051
  },
64578
- kwhTotal: {
65052
+ energy: {
64579
65053
  kind: "counter",
64580
65054
  unit: "kWh",
64581
65055
  deadband: .01,
64582
65056
  minIntervalMs: 6e4
64583
65057
  },
64584
- volts: {
65058
+ voltage: {
64585
65059
  kind: "gauge",
64586
65060
  unit: "V",
64587
65061
  deadband: 1,
64588
65062
  minIntervalMs: 3e4
64589
65063
  },
64590
- amps: {
65064
+ current: {
64591
65065
  kind: "gauge",
64592
65066
  unit: "A",
64593
65067
  deadband: .05,
64594
65068
  minIntervalMs: 3e4
64595
65069
  },
64596
- va: {
65070
+ apparentPower: {
64597
65071
  kind: "gauge",
64598
65072
  unit: "VA",
64599
65073
  deadband: 1,
@@ -64643,9 +65117,6 @@ var PresenceStatusSchema = object({
64643
65117
  location: string().nullable(),
64644
65118
  /** GPS coordinates when available. Null otherwise. */
64645
65119
  gps: GpsLocationSchema.nullable(),
64646
- /** Optional battery level of the tracking device (0..100). Null
64647
- * when not reported. */
64648
- batteryPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
64649
65120
  /** Ms epoch when the slice was last updated. */
64650
65121
  lastChangedAt: number()
64651
65122
  });
@@ -64674,14 +65145,7 @@ var presenceCapability = {
64674
65145
  * `scripts/check-runtime-state-durability.ts`.
64675
65146
  */
64676
65147
  durability: "restored",
64677
- /**
64678
- * History (D850): recorded series.
64679
- */
64680
- history: { fields: { batteryPercent: {
64681
- kind: "gauge",
64682
- unit: "%",
64683
- deadband: 1
64684
- } } },
65148
+ history: "none",
64685
65149
  /** Clock fields: written, but excluded from the compare that decides
64686
65150
  * whether persisting is worth a SQLite commit. */
64687
65151
  volatileStateFields: ["lastChangedAt"]
@@ -64696,7 +65160,7 @@ var presenceCapability = {
64696
65160
  */
64697
65161
  var PressureSensorStatusSchema = object({
64698
65162
  /** Current pressure in hPa. `null` when the sample was refused (D393). */
64699
- hpa: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
65163
+ pressure: number().nullable().meta(readingMeta("pressure", { precision: 0 })),
64700
65164
  /** Ms epoch when the slice was last updated. */
64701
65165
  lastFetchedAt: number()
64702
65166
  });
@@ -64722,7 +65186,7 @@ var pressureSensorCapability = {
64722
65186
  /**
64723
65187
  * History (D850): recorded series.
64724
65188
  */
64725
- history: { fields: { hpa: {
65189
+ history: { fields: { pressure: {
64726
65190
  kind: "gauge",
64727
65191
  unit: "hPa",
64728
65192
  deadband: .1
@@ -68421,7 +68885,7 @@ var tamperCapability = {
68421
68885
  */
68422
68886
  var TemperatureSensorStatusSchema = object({
68423
68887
  /** Current temperature in Celsius. `null` when the sample was refused (D393). */
68424
- celsius: number().nullable().meta(readingMeta("temperature", {
68888
+ temperature: number().nullable().meta(readingMeta("temperature", {
68425
68889
  precision: 1,
68426
68890
  label: "Temperature"
68427
68891
  })),
@@ -68450,7 +68914,7 @@ var temperatureSensorCapability = {
68450
68914
  /**
68451
68915
  * History (D850): recorded series.
68452
68916
  */
68453
- history: { fields: { celsius: {
68917
+ history: { fields: { temperature: {
68454
68918
  kind: "gauge",
68455
68919
  unit: "°C",
68456
68920
  deadband: .1
@@ -68747,7 +69211,7 @@ var VacuumControlStatusSchema = object({
68747
69211
  /** Speed tokens the hardware accepts — drives the UI selector. */
68748
69212
  availableFanSpeeds: array(string()),
68749
69213
  /** 0..100 cleaning-completion percentage of the current task, or null. */
68750
- progressPercent: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
69214
+ progress: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
68751
69215
  /** Current error code (0 / null = no error). */
68752
69216
  errorCode: number().nullable().meta(readingMeta("none")),
68753
69217
  /** Human label for {@link errorCode}, or null when none / undecodable. */
@@ -70784,7 +71248,7 @@ var BaseDevice = class {
70784
71248
  * `device-local-state.ts`. Drivers access via:
70785
71249
  *
70786
71250
  * `this.state.battery.sleeping = true` // patches the battery slice
70787
- * `const pct = this.state.battery.percentage` // reads the battery slice
71251
+ * `const pct = this.state.battery.level` // reads the battery slice
70788
71252
  * `this.state.deviceStatus.online = true` // mirrors `markOnline(true)`
70789
71253
  *
70790
71254
  * Adding a new cap with `runtimeState:` automatically extends this
@@ -70824,7 +71288,7 @@ var BaseDevice = class {
70824
71288
  * shape; drivers don't redeclare it, they just write through.
70825
71289
  *
70826
71290
  * Read: `this.runtimeState.getCapState('battery')` →
70827
- * `{percentage, charging, sleeping, lastUpdated}` for any
71291
+ * `{level, charging, sleeping, lastUpdated}` for any
70828
71292
  * provider that registers `batteryCapability`.
70829
71293
  * Write: `this.runtimeState.setCapState('battery', { … })`.
70830
71294
  *
@@ -71998,6 +72462,104 @@ Object.freeze({
71998
72462
  access: "create",
71999
72463
  role: "admin"
72000
72464
  },
72465
+ "actions.create": {
72466
+ capName: "actions",
72467
+ capScope: "system",
72468
+ addonId: null,
72469
+ access: "create",
72470
+ role: "admin"
72471
+ },
72472
+ "actions.delete": {
72473
+ capName: "actions",
72474
+ capScope: "system",
72475
+ addonId: null,
72476
+ access: "delete",
72477
+ role: "admin"
72478
+ },
72479
+ "actions.get": {
72480
+ capName: "actions",
72481
+ capScope: "system",
72482
+ addonId: null,
72483
+ access: "view",
72484
+ role: "viewer"
72485
+ },
72486
+ "actions.getLinks": {
72487
+ capName: "actions",
72488
+ capScope: "system",
72489
+ addonId: null,
72490
+ access: "view",
72491
+ role: "admin"
72492
+ },
72493
+ "actions.getTraces": {
72494
+ capName: "actions",
72495
+ capScope: "system",
72496
+ addonId: null,
72497
+ access: "view",
72498
+ role: "admin"
72499
+ },
72500
+ "actions.list": {
72501
+ capName: "actions",
72502
+ capScope: "system",
72503
+ addonId: null,
72504
+ access: "view",
72505
+ role: "admin"
72506
+ },
72507
+ "actions.listForCamera": {
72508
+ capName: "actions",
72509
+ capScope: "system",
72510
+ addonId: null,
72511
+ access: "view",
72512
+ role: "viewer"
72513
+ },
72514
+ "actions.run": {
72515
+ capName: "actions",
72516
+ capScope: "system",
72517
+ addonId: null,
72518
+ access: "create",
72519
+ role: "viewer"
72520
+ },
72521
+ "actions.setLinks": {
72522
+ capName: "actions",
72523
+ capScope: "system",
72524
+ addonId: null,
72525
+ access: "create",
72526
+ role: "admin"
72527
+ },
72528
+ "actions.stop": {
72529
+ capName: "actions",
72530
+ capScope: "system",
72531
+ addonId: null,
72532
+ access: "create",
72533
+ role: "admin"
72534
+ },
72535
+ "actions.update": {
72536
+ capName: "actions",
72537
+ capScope: "system",
72538
+ addonId: null,
72539
+ access: "create",
72540
+ role: "admin"
72541
+ },
72542
+ "actionSource.listActions": {
72543
+ capName: "action-source",
72544
+ capScope: "system",
72545
+ addonId: null,
72546
+ access: "view",
72547
+ role: "admin"
72548
+ },
72549
+ "actionSource.runAction": {
72550
+ capName: "action-source",
72551
+ capScope: "system",
72552
+ addonId: null,
72553
+ access: "create",
72554
+ role: "admin"
72555
+ },
72556
+ "actionSource.stopAction": {
72557
+ capName: "action-source",
72558
+ capScope: "system",
72559
+ addonId: null,
72560
+ access: "create",
72561
+ role: "admin"
72562
+ },
72001
72563
  "addonPages.listPages": {
72002
72564
  capName: "addon-pages",
72003
72565
  capScope: "system",
@@ -73279,6 +73841,13 @@ Object.freeze({
73279
73841
  access: "view",
73280
73842
  role: "admin"
73281
73843
  },
73844
+ "coreBlocks.getAutomationRunState": {
73845
+ capName: "core-blocks",
73846
+ capScope: "system",
73847
+ addonId: null,
73848
+ access: "view",
73849
+ role: "admin"
73850
+ },
73282
73851
  "coreBlocks.getBlockSettings": {
73283
73852
  capName: "core-blocks",
73284
73853
  capScope: "system",
@@ -73300,6 +73869,13 @@ Object.freeze({
73300
73869
  access: "view",
73301
73870
  role: "admin"
73302
73871
  },
73872
+ "coreBlocks.getTraces": {
73873
+ capName: "core-blocks",
73874
+ capScope: "system",
73875
+ addonId: null,
73876
+ access: "view",
73877
+ role: "admin"
73878
+ },
73303
73879
  "coreBlocks.getTypeDefs": {
73304
73880
  capName: "core-blocks",
73305
73881
  capScope: "system",
@@ -73335,6 +73911,13 @@ Object.freeze({
73335
73911
  access: "create",
73336
73912
  role: "admin"
73337
73913
  },
73914
+ "coreBlocks.reportAutomationRun": {
73915
+ capName: "core-blocks",
73916
+ capScope: "system",
73917
+ addonId: null,
73918
+ access: "create",
73919
+ role: "admin"
73920
+ },
73338
73921
  "coreBlocks.restart": {
73339
73922
  capName: "core-blocks",
73340
73923
  capScope: "system",
@@ -81908,7 +82491,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81908
82491
  label: t("Full brightness", "Luminosità massima"),
81909
82492
  phrase: t("Set {device} to full brightness", "Porta {device} alla massima luminosità"),
81910
82493
  icon: "sun",
81911
- args: { percentage: 100 }
82494
+ args: { level: 100 }
81912
82495
  },
81913
82496
  {
81914
82497
  id: "brightness.half",
@@ -81916,7 +82499,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81916
82499
  label: t("Half brightness", "Luminosità a metà"),
81917
82500
  phrase: t("Dim {device} to half", "Abbassa {device} a metà luminosità"),
81918
82501
  icon: "sun-dim",
81919
- args: { percentage: 50 }
82502
+ args: { level: 50 }
81920
82503
  },
81921
82504
  {
81922
82505
  id: "brightness.off",
@@ -81924,16 +82507,16 @@ var ACTUATOR_CAP_VOCABULARY = {
81924
82507
  label: t("Brightness off", "Luminosità a zero"),
81925
82508
  phrase: t("Dim {device} to zero", "Abbassa {device} a zero"),
81926
82509
  icon: "lightbulb-off",
81927
- args: { percentage: 0 }
82510
+ args: { level: 0 }
81928
82511
  },
81929
82512
  {
81930
82513
  id: "brightness.set",
81931
82514
  method: "setBrightness",
81932
82515
  label: t("Set brightness", "Imposta la luminosità"),
81933
- phrase: t("Set the brightness of {device} to {percentage}", "Imposta la luminosità di {device} a {percentage}"),
82516
+ phrase: t("Set the brightness of {device} to {level}", "Imposta la luminosità di {device} a {level}"),
81934
82517
  icon: "sun-medium",
81935
82518
  openArgs: [{
81936
- key: "percentage",
82519
+ key: "level",
81937
82520
  label: PERCENT,
81938
82521
  offer: {
81939
82522
  kind: "number",
@@ -81947,13 +82530,13 @@ var ACTUATOR_CAP_VOCABULARY = {
81947
82530
  ],
81948
82531
  state: [{
81949
82532
  kind: "numeric",
81950
- field: "percentage",
82533
+ field: "level",
81951
82534
  quantity: t("the brightness", "la luminosità"),
81952
82535
  label: t("Brightness", "Luminosità"),
81953
82536
  unit: "%",
81954
82537
  icon: "sun"
81955
82538
  }],
81956
- events: { onBrightnessChanged: { notOperatorFacing: "the `percentage` state trigger reads the same change" } }
82539
+ events: { onBrightnessChanged: { notOperatorFacing: "the `level` state trigger reads the same change" } }
81957
82540
  },
81958
82541
  color: {
81959
82542
  scope: "device",
@@ -81967,7 +82550,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81967
82550
  icon: "sun",
81968
82551
  args: { color: {
81969
82552
  mode: "mired",
81970
- mireds: 370
82553
+ colorTemperature: 370
81971
82554
  } }
81972
82555
  },
81973
82556
  {
@@ -81978,7 +82561,7 @@ var ACTUATOR_CAP_VOCABULARY = {
81978
82561
  icon: "snowflake",
81979
82562
  args: { color: {
81980
82563
  mode: "mired",
81981
- mireds: 200
82564
+ colorTemperature: 200
81982
82565
  } }
81983
82566
  },
81984
82567
  {
@@ -82592,7 +83175,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82592
83175
  label: t("Fan off", "Ventilatore spento"),
82593
83176
  phrase: t("Stop {device}", "Ferma {device}"),
82594
83177
  icon: "power-off",
82595
- args: { percentage: 0 }
83178
+ args: { speed: 0 }
82596
83179
  },
82597
83180
  {
82598
83181
  id: "fan.full",
@@ -82600,16 +83183,16 @@ var ACTUATOR_CAP_VOCABULARY = {
82600
83183
  label: t("Fan full", "Ventilatore al massimo"),
82601
83184
  phrase: t("Run {device} at full speed", "Porta {device} alla massima velocità"),
82602
83185
  icon: "fan",
82603
- args: { percentage: 100 }
83186
+ args: { speed: 100 }
82604
83187
  },
82605
83188
  {
82606
83189
  id: "fan.speed",
82607
83190
  method: "setPercentage",
82608
83191
  label: t("Set speed", "Imposta la velocità"),
82609
- phrase: t("Set the speed of {device} to {percentage}", "Imposta la velocità di {device} al {percentage}"),
83192
+ phrase: t("Set the speed of {device} to {speed}", "Imposta la velocità di {device} al {speed}"),
82610
83193
  icon: "fan",
82611
83194
  openArgs: [{
82612
- key: "percentage",
83195
+ key: "speed",
82613
83196
  label: t("Speed", "Velocità"),
82614
83197
  offer: {
82615
83198
  kind: "number",
@@ -82671,7 +83254,7 @@ var ACTUATOR_CAP_VOCABULARY = {
82671
83254
  ],
82672
83255
  state: [{
82673
83256
  kind: "numeric",
82674
- field: "percentage",
83257
+ field: "speed",
82675
83258
  quantity: t("the speed", "la velocità"),
82676
83259
  label: t("Speed", "Velocità"),
82677
83260
  unit: "%",
@@ -83469,7 +84052,7 @@ var APPLIANCE_CAP_VOCABULARY = {
83469
84052
  },
83470
84053
  {
83471
84054
  kind: "numeric",
83472
- field: "progressPercent",
84055
+ field: "progress",
83473
84056
  quantity: t("the cycle progress", "l’avanzamento del lavaggio"),
83474
84057
  label: t("Progress", "Avanzamento"),
83475
84058
  unit: "%",
@@ -83827,10 +84410,10 @@ var APPLIANCE_CAP_VOCABULARY = {
83827
84410
  id: "media.seek",
83828
84411
  method: "seek",
83829
84412
  label: t("Seek", "Vai al punto"),
83830
- phrase: t("Move {device} to {positionMs}", "Porta {device} al punto {positionMs}"),
84413
+ phrase: t("Move {device} to {position}", "Porta {device} al punto {position}"),
83831
84414
  icon: "fast-forward",
83832
84415
  openArgs: [{
83833
- key: "positionMs",
84416
+ key: "position",
83834
84417
  label: t("Position", "Posizione"),
83835
84418
  offer: {
83836
84419
  kind: "number",
@@ -84879,7 +85462,7 @@ var SENSOR_CAP_VOCABULARY = {
84879
85462
  state: [
84880
85463
  {
84881
85464
  kind: "numeric",
84882
- field: "co2Ppm",
85465
+ field: "co2",
84883
85466
  quantity: t("the CO₂", "la CO₂"),
84884
85467
  label: t("CO₂", "CO₂"),
84885
85468
  unit: "ppm",
@@ -84887,7 +85470,7 @@ var SENSOR_CAP_VOCABULARY = {
84887
85470
  },
84888
85471
  {
84889
85472
  kind: "numeric",
84890
- field: "vocPpb",
85473
+ field: "voc",
84891
85474
  quantity: t("the VOC level", "il livello di COV"),
84892
85475
  label: t("VOC", "COV"),
84893
85476
  unit: "ppb",
@@ -84923,7 +85506,7 @@ var SENSOR_CAP_VOCABULARY = {
84923
85506
  noun: t("Light level", "Luminosità ambiente"),
84924
85507
  state: [{
84925
85508
  kind: "numeric",
84926
- field: "lux",
85509
+ field: "illuminance",
84927
85510
  quantity: t("the light level", "la luminosità"),
84928
85511
  label: t("Illuminance", "Illuminamento"),
84929
85512
  unit: "lx",
@@ -85126,7 +85709,7 @@ var SENSOR_CAP_VOCABULARY = {
85126
85709
  noun: t("Humidity", "Umidità"),
85127
85710
  state: [{
85128
85711
  kind: "numeric",
85129
- field: "percent",
85712
+ field: "humidity",
85130
85713
  quantity: t("the humidity", "l’umidità"),
85131
85714
  label: t("Humidity", "Umidità"),
85132
85715
  unit: "%",
@@ -85174,7 +85757,7 @@ var SENSOR_CAP_VOCABULARY = {
85174
85757
  state: [
85175
85758
  {
85176
85759
  kind: "numeric",
85177
- field: "watts",
85760
+ field: "power",
85178
85761
  quantity: t("the power draw", "il consumo"),
85179
85762
  label: t("Power", "Potenza"),
85180
85763
  unit: "W",
@@ -85182,7 +85765,7 @@ var SENSOR_CAP_VOCABULARY = {
85182
85765
  },
85183
85766
  {
85184
85767
  kind: "numeric",
85185
- field: "kwhTotal",
85768
+ field: "energy",
85186
85769
  quantity: t("the energy used", "l’energia consumata"),
85187
85770
  label: t("Energy", "Energia"),
85188
85771
  unit: "kWh",
@@ -85190,7 +85773,7 @@ var SENSOR_CAP_VOCABULARY = {
85190
85773
  },
85191
85774
  {
85192
85775
  kind: "numeric",
85193
- field: "volts",
85776
+ field: "voltage",
85194
85777
  quantity: t("the voltage", "la tensione"),
85195
85778
  label: t("Voltage", "Tensione"),
85196
85779
  unit: "V",
@@ -85198,7 +85781,7 @@ var SENSOR_CAP_VOCABULARY = {
85198
85781
  },
85199
85782
  {
85200
85783
  kind: "numeric",
85201
- field: "amps",
85784
+ field: "current",
85202
85785
  quantity: t("the current", "la corrente"),
85203
85786
  label: t("Current", "Corrente"),
85204
85787
  unit: "A",
@@ -85215,13 +85798,6 @@ var SENSOR_CAP_VOCABULARY = {
85215
85798
  label: t("Where", "Posizione"),
85216
85799
  phrase: t("When {device} is at {value}", "Quando {device} è in {value}"),
85217
85800
  icon: "map-pin"
85218
- }, {
85219
- kind: "numeric",
85220
- field: "batteryPercent",
85221
- quantity: t("the phone battery", "la batteria del telefono"),
85222
- label: t("Battery", "Batteria"),
85223
- unit: "%",
85224
- icon: "battery"
85225
85801
  }]
85226
85802
  },
85227
85803
  "pressure-sensor": {
@@ -85229,7 +85805,7 @@ var SENSOR_CAP_VOCABULARY = {
85229
85805
  noun: t("Pressure", "Pressione"),
85230
85806
  state: [{
85231
85807
  kind: "numeric",
85232
- field: "hpa",
85808
+ field: "pressure",
85233
85809
  quantity: t("the pressure", "la pressione"),
85234
85810
  label: t("Pressure", "Pressione"),
85235
85811
  unit: "hPa",
@@ -85265,7 +85841,7 @@ var SENSOR_CAP_VOCABULARY = {
85265
85841
  noun: t("Temperature", "Temperatura"),
85266
85842
  state: [{
85267
85843
  kind: "numeric",
85268
- field: "celsius",
85844
+ field: "temperature",
85269
85845
  quantity: t("the temperature", "la temperatura"),
85270
85846
  label: t("Temperature", "Temperatura"),
85271
85847
  unit: "°C",
@@ -85336,7 +85912,7 @@ var SENSOR_CAP_VOCABULARY = {
85336
85912
  state: [
85337
85913
  {
85338
85914
  kind: "numeric",
85339
- field: "percentage",
85915
+ field: "level",
85340
85916
  quantity: t("the battery level", "il livello della batteria"),
85341
85917
  label: t("Battery", "Batteria"),
85342
85918
  unit: "%",
@@ -85378,7 +85954,7 @@ var SENSOR_CAP_VOCABULARY = {
85378
85954
  icon: "battery-charging"
85379
85955
  }
85380
85956
  ],
85381
- events: { onStatusChanged: { notOperatorFacing: "the percentage / sleeping / charging state triggers each read one field of this change" } },
85957
+ events: { onStatusChanged: { notOperatorFacing: "the level / sleeping / charging state triggers each read one field of this change" } },
85382
85958
  extraEvents: [{
85383
85959
  category: EventCategory.DeviceAwake,
85384
85960
  label: t("Woke up", "Risvegliato"),
@@ -85396,7 +85972,7 @@ var SENSOR_CAP_VOCABULARY = {
85396
85972
  noun: t("Network link", "Collegamento di rete"),
85397
85973
  state: [{
85398
85974
  kind: "numeric",
85399
- field: "signalPercent",
85975
+ field: "signal",
85400
85976
  quantity: t("the signal strength", "l’intensità del segnale"),
85401
85977
  label: t("Signal", "Segnale"),
85402
85978
  unit: "%",
@@ -85489,6 +86065,8 @@ var ML = "model and training machinery — no device action";
85489
86065
  var INTERNAL = "internal plumbing between addons — never operator-facing";
85490
86066
  /** Every system-scoped cap, with why it is not a device's vocabulary. */
85491
86067
  var SYSTEM_CAP_VOCABULARY = {
86068
+ "action-source": system(INTERNAL),
86069
+ actions: system("declared actions — run from the Actions page and from the cameras that link them"),
85492
86070
  "addon-pages": system(UI_PLUMBING),
85493
86071
  "addon-pages-source": system(UI_PLUMBING),
85494
86072
  "addon-routes": system(UI_PLUMBING),
@@ -85685,6 +86263,31 @@ Object.freeze({
85685
86263
  form: "single",
85686
86264
  optional: false
85687
86265
  }],
86266
+ "actions.get": [{
86267
+ name: "deviceId",
86268
+ form: "single",
86269
+ optional: true
86270
+ }],
86271
+ "actions.getLinks": [{
86272
+ name: "deviceId",
86273
+ form: "single",
86274
+ optional: false
86275
+ }],
86276
+ "actions.listForCamera": [{
86277
+ name: "deviceId",
86278
+ form: "single",
86279
+ optional: false
86280
+ }],
86281
+ "actions.run": [{
86282
+ name: "deviceId",
86283
+ form: "single",
86284
+ optional: true
86285
+ }],
86286
+ "actions.setLinks": [{
86287
+ name: "deviceId",
86288
+ form: "single",
86289
+ optional: false
86290
+ }],
85688
86291
  "addonSettings.getDeviceSettings": [{
85689
86292
  name: "deviceId",
85690
86293
  form: "single",
@@ -89856,6 +90459,7 @@ function ingestReading(input) {
89856
90459
  value: converted
89857
90460
  };
89858
90461
  }
90462
+ String.raw`(?<=^|["'(\s>,\[{])`;
89859
90463
  var MB = 1024 * 1024;
89860
90464
  1024 * MB, 3072 * MB;
89861
90465
  //#endregion
@@ -96288,10 +96892,10 @@ function batteryModeForUnit(unit) {
96288
96892
  /** The canonical "value" field name for a typed sensor cap's slice. */
96289
96893
  function valueFieldForCap(cap) {
96290
96894
  switch (cap) {
96291
- case "temperature-sensor": return "celsius";
96292
- case "humidity-sensor": return "percent";
96293
- case "pressure-sensor": return "hpa";
96294
- case "ambient-light-sensor": return "lux";
96895
+ case "temperature-sensor": return "temperature";
96896
+ case "humidity-sensor": return "humidity";
96897
+ case "pressure-sensor": return "pressure";
96898
+ case "ambient-light-sensor": return "illuminance";
96295
96899
  case "numeric-sensor": return "value";
96296
96900
  }
96297
96901
  }
@@ -96536,7 +97140,7 @@ var SUPPORTED_CAPS = new Set([
96536
97140
  * - `'%'` (binary/bar batteries, already decoded to a percent) → the typed
96537
97141
  * `battery` cap (which models a 0..100 percentage).
96538
97142
  * - `'V'` (raw voltage, e.g. WS90/WH90/WS85 capacitor + soil/leaf push) →
96539
- * `battery.volts`. A voltage has no honest percentage, so `percentage`
97143
+ * `battery.voltage`. A voltage has no honest percentage, so `level`
96540
97144
  * stays null. The field lives on `battery`, so a numeric primary sensor
96541
97145
  * and a voltage battery do not share a slice.
96542
97146
  */
@@ -96550,7 +97154,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96550
97154
  /**
96551
97155
  * Which battery cap (if any) was registered for this sensor:
96552
97156
  * - `'percent'` → the typed `battery` cap (percentage),
96553
- * - `'voltage'` → `battery.volts` (percentage stays null),
97157
+ * - `'voltage'` → `battery.voltage` (level stays null),
96554
97158
  * - `'none'` → no battery cap.
96555
97159
  */
96556
97160
  batteryMode = "none";
@@ -96621,7 +97225,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96621
97225
  this.runtimeState.setCapState(this.capName, slice);
96622
97226
  if (this.batteryMode === "percent" && sensor.batteryUnit === "%" && typeof sensor.battery === "number") {
96623
97227
  const next = {
96624
- percentage: Math.max(0, Math.min(100, sensor.battery)),
97228
+ level: Math.max(0, Math.min(100, sensor.battery)),
96625
97229
  charging: "none",
96626
97230
  sleeping: false,
96627
97231
  lastUpdated: lastFetchedAt
@@ -96630,8 +97234,8 @@ var EcowittSensorDevice = class extends BaseDevice {
96630
97234
  }
96631
97235
  if (this.batteryMode === "voltage" && sensor.batteryUnit === "V" && typeof sensor.battery === "number" && Number.isFinite(sensor.battery)) {
96632
97236
  const next = {
96633
- percentage: null,
96634
- volts: sensor.battery,
97237
+ level: null,
97238
+ voltage: sensor.battery,
96635
97239
  charging: "none",
96636
97240
  sleeping: false,
96637
97241
  lastUpdated: lastFetchedAt
@@ -96643,7 +97247,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96643
97247
  switch (this.capName) {
96644
97248
  case "temperature-sensor": {
96645
97249
  const COLD = {
96646
- celsius: 0,
97250
+ temperature: 0,
96647
97251
  lastFetchedAt: 0
96648
97252
  };
96649
97253
  this.ctx.registerNativeCap(temperatureSensorCapability, { getStatus: async () => this.readSlice(COLD) });
@@ -96652,7 +97256,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96652
97256
  }
96653
97257
  case "humidity-sensor": {
96654
97258
  const COLD = {
96655
- percent: 0,
97259
+ humidity: 0,
96656
97260
  lastFetchedAt: 0
96657
97261
  };
96658
97262
  this.ctx.registerNativeCap(humiditySensorCapability, { getStatus: async () => this.readSlice(COLD) });
@@ -96661,7 +97265,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96661
97265
  }
96662
97266
  case "pressure-sensor": {
96663
97267
  const COLD = {
96664
- hpa: 0,
97268
+ pressure: 0,
96665
97269
  lastFetchedAt: 0
96666
97270
  };
96667
97271
  this.ctx.registerNativeCap(pressureSensorCapability, { getStatus: async () => this.readSlice(COLD) });
@@ -96670,7 +97274,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96670
97274
  }
96671
97275
  case "ambient-light-sensor": {
96672
97276
  const COLD = {
96673
- lux: 0,
97277
+ illuminance: 0,
96674
97278
  lastFetchedAt: 0
96675
97279
  };
96676
97280
  this.ctx.registerNativeCap(ambientLightSensorCapability, { getStatus: async () => this.readSlice(COLD) });
@@ -96689,8 +97293,8 @@ var EcowittSensorDevice = class extends BaseDevice {
96689
97293
  }
96690
97294
  }
96691
97295
  /**
96692
- * Register the `battery` cap. Percent batteries fill `percentage`. Voltage
96693
- * batteries fill `volts` and leave `percentage` null.
97296
+ * Register the `battery` cap. Percent batteries fill `level`. Voltage
97297
+ * batteries fill `voltage` and leave `level` null.
96694
97298
  */
96695
97299
  maybeRegisterBatteryCap() {
96696
97300
  const sensor = this.resolveSensor();
@@ -96702,7 +97306,7 @@ var EcowittSensorDevice = class extends BaseDevice {
96702
97306
  /** Register the typed `battery` (percentage) cap for a `%`-unit battery. */
96703
97307
  registerPercentBatteryCap() {
96704
97308
  const COLD = {
96705
- percentage: 0,
97309
+ level: 0,
96706
97310
  charging: "none",
96707
97311
  sleeping: false,
96708
97312
  lastUpdated: 0
@@ -96717,11 +97321,11 @@ var EcowittSensorDevice = class extends BaseDevice {
96717
97321
  this.runtimeState.setCapState("battery", COLD);
96718
97322
  this.batteryMode = "percent";
96719
97323
  }
96720
- /** Voltage batteries share the `battery` cap. `percentage` stays unknown. */
97324
+ /** Voltage batteries share the `battery` cap. `level` stays unknown. */
96721
97325
  registerVoltageBatteryCap() {
96722
97326
  const COLD = {
96723
- percentage: null,
96724
- volts: null,
97327
+ level: null,
97328
+ voltage: null,
96725
97329
  charging: "unknown",
96726
97330
  sleeping: false,
96727
97331
  lastUpdated: 0