@camstack/addon-provider-dreame 0.2.153 → 0.2.155

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.
Files changed (3) hide show
  1. package/dist/addon.js +3022 -190
  2. package/dist/addon.mjs +3022 -190
  3. package/package.json +7 -2
package/dist/addon.js CHANGED
@@ -44,7 +44,7 @@ let net = require("net");
44
44
  net = __toESM(net, 1);
45
45
  let zlib = require("zlib");
46
46
  zlib = __toESM(zlib, 1);
47
- //#region ../types/dist/event-category-Ceif8n-v.mjs
47
+ //#region ../types/dist/event-category-DHXxB8t9.mjs
48
48
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
49
49
  EventCategory["SystemBoot"] = "system.boot";
50
50
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -340,7 +340,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
340
340
  * TRANSITION into that state (never per dispatch), and the node is dropped
341
341
  * from the placement candidate set for as long as it holds.
342
342
  *
343
- * This exists because the state was previously invisible: little-unraid
343
+ * This exists because the state was previously invisible: agent-a
344
344
  * absorbed 283k inference errors in a day while still being handed cameras,
345
345
  * and nothing in the system said so.
346
346
  *
@@ -5479,7 +5479,7 @@ var ZodIssueCode$1 = {
5479
5479
  var ZodFirstPartyTypeKind$1;
5480
5480
  ZodFirstPartyTypeKind$1 || (ZodFirstPartyTypeKind$1 = {});
5481
5481
  //#endregion
5482
- //#region ../types/dist/sleep-CYfIZzGv.mjs
5482
+ //#region ../types/dist/sleep-BErAxhul.mjs
5483
5483
  /**
5484
5484
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5485
5485
  * window to float samples (D455).
@@ -8502,6 +8502,1980 @@ method(object({ deviceId: number() }), array(StreamSourceEntrySchema)), method(o
8502
8502
  kind: "mutation",
8503
8503
  auth: "admin"
8504
8504
  }), method(object({ deviceId: number() }), unknown().nullable()), method(object({ deviceId: number() }), RawStateResultSchema.nullable(), { auth: "protected" });
8505
+ Object.freeze({ "doorbell": "lastPressedAt" });
8506
+ /** Every capability name, so addon code can check a name without the schema graph. */
8507
+ var CAP_NAMES = Object.freeze([
8508
+ "accessories",
8509
+ "addon-pages",
8510
+ "addon-pages-source",
8511
+ "addon-routes",
8512
+ "addon-settings",
8513
+ "addon-widgets",
8514
+ "addon-widgets-source",
8515
+ "addons",
8516
+ "admin-ui",
8517
+ "air-quality-sensor",
8518
+ "alarm-panel",
8519
+ "alerts",
8520
+ "ambient-light-sensor",
8521
+ "audio-analysis",
8522
+ "audio-analyzer",
8523
+ "audio-codec",
8524
+ "audio-metrics",
8525
+ "auth-provider",
8526
+ "automation-control",
8527
+ "backup",
8528
+ "battery",
8529
+ "binary",
8530
+ "brightness",
8531
+ "broker",
8532
+ "button",
8533
+ "calendar-source",
8534
+ "calendars",
8535
+ "camera-credentials",
8536
+ "camera-grid-layout",
8537
+ "camera-pipeline-config",
8538
+ "camera-streams",
8539
+ "carbon-monoxide",
8540
+ "climate-control",
8541
+ "color",
8542
+ "composer",
8543
+ "connection-test",
8544
+ "connectivity",
8545
+ "consumables",
8546
+ "contact",
8547
+ "control",
8548
+ "core-blocks",
8549
+ "cover",
8550
+ "custom-model-registry",
8551
+ "data-store-provider",
8552
+ "database-snapshot",
8553
+ "day-night",
8554
+ "decoder",
8555
+ "detection-pipeline",
8556
+ "device-admin-link",
8557
+ "device-adoption",
8558
+ "device-credentials",
8559
+ "device-discovery",
8560
+ "device-export",
8561
+ "device-extension",
8562
+ "device-history",
8563
+ "device-manager",
8564
+ "device-ops",
8565
+ "device-provider",
8566
+ "device-removal-hook",
8567
+ "device-state",
8568
+ "device-status",
8569
+ "dishwasher",
8570
+ "display-palette",
8571
+ "doorbell",
8572
+ "embedding-encoder",
8573
+ "enum-sensor",
8574
+ "event-emitter",
8575
+ "face-gallery",
8576
+ "failure-contribution",
8577
+ "fan-control",
8578
+ "feature-probe",
8579
+ "filesystem-browse",
8580
+ "flood",
8581
+ "gas",
8582
+ "heating-valve",
8583
+ "humidifier",
8584
+ "humidity-sensor",
8585
+ "image",
8586
+ "image-settings",
8587
+ "integrations",
8588
+ "intercom",
8589
+ "keychain",
8590
+ "keychain-admin",
8591
+ "lawn-mower-control",
8592
+ "llm",
8593
+ "llm-runtime",
8594
+ "load-contribution",
8595
+ "local-network",
8596
+ "lock-control",
8597
+ "log-channels",
8598
+ "log-destination",
8599
+ "login-method",
8600
+ "media-player",
8601
+ "mesh-network",
8602
+ "metrics-provider",
8603
+ "model-convert",
8604
+ "model-distributor",
8605
+ "motion",
8606
+ "motion-detection",
8607
+ "motion-trigger",
8608
+ "motion-zones",
8609
+ "mqtt-broker",
8610
+ "native-object-detection",
8611
+ "navigation",
8612
+ "network-access",
8613
+ "network-link",
8614
+ "network-quality",
8615
+ "node-certificates",
8616
+ "nodes",
8617
+ "notification-output",
8618
+ "notification-rules",
8619
+ "notifier",
8620
+ "numeric-sensor",
8621
+ "oauth-integration",
8622
+ "oidc-connections",
8623
+ "osd",
8624
+ "osd-manager",
8625
+ "pet-feeder",
8626
+ "pipeline-analytics",
8627
+ "pipeline-executor",
8628
+ "pipeline-orchestrator",
8629
+ "pipeline-runner",
8630
+ "plate-gallery",
8631
+ "platform-probe",
8632
+ "power-meter",
8633
+ "presence",
8634
+ "pressure-sensor",
8635
+ "privacy-mask",
8636
+ "ptz",
8637
+ "ptz-autotrack",
8638
+ "reboot",
8639
+ "record-entries",
8640
+ "recording",
8641
+ "recording-archive",
8642
+ "recording-export",
8643
+ "recording-onboard",
8644
+ "recording-signal",
8645
+ "records",
8646
+ "running-state",
8647
+ "scene-monitor",
8648
+ "script-runner",
8649
+ "server-management",
8650
+ "settings-store",
8651
+ "smoke",
8652
+ "smtp-provider",
8653
+ "snapshot",
8654
+ "sso-bridge",
8655
+ "storage",
8656
+ "storage-admin",
8657
+ "storage-evictable",
8658
+ "storage-migration",
8659
+ "storage-occupancy",
8660
+ "storage-provider",
8661
+ "stream-broker",
8662
+ "stream-catalog",
8663
+ "stream-params",
8664
+ "stream-signals",
8665
+ "switch",
8666
+ "system",
8667
+ "tamper",
8668
+ "temperature-sensor",
8669
+ "terminal-session",
8670
+ "toast",
8671
+ "training",
8672
+ "training-provider",
8673
+ "turn-provider",
8674
+ "update",
8675
+ "user-management",
8676
+ "user-passkeys",
8677
+ "vacuum-control",
8678
+ "valve",
8679
+ "vector-store",
8680
+ "vibration",
8681
+ "videoclips",
8682
+ "viewer-ui",
8683
+ "water-heater",
8684
+ "weather",
8685
+ "webrtc-session",
8686
+ "zone-analytics",
8687
+ "zone-rules",
8688
+ "zones"
8689
+ ]);
8690
+ Object.freeze({
8691
+ "air-quality-sensor": [
8692
+ {
8693
+ "path": "co2Ppm",
8694
+ "valueType": "number"
8695
+ },
8696
+ {
8697
+ "path": "vocPpb",
8698
+ "valueType": "number"
8699
+ },
8700
+ {
8701
+ "path": "pm25",
8702
+ "valueType": "number"
8703
+ },
8704
+ {
8705
+ "path": "pm10",
8706
+ "valueType": "number"
8707
+ },
8708
+ {
8709
+ "path": "aqi",
8710
+ "valueType": "number"
8711
+ },
8712
+ {
8713
+ "path": "unit",
8714
+ "valueType": "string"
8715
+ },
8716
+ {
8717
+ "path": "precision",
8718
+ "valueType": "number"
8719
+ }
8720
+ ],
8721
+ "alarm-panel": [
8722
+ {
8723
+ "path": "state",
8724
+ "valueType": "enum",
8725
+ "enumValues": [
8726
+ "disarmed",
8727
+ "armed_home",
8728
+ "armed_away",
8729
+ "armed_night",
8730
+ "armed_vacation",
8731
+ "armed_custom_bypass",
8732
+ "arming",
8733
+ "disarming",
8734
+ "pending",
8735
+ "triggered"
8736
+ ]
8737
+ },
8738
+ {
8739
+ "path": "targetMode",
8740
+ "valueType": "enum",
8741
+ "enumValues": [
8742
+ "home",
8743
+ "away",
8744
+ "night",
8745
+ "vacation",
8746
+ "custom_bypass"
8747
+ ]
8748
+ },
8749
+ {
8750
+ "path": "requiresCode",
8751
+ "valueType": "boolean"
8752
+ }
8753
+ ],
8754
+ "ambient-light-sensor": [
8755
+ {
8756
+ "path": "lux",
8757
+ "valueType": "number"
8758
+ },
8759
+ {
8760
+ "path": "unit",
8761
+ "valueType": "string"
8762
+ },
8763
+ {
8764
+ "path": "precision",
8765
+ "valueType": "number"
8766
+ }
8767
+ ],
8768
+ "audio-metrics": [
8769
+ {
8770
+ "path": "ts",
8771
+ "valueType": "number"
8772
+ },
8773
+ {
8774
+ "path": "windowSec",
8775
+ "valueType": "number"
8776
+ },
8777
+ {
8778
+ "path": "level.rms",
8779
+ "valueType": "number"
8780
+ },
8781
+ {
8782
+ "path": "level.dbfs",
8783
+ "valueType": "number"
8784
+ },
8785
+ {
8786
+ "path": "peakDbfs",
8787
+ "valueType": "number"
8788
+ },
8789
+ {
8790
+ "path": "avgDbfs",
8791
+ "valueType": "number"
8792
+ },
8793
+ {
8794
+ "path": "current.className",
8795
+ "valueType": "string"
8796
+ },
8797
+ {
8798
+ "path": "current.score",
8799
+ "valueType": "number"
8800
+ },
8801
+ {
8802
+ "path": "current.timestamp",
8803
+ "valueType": "number"
8804
+ }
8805
+ ],
8806
+ "automation-control": [
8807
+ {
8808
+ "path": "enabled",
8809
+ "valueType": "boolean"
8810
+ },
8811
+ {
8812
+ "path": "isRunning",
8813
+ "valueType": "boolean"
8814
+ },
8815
+ {
8816
+ "path": "lastTriggeredAt",
8817
+ "valueType": "number"
8818
+ },
8819
+ {
8820
+ "path": "lastError",
8821
+ "valueType": "string"
8822
+ }
8823
+ ],
8824
+ "battery": [
8825
+ {
8826
+ "path": "percentage",
8827
+ "valueType": "number"
8828
+ },
8829
+ {
8830
+ "path": "charging",
8831
+ "valueType": "enum",
8832
+ "enumValues": [
8833
+ "dc",
8834
+ "solar",
8835
+ "none",
8836
+ "unknown"
8837
+ ]
8838
+ },
8839
+ {
8840
+ "path": "sleeping",
8841
+ "valueType": "boolean"
8842
+ },
8843
+ {
8844
+ "path": "lastUpdated",
8845
+ "valueType": "number"
8846
+ },
8847
+ {
8848
+ "path": "lastContactAt",
8849
+ "valueType": "number"
8850
+ },
8851
+ {
8852
+ "path": "lastFullRefreshAt",
8853
+ "valueType": "number"
8854
+ },
8855
+ {
8856
+ "path": "binary",
8857
+ "valueType": "boolean"
8858
+ }
8859
+ ],
8860
+ "binary": [{
8861
+ "path": "on",
8862
+ "valueType": "boolean"
8863
+ }],
8864
+ "brightness": [{
8865
+ "path": "percentage",
8866
+ "valueType": "number"
8867
+ }],
8868
+ "broker": [{
8869
+ "path": "brokerCount",
8870
+ "valueType": "number"
8871
+ }, {
8872
+ "path": "connectedCount",
8873
+ "valueType": "number"
8874
+ }],
8875
+ "camera-credentials": [
8876
+ {
8877
+ "path": "host",
8878
+ "valueType": "string"
8879
+ },
8880
+ {
8881
+ "path": "port",
8882
+ "valueType": "number"
8883
+ },
8884
+ {
8885
+ "path": "onvifPort",
8886
+ "valueType": "number"
8887
+ },
8888
+ {
8889
+ "path": "rtspPort",
8890
+ "valueType": "number"
8891
+ },
8892
+ {
8893
+ "path": "https",
8894
+ "valueType": "boolean"
8895
+ },
8896
+ {
8897
+ "path": "hasUsername",
8898
+ "valueType": "boolean"
8899
+ },
8900
+ {
8901
+ "path": "hasPassword",
8902
+ "valueType": "boolean"
8903
+ },
8904
+ {
8905
+ "path": "onvifProfile",
8906
+ "valueType": "string"
8907
+ }
8908
+ ],
8909
+ "camera-streams": [
8910
+ {
8911
+ "path": "online",
8912
+ "valueType": "boolean"
8913
+ },
8914
+ {
8915
+ "path": "slotStatuses.high",
8916
+ "valueType": "enum",
8917
+ "enumValues": [
8918
+ "unassigned",
8919
+ "idle",
8920
+ "connecting",
8921
+ "streaming",
8922
+ "error"
8923
+ ]
8924
+ },
8925
+ {
8926
+ "path": "slotStatuses.mid",
8927
+ "valueType": "enum",
8928
+ "enumValues": [
8929
+ "unassigned",
8930
+ "idle",
8931
+ "connecting",
8932
+ "streaming",
8933
+ "error"
8934
+ ]
8935
+ },
8936
+ {
8937
+ "path": "slotStatuses.low",
8938
+ "valueType": "enum",
8939
+ "enumValues": [
8940
+ "unassigned",
8941
+ "idle",
8942
+ "connecting",
8943
+ "streaming",
8944
+ "error"
8945
+ ]
8946
+ },
8947
+ {
8948
+ "path": "slotErrors.high",
8949
+ "valueType": "string"
8950
+ },
8951
+ {
8952
+ "path": "slotErrors.mid",
8953
+ "valueType": "string"
8954
+ },
8955
+ {
8956
+ "path": "slotErrors.low",
8957
+ "valueType": "string"
8958
+ }
8959
+ ],
8960
+ "carbon-monoxide": [{
8961
+ "path": "detected",
8962
+ "valueType": "boolean"
8963
+ }],
8964
+ "climate-control": [
8965
+ {
8966
+ "path": "mode",
8967
+ "valueType": "enum",
8968
+ "enumValues": [
8969
+ "off",
8970
+ "heat",
8971
+ "cool",
8972
+ "auto",
8973
+ "heat_cool",
8974
+ "fan_only",
8975
+ "dry"
8976
+ ]
8977
+ },
8978
+ {
8979
+ "path": "fanMode",
8980
+ "valueType": "string"
8981
+ },
8982
+ {
8983
+ "path": "preset",
8984
+ "valueType": "string"
8985
+ },
8986
+ {
8987
+ "path": "target",
8988
+ "valueType": "number"
8989
+ },
8990
+ {
8991
+ "path": "targetHigh",
8992
+ "valueType": "number"
8993
+ },
8994
+ {
8995
+ "path": "targetLow",
8996
+ "valueType": "number"
8997
+ },
8998
+ {
8999
+ "path": "targetHumidity",
9000
+ "valueType": "number"
9001
+ },
9002
+ {
9003
+ "path": "currentTemp",
9004
+ "valueType": "number"
9005
+ },
9006
+ {
9007
+ "path": "currentHumidity",
9008
+ "valueType": "number"
9009
+ },
9010
+ {
9011
+ "path": "swingVertical",
9012
+ "valueType": "boolean"
9013
+ },
9014
+ {
9015
+ "path": "swingHorizontal",
9016
+ "valueType": "boolean"
9017
+ },
9018
+ {
9019
+ "path": "minTemp",
9020
+ "valueType": "number"
9021
+ },
9022
+ {
9023
+ "path": "maxTemp",
9024
+ "valueType": "number"
9025
+ },
9026
+ {
9027
+ "path": "tempStep",
9028
+ "valueType": "number"
9029
+ }
9030
+ ],
9031
+ "color": [
9032
+ {
9033
+ "path": "mode",
9034
+ "valueType": "enum",
9035
+ "enumValues": [
9036
+ "rgb",
9037
+ "hsv",
9038
+ "mired"
9039
+ ]
9040
+ },
9041
+ {
9042
+ "path": "rgb.r",
9043
+ "valueType": "number"
9044
+ },
9045
+ {
9046
+ "path": "rgb.g",
9047
+ "valueType": "number"
9048
+ },
9049
+ {
9050
+ "path": "rgb.b",
9051
+ "valueType": "number"
9052
+ },
9053
+ {
9054
+ "path": "hsv.h",
9055
+ "valueType": "number"
9056
+ },
9057
+ {
9058
+ "path": "hsv.s",
9059
+ "valueType": "number"
9060
+ },
9061
+ {
9062
+ "path": "hsv.v",
9063
+ "valueType": "number"
9064
+ },
9065
+ {
9066
+ "path": "mireds",
9067
+ "valueType": "number"
9068
+ }
9069
+ ],
9070
+ "connectivity": [{
9071
+ "path": "connected",
9072
+ "valueType": "boolean"
9073
+ }],
9074
+ "contact": [{
9075
+ "path": "entryOpen",
9076
+ "valueType": "boolean"
9077
+ }],
9078
+ "control": [
9079
+ {
9080
+ "path": "kind",
9081
+ "valueType": "enum",
9082
+ "enumValues": [
9083
+ "numeric",
9084
+ "select",
9085
+ "text",
9086
+ "datetime"
9087
+ ]
9088
+ },
9089
+ {
9090
+ "path": "unit",
9091
+ "valueType": "string"
9092
+ },
9093
+ {
9094
+ "path": "min",
9095
+ "valueType": "number"
9096
+ },
9097
+ {
9098
+ "path": "max",
9099
+ "valueType": "number"
9100
+ },
9101
+ {
9102
+ "path": "step",
9103
+ "valueType": "number"
9104
+ },
9105
+ {
9106
+ "path": "precision",
9107
+ "valueType": "number"
9108
+ },
9109
+ {
9110
+ "path": "format",
9111
+ "valueType": "enum",
9112
+ "enumValues": [
9113
+ "date",
9114
+ "time",
9115
+ "datetime"
9116
+ ]
9117
+ }
9118
+ ],
9119
+ "cover": [
9120
+ {
9121
+ "path": "state",
9122
+ "valueType": "enum",
9123
+ "enumValues": [
9124
+ "open",
9125
+ "opening",
9126
+ "closing",
9127
+ "closed",
9128
+ "stopped"
9129
+ ]
9130
+ },
9131
+ {
9132
+ "path": "position",
9133
+ "valueType": "number"
9134
+ },
9135
+ {
9136
+ "path": "tiltPosition",
9137
+ "valueType": "number"
9138
+ }
9139
+ ],
9140
+ "day-night": [
9141
+ {
9142
+ "path": "mode",
9143
+ "valueType": "enum",
9144
+ "enumValues": [
9145
+ "auto",
9146
+ "day",
9147
+ "night",
9148
+ "schedule"
9149
+ ]
9150
+ },
9151
+ {
9152
+ "path": "sensitivity",
9153
+ "valueType": "number"
9154
+ },
9155
+ {
9156
+ "path": "switchDelaySec",
9157
+ "valueType": "number"
9158
+ }
9159
+ ],
9160
+ "device-adoption": [
9161
+ {
9162
+ "path": "lastDiscoveryAt",
9163
+ "valueType": "number"
9164
+ },
9165
+ {
9166
+ "path": "candidateCount",
9167
+ "valueType": "number"
9168
+ },
9169
+ {
9170
+ "path": "adoptedCount",
9171
+ "valueType": "number"
9172
+ },
9173
+ {
9174
+ "path": "lastError",
9175
+ "valueType": "string"
9176
+ }
9177
+ ],
9178
+ "device-discovery": [{
9179
+ "path": "lastDiscoveryAt",
9180
+ "valueType": "number"
9181
+ }, {
9182
+ "path": "lastError",
9183
+ "valueType": "string"
9184
+ }],
9185
+ "device-export": [
9186
+ {
9187
+ "path": "linkState",
9188
+ "valueType": "enum",
9189
+ "enumValues": [
9190
+ "unlinked",
9191
+ "linked",
9192
+ "error"
9193
+ ]
9194
+ },
9195
+ {
9196
+ "path": "exposedDeviceCount",
9197
+ "valueType": "number"
9198
+ },
9199
+ {
9200
+ "path": "error",
9201
+ "valueType": "string"
9202
+ },
9203
+ {
9204
+ "path": "setup.qr",
9205
+ "valueType": "string"
9206
+ },
9207
+ {
9208
+ "path": "setup.note",
9209
+ "valueType": "string"
9210
+ }
9211
+ ],
9212
+ "device-status": [{
9213
+ "path": "online",
9214
+ "valueType": "boolean"
9215
+ }],
9216
+ "dishwasher": [
9217
+ {
9218
+ "path": "availability",
9219
+ "valueType": "enum",
9220
+ "enumValues": [
9221
+ "available",
9222
+ "offline",
9223
+ "description-missing"
9224
+ ]
9225
+ },
9226
+ {
9227
+ "path": "state",
9228
+ "valueType": "enum",
9229
+ "enumValues": [
9230
+ "idle",
9231
+ "running",
9232
+ "paused",
9233
+ "finished",
9234
+ "error",
9235
+ "unavailable"
9236
+ ]
9237
+ },
9238
+ {
9239
+ "path": "operationState",
9240
+ "valueType": "enum",
9241
+ "enumValues": [
9242
+ "Inactive",
9243
+ "Ready",
9244
+ "DelayedStart",
9245
+ "Run",
9246
+ "Pause",
9247
+ "ActionRequired",
9248
+ "Finished",
9249
+ "Error",
9250
+ "Aborting"
9251
+ ]
9252
+ },
9253
+ {
9254
+ "path": "program",
9255
+ "valueType": "string"
9256
+ },
9257
+ {
9258
+ "path": "selectedProgram",
9259
+ "valueType": "string"
9260
+ },
9261
+ {
9262
+ "path": "remainingSeconds",
9263
+ "valueType": "number"
9264
+ },
9265
+ {
9266
+ "path": "delayedStartSeconds",
9267
+ "valueType": "number"
9268
+ },
9269
+ {
9270
+ "path": "progressPercent",
9271
+ "valueType": "number"
9272
+ },
9273
+ {
9274
+ "path": "doorOpen",
9275
+ "valueType": "boolean"
9276
+ },
9277
+ {
9278
+ "path": "doorLocked",
9279
+ "valueType": "boolean"
9280
+ },
9281
+ {
9282
+ "path": "remoteStartAllowed",
9283
+ "valueType": "boolean"
9284
+ },
9285
+ {
9286
+ "path": "remoteControlActive",
9287
+ "valueType": "boolean"
9288
+ },
9289
+ {
9290
+ "path": "localControlActive",
9291
+ "valueType": "boolean"
9292
+ },
9293
+ {
9294
+ "path": "powerOn",
9295
+ "valueType": "boolean"
9296
+ },
9297
+ {
9298
+ "path": "powerState",
9299
+ "valueType": "string"
9300
+ },
9301
+ {
9302
+ "path": "filterCleaningDue",
9303
+ "valueType": "boolean"
9304
+ },
9305
+ {
9306
+ "path": "machineCareDue",
9307
+ "valueType": "boolean"
9308
+ },
9309
+ {
9310
+ "path": "machineCareRemainingRuns",
9311
+ "valueType": "number"
9312
+ },
9313
+ {
9314
+ "path": "halfLoad",
9315
+ "valueType": "boolean"
9316
+ },
9317
+ {
9318
+ "path": "hygienePlus",
9319
+ "valueType": "boolean"
9320
+ },
9321
+ {
9322
+ "path": "extraDry",
9323
+ "valueType": "boolean"
9324
+ },
9325
+ {
9326
+ "path": "intensiveZone",
9327
+ "valueType": "boolean"
9328
+ },
9329
+ {
9330
+ "path": "varioSpeedPlus",
9331
+ "valueType": "boolean"
9332
+ },
9333
+ {
9334
+ "path": "childLock",
9335
+ "valueType": "boolean"
9336
+ },
9337
+ {
9338
+ "path": "errorCode",
9339
+ "valueType": "number"
9340
+ },
9341
+ {
9342
+ "path": "errorLabel",
9343
+ "valueType": "string"
9344
+ }
9345
+ ],
9346
+ "doorbell": [{
9347
+ "path": "lastPressedAt",
9348
+ "valueType": "number"
9349
+ }, {
9350
+ "path": "pressCountSinceStart",
9351
+ "valueType": "number"
9352
+ }],
9353
+ "enum-sensor": [{
9354
+ "path": "value",
9355
+ "valueType": "string"
9356
+ }, {
9357
+ "path": "format",
9358
+ "valueType": "enum",
9359
+ "enumValues": [
9360
+ "date",
9361
+ "time",
9362
+ "datetime"
9363
+ ]
9364
+ }],
9365
+ "event-emitter": [
9366
+ {
9367
+ "path": "lastEvent.deviceId",
9368
+ "valueType": "number"
9369
+ },
9370
+ {
9371
+ "path": "lastEvent.eventType",
9372
+ "valueType": "string"
9373
+ },
9374
+ {
9375
+ "path": "lastEvent.timestamp",
9376
+ "valueType": "number"
9377
+ },
9378
+ {
9379
+ "path": "lastEvent.seq",
9380
+ "valueType": "number"
9381
+ },
9382
+ {
9383
+ "path": "eventCountSinceStart",
9384
+ "valueType": "number"
9385
+ }
9386
+ ],
9387
+ "fan-control": [
9388
+ {
9389
+ "path": "percentage",
9390
+ "valueType": "number"
9391
+ },
9392
+ {
9393
+ "path": "percentageStep",
9394
+ "valueType": "number"
9395
+ },
9396
+ {
9397
+ "path": "preset",
9398
+ "valueType": "string"
9399
+ },
9400
+ {
9401
+ "path": "direction",
9402
+ "valueType": "enum",
9403
+ "enumValues": ["forward", "reverse"]
9404
+ },
9405
+ {
9406
+ "path": "oscillating",
9407
+ "valueType": "boolean"
9408
+ }
9409
+ ],
9410
+ "feature-probe": [
9411
+ {
9412
+ "path": "deviceType",
9413
+ "valueType": "string"
9414
+ },
9415
+ {
9416
+ "path": "model",
9417
+ "valueType": "string"
9418
+ },
9419
+ {
9420
+ "path": "channelCount",
9421
+ "valueType": "number"
9422
+ },
9423
+ {
9424
+ "path": "lastProbedAt",
9425
+ "valueType": "number"
9426
+ }
9427
+ ],
9428
+ "flood": [{
9429
+ "path": "flooded",
9430
+ "valueType": "boolean"
9431
+ }],
9432
+ "gas": [{
9433
+ "path": "detected",
9434
+ "valueType": "boolean"
9435
+ }],
9436
+ "heating-valve": [{
9437
+ "path": "position",
9438
+ "valueType": "number"
9439
+ }],
9440
+ "humidifier": [
9441
+ {
9442
+ "path": "on",
9443
+ "valueType": "boolean"
9444
+ },
9445
+ {
9446
+ "path": "currentHumidity",
9447
+ "valueType": "number"
9448
+ },
9449
+ {
9450
+ "path": "targetHumidity",
9451
+ "valueType": "number"
9452
+ },
9453
+ {
9454
+ "path": "mode",
9455
+ "valueType": "string"
9456
+ },
9457
+ {
9458
+ "path": "action",
9459
+ "valueType": "string"
9460
+ },
9461
+ {
9462
+ "path": "minHumidity",
9463
+ "valueType": "number"
9464
+ },
9465
+ {
9466
+ "path": "maxHumidity",
9467
+ "valueType": "number"
9468
+ }
9469
+ ],
9470
+ "humidity-sensor": [
9471
+ {
9472
+ "path": "percent",
9473
+ "valueType": "number"
9474
+ },
9475
+ {
9476
+ "path": "unit",
9477
+ "valueType": "string"
9478
+ },
9479
+ {
9480
+ "path": "precision",
9481
+ "valueType": "number"
9482
+ }
9483
+ ],
9484
+ "image": [{
9485
+ "path": "url",
9486
+ "valueType": "string"
9487
+ }, {
9488
+ "path": "lastUpdated",
9489
+ "valueType": "number"
9490
+ }],
9491
+ "image-settings": [
9492
+ {
9493
+ "path": "brightness",
9494
+ "valueType": "number"
9495
+ },
9496
+ {
9497
+ "path": "contrast",
9498
+ "valueType": "number"
9499
+ },
9500
+ {
9501
+ "path": "saturation",
9502
+ "valueType": "number"
9503
+ },
9504
+ {
9505
+ "path": "sharpness",
9506
+ "valueType": "number"
9507
+ },
9508
+ {
9509
+ "path": "mirror",
9510
+ "valueType": "boolean"
9511
+ },
9512
+ {
9513
+ "path": "flip",
9514
+ "valueType": "boolean"
9515
+ },
9516
+ {
9517
+ "path": "rotate",
9518
+ "valueType": "enum",
9519
+ "enumValues": [
9520
+ "0",
9521
+ "90",
9522
+ "180",
9523
+ "270"
9524
+ ]
9525
+ },
9526
+ {
9527
+ "path": "whiteBalance",
9528
+ "valueType": "enum",
9529
+ "enumValues": ["auto", "manual"]
9530
+ },
9531
+ {
9532
+ "path": "warmth",
9533
+ "valueType": "number"
9534
+ },
9535
+ {
9536
+ "path": "exposureMode",
9537
+ "valueType": "enum",
9538
+ "enumValues": ["auto", "manual"]
9539
+ },
9540
+ {
9541
+ "path": "backlightMode",
9542
+ "valueType": "enum",
9543
+ "enumValues": [
9544
+ "off",
9545
+ "blc",
9546
+ "wdr",
9547
+ "hlc"
9548
+ ]
9549
+ }
9550
+ ],
9551
+ "intercom": [
9552
+ {
9553
+ "path": "talking",
9554
+ "valueType": "boolean"
9555
+ },
9556
+ {
9557
+ "path": "lastSessionAt",
9558
+ "valueType": "number"
9559
+ },
9560
+ {
9561
+ "path": "ability.sampleRate",
9562
+ "valueType": "number"
9563
+ },
9564
+ {
9565
+ "path": "ability.duplex",
9566
+ "valueType": "enum",
9567
+ "enumValues": ["half", "full"]
9568
+ },
9569
+ {
9570
+ "path": "ability.maxBacklogMs",
9571
+ "valueType": "number"
9572
+ }
9573
+ ],
9574
+ "lawn-mower-control": [
9575
+ {
9576
+ "path": "activity",
9577
+ "valueType": "enum",
9578
+ "enumValues": [
9579
+ "idle",
9580
+ "mowing",
9581
+ "paused",
9582
+ "docked",
9583
+ "error"
9584
+ ]
9585
+ },
9586
+ {
9587
+ "path": "batteryLevel",
9588
+ "valueType": "number"
9589
+ },
9590
+ {
9591
+ "path": "progressPercent",
9592
+ "valueType": "number"
9593
+ },
9594
+ {
9595
+ "path": "currentCode",
9596
+ "valueType": "number"
9597
+ },
9598
+ {
9599
+ "path": "currentCodeLabel",
9600
+ "valueType": "string"
9601
+ },
9602
+ {
9603
+ "path": "severity",
9604
+ "valueType": "enum",
9605
+ "enumValues": [
9606
+ "info",
9607
+ "warning",
9608
+ "error"
9609
+ ]
9610
+ }
9611
+ ],
9612
+ "lock-control": [{
9613
+ "path": "state",
9614
+ "valueType": "enum",
9615
+ "enumValues": [
9616
+ "locked",
9617
+ "unlocked",
9618
+ "locking",
9619
+ "unlocking",
9620
+ "jammed"
9621
+ ]
9622
+ }],
9623
+ "media-player": [
9624
+ {
9625
+ "path": "state",
9626
+ "valueType": "enum",
9627
+ "enumValues": [
9628
+ "off",
9629
+ "on",
9630
+ "idle",
9631
+ "playing",
9632
+ "paused",
9633
+ "buffering",
9634
+ "standby"
9635
+ ]
9636
+ },
9637
+ {
9638
+ "path": "volumeLevel",
9639
+ "valueType": "number"
9640
+ },
9641
+ {
9642
+ "path": "isMuted",
9643
+ "valueType": "boolean"
9644
+ },
9645
+ {
9646
+ "path": "source",
9647
+ "valueType": "string"
9648
+ },
9649
+ {
9650
+ "path": "currentMedia.type",
9651
+ "valueType": "string"
9652
+ },
9653
+ {
9654
+ "path": "currentMedia.title",
9655
+ "valueType": "string"
9656
+ },
9657
+ {
9658
+ "path": "currentMedia.artist",
9659
+ "valueType": "string"
9660
+ },
9661
+ {
9662
+ "path": "currentMedia.album",
9663
+ "valueType": "string"
9664
+ },
9665
+ {
9666
+ "path": "currentMedia.imageUrl",
9667
+ "valueType": "string"
9668
+ },
9669
+ {
9670
+ "path": "positionMs",
9671
+ "valueType": "number"
9672
+ },
9673
+ {
9674
+ "path": "durationMs",
9675
+ "valueType": "number"
9676
+ },
9677
+ {
9678
+ "path": "shuffle",
9679
+ "valueType": "boolean"
9680
+ },
9681
+ {
9682
+ "path": "repeat",
9683
+ "valueType": "enum",
9684
+ "enumValues": [
9685
+ "off",
9686
+ "all",
9687
+ "one"
9688
+ ]
9689
+ }
9690
+ ],
9691
+ "motion": [
9692
+ {
9693
+ "path": "detected",
9694
+ "valueType": "boolean"
9695
+ },
9696
+ {
9697
+ "path": "lastDetectedAt",
9698
+ "valueType": "number"
9699
+ },
9700
+ {
9701
+ "path": "autoClearAfterMs",
9702
+ "valueType": "number"
9703
+ }
9704
+ ],
9705
+ "motion-trigger": [{
9706
+ "path": "enabled",
9707
+ "valueType": "boolean"
9708
+ }],
9709
+ "motion-zones": [{
9710
+ "path": "enabled",
9711
+ "valueType": "boolean"
9712
+ }, {
9713
+ "path": "sensitivity",
9714
+ "valueType": "number"
9715
+ }],
9716
+ "mqtt-broker": [{
9717
+ "path": "brokerCount",
9718
+ "valueType": "number"
9719
+ }, {
9720
+ "path": "embeddedRunning",
9721
+ "valueType": "boolean"
9722
+ }],
9723
+ "native-object-detection": [{
9724
+ "path": "enabled",
9725
+ "valueType": "boolean"
9726
+ }],
9727
+ "navigation": [
9728
+ {
9729
+ "path": "mode",
9730
+ "valueType": "enum",
9731
+ "enumValues": [
9732
+ "idle",
9733
+ "cleaning",
9734
+ "spot",
9735
+ "following",
9736
+ "goto",
9737
+ "returning",
9738
+ "paused",
9739
+ "unknown"
9740
+ ]
9741
+ },
9742
+ {
9743
+ "path": "following",
9744
+ "valueType": "boolean"
9745
+ },
9746
+ {
9747
+ "path": "flash",
9748
+ "valueType": "boolean"
9749
+ },
9750
+ {
9751
+ "path": "lightMode",
9752
+ "valueType": "enum",
9753
+ "enumValues": ["auto", "manual"]
9754
+ },
9755
+ {
9756
+ "path": "lightLevel",
9757
+ "valueType": "number"
9758
+ }
9759
+ ],
9760
+ "network-link": [
9761
+ {
9762
+ "path": "type",
9763
+ "valueType": "enum",
9764
+ "enumValues": [
9765
+ "wifi",
9766
+ "ethernet",
9767
+ "cellular",
9768
+ "unknown"
9769
+ ]
9770
+ },
9771
+ {
9772
+ "path": "signalPercent",
9773
+ "valueType": "number"
9774
+ },
9775
+ {
9776
+ "path": "rssiDbm",
9777
+ "valueType": "number"
9778
+ },
9779
+ {
9780
+ "path": "ssid",
9781
+ "valueType": "string"
9782
+ },
9783
+ {
9784
+ "path": "lastUpdated",
9785
+ "valueType": "number"
9786
+ }
9787
+ ],
9788
+ "notifier": [
9789
+ {
9790
+ "path": "lastSentAt",
9791
+ "valueType": "number"
9792
+ },
9793
+ {
9794
+ "path": "lastError",
9795
+ "valueType": "string"
9796
+ },
9797
+ {
9798
+ "path": "queueDepth",
9799
+ "valueType": "number"
9800
+ },
9801
+ {
9802
+ "path": "supports.image",
9803
+ "valueType": "boolean"
9804
+ },
9805
+ {
9806
+ "path": "supports.priority",
9807
+ "valueType": "boolean"
9808
+ },
9809
+ {
9810
+ "path": "supports.data",
9811
+ "valueType": "boolean"
9812
+ },
9813
+ {
9814
+ "path": "supports.actions",
9815
+ "valueType": "boolean"
9816
+ },
9817
+ {
9818
+ "path": "supports.recipients",
9819
+ "valueType": "boolean"
9820
+ }
9821
+ ],
9822
+ "numeric-sensor": [
9823
+ {
9824
+ "path": "value",
9825
+ "valueType": "number"
9826
+ },
9827
+ {
9828
+ "path": "unit",
9829
+ "valueType": "string"
9830
+ },
9831
+ {
9832
+ "path": "precision",
9833
+ "valueType": "number"
9834
+ }
9835
+ ],
9836
+ "pet-feeder": [
9837
+ {
9838
+ "path": "foodLevel",
9839
+ "valueType": "number"
9840
+ },
9841
+ {
9842
+ "path": "food1",
9843
+ "valueType": "number"
9844
+ },
9845
+ {
9846
+ "path": "food2",
9847
+ "valueType": "number"
9848
+ },
9849
+ {
9850
+ "path": "lowFood",
9851
+ "valueType": "boolean"
9852
+ },
9853
+ {
9854
+ "path": "batteryPower",
9855
+ "valueType": "number"
9856
+ },
9857
+ {
9858
+ "path": "desiccantLeftDays",
9859
+ "valueType": "number"
9860
+ },
9861
+ {
9862
+ "path": "feeding",
9863
+ "valueType": "boolean"
9864
+ },
9865
+ {
9866
+ "path": "status",
9867
+ "valueType": "enum",
9868
+ "enumValues": [
9869
+ "normal",
9870
+ "offline",
9871
+ "on_batteries"
9872
+ ]
9873
+ },
9874
+ {
9875
+ "path": "error",
9876
+ "valueType": "string"
9877
+ },
9878
+ {
9879
+ "path": "errorCode",
9880
+ "valueType": "number"
9881
+ },
9882
+ {
9883
+ "path": "isDualHopper",
9884
+ "valueType": "boolean"
9885
+ },
9886
+ {
9887
+ "path": "childLock",
9888
+ "valueType": "boolean"
9889
+ },
9890
+ {
9891
+ "path": "indicatorLight",
9892
+ "valueType": "boolean"
9893
+ },
9894
+ {
9895
+ "path": "feedSound",
9896
+ "valueType": "boolean"
9897
+ },
9898
+ {
9899
+ "path": "volume",
9900
+ "valueType": "number"
9901
+ }
9902
+ ],
9903
+ "power-meter": [
9904
+ {
9905
+ "path": "watts",
9906
+ "valueType": "number"
9907
+ },
9908
+ {
9909
+ "path": "kwhTotal",
9910
+ "valueType": "number"
9911
+ },
9912
+ {
9913
+ "path": "volts",
9914
+ "valueType": "number"
9915
+ },
9916
+ {
9917
+ "path": "amps",
9918
+ "valueType": "number"
9919
+ },
9920
+ {
9921
+ "path": "va",
9922
+ "valueType": "number"
9923
+ },
9924
+ {
9925
+ "path": "powerFactor",
9926
+ "valueType": "number"
9927
+ },
9928
+ {
9929
+ "path": "unit",
9930
+ "valueType": "string"
9931
+ },
9932
+ {
9933
+ "path": "precision",
9934
+ "valueType": "number"
9935
+ }
9936
+ ],
9937
+ "presence": [
9938
+ {
9939
+ "path": "state",
9940
+ "valueType": "string"
9941
+ },
9942
+ {
9943
+ "path": "location",
9944
+ "valueType": "string"
9945
+ },
9946
+ {
9947
+ "path": "gps.latitude",
9948
+ "valueType": "number"
9949
+ },
9950
+ {
9951
+ "path": "gps.longitude",
9952
+ "valueType": "number"
9953
+ },
9954
+ {
9955
+ "path": "gps.accuracyMeters",
9956
+ "valueType": "number"
9957
+ },
9958
+ {
9959
+ "path": "batteryPercent",
9960
+ "valueType": "number"
9961
+ }
9962
+ ],
9963
+ "pressure-sensor": [
9964
+ {
9965
+ "path": "hpa",
9966
+ "valueType": "number"
9967
+ },
9968
+ {
9969
+ "path": "unit",
9970
+ "valueType": "string"
9971
+ },
9972
+ {
9973
+ "path": "precision",
9974
+ "valueType": "number"
9975
+ }
9976
+ ],
9977
+ "privacy-mask": [{
9978
+ "path": "enabled",
9979
+ "valueType": "boolean"
9980
+ }, {
9981
+ "path": "audioEnabled",
9982
+ "valueType": "boolean"
9983
+ }],
9984
+ "ptz": [
9985
+ {
9986
+ "path": "pan",
9987
+ "valueType": "number"
9988
+ },
9989
+ {
9990
+ "path": "tilt",
9991
+ "valueType": "number"
9992
+ },
9993
+ {
9994
+ "path": "zoom",
9995
+ "valueType": "number"
9996
+ },
9997
+ {
9998
+ "path": "autofocus",
9999
+ "valueType": "boolean"
10000
+ }
10001
+ ],
10002
+ "ptz-autotrack": [
10003
+ {
10004
+ "path": "enabled",
10005
+ "valueType": "boolean"
10006
+ },
10007
+ {
10008
+ "path": "currentSettings.targetType",
10009
+ "valueType": "string"
10010
+ },
10011
+ {
10012
+ "path": "currentSettings.stopDelaySeconds",
10013
+ "valueType": "number"
10014
+ },
10015
+ {
10016
+ "path": "currentSettings.disappearDelaySeconds",
10017
+ "valueType": "number"
10018
+ }
10019
+ ],
10020
+ "recording-archive": [
10021
+ {
10022
+ "path": "deviceId",
10023
+ "valueType": "number"
10024
+ },
10025
+ {
10026
+ "path": "enabled",
10027
+ "valueType": "boolean"
10028
+ },
10029
+ {
10030
+ "path": "activeMode",
10031
+ "valueType": "enum",
10032
+ "enumValues": [
10033
+ "off",
10034
+ "events",
10035
+ "continuous",
10036
+ "on-device-decision"
10037
+ ]
10038
+ },
10039
+ {
10040
+ "path": "nodeId",
10041
+ "valueType": "string"
10042
+ },
10043
+ {
10044
+ "path": "storageBytes",
10045
+ "valueType": "number"
10046
+ }
10047
+ ],
10048
+ "recording-onboard": [
10049
+ {
10050
+ "path": "primaryTrackId",
10051
+ "valueType": "string"
10052
+ },
10053
+ {
10054
+ "path": "enabled",
10055
+ "valueType": "boolean"
10056
+ },
10057
+ {
10058
+ "path": "overwriteWhenFull",
10059
+ "valueType": "boolean"
10060
+ },
10061
+ {
10062
+ "path": "preRecordSec",
10063
+ "valueType": "number"
10064
+ },
10065
+ {
10066
+ "path": "postRecordSec",
10067
+ "valueType": "number"
10068
+ },
10069
+ {
10070
+ "path": "segmentMinutes",
10071
+ "valueType": "number"
10072
+ },
10073
+ {
10074
+ "path": "unreadableWindows",
10075
+ "valueType": "number"
10076
+ },
10077
+ {
10078
+ "path": "recordingToNowhere",
10079
+ "valueType": "boolean"
10080
+ }
10081
+ ],
10082
+ "recording-signal": [{
10083
+ "path": "active",
10084
+ "valueType": "boolean"
10085
+ }, {
10086
+ "path": "reason",
10087
+ "valueType": "string"
10088
+ }],
10089
+ "running-state": [
10090
+ {
10091
+ "path": "running",
10092
+ "valueType": "boolean"
10093
+ },
10094
+ {
10095
+ "path": "since",
10096
+ "valueType": "number"
10097
+ },
10098
+ {
10099
+ "path": "source",
10100
+ "valueType": "enum",
10101
+ "enumValues": ["native", "assigned"]
10102
+ },
10103
+ {
10104
+ "path": "phase",
10105
+ "valueType": "string"
10106
+ }
10107
+ ],
10108
+ "script-runner": [
10109
+ {
10110
+ "path": "isRunning",
10111
+ "valueType": "boolean"
10112
+ },
10113
+ {
10114
+ "path": "lastRunAt",
10115
+ "valueType": "number"
10116
+ },
10117
+ {
10118
+ "path": "lastRunSuccess",
10119
+ "valueType": "boolean"
10120
+ },
10121
+ {
10122
+ "path": "lastError",
10123
+ "valueType": "string"
10124
+ }
10125
+ ],
10126
+ "smoke": [{
10127
+ "path": "detected",
10128
+ "valueType": "boolean"
10129
+ }],
10130
+ "snapshot": [
10131
+ {
10132
+ "path": "lastCapturedAt",
10133
+ "valueType": "number"
10134
+ },
10135
+ {
10136
+ "path": "cacheAgeMs",
10137
+ "valueType": "number"
10138
+ },
10139
+ {
10140
+ "path": "lastBytes",
10141
+ "valueType": "number"
10142
+ },
10143
+ {
10144
+ "path": "lastStreamId",
10145
+ "valueType": "string"
10146
+ }
10147
+ ],
10148
+ "stream-params": [
10149
+ {
10150
+ "path": "main.width",
10151
+ "valueType": "number"
10152
+ },
10153
+ {
10154
+ "path": "main.height",
10155
+ "valueType": "number"
10156
+ },
10157
+ {
10158
+ "path": "main.codec",
10159
+ "valueType": "enum",
10160
+ "enumValues": ["h264", "h265"]
10161
+ },
10162
+ {
10163
+ "path": "main.framerate",
10164
+ "valueType": "number"
10165
+ },
10166
+ {
10167
+ "path": "main.bitrate",
10168
+ "valueType": "number"
10169
+ },
10170
+ {
10171
+ "path": "main.bitrateMode",
10172
+ "valueType": "enum",
10173
+ "enumValues": ["vbr", "cbr"]
10174
+ },
10175
+ {
10176
+ "path": "main.encoderProfile",
10177
+ "valueType": "enum",
10178
+ "enumValues": [
10179
+ "high",
10180
+ "main",
10181
+ "baseline"
10182
+ ]
10183
+ },
10184
+ {
10185
+ "path": "main.gop",
10186
+ "valueType": "number"
10187
+ },
10188
+ {
10189
+ "path": "main.audio",
10190
+ "valueType": "boolean"
10191
+ },
10192
+ {
10193
+ "path": "sub.width",
10194
+ "valueType": "number"
10195
+ },
10196
+ {
10197
+ "path": "sub.height",
10198
+ "valueType": "number"
10199
+ },
10200
+ {
10201
+ "path": "sub.codec",
10202
+ "valueType": "enum",
10203
+ "enumValues": ["h264", "h265"]
10204
+ },
10205
+ {
10206
+ "path": "sub.framerate",
10207
+ "valueType": "number"
10208
+ },
10209
+ {
10210
+ "path": "sub.bitrate",
10211
+ "valueType": "number"
10212
+ },
10213
+ {
10214
+ "path": "sub.bitrateMode",
10215
+ "valueType": "enum",
10216
+ "enumValues": ["vbr", "cbr"]
10217
+ },
10218
+ {
10219
+ "path": "sub.encoderProfile",
10220
+ "valueType": "enum",
10221
+ "enumValues": [
10222
+ "high",
10223
+ "main",
10224
+ "baseline"
10225
+ ]
10226
+ },
10227
+ {
10228
+ "path": "sub.gop",
10229
+ "valueType": "number"
10230
+ },
10231
+ {
10232
+ "path": "sub.audio",
10233
+ "valueType": "boolean"
10234
+ },
10235
+ {
10236
+ "path": "ext.width",
10237
+ "valueType": "number"
10238
+ },
10239
+ {
10240
+ "path": "ext.height",
10241
+ "valueType": "number"
10242
+ },
10243
+ {
10244
+ "path": "ext.codec",
10245
+ "valueType": "enum",
10246
+ "enumValues": ["h264", "h265"]
10247
+ },
10248
+ {
10249
+ "path": "ext.framerate",
10250
+ "valueType": "number"
10251
+ },
10252
+ {
10253
+ "path": "ext.bitrate",
10254
+ "valueType": "number"
10255
+ },
10256
+ {
10257
+ "path": "ext.bitrateMode",
10258
+ "valueType": "enum",
10259
+ "enumValues": ["vbr", "cbr"]
10260
+ },
10261
+ {
10262
+ "path": "ext.encoderProfile",
10263
+ "valueType": "enum",
10264
+ "enumValues": [
10265
+ "high",
10266
+ "main",
10267
+ "baseline"
10268
+ ]
10269
+ },
10270
+ {
10271
+ "path": "ext.gop",
10272
+ "valueType": "number"
10273
+ },
10274
+ {
10275
+ "path": "ext.audio",
10276
+ "valueType": "boolean"
10277
+ }
10278
+ ],
10279
+ "switch": [{
10280
+ "path": "on",
10281
+ "valueType": "boolean"
10282
+ }],
10283
+ "tamper": [{
10284
+ "path": "tampered",
10285
+ "valueType": "boolean"
10286
+ }],
10287
+ "temperature-sensor": [
10288
+ {
10289
+ "path": "celsius",
10290
+ "valueType": "number"
10291
+ },
10292
+ {
10293
+ "path": "unit",
10294
+ "valueType": "string"
10295
+ },
10296
+ {
10297
+ "path": "precision",
10298
+ "valueType": "number"
10299
+ }
10300
+ ],
10301
+ "update": [
10302
+ {
10303
+ "path": "currentVersion",
10304
+ "valueType": "string"
10305
+ },
10306
+ {
10307
+ "path": "availableVersion",
10308
+ "valueType": "string"
10309
+ },
10310
+ {
10311
+ "path": "updatable",
10312
+ "valueType": "boolean"
10313
+ },
10314
+ {
10315
+ "path": "state",
10316
+ "valueType": "string"
10317
+ },
10318
+ {
10319
+ "path": "inProgress",
10320
+ "valueType": "boolean"
10321
+ }
10322
+ ],
10323
+ "vacuum-control": [
10324
+ {
10325
+ "path": "state",
10326
+ "valueType": "enum",
10327
+ "enumValues": [
10328
+ "idle",
10329
+ "cleaning",
10330
+ "paused",
10331
+ "returning",
10332
+ "docked",
10333
+ "drying",
10334
+ "error"
10335
+ ]
10336
+ },
10337
+ {
10338
+ "path": "batteryLevel",
10339
+ "valueType": "number"
10340
+ },
10341
+ {
10342
+ "path": "fanSpeed",
10343
+ "valueType": "string"
10344
+ },
10345
+ {
10346
+ "path": "progressPercent",
10347
+ "valueType": "number"
10348
+ },
10349
+ {
10350
+ "path": "errorCode",
10351
+ "valueType": "number"
10352
+ },
10353
+ {
10354
+ "path": "errorLabel",
10355
+ "valueType": "string"
10356
+ }
10357
+ ],
10358
+ "valve": [{
10359
+ "path": "state",
10360
+ "valueType": "enum",
10361
+ "enumValues": [
10362
+ "open",
10363
+ "opening",
10364
+ "closing",
10365
+ "closed",
10366
+ "stopped"
10367
+ ]
10368
+ }, {
10369
+ "path": "position",
10370
+ "valueType": "number"
10371
+ }],
10372
+ "vibration": [{
10373
+ "path": "detected",
10374
+ "valueType": "boolean"
10375
+ }],
10376
+ "water-heater": [
10377
+ {
10378
+ "path": "currentTemp",
10379
+ "valueType": "number"
10380
+ },
10381
+ {
10382
+ "path": "targetTemp",
10383
+ "valueType": "number"
10384
+ },
10385
+ {
10386
+ "path": "operationMode",
10387
+ "valueType": "string"
10388
+ },
10389
+ {
10390
+ "path": "away",
10391
+ "valueType": "boolean"
10392
+ },
10393
+ {
10394
+ "path": "minTemp",
10395
+ "valueType": "number"
10396
+ },
10397
+ {
10398
+ "path": "maxTemp",
10399
+ "valueType": "number"
10400
+ }
10401
+ ],
10402
+ "weather": [
10403
+ {
10404
+ "path": "condition",
10405
+ "valueType": "string"
10406
+ },
10407
+ {
10408
+ "path": "temperature",
10409
+ "valueType": "number"
10410
+ },
10411
+ {
10412
+ "path": "temperatureUnit",
10413
+ "valueType": "string"
10414
+ },
10415
+ {
10416
+ "path": "humidity",
10417
+ "valueType": "number"
10418
+ },
10419
+ {
10420
+ "path": "pressure",
10421
+ "valueType": "number"
10422
+ },
10423
+ {
10424
+ "path": "pressureUnit",
10425
+ "valueType": "string"
10426
+ },
10427
+ {
10428
+ "path": "windSpeed",
10429
+ "valueType": "number"
10430
+ },
10431
+ {
10432
+ "path": "windSpeedUnit",
10433
+ "valueType": "string"
10434
+ },
10435
+ {
10436
+ "path": "windBearing",
10437
+ "valueType": "number"
10438
+ }
10439
+ ],
10440
+ "zone-analytics": [
10441
+ {
10442
+ "path": "ts",
10443
+ "valueType": "number"
10444
+ },
10445
+ {
10446
+ "path": "frameWidth",
10447
+ "valueType": "number"
10448
+ },
10449
+ {
10450
+ "path": "frameHeight",
10451
+ "valueType": "number"
10452
+ },
10453
+ {
10454
+ "path": "frame.totalObjects",
10455
+ "valueType": "number"
10456
+ },
10457
+ {
10458
+ "path": "frame.standingObjects",
10459
+ "valueType": "number"
10460
+ },
10461
+ {
10462
+ "path": "frame.transientObjects",
10463
+ "valueType": "number"
10464
+ },
10465
+ {
10466
+ "path": "unzoned.totalObjects",
10467
+ "valueType": "number"
10468
+ },
10469
+ {
10470
+ "path": "unzoned.standingObjects",
10471
+ "valueType": "number"
10472
+ },
10473
+ {
10474
+ "path": "unzoned.transientObjects",
10475
+ "valueType": "number"
10476
+ }
10477
+ ]
10478
+ });
8505
10479
  object({
8506
10480
  code: string().regex(/^[a-z][a-z0-9-]*(\.[a-z0-9-]+)+$/),
8507
10481
  params: record(string(), union([string(), number()])).optional()
@@ -8874,7 +10848,7 @@ function errMsg(err) {
8874
10848
  return String(err);
8875
10849
  }
8876
10850
  //#endregion
8877
- //#region ../types/dist/composition-xz-ud5EQ.mjs
10851
+ //#region ../types/dist/composition-kEl9mevu.mjs
8878
10852
  /**
8879
10853
  * The ffmpeg build every CamStack node downloads, per platform and arch.
8880
10854
  *
@@ -8934,7 +10908,7 @@ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac
8934
10908
  * ONE table for everyone who asks "is this device HIGH?": the
8935
10909
  * recorder's `RecordingTriggers.sensorDeviceIds` trigger, the post-analysis
8936
10910
  * sensor markers, the orchestrator's camera-sensors bridge and
8937
- * the sources of a composite doorbell (`doorbellFeatureSources`, D671).
10911
+ * the sources of a pulse (`compilePulseOverride`, D936).
8938
10912
  * A second copy would diverge at the first cap added, and the symptom — "the
8939
10913
  * sensor rings the doorbell but does not record" — is exactly D62.
8940
10914
  *
@@ -12089,7 +14063,7 @@ var LogChannelDescriptorSchema = object({
12089
14063
  * `true` is a PROMISE with two halves, and both must hold: the gate is
12090
14064
  * consulted with the numeric device id, AND every line the channel admits
12091
14065
  * carries `tags: { deviceId }` with that same numeric id. The second half is
12092
- * what makes `| json | deviceId="617"` work in Loki — `loki-payload.ts`
14066
+ * what makes `| json | deviceId="102"` work in Loki — `loki-payload.ts`
12093
14067
  * keeps `deviceId` out of the stream labels for cardinality, so the tag in
12094
14068
  * the body is the only way to filter.
12095
14069
  *
@@ -12277,7 +14251,7 @@ var ModelVariantGroupSchema = object({
12277
14251
  precision: _enum(["fp32", "int8"]).optional(),
12278
14252
  /**
12279
14253
  * Training / latency-variant axis. Omit ⇒ the standard build. `test` marks
12280
- * an alternate training of the same family (Scrypted `relu_test`); chip
14254
+ * an alternate training of the same family (plugin catalog `relu_test`); chip
12281
14255
  * label is "Test".
12282
14256
  */
12283
14257
  optimization: _enum(["standard", "test"]).optional(),
@@ -12529,8 +14503,8 @@ var ModelCatalogEntrySchema = object({
12529
14503
  provider: ModelProviderIdSchema.optional(),
12530
14504
  /**
12531
14505
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
12532
- * applies (Frigate / COCO public catalog). Set on a custom model whose raw
12533
- * labels already ARE the CamStack macros (Scrypted identity map).
14506
+ * applies (plus catalog / COCO public catalog). Set on a custom model whose raw
14507
+ * labels already ARE the CamStack macros (plugin catalog identity map).
12534
14508
  */
12535
14509
  classMap: DetectionCatalogClassMapSchema.optional(),
12536
14510
  /**
@@ -15499,7 +17473,7 @@ method(object({
15499
17473
  * `1` is real time and is the ONLY value that allows the copy branch —
15500
17474
  * anything else forces `libx264` over the window. That was priced
15501
17475
  * before it was chosen: a per-event burst measured at 0.23 s and 254 KB
15502
- * on a real 615 720p cut, against 922 KB for the copy it replaces. A
17476
+ * on a real 101 720p cut, against 922 KB for the copy it replaces. A
15503
17477
  * re-encode is capped at 720p (`EVENT_CLIP_ENCODE_MAX_WIDTH`), because
15504
17478
  * once the decode is forced the width stops being free.
15505
17479
  */
@@ -16025,6 +17999,7 @@ var CompositionRunStatusSchema = _enum([
16025
17999
  "starting",
16026
18000
  "running",
16027
18001
  "degraded",
18002
+ "incomplete",
16028
18003
  "failed"
16029
18004
  ]);
16030
18005
  var CompositionFieldStateKindSchema = _enum([
@@ -16074,6 +18049,13 @@ var ComposerUnreadableBlockSchema = object({
16074
18049
  /** The parse error, in the operator's words. */
16075
18050
  error: string()
16076
18051
  });
18052
+ /** A confirmed release the hub did not accept. `deviceId` is the claim's device. */
18053
+ var UnreleasedClaimSchema = object({
18054
+ deviceId: number().int(),
18055
+ capName: string(),
18056
+ owner: string(),
18057
+ error: string()
18058
+ });
16077
18059
  method(object({
16078
18060
  /** The shared Blocks integration; null until `core-blocks` has reconciled it. */
16079
18061
  integrationId: string().nullable(),
@@ -16083,7 +18065,13 @@ method(object({
16083
18065
  /** Operator restarts: rebuild these runtimes and re-resolve their sources. Stores nothing (D62). */
16084
18066
  restartBlockIds: array(string()),
16085
18067
  /** Composition rows that exist but do not parse: held, never withdrawn, reported failed. */
16086
- unreadableBlocks: array(ComposerUnreadableBlockSchema)
18068
+ unreadableBlocks: array(ComposerUnreadableBlockSchema),
18069
+ /**
18070
+ * Operator-confirmed deletions. Their claims are released on this apply,
18071
+ * before any replacement block claims. A block that merely vanished from the
18072
+ * snapshot is not listed here and still waits for two applies (D49).
18073
+ */
18074
+ retiredBlockIds: array(string()).optional()
16087
18075
  }), object({
16088
18076
  blocks: array(object({
16089
18077
  blockId: string(),
@@ -16095,7 +18083,13 @@ method(object({
16095
18083
  * integration unknown, its own rows unread or read empty once). An empty
16096
18084
  * apply the caller owes is paid off only by one the composer acted on (D49).
16097
18085
  */
16098
- acted: boolean()
18086
+ acted: boolean(),
18087
+ /**
18088
+ * Confirmed releases this apply tried and the hub did not accept. Empty when
18089
+ * every one landed (or there was nothing to hand back). Absent on a result
18090
+ * that never got that far.
18091
+ */
18092
+ unreleasedClaims: array(UnreleasedClaimSchema).optional()
16099
18093
  }), {
16100
18094
  kind: "mutation",
16101
18095
  auth: "admin"
@@ -16219,6 +18213,7 @@ var CoreBlockStatusSchema = _enum([
16219
18213
  "starting",
16220
18214
  "running",
16221
18215
  "degraded",
18216
+ "incomplete",
16222
18217
  "failed"
16223
18218
  ]);
16224
18219
  /** path → TypeScript source for a multi-file block. */
@@ -38270,7 +40265,7 @@ var PRIMARY_CATEGORIES = new Set(ENTRIES.map((e) => e.primaryCategory));
38270
40265
  * `locationKey` is ALWAYS {@link locationIconKey} of the label — never the
38271
40266
  * operator's casing. The registry matches labels trimmed + case-insensitively
38272
40267
  * everywhere (`addLocation`, `removeLocation`, `renameLocation`), and a
38273
- * case-only rename (`cucina` → `Cucina`) is a real edit this repo supports; a
40268
+ * case-only rename (`kitchen` → `Kitchen`) is a real edit this repo supports; a
38274
40269
  * map keyed on the displayed casing would orphan its entry on exactly that
38275
40270
  * edit. Consumers join by keying their own label through `locationIconKey`.
38276
40271
  */
@@ -38295,7 +40290,7 @@ var LocationDescriptionAssignmentSchema = object({
38295
40290
  /**
38296
40291
  * A SITE ZONE — a named part of the property that several locations belong to.
38297
40292
  *
38298
- * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
40293
+ * "Night zone" holds every bedroom; "Zona giorno" the living room and the
38299
40294
  * kitchen. A camera belongs to exactly one location, and a location to at most
38300
40295
  * one zone, so a camera's zone is derived and never stored on the device: the
38301
40296
  * whole point of this entity is that grouping rooms touches no device row.
@@ -38324,7 +40319,7 @@ var LocationDescriptionAssignmentSchema = object({
38324
40319
  * the locations inside it.
38325
40320
  *
38326
40321
  * The LABEL is carried alongside the key because the key is lossy on purpose —
38327
- * a surface must show "Zona notte", not "zona notte". Locations are carried
40322
+ * a surface must show "Night zone", not "night zone". Locations are carried
38328
40323
  * here, rather than left to a second call, because every consumer wants both
38329
40324
  * at once and a viewer that asked twice could render a zone whose membership
38330
40325
  * it has not fetched yet.
@@ -40530,8 +42525,8 @@ var LoadContributionSchema = object({
40530
42525
  "unattributable"
40531
42526
  ]),
40532
42527
  /**
40533
- * What ONE entry is, in the contributor's own words — `615/high`,
40534
- * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
42528
+ * What ONE entry is, in the contributor's own words — `101/high`,
42529
+ * `102/native`, `cuda:0 shared pool`. Free text because the unit differs per
40535
42530
  * family and inventing a common one would lose the only information that
40536
42531
  * makes two entries for the same camera distinguishable.
40537
42532
  */
@@ -42179,6 +44174,381 @@ var _macroLookup = /* @__PURE__ */ new Map();
42179
44174
  for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42180
44175
  for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
42181
44176
  /**
44177
+ * Palette entry ids (D939). Audio is the one gradient; `audio-*` leaves are
44178
+ * not entries. `heatmapScrub` is a mark, not an event kind.
44179
+ */
44180
+ var PALETTE_ENTRY_IDS = [
44181
+ "motion",
44182
+ "audio",
44183
+ "recording",
44184
+ "live",
44185
+ "heatmapScrub",
44186
+ "person",
44187
+ "vehicle",
44188
+ "animal",
44189
+ "package",
44190
+ "sensor",
44191
+ "control",
44192
+ "face",
44193
+ "plate",
44194
+ "car",
44195
+ "truck",
44196
+ "bus",
44197
+ "motorcycle",
44198
+ "bicycle",
44199
+ "airplane",
44200
+ "boat",
44201
+ "train",
44202
+ "bird",
44203
+ "dog",
44204
+ "cat",
44205
+ "horse",
44206
+ "sheep",
44207
+ "cow",
44208
+ "elephant",
44209
+ "bear",
44210
+ "zebra",
44211
+ "giraffe",
44212
+ "package-delivered",
44213
+ "package-picked-up",
44214
+ "suitcase",
44215
+ "backpack",
44216
+ "handbag",
44217
+ "contact",
44218
+ "motion-sensor",
44219
+ "smoke",
44220
+ "flood",
44221
+ "gas",
44222
+ "carbon-monoxide",
44223
+ "vibration",
44224
+ "tamper",
44225
+ "presence",
44226
+ "enum-sensor",
44227
+ "device-event",
44228
+ "lock",
44229
+ "cover",
44230
+ "switch",
44231
+ "siren",
44232
+ "button",
44233
+ "doorbell"
44234
+ ];
44235
+ var AUDIO_ENTRY_ID = "audio";
44236
+ /** Six rungs, quiet → loud. The opaque end is the entry's hex. */
44237
+ var AUDIO_GRADIENT_ALPHAS = [
44238
+ .3,
44239
+ .42,
44240
+ .55,
44241
+ .7,
44242
+ .85,
44243
+ 1
44244
+ ];
44245
+ var PALETTE_PRESET_IDS = [
44246
+ "camstack",
44247
+ "high-contrast",
44248
+ "okabe-ito"
44249
+ ];
44250
+ /** Frozen palette tables (D939). The spec refuses a table that breaks the rule. */
44251
+ var CAMSTACK_HEX = {
44252
+ motion: "#d946ef",
44253
+ audio: "#059eb8",
44254
+ recording: "#ef4444",
44255
+ live: "#8d7a00",
44256
+ heatmapScrub: "#4b32ff",
44257
+ person: "#11a64c",
44258
+ vehicle: "#3b82f6",
44259
+ animal: "#ea6a09",
44260
+ package: "#924667",
44261
+ sensor: "#624bbc",
44262
+ control: "#944d24",
44263
+ face: "#ed4f8d",
44264
+ plate: "#4b7027",
44265
+ car: "#9684cf",
44266
+ truck: "#0f9b89",
44267
+ bus: "#a734a9",
44268
+ motorcycle: "#c1133a",
44269
+ bicycle: "#0e6a9b",
44270
+ airplane: "#7c9928",
44271
+ boat: "#b17933",
44272
+ train: "#ad6ca3",
44273
+ bird: "#0f7c55",
44274
+ dog: "#c82700",
44275
+ cat: "#7268f2",
44276
+ horse: "#cb795e",
44277
+ sheep: "#b8636b",
44278
+ cow: "#cb2969",
44279
+ elephant: "#1158d2",
44280
+ bear: "#8d5e00",
44281
+ zebra: "#0097d6",
44282
+ giraffe: "#8f61bb",
44283
+ "package-delivered": "#cd3f9b",
44284
+ "package-picked-up": "#388a08",
44285
+ suitcase: "#666800",
44286
+ backpack: "#ec5022",
44287
+ handbag: "#a76ef8",
44288
+ contact: "#ab5a49",
44289
+ "motion-sensor": "#b95d1a",
44290
+ smoke: "#dd3858",
44291
+ flood: "#b31e7d",
44292
+ gas: "#5b70b5",
44293
+ "carbon-monoxide": "#7b4e8e",
44294
+ vibration: "#e65bba",
44295
+ tamper: "#98464b",
44296
+ presence: "#3a9468",
44297
+ "enum-sensor": "#7885f8",
44298
+ "device-event": "#8c43c8",
44299
+ lock: "#649653",
44300
+ cover: "#c67597",
44301
+ switch: "#7a812a",
44302
+ siren: "#ac5d7f",
44303
+ button: "#b276cd",
44304
+ doorbell: "#0087ab"
44305
+ };
44306
+ var CAMSTACK_FALLBACK = [
44307
+ "#b34dc7",
44308
+ "#1d7d34",
44309
+ "#db6b6c",
44310
+ "#a43d29",
44311
+ "#0e6ee6",
44312
+ "#29a10b",
44313
+ "#a98731",
44314
+ "#0181c6"
44315
+ ];
44316
+ var HIGH_CONTRAST_HEX = {
44317
+ motion: "#964360",
44318
+ audio: "#23a132",
44319
+ recording: "#2494ca",
44320
+ live: "#bd7e2b",
44321
+ heatmapScrub: "#ad6eea",
44322
+ person: "#62611e",
44323
+ vehicle: "#f4534c",
44324
+ animal: "#1556cd",
44325
+ package: "#9c4415",
44326
+ sensor: "#066c48",
44327
+ control: "#f2479f",
44328
+ face: "#139d8a",
44329
+ plate: "#909024",
44330
+ car: "#8e35ab",
44331
+ truck: "#bd0b2b",
44332
+ bus: "#7a88ca",
44333
+ motorcycle: "#e26725",
44334
+ bicycle: "#a6679b",
44335
+ airplane: "#7c5720",
44336
+ boat: "#467a1b",
44337
+ train: "#6f65a4",
44338
+ bird: "#cb717f",
44339
+ dog: "#c62490",
44340
+ cat: "#b36850",
44341
+ horse: "#1872ac",
44342
+ sheep: "#927939",
44343
+ cow: "#428a5c",
44344
+ elephant: "#d41160",
44345
+ bear: "#799453",
44346
+ zebra: "#a85455",
44347
+ giraffe: "#746be8",
44348
+ "package-delivered": "#824a80",
44349
+ "package-picked-up": "#614ac1",
44350
+ suitcase: "#2f77f3",
44351
+ backpack: "#fa476d",
44352
+ handbag: "#c14cbe",
44353
+ contact: "#c83921",
44354
+ "motion-sensor": "#a07ebd",
44355
+ smoke: "#a25b13",
44356
+ flood: "#526bab",
44357
+ gas: "#924938",
44358
+ "carbon-monoxide": "#bb7e53",
44359
+ vibration: "#b66182",
44360
+ tamper: "#3c6931",
44361
+ presence: "#6c851d",
44362
+ "enum-sensor": "#ad2d48",
44363
+ "device-event": "#5e9b04",
44364
+ lock: "#00a062",
44365
+ cover: "#ad8624",
44366
+ switch: "#d05259",
44367
+ siren: "#cd67b3",
44368
+ button: "#c9746a",
44369
+ doorbell: "#338eeb"
44370
+ };
44371
+ var HIGH_CONTRAST_FALLBACK = [
44372
+ "#817f3b",
44373
+ "#a0733e",
44374
+ "#8658b2",
44375
+ "#956301",
44376
+ "#bc652d",
44377
+ "#647331",
44378
+ "#a14c9e",
44379
+ "#d14e71"
44380
+ ];
44381
+ var OKABE_ITO_HEX = {
44382
+ motion: "#b88128",
44383
+ audio: "#1096c8",
44384
+ recording: "#009e73",
44385
+ live: "#9c8c22",
44386
+ heatmapScrub: "#0072b2",
44387
+ person: "#d55e00",
44388
+ vehicle: "#c0739f",
44389
+ animal: "#226d18",
44390
+ package: "#91446c",
44391
+ sensor: "#217b56",
44392
+ control: "#648647",
44393
+ face: "#c22998",
44394
+ plate: "#fa4575",
44395
+ car: "#956301",
44396
+ truck: "#2f77f3",
44397
+ bus: "#7a4e86",
44398
+ motorcycle: "#f54597",
44399
+ bicycle: "#bb3e75",
44400
+ airplane: "#e054c0",
44401
+ boat: "#457942",
44402
+ train: "#867afa",
44403
+ bird: "#88914c",
44404
+ dog: "#1556cd",
44405
+ cat: "#71702c",
44406
+ horse: "#9b4fa4",
44407
+ sheep: "#c0559d",
44408
+ cow: "#d14f65",
44409
+ elephant: "#98470f",
44410
+ bear: "#595896",
44411
+ zebra: "#96790e",
44412
+ giraffe: "#cb717b",
44413
+ "package-delivered": "#139d8a",
44414
+ "package-picked-up": "#906ead",
44415
+ suitcase: "#d02939",
44416
+ backpack: "#d41160",
44417
+ handbag: "#f64f54",
44418
+ contact: "#7258d2",
44419
+ "motion-sensor": "#b66182",
44420
+ smoke: "#627abb",
44421
+ flood: "#b86ae4",
44422
+ gas: "#a95261",
44423
+ "carbon-monoxide": "#c65d3c",
44424
+ vibration: "#7a40b7",
44425
+ tamper: "#914b34",
44426
+ presence: "#9481c3",
44427
+ "enum-sensor": "#ac6d47",
44428
+ "device-event": "#7b6fce",
44429
+ lock: "#c67662",
44430
+ cover: "#a6564d",
44431
+ switch: "#ad2c4e",
44432
+ siren: "#348e08",
44433
+ button: "#d27303",
44434
+ doorbell: "#55770f"
44435
+ };
44436
+ var OKABE_ITO_FALLBACK = [
44437
+ "#9a3784",
44438
+ "#a7392c",
44439
+ "#409d50",
44440
+ "#6987e7",
44441
+ "#ee5b3d",
44442
+ "#c0430d",
44443
+ "#af79b3",
44444
+ "#4b6628"
44445
+ ];
44446
+ /**
44447
+ * The display palette (D939). One table of colours, three presets, one
44448
+ * validator. Taxonomy colours and every consumer read this — there is no
44449
+ * second hex table.
44450
+ */
44451
+ var paletteHexSchema = string().regex(/^#[0-9a-f]{6}$/);
44452
+ var paletteSwatchSchema = discriminatedUnion("form", [object({
44453
+ form: literal("solid"),
44454
+ hex: paletteHexSchema
44455
+ }), object({
44456
+ form: literal("gradient"),
44457
+ hex: paletteHexSchema,
44458
+ alphas: array(number().gt(0).lte(1)).length(AUDIO_GRADIENT_ALPHAS.length)
44459
+ })]);
44460
+ var paletteReadySchema = object({
44461
+ status: literal("ready"),
44462
+ presetId: _enum(PALETTE_PRESET_IDS),
44463
+ customized: boolean(),
44464
+ source: _enum(["stored", "unconfigured"]),
44465
+ swatches: record(string(), paletteSwatchSchema),
44466
+ fallbacks: array(paletteHexSchema).length(8)
44467
+ });
44468
+ var paletteResultSchema = discriminatedUnion("status", [paletteReadySchema, object({
44469
+ status: literal("unknown"),
44470
+ reason: string()
44471
+ })]);
44472
+ var setPaletteInputSchema = union([object({ presetId: string() }), object({
44473
+ presetId: string(),
44474
+ overrides: record(string(), paletteSwatchSchema)
44475
+ })]);
44476
+ object({
44477
+ presetId: string(),
44478
+ overrides: record(string(), paletteSwatchSchema)
44479
+ });
44480
+ function solid(hex) {
44481
+ return {
44482
+ form: "solid",
44483
+ hex
44484
+ };
44485
+ }
44486
+ function audioGradient(hex) {
44487
+ return {
44488
+ form: "gradient",
44489
+ hex,
44490
+ alphas: [...AUDIO_GRADIENT_ALPHAS]
44491
+ };
44492
+ }
44493
+ function swatchesFrom(hexes) {
44494
+ const out = {};
44495
+ for (const id of PALETTE_ENTRY_IDS) {
44496
+ const hex = hexes[id];
44497
+ if (hex === void 0) throw new Error(`palette table missing ${id}`);
44498
+ out[id] = id === "audio" ? audioGradient(hex) : solid(hex);
44499
+ }
44500
+ return out;
44501
+ }
44502
+ function preset(id, name, hexes, fallbacks) {
44503
+ return {
44504
+ id,
44505
+ name,
44506
+ swatches: swatchesFrom(hexes),
44507
+ fallbacks
44508
+ };
44509
+ }
44510
+ var DISPLAY_PRESETS = [
44511
+ preset("camstack", "CamStack", CAMSTACK_HEX, CAMSTACK_FALLBACK),
44512
+ preset("high-contrast", "High contrast", HIGH_CONTRAST_HEX, HIGH_CONTRAST_FALLBACK),
44513
+ preset("okabe-ito", "Colour-blind safe", OKABE_ITO_HEX, OKABE_ITO_FALLBACK)
44514
+ ];
44515
+ function presetById(id) {
44516
+ return DISPLAY_PRESETS.find((item) => item.id === id);
44517
+ }
44518
+ function bundledCamstack() {
44519
+ const presetRow = presetById("camstack");
44520
+ if (presetRow === void 0) throw new Error("CamStack preset missing");
44521
+ return readyOf(presetRow, "unconfigured", false);
44522
+ }
44523
+ function readyOf(row, source, customized) {
44524
+ return {
44525
+ status: "ready",
44526
+ presetId: row.id,
44527
+ customized,
44528
+ source,
44529
+ swatches: row.swatches,
44530
+ fallbacks: [...row.fallbacks]
44531
+ };
44532
+ }
44533
+ function hashFallback(kind, fallbacks) {
44534
+ let hash = 0;
44535
+ for (let i = 0; i < kind.length; i++) hash = hash * 31 + (kind.codePointAt(i) ?? 0) >>> 0;
44536
+ const hex = fallbacks[hash % fallbacks.length];
44537
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44538
+ return hex;
44539
+ }
44540
+ /** Colour a kind paints with. Audio leaves share the audio gradient's hex. */
44541
+ function paintHex(swatches, fallbacks, kind) {
44542
+ const key = kind.trim().toLowerCase();
44543
+ if (key.startsWith("audio-")) {
44544
+ const audio = swatches[AUDIO_ENTRY_ID];
44545
+ return audio !== void 0 ? audio.hex : hashFallback(key, fallbacks);
44546
+ }
44547
+ const direct = swatches[key];
44548
+ if (direct !== void 0) return direct.hex;
44549
+ return hashFallback(key, fallbacks);
44550
+ }
44551
+ /**
42182
44552
  * Unified event-kind taxonomy — THE single source of truth for
42183
44553
  * `kind → { parentKind, category, level, color, iconId, labelKey, label,
42184
44554
  * icon }`.
@@ -42192,109 +44562,88 @@ for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set
42192
44562
  * - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
42193
44563
  * - the COCO / audio class maps (macro ↔ sub relationships)
42194
44564
  *
42195
- * The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
42196
- * `@camstack/types`. The UI-side mapping `iconId → lucide component` and
42197
- * `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
42198
- * color or an icon: they read this dictionary (server descriptors carry the
42199
- * fields inline; the client resolves color/icon/label from `iconId`/`kind`).
44565
+ * The DATA (serializable — parentKind / iconId / labelKey) lives here in
44566
+ * `@camstack/types`. Colour is NOT a second table: each entry's `color` is
44567
+ * the bundled CamStack display palette (D939). The effective cluster palette
44568
+ * is the `display-palette` capability. The UI-side mapping `iconId → lucide
44569
+ * component` and `labelKey → t()` lives in `@camstack/ui-library`.
42200
44570
  *
42201
44571
  * Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
42202
44572
  */
42203
- var TAXONOMY_COLORS = {
42204
- motion: "#f59e0b",
42205
- audio: "#06b6d4",
42206
- person: "#22c55e",
42207
- vehicle: "#3b82f6",
42208
- animal: "#f97316",
42209
- package: "#a855f7",
42210
- sensor: "#8b5cf6",
42211
- control: "#10b981",
42212
- genericDetection: "#64748b"
42213
- };
42214
- var DETECTION_SUB_COLORS = {
42215
- car: "#f59e0b",
42216
- truck: "#d97706",
42217
- bus: "#b45309",
42218
- motorcycle: "#eab308",
42219
- bicycle: "#ca8a04",
42220
- airplane: "#60a5fa",
42221
- boat: "#2563eb",
42222
- train: "#1d4ed8",
42223
- bird: "#14b8a6",
42224
- dog: "#84cc16",
42225
- cat: "#f97316",
42226
- horse: "#a16207",
42227
- sheep: "#a3a3a3",
42228
- cow: "#78716c",
42229
- elephant: "#6b7280",
42230
- bear: "#7c2d12",
42231
- zebra: "#404040",
42232
- giraffe: "#d4a373"
42233
- };
44573
+ var BUNDLED_PALETTE = bundledCamstack();
44574
+ function kindColor(kind) {
44575
+ return paintHex(BUNDLED_PALETTE.swatches, BUNDLED_PALETTE.fallbacks, kind);
44576
+ }
44577
+ function firstFallback(fallbacks) {
44578
+ const hex = fallbacks[0];
44579
+ if (hex === void 0) throw new Error("display palette has no fallback colour");
44580
+ return hex;
44581
+ }
44582
+ firstFallback(BUNDLED_PALETTE.fallbacks);
42234
44583
  function titleCase(id) {
42235
44584
  return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
42236
44585
  }
42237
44586
  var entries = /* @__PURE__ */ new Map();
42238
- function macro(kind, category, color, iconId, label) {
44587
+ function macro(kind, category, iconId, label) {
42239
44588
  entries.set(kind, {
42240
44589
  kind,
42241
44590
  parentKind: null,
42242
44591
  level: "macro",
42243
44592
  category,
42244
- color,
44593
+ color: kindColor(kind),
42245
44594
  iconId,
42246
44595
  labelKey: `eventKind.${kind}`,
42247
44596
  label
42248
44597
  });
42249
44598
  }
42250
- function sub(kind, parentKind, category, color, iconId, label) {
44599
+ function sub(kind, parentKind, category, iconId, label) {
42251
44600
  entries.set(kind, {
42252
44601
  kind,
42253
44602
  parentKind,
42254
44603
  level: "sub",
42255
44604
  category,
42256
- color,
44605
+ color: kindColor(kind),
42257
44606
  iconId,
42258
44607
  labelKey: `eventKind.${kind}`,
42259
44608
  label
42260
44609
  });
42261
44610
  }
42262
- macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
42263
- macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
42264
- macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
42265
- macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
42266
- macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
42267
- macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
42268
- macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
42269
- macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
44611
+ macro("motion", "motion", "motion", "Motion");
44612
+ macro("audio", "audio", "audio", "Audio");
44613
+ macro("person", "detection", "person", "Person");
44614
+ macro("vehicle", "detection", "vehicle", "Vehicle");
44615
+ macro("animal", "detection", "animal", "Animal");
44616
+ macro("package", "package", "package", "Package");
44617
+ macro("sensor", "sensor", "sensor", "Sensor");
44618
+ macro("control", "control", "control", "Control");
42270
44619
  for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
42271
44620
  if (macroClass !== "vehicle" && macroClass !== "animal") continue;
42272
44621
  if (entries.has(cocoClass)) continue;
42273
- sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
42274
- }
42275
- sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
42276
- sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
42277
- sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
42278
- sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
42279
- sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
42280
- sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
42281
- sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
42282
- sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
42283
- sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
42284
- sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
42285
- sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
42286
- sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
42287
- sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
42288
- sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
42289
- sub("cover", "control", "control", "#0ea5e9", "door", "Cover");
42290
- sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
42291
- sub("siren", "control", "control", "#dc2626", "siren", "Siren");
42292
- sub("button", "control", "control", "#10b981", "button", "Button");
42293
- sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
44622
+ sub(cocoClass, macroClass, "detection", cocoClass, titleCase(cocoClass));
44623
+ }
44624
+ sub("package-delivered", "package", "package", "package", "Package delivered");
44625
+ sub("package-picked-up", "package", "package", "package", "Package picked up");
44626
+ sub("contact", "sensor", "sensor", "door", "Contact");
44627
+ sub("motion-sensor", "sensor", "sensor", "pir", "Motion sensor");
44628
+ sub("smoke", "sensor", "sensor", "smoke", "Smoke");
44629
+ sub("flood", "sensor", "sensor", "water", "Water leak");
44630
+ sub("gas", "sensor", "sensor", "gas", "Gas");
44631
+ sub("carbon-monoxide", "sensor", "sensor", "smoke", "Carbon monoxide");
44632
+ sub("vibration", "sensor", "sensor", "vibration", "Vibration");
44633
+ sub("tamper", "sensor", "sensor", "tamper", "Tamper");
44634
+ sub("presence", "sensor", "sensor", "presence", "Presence");
44635
+ sub("enum-sensor", "sensor", "sensor", "generic", "Sensor state");
44636
+ sub("device-event", "sensor", "sensor", "button", "Device event");
44637
+ sub("lock", "control", "control", "lock", "Lock");
44638
+ sub("cover", "control", "control", "door", "Cover");
44639
+ sub("switch", "control", "control", "switch", "Switch");
44640
+ sub("siren", "control", "control", "siren", "Siren");
44641
+ sub("button", "control", "control", "button", "Button");
44642
+ sub("doorbell", "control", "control", "doorbell", "Doorbell");
42294
44643
  for (const l of AUDIO_MACRO_LABELS) {
42295
44644
  const kind = `audio-${l.id}`;
42296
44645
  if (entries.has(kind)) continue;
42297
- sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
44646
+ sub(kind, "audio", "audio", kind, l.name);
42298
44647
  }
42299
44648
  /** The complete taxonomy dictionary, keyed by kind. */
42300
44649
  var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
@@ -43181,7 +45530,7 @@ var NcConditionsSchema = object({
43181
45530
  * with the list under it is worse than no switch (D62).
43182
45531
  *
43183
45532
  * MEMBERS ARE FACE-GALLERY `Identity.id`s (uuid), not display names. A name is
43184
- * renameable, and a rule authored on "Gianluca" went silently dark the moment
45533
+ * renameable, and a rule authored on "Alice" went silently dark the moment
43185
45534
  * the operator fixed the spelling. The id reaches the record on
43186
45535
  * `LabelAttribution.identityId`; the name is what the editor shows and what
43187
45536
  * `{{label}}` renders.
@@ -43732,7 +46081,7 @@ var NcRulePatchSchema = NcRuleInputSchema.partial().extend({
43732
46081
  * A rule scoped to one camera and one zone silently became a rule that
43733
46082
  * matches EVERY event on EVERY camera, and lost its `media` policy
43734
46083
  * (zoneCrop / gif / clip / frame) and its `priority` at the same time. Seen
43735
- * live on 2026-08-12: a rule scoped to device 617 fired on 590 and 615
46084
+ * live on 2026-08-12: a rule scoped to device 102 fired on 104 and 101
43736
46085
  * within a minute of a two-field patch.
43737
46086
  *
43738
46087
  * So every defaulted field is re-declared here WITHOUT its default. The
@@ -45545,7 +47894,7 @@ var LabelAttributionSchema = object({
45545
47894
  * `Identity.id` or a plate-gallery `Vehicle.id` (both `randomUUID`).
45546
47895
  *
45547
47896
  * The text alone is a DISPLAY NAME, and a display name is renameable: a
45548
- * notification rule authored on "Gianluca" stopped matching the moment the
47897
+ * notification rule authored on "Alice" stopped matching the moment the
45549
47898
  * operator fixed the spelling in the gallery, and nothing said so. The id is
45550
47899
  * the thing that does not move, so it is what a rule matches on
45551
47900
  * (`NcConditions.identities`) and the text is what a human is shown.
@@ -48084,7 +50433,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
48084
50433
  /**
48085
50434
  * Root-supplied detections for the tree's ROOT step (D730). Set by
48086
50435
  * `runDetailSubtree` when the camera's root model supplies a crop-kind
48087
- * step (a Frigate+ `license_plate` for `plate-detection`): the step is
50436
+ * step (a plus catalog `license_plate` for `plate-detection`): the step is
48088
50437
  * NOT inferred, these boxes are its output, and its children (the plate
48089
50438
  * reader) run on them through their own crop policy. Boxes are in the
48090
50439
  * PIXELS of the image this call carries. Absent ⇒ the root step runs.
@@ -49761,7 +52110,7 @@ var RunnerCameraConfigSchema = object({
49761
52110
  * detection session that asks for history. What shipped was a last-moment
49762
52111
  * discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
49763
52112
  * arriving inside a few hundred ms of wall clock looks to it like one frame's
49764
- * worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
52113
+ * worth. Device 102, 2026-09-08: a re-run of the SAME model over the stored
49765
52114
  * recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
49766
52115
  * 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
49767
52116
  * was decoded, and was freed.
@@ -51791,7 +54140,7 @@ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config:
51791
54140
  * The signals a device can emit to WAKE its own stream.
51792
54141
  *
51793
54142
  * A camera whose stream is built on demand sleeps until something asks for it,
51794
- * and "something" cannot be a consumer that is merely attached — a Frigate-style
54143
+ * and "something" cannot be a consumer that is merely attached — a external-catalog
51795
54144
  * puller holds a session open for ever, and treating that as demand would keep
51796
54145
  * a battery camera awake for ever, which is the whole thing the battery is for
51797
54146
  * (D173). So the wake has to come from the CAMERA: an event it noticed by
@@ -52511,7 +54860,7 @@ var ClipSchema = object({
52511
54860
  * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
52512
54861
  *
52513
54862
  * Bounded because it is not a payload the surface pages through: one visit on
52514
- * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
54863
+ * device 101 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
52515
54864
  * camera-day. Read {@link eventCount} for the true total.
52516
54865
  */
52517
54866
  eventIds: array(string()).optional(),
@@ -52656,7 +55005,7 @@ var ClipPlaybackSchema = object({
52656
55005
  * camera has no recordings", which is the defect this whole line of work is
52657
55006
  * about: a battery camera nobody woke (`sleeping`), a camera that could not be
52658
55007
  * reached at all (`unreachable`, also what a provider that THREW reports), a
52659
- * camera whose SD card is not mounted (`no-storage`, measured on 640 —
55008
+ * camera whose SD card is not mounted (`no-storage`, measured on 106 —
52660
55009
  * `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
52661
55010
  * camera whose OWN index disagrees with its OWN calendar (`index-empty`,
52662
55011
  * measured on 618: the calendar marks 3–20 September, days 6–20 list zero
@@ -52921,7 +55270,7 @@ DeviceType.Camera, method(object({
52921
55270
  *
52922
55271
  * It was optional, documented as "absent means the device's BOUND
52923
55272
  * provider, which is CamStack on every camera". No code implemented
52924
- * that. Measured on the live hub 2026-09-20 — device 592, bound to
55273
+ * that. Measured on the live hub 2026-09-20 — device 107, bound to
52925
55274
  * `recorder` AND `provider-reolink` — a bare call with `limit: 3`
52926
55275
  * answered SIX rows, three from each source, merged newest-first:
52927
55276
  * `device-collection-dispatch.ts` simply left the fan-out un-narrowed,
@@ -54064,7 +56413,10 @@ var airQualitySensorCapability = {
54064
56413
  */
54065
56414
  var AmbientLightSensorStatusSchema = object({
54066
56415
  /** Current illuminance in lux (lx). */
54067
- lux: number().min(0),
56416
+ lux: number().min(0).meta({
56417
+ unit: "lx",
56418
+ label: "Illuminance"
56419
+ }),
54068
56420
  /** Ms epoch when the slice was last updated. */
54069
56421
  lastFetchedAt: number(),
54070
56422
  /** Live display unit from the upstream source (e.g. HA
@@ -54107,7 +56459,12 @@ var ambientLightSensorCapability = {
54107
56459
  } } },
54108
56460
  /** Clock fields: written, but excluded from the compare that decides
54109
56461
  * whether persisting is worth a SQLite commit. */
54110
- volatileStateFields: ["lastFetchedAt"]
56462
+ volatileStateFields: ["lastFetchedAt"],
56463
+ customize: {
56464
+ version: 1,
56465
+ advanced: "derive",
56466
+ targets: []
56467
+ }
54111
56468
  };
54112
56469
  /**
54113
56470
  * Per-class audio metrics aggregated over a sliding window.
@@ -54334,7 +56691,10 @@ var BatteryStatusSchema = object({
54334
56691
  * Consumers must SKIP a null rather than coerce it — `battery-band` already
54335
56692
  * declines to band a non-finite reading, which is the correct shape.
54336
56693
  */
54337
- percentage: number().min(0).max(100).nullable(),
56694
+ percentage: number().min(0).max(100).nullable().meta({
56695
+ unit: "%",
56696
+ label: "Charge"
56697
+ }),
54338
56698
  /**
54339
56699
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
54340
56700
  * Reolink-specific for the Solar Panel 2 accessory (will become
@@ -54353,13 +56713,13 @@ var BatteryStatusSchema = object({
54353
56713
  "solar",
54354
56714
  "none",
54355
56715
  "unknown"
54356
- ]),
56716
+ ]).meta({ label: "Charging source" }),
54357
56717
  /**
54358
56718
  * True when the camera firmware has gone into low-power mode. Battery
54359
56719
  * providers MUST avoid polling during sleep — reading the battery
54360
56720
  * wakes the camera up and drains charge.
54361
56721
  */
54362
- sleeping: boolean(),
56722
+ sleeping: boolean().meta({ label: "Sleeping" }),
54363
56723
  /** Ms epoch of the last observation. Lets consumers reason about freshness. */
54364
56724
  lastUpdated: number(),
54365
56725
  /**
@@ -54399,22 +56759,71 @@ var BatteryStatusSchema = object({
54399
56759
  * sub-threshold = low). UI MUST render "Normal"/"Low" instead of a
54400
56760
  * misleading exact percentage. Absent/false → genuine 0–100 % reading.
54401
56761
  */
54402
- binary: boolean().optional()
56762
+ binary: boolean().optional().meta({ label: "Binary indicator" })
54403
56763
  });
56764
+ var BATTERY_DEVICE_TYPES = [
56765
+ DeviceType.Camera,
56766
+ DeviceType.Sensor,
56767
+ DeviceType.Button,
56768
+ DeviceType.Switch,
56769
+ DeviceType.PetFeeder,
56770
+ DeviceType.Container,
56771
+ DeviceType.Thermostat
56772
+ ];
56773
+ /** Generic Customize target for the percentage reading (D936). */
56774
+ var batteryCustomize = {
56775
+ version: 1,
56776
+ advanced: "derive",
56777
+ targets: [{
56778
+ id: "percentage",
56779
+ cardinality: "scalar",
56780
+ vocabulary: {
56781
+ cap: "battery",
56782
+ stateField: "percentage"
56783
+ },
56784
+ deviceTypes: BATTERY_DEVICE_TYPES,
56785
+ apply: "add-or-replace",
56786
+ path: "percentage",
56787
+ sources: [{
56788
+ kind: "field",
56789
+ valueKinds: ["number", "string"],
56790
+ transforms: [{ kind: "identity" }, {
56791
+ kind: "linear",
56792
+ defaultScale: 1,
56793
+ defaultOffset: 0,
56794
+ clampMin: 0,
56795
+ clampMax: 100
56796
+ }]
56797
+ }],
56798
+ companions: [
56799
+ {
56800
+ kind: "constant",
56801
+ path: "charging",
56802
+ value: "unknown",
56803
+ when: "add"
56804
+ },
56805
+ {
56806
+ kind: "constant",
56807
+ path: "sleeping",
56808
+ value: false,
56809
+ when: "add"
56810
+ },
56811
+ {
56812
+ kind: "clock",
56813
+ path: "lastUpdated",
56814
+ when: "add"
56815
+ }
56816
+ ],
56817
+ sourceReport: { status: "assignment-status" },
56818
+ advancedExpression: true
56819
+ }]
56820
+ };
54404
56821
  var batteryCapability = {
54405
56822
  name: "battery",
54406
56823
  scope: "device",
54407
56824
  deviceNative: true,
54408
56825
  mode: "singleton",
54409
- deviceTypes: [
54410
- DeviceType.Camera,
54411
- DeviceType.Sensor,
54412
- DeviceType.Button,
54413
- DeviceType.Switch,
54414
- DeviceType.PetFeeder,
54415
- DeviceType.Container,
54416
- DeviceType.Thermostat
54417
- ],
56826
+ deviceTypes: BATTERY_DEVICE_TYPES,
54418
56827
  methods: {
54419
56828
  /**
54420
56829
  * Explicitly wake the camera from low-power sleep ahead of a
@@ -54498,6 +56907,7 @@ onStatusChanged: { data: object({
54498
56907
  kind: "gauge",
54499
56908
  unit: "%"
54500
56909
  } } },
56910
+ customize: batteryCustomize,
54501
56911
  /** Clock fields: written, but excluded from the compare that decides
54502
56912
  * whether persisting is worth a SQLite commit. */
54503
56913
  volatileStateFields: ["lastUpdated"]
@@ -54514,7 +56924,7 @@ onStatusChanged: { data: object({
54514
56924
  * with the right HomeKit / Alexa display category.
54515
56925
  */
54516
56926
  var BinaryStatusSchema = object({
54517
- on: boolean(),
56927
+ on: boolean().meta({ label: "On" }),
54518
56928
  /** Ms epoch of the last transition. 0 if never observed. */
54519
56929
  lastChangedAt: number()
54520
56930
  });
@@ -54543,7 +56953,12 @@ var binaryCapability = {
54543
56953
  history: { fields: { on: { kind: "boolean" } } },
54544
56954
  /** Clock fields: written, but excluded from the compare that decides
54545
56955
  * whether persisting is worth a SQLite commit. */
54546
- volatileStateFields: ["lastChangedAt"]
56956
+ volatileStateFields: ["lastChangedAt"],
56957
+ customize: {
56958
+ version: 1,
56959
+ advanced: "derive",
56960
+ targets: []
56961
+ }
54547
56962
  };
54548
56963
  /**
54549
56964
  * Dimmable-light brightness control. Co-exists with `switch` on the
@@ -54866,7 +57281,7 @@ var GridLayoutCellSchema = object({
54866
57281
  *
54867
57282
  * A grid's `high` composes its sources' `high` and its `low` their `low`, so a
54868
57283
  * profile is on offer only when EVERY source can serve it. The refusal NAMES
54869
- * the sources, because "this grid has no low" is not a finding — "615 has no
57284
+ * the sources, because "this grid has no low" is not a finding — "101 has no
54870
57285
  * low" is, and it is the one an operator can act on.
54871
57286
  */
54872
57287
  var GridProfileOfferSchema = object({
@@ -55487,6 +57902,106 @@ var ConsumablesStatusSchema = object({
55487
57902
  items: array(ConsumableItemSchema),
55488
57903
  lastChangedAt: number()
55489
57904
  });
57905
+ /** Synthesize seed for a link-built status (no native provider).
57906
+ *
57907
+ * ⚠ NO LIVE CALLER since 2026-08-08 (device-links deleted; see
57908
+ * `CapabilityStatusSchema.empty`). The wiring guidance below was written for
57909
+ * exactly the case the operator is asking about again — a Dreame's HA
57910
+ * consumable-life sensors — so it is kept for that conversation, not because
57911
+ * anything reads it today. */
57912
+ var EMPTY_STATUS = {
57913
+ items: [],
57914
+ lastChangedAt: 0
57915
+ };
57916
+ /** Seed for a NEW link-built consumable item. `key`/`label` are overwritten
57917
+ * with the link's `itemKey` (see `status.itemArray`), so the placeholder
57918
+ * empty strings never survive into a validated item. Link-built items are
57919
+ * not resettable — there is no native provider to receive `reset()`.
57920
+ *
57921
+ * Wiring guidance (HA vacuum consumable-life sensors):
57922
+ * - a percent-remaining source (`numeric-sensor`, unit '%') → `level` via
57923
+ * `identity` (or `linear` scale 1 offset 0 clamp [0,100] to be safe);
57924
+ * - an hours-remaining source (e.g. Dreame 'Main Brush Time Left', unit 'h')
57925
+ * → `level` via `linear` with scale = 100 / max-hours for that item
57926
+ * (e.g. main brush 300 h → scale 0.3333) + clamp [0,100];
57927
+ * - a discrete source (`enum-sensor`, e.g. mop pad 'installed') → `status`
57928
+ * via `enum-map` (e.g. { installed: 'ok', missing: 'replace' }).
57929
+ * A numeric→'replace' THRESHOLD (level < 10 → 'replace') is NOT expressible
57930
+ * with the current transform kinds — leave `status` null (valid) until the
57931
+ * expression transform lands. */
57932
+ /** Generic Customize target for one consumable item (D936). Native rows stay read-only. */
57933
+ var consumablesCustomize = {
57934
+ version: 1,
57935
+ targets: [{
57936
+ id: "items",
57937
+ cardinality: "keyedArray",
57938
+ vocabulary: { cap: "consumables" },
57939
+ deviceTypes: Object.values(DeviceType),
57940
+ apply: "add",
57941
+ path: "items",
57942
+ keyField: "key",
57943
+ labelField: "label",
57944
+ itemSchema: ConsumableItemSchema,
57945
+ nativeItems: "read-only",
57946
+ sourceReport: { status: "assignment-status" },
57947
+ fields: [
57948
+ {
57949
+ path: "level",
57950
+ sources: [{
57951
+ kind: "numeric",
57952
+ transforms: [{ kind: "identity" }, {
57953
+ kind: "linear",
57954
+ defaultScale: 1,
57955
+ defaultOffset: 0,
57956
+ clampMin: 0,
57957
+ clampMax: 100
57958
+ }]
57959
+ }]
57960
+ },
57961
+ {
57962
+ path: "remaining.value",
57963
+ sources: [{
57964
+ kind: "numeric",
57965
+ transforms: [{ kind: "identity" }]
57966
+ }],
57967
+ literals: [{
57968
+ path: "remaining.unit",
57969
+ values: [...ConsumableRemainingUnitSchema.options]
57970
+ }]
57971
+ },
57972
+ {
57973
+ path: "status",
57974
+ sources: [{
57975
+ kind: "enum",
57976
+ transforms: [{
57977
+ kind: "enum-map",
57978
+ outputValues: [...ConsumableStatusSchema.options],
57979
+ unmapped: null
57980
+ }]
57981
+ }]
57982
+ }
57983
+ ],
57984
+ traits: [{
57985
+ path: "kind",
57986
+ values: [...ConsumableKindSchema.options],
57987
+ defaultValue: "wear"
57988
+ }, {
57989
+ path: "form",
57990
+ values: [...ConsumableFormSchema.options],
57991
+ defaultValue: "part"
57992
+ }],
57993
+ companions: [{
57994
+ kind: "clock",
57995
+ path: "lastChangedAt",
57996
+ when: "add"
57997
+ }, {
57998
+ kind: "clock",
57999
+ path: "lastFetchedAt",
58000
+ when: "add"
58001
+ }],
58002
+ advancedExpression: true
58003
+ }]
58004
+ };
55490
58005
  var consumablesCapability = {
55491
58006
  name: "consumables",
55492
58007
  scope: "device",
@@ -55524,10 +58039,7 @@ reset: method(object({
55524
58039
  status: {
55525
58040
  schema: ConsumablesStatusSchema,
55526
58041
  kind: "push",
55527
- empty: {
55528
- items: [],
55529
- lastChangedAt: 0
55530
- },
58042
+ empty: EMPTY_STATUS,
55531
58043
  itemArray: {
55532
58044
  path: "items",
55533
58045
  keyField: "key",
@@ -55563,6 +58075,7 @@ reset: method(object({
55563
58075
  * brush's remaining life and a dishwasher's salt are each recorded the moment
55564
58076
  * their provider reports them; an item that appears later gets its series.
55565
58077
  */
58078
+ customize: consumablesCustomize,
55566
58079
  history: {
55567
58080
  fields: {},
55568
58081
  items: {
@@ -55942,6 +58455,30 @@ var dayNightCapability = {
55942
58455
  volatileStateFields: ["lastFetchedAt"]
55943
58456
  };
55944
58457
  /**
58458
+ * display-palette — the cluster's one colour table (D939).
58459
+ *
58460
+ * Hub singleton. `getPalette` reports `unknown` when the settings store
58461
+ * cannot be read; it does not pretend the bundled preset was stored.
58462
+ * `setPalette` refuses a palette that fails the ΔE / contrast rule and names
58463
+ * the pairs.
58464
+ */
58465
+ var presetSummarySchema = object({
58466
+ id: string(),
58467
+ name: string(),
58468
+ swatches: record(string(), paletteSwatchSchema),
58469
+ fallbacks: array(string())
58470
+ });
58471
+ method(_void(), paletteResultSchema, {
58472
+ auth: "protected",
58473
+ role: "viewer"
58474
+ }), method(_void(), array(presetSummarySchema).readonly(), {
58475
+ auth: "protected",
58476
+ role: "viewer"
58477
+ }), method(setPaletteInputSchema, paletteReadySchema, {
58478
+ kind: "mutation",
58479
+ auth: "admin"
58480
+ });
58481
+ /**
55945
58482
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
55946
58483
  * for every device, regardless of provider — the kernel needs a uniform
55947
58484
  * cap-keyed slice for the basic device flags every consumer expects to
@@ -56305,6 +58842,37 @@ var dishwasherCapability = {
56305
58842
  powerOn: { kind: "boolean" }
56306
58843
  } }
56307
58844
  };
58845
+ /** Pulse override: a rising edge advances `lastPressedAt` and the press count. */
58846
+ var doorbellCustomize = {
58847
+ version: 1,
58848
+ targets: [{
58849
+ id: "pressed",
58850
+ cardinality: "event",
58851
+ shape: "pulse",
58852
+ vocabulary: {
58853
+ cap: "doorbell",
58854
+ eventName: "onPressed"
58855
+ },
58856
+ deviceTypes: [DeviceType.Camera],
58857
+ apply: "add",
58858
+ applyAuthority: { kind: "composition-claim" },
58859
+ eventName: "onPressed",
58860
+ edges: ["rising"],
58861
+ defaultEdge: "rising",
58862
+ timestampPath: "lastPressedAt",
58863
+ counterPath: "pressCountSinceStart",
58864
+ highWater: "composer-advance",
58865
+ combine: "any",
58866
+ debounce: {
58867
+ kind: "rising-edge",
58868
+ defaultDebounceMs: 2e3,
58869
+ changedAtRequired: true
58870
+ },
58871
+ sources: [{ kind: "binary" }, { kind: "switch" }],
58872
+ sourceReport: { status: "assignment-status" },
58873
+ advancedExpression: true
58874
+ }]
58875
+ };
56308
58876
  var DoorbellStatusSchema = object({
56309
58877
  /** Ms epoch of the last press. null = never observed since this provider started. */
56310
58878
  lastPressedAt: number().nullable(),
@@ -56371,7 +58939,8 @@ onPressed: {
56371
58939
  /**
56372
58940
  * History (D850): none — `pressCountSinceStart` resets with the addon, so it is not a monotonic meter; presses live in the events ledger.
56373
58941
  */
56374
- history: "none"
58942
+ history: "none",
58943
+ customize: doorbellCustomize
56375
58944
  };
56376
58945
  /**
56377
58946
  * Enum-state sensor — a string value picked from a finite option set.
@@ -57243,7 +59812,10 @@ var humidifierCapability = {
57243
59812
  */
57244
59813
  var HumiditySensorStatusSchema = object({
57245
59814
  /** Current relative humidity, 0..100. */
57246
- percent: number().min(0).max(100),
59815
+ percent: number().min(0).max(100).meta({
59816
+ unit: "%",
59817
+ label: "Humidity"
59818
+ }),
57247
59819
  /** Ms epoch when the slice was last updated. */
57248
59820
  lastFetchedAt: number(),
57249
59821
  /** Live display unit from the upstream source (e.g. HA
@@ -57285,7 +59857,12 @@ var humiditySensorCapability = {
57285
59857
  } } },
57286
59858
  /** Clock fields: written, but excluded from the compare that decides
57287
59859
  * whether persisting is worth a SQLite commit. */
57288
- volatileStateFields: ["lastFetchedAt"]
59860
+ volatileStateFields: ["lastFetchedAt"],
59861
+ customize: {
59862
+ version: 1,
59863
+ advanced: "derive",
59864
+ targets: []
59865
+ }
57289
59866
  };
57290
59867
  /**
57291
59868
  * Image display cap. Models a single still image exposed by an integration —
@@ -58767,6 +61344,38 @@ authKey: string().optional() }), object({
58767
61344
  /** Human-readable error when `ok: false`. */
58768
61345
  error: string().optional()
58769
61346
  }), { kind: "mutation" });
61347
+ /** Span override: start on a rising edge, end on a fall or this timeout. */
61348
+ var motionCustomize = {
61349
+ version: 1,
61350
+ targets: [{
61351
+ id: "detected",
61352
+ cardinality: "event",
61353
+ shape: "span",
61354
+ vocabulary: {
61355
+ cap: "motion",
61356
+ eventName: "onMotionChanged"
61357
+ },
61358
+ deviceTypes: [DeviceType.Camera],
61359
+ apply: "replace",
61360
+ applyAuthority: {
61361
+ kind: "camera-sensors",
61362
+ timeoutField: "motionCooldownMs"
61363
+ },
61364
+ eventName: "onMotionChanged",
61365
+ start: "rising-edge",
61366
+ end: "falling-edge-or-timeout",
61367
+ timeoutMs: 3e4,
61368
+ combine: "any",
61369
+ sourceModes: [
61370
+ "in-addition",
61371
+ "confirm",
61372
+ "replace"
61373
+ ],
61374
+ sources: [{ kind: "binary" }, { kind: "switch" }],
61375
+ sourceReport: { status: "assignment-status" },
61376
+ advancedExpression: false
61377
+ }]
61378
+ };
58770
61379
  var MotionStatusSchema = object({
58771
61380
  detected: boolean(),
58772
61381
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -58906,7 +61515,8 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
58906
61515
  history: { fields: { detected: {
58907
61516
  kind: "boolean",
58908
61517
  excludeDeviceTypes: [DeviceType.Camera]
58909
- } } }
61518
+ } } },
61519
+ customize: motionCustomize
58910
61520
  };
58911
61521
  /**
58912
61522
  * Motion-trigger toggle for accessory devices.
@@ -61033,9 +63643,15 @@ method(_void(), PlatformCapabilitiesSchema), method(_void(), HardwareInfoSchema)
61033
63643
  */
61034
63644
  var PowerMeterStatusSchema = object({
61035
63645
  /** Instantaneous power draw in watts. */
61036
- watts: number().optional(),
63646
+ watts: number().optional().meta({
63647
+ unit: "W",
63648
+ label: "Power"
63649
+ }),
61037
63650
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
61038
- kwhTotal: number().optional(),
63651
+ kwhTotal: number().optional().meta({
63652
+ unit: "kWh",
63653
+ label: "Energy"
63654
+ }),
61039
63655
  /** Voltage in volts. */
61040
63656
  volts: number().optional(),
61041
63657
  /** Current in amperes. */
@@ -61120,7 +63736,12 @@ var powerMeterCapability = {
61120
63736
  } },
61121
63737
  /** Clock fields: written, but excluded from the compare that decides
61122
63738
  * whether persisting is worth a SQLite commit. */
61123
- volatileStateFields: ["lastFetchedAt"]
63739
+ volatileStateFields: ["lastFetchedAt"],
63740
+ customize: {
63741
+ version: 1,
63742
+ advanced: "derive",
63743
+ targets: []
63744
+ }
61124
63745
  };
61125
63746
  /**
61126
63747
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -61542,9 +64163,9 @@ var PtzOptionsSchema = object({
61542
64163
  * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
61543
64164
  * not one of the three cameras honours its own:
61544
64165
  *
61545
- * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
61546
- * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
61547
- * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
64166
+ * 107 Camera camera Carol (reolink) preset 0 holds "stanza"
64167
+ * 1438 Camera dispensa (hikvision) preset 1 holds "Credenza"
64168
+ * 3836 Camera studio (amcrest) preset 1 holds "Preset1"
61548
64169
  *
61549
64170
  * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
61550
64171
  * and two of the three swallowed the failure in a bare `catch`. For autotrack
@@ -61780,27 +64401,120 @@ var ptzAutotrackCapability = {
61780
64401
  */
61781
64402
  history: "none"
61782
64403
  };
64404
+ var RUNNING_POWER_START_DELAY_MS = 3e4;
64405
+ var RUNNING_POWER_STOP_DELAY_MS = 18e4;
64406
+ /** Before any provider reading — all fields unknown (D933). */
64407
+ var RUNNING_STATE_COLD = {
64408
+ running: null,
64409
+ since: null,
64410
+ source: "native",
64411
+ phase: null,
64412
+ lastFetchedAt: null
64413
+ };
61783
64414
  var RunningStateSourceSchema = _enum(["native", "assigned"]);
61784
64415
  var RunningStateStatusSchema = object({
61785
64416
  /** null = unknown — never coerced to false (D393). */
61786
64417
  running: boolean().nullable(),
61787
64418
  /** Epoch ms the current boolean began; null while `running` is null. */
61788
64419
  since: number().nullable(),
61789
- source: RunningStateSourceSchema,
64420
+ source: RunningStateSourceSchema.meta({ label: "Source" }),
61790
64421
  phase: string().nullable(),
61791
- lastFetchedAt: number()
64422
+ /** null until a reading has been published (D393). */
64423
+ lastFetchedAt: number().nullable()
61792
64424
  });
61793
64425
  var RunningFlipEventDataSchema = object({
61794
64426
  deviceId: number(),
61795
64427
  since: number().nullable(),
61796
64428
  phase: string().nullable()
61797
64429
  });
64430
+ var RUNNING_DEVICE_TYPES = Object.values(DeviceType);
64431
+ /** Generic Customize target for the running boolean (D936). */
64432
+ var runningCustomize = {
64433
+ version: 1,
64434
+ advanced: "derive",
64435
+ targets: [{
64436
+ id: "running",
64437
+ cardinality: "scalar",
64438
+ vocabulary: {
64439
+ cap: "running-state",
64440
+ stateField: "running"
64441
+ },
64442
+ deviceTypes: [
64443
+ DeviceType.Dishwasher,
64444
+ DeviceType.Vacuum,
64445
+ DeviceType.LawnMower,
64446
+ DeviceType.MediaPlayer,
64447
+ DeviceType.WaterHeater,
64448
+ DeviceType.Humidifier,
64449
+ DeviceType.Fan,
64450
+ DeviceType.Climate,
64451
+ DeviceType.Thermostat,
64452
+ DeviceType.PetFeeder
64453
+ ],
64454
+ apply: "add-or-replace",
64455
+ path: "running",
64456
+ sources: [
64457
+ {
64458
+ kind: "switch",
64459
+ transforms: [{ kind: "identity" }]
64460
+ },
64461
+ {
64462
+ kind: "binary",
64463
+ transforms: [{ kind: "identity" }, { kind: "invert" }]
64464
+ },
64465
+ {
64466
+ kind: "numeric",
64467
+ requiredUnit: "W",
64468
+ transforms: [{
64469
+ kind: "threshold",
64470
+ comparisons: ["gte", "lte"],
64471
+ comparison: "gte",
64472
+ defaultThreshold: 5,
64473
+ defaultStartDwellMs: RUNNING_POWER_START_DELAY_MS,
64474
+ defaultStopDwellMs: RUNNING_POWER_STOP_DELAY_MS,
64475
+ thresholdUnit: "W"
64476
+ }]
64477
+ }
64478
+ ],
64479
+ companions: [
64480
+ {
64481
+ kind: "constant",
64482
+ path: "source",
64483
+ value: "assigned",
64484
+ when: "always"
64485
+ },
64486
+ {
64487
+ kind: "constant",
64488
+ path: "phase",
64489
+ value: null,
64490
+ when: "always"
64491
+ },
64492
+ {
64493
+ kind: "clock",
64494
+ path: "lastFetchedAt",
64495
+ when: "always"
64496
+ },
64497
+ {
64498
+ kind: "transition-time",
64499
+ path: "since",
64500
+ sourceChangedAt: "prefer"
64501
+ }
64502
+ ],
64503
+ sourceReport: {
64504
+ status: "assignment-status",
64505
+ runtimeField: "source",
64506
+ nativeValue: "native",
64507
+ assignedValue: "assigned"
64508
+ },
64509
+ advancedExpression: true
64510
+ }]
64511
+ };
61798
64512
  var runningStateCapability = {
61799
64513
  name: "running-state",
61800
64514
  scope: "device",
61801
64515
  deviceNative: true,
61802
64516
  mode: "singleton",
61803
- deviceTypes: Object.values(DeviceType),
64517
+ deviceTypes: RUNNING_DEVICE_TYPES,
61804
64518
  methods: {},
61805
64519
  events: {
61806
64520
  onStarted: { data: RunningFlipEventDataSchema },
@@ -61813,7 +64527,8 @@ var runningStateCapability = {
61813
64527
  runtimeState: RunningStateStatusSchema,
61814
64528
  durability: "restored",
61815
64529
  history: { fields: { running: { kind: "boolean" } } },
61816
- volatileStateFields: ["lastFetchedAt"]
64530
+ volatileStateFields: ["lastFetchedAt"],
64531
+ customize: runningCustomize
61817
64532
  };
61818
64533
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
61819
64534
  kind: "mutation",
@@ -61856,7 +64571,7 @@ var RecordingAvailabilitySchema = object({
61856
64571
  * would look identical. But the answer used to say nothing about that, so a
61857
64572
  * caller asking "what can I export?" read the single preferred profile as
61858
64573
  * the only one that exists — on this deployment every camera records `high`
61859
- * AND `low`, the low tree holding 14 GB for camera 615 alone, and the export
64574
+ * AND `low`, the low tree holding 14 GB for camera 101 alone, and the export
61860
64575
  * UI could not see it.
61861
64576
  *
61862
64577
  * Cheap: it is the same shallow directory read the profile CHOICE already
@@ -61955,7 +64670,7 @@ var RecordingSourceOptionsSchema = object({
61955
64670
  * `sparse` = gaps are the absence of one, and must be drawn as such.
61956
64671
  *
61957
64672
  * Not an onboard-only concession: measured 2026-09-24, OUR bar covers 98.8 %
61958
- * of 592's day and 1.2 % of 1436's. It is a fact about a (source, camera)
64673
+ * of 107's day and 1.2 % of 1436's. It is a fact about a (source, camera)
61959
64674
  * pair, and ours answers it per camera from `deriveRecordingMode`. */
61960
64675
  coverage: _enum(["continuous", "sparse"]),
61961
64676
  /** Where the playhead may be put.
@@ -62031,7 +64746,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(RecordingSourceS
62031
64746
  * merely discouraged (D554 amended).
62032
64747
  *
62033
64748
  * It was learned the expensive way on `videoclips.listClips`: measured
62034
- * on the live hub 2026-09-20, device 592 bound to `recorder` AND
64749
+ * on the live hub 2026-09-20, device 107 bound to `recorder` AND
62035
64750
  * `provider-reolink`, a bare call with `limit: 3` answered SIX rows,
62036
64751
  * three from each source, merged — `device-collection-dispatch.ts`
62037
64752
  * leaves an unpinned fan-out un-narrowed, so absence buys the union the
@@ -62632,7 +65347,7 @@ var ExportSpeedSchema = number().min(.25).max(32);
62632
65347
  * on a 10 h window holding 29,393 s of footage every range landed late by the
62633
65348
  * gap accumulated before it — up to 6,607 s, well past EOF. Nothing matched,
62634
65349
  * the video was a uniform timelapse, and the log line reported the five ranges
62635
- * that had been ASKED for (2026-08-13, export `57d14363`, camera 615).
65350
+ * that had been ASKED for (2026-08-13, export `57d14363`, camera 101).
62636
65351
  *
62637
65352
  * Relative and not absolute epoch, because an absolute epoch would make every
62638
65353
  * call site responsible for the same subtraction.
@@ -63343,7 +66058,7 @@ getStatus: method(object({ deviceId: number() }), RecordingSignalStatusSchema) }
63343
66058
  * which put a "Scenes" tab on one camera's detail page. That is the wrong shape
63344
66059
  * for the thing: a scene is a standing question about the property ("is the bin
63345
66060
  * still out"), and the operator's question is "which of my scenes have tripped",
63346
- * across every camera at once — not "what does camera 617 think". Buried one
66061
+ * across every camera at once — not "what does camera 102 think". Buried one
63347
66062
  * camera deep it also could not be found. The surface is now a top-level admin
63348
66063
  * page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
63349
66064
  * picks the camera inside the create flow, the same shape Events and Faces have.
@@ -64202,7 +66917,7 @@ var streamParamsCapability = {
64202
66917
  * `getSettingsUISchema()` surface.
64203
66918
  */
64204
66919
  var SwitchStatusSchema = object({
64205
- on: boolean(),
66920
+ on: boolean().meta({ label: "On" }),
64206
66921
  /** Ms epoch of the last state change. Useful for UI "X minutes ago". */
64207
66922
  lastChangedAt: number()
64208
66923
  });
@@ -64261,7 +66976,12 @@ var switchCapability = {
64261
66976
  label: "On",
64262
66977
  kind: "boolean"
64263
66978
  }
64264
- }] }
66979
+ }] },
66980
+ customize: {
66981
+ version: 1,
66982
+ advanced: "derive",
66983
+ targets: []
66984
+ }
64265
66985
  };
64266
66986
  /** C0 controls, DEL and the C1 range: none of them belongs in a name. */
64267
66987
  function hasControlCharacter(value) {
@@ -64857,7 +67577,10 @@ var tamperCapability = {
64857
67577
  */
64858
67578
  var TemperatureSensorStatusSchema = object({
64859
67579
  /** Current temperature in Celsius. */
64860
- celsius: number(),
67580
+ celsius: number().meta({
67581
+ unit: "°C",
67582
+ label: "Temperature"
67583
+ }),
64861
67584
  /** Ms epoch when the slice was last updated (push or poll). */
64862
67585
  lastFetchedAt: number(),
64863
67586
  /** Live display unit from the upstream source (e.g. HA
@@ -64900,7 +67623,12 @@ var temperatureSensorCapability = {
64900
67623
  } } },
64901
67624
  /** Clock fields: written, but excluded from the compare that decides
64902
67625
  * whether persisting is worth a SQLite commit. */
64903
- volatileStateFields: ["lastFetchedAt"]
67626
+ volatileStateFields: ["lastFetchedAt"],
67627
+ customize: {
67628
+ version: 1,
67629
+ advanced: "derive",
67630
+ targets: []
67631
+ }
64904
67632
  };
64905
67633
  /**
64906
67634
  * toast — system-scoped singleton capability that streams toast
@@ -66445,33 +69173,41 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
66445
69173
  kind: "mutation",
66446
69174
  auth: "admin"
66447
69175
  });
66448
- function resolveSince(running, previous, sinceMs) {
69176
+ function resolveSince(running, previous, transitionAtMs, bootstrapSinceMs) {
66449
69177
  if (running === null) return null;
66450
- if ((previous?.running ?? null) !== running) return sinceMs;
66451
- return previous?.since ?? sinceMs;
69178
+ const prevRunning = previous?.running ?? null;
69179
+ if (prevRunning === null) return bootstrapSinceMs;
69180
+ if (prevRunning !== running) return transitionAtMs;
69181
+ return previous?.since ?? null;
66452
69182
  }
66453
- function nativeSlice(running, phase, previous, sinceMs, now) {
69183
+ function nativeSlice(running, phase, previous, transitionAtMs, fetchedAt, bootstrapSinceMs) {
66454
69184
  return {
66455
69185
  running,
66456
- since: resolveSince(running, previous, sinceMs),
69186
+ since: resolveSince(running, previous, transitionAtMs, bootstrapSinceMs),
66457
69187
  source: "native",
66458
69188
  phase: running === null ? null : phase,
66459
- lastFetchedAt: now
69189
+ lastFetchedAt: fetchedAt
66460
69190
  };
66461
69191
  }
66462
- function runningFromVacuumState(state, previous, now) {
66463
- if (state === null) return nativeSlice(null, null, previous, now, now);
66464
- if (state === "cleaning" || state === "returning" || state === "drying") return nativeSlice(true, state, previous, now, now);
66465
- if (state === "paused") return nativeSlice(false, "paused", previous, now, now);
66466
- return nativeSlice(false, state, previous, now, now);
69192
+ function runningFromVacuumState(state, previous, fetchedAt, transitionAt) {
69193
+ const transitionAtMs = transitionAt ?? fetchedAt;
69194
+ if (state === null) return nativeSlice(null, null, previous, transitionAtMs, fetchedAt, null);
69195
+ if (state === "cleaning" || state === "returning" || state === "drying") return nativeSlice(true, state, previous, transitionAtMs, fetchedAt, null);
69196
+ if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
69197
+ return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
66467
69198
  }
66468
- function runningFromLawnMower(activity, previous, now) {
66469
- if (activity === null) return nativeSlice(null, null, previous, now, now);
66470
- if (activity === "mowing") return nativeSlice(true, activity, previous, now, now);
66471
- if (activity === "paused") return nativeSlice(false, "paused", previous, now, now);
66472
- return nativeSlice(false, activity, previous, now, now);
69199
+ function runningFromLawnMower(activity, previous, fetchedAt, transitionAt) {
69200
+ const transitionAtMs = transitionAt ?? fetchedAt;
69201
+ if (activity === null) return nativeSlice(null, null, previous, transitionAtMs, fetchedAt, null);
69202
+ if (activity === "mowing") return nativeSlice(true, activity, previous, transitionAtMs, fetchedAt, null);
69203
+ if (activity === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
69204
+ return nativeSlice(false, activity, previous, transitionAtMs, fetchedAt, null);
66473
69205
  }
66474
69206
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
69207
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Camera, DeviceType.Camera, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
69208
+ String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
69209
+ DeviceRole.BinarySensor, DeviceRole.MotionSensor;
69210
+ new Set(CAP_NAMES);
66475
69211
  Object.freeze({
66476
69212
  person: .5,
66477
69213
  vehicle: .5,
@@ -67721,7 +70457,7 @@ var BaseDeviceProvider = class extends BaseAddon {
67721
70457
  * A top-level persisted row with NO configuration is a leftover, not a
67722
70458
  * device — quarantine it instead of dialling it.
67723
70459
  *
67724
- * Device 614 was deleted, resurrected as a config-less shell by a write
70460
+ * Device 105 was deleted, resurrected as a config-less shell by a write
67725
70461
  * already in flight (D376), and then dialled at every single boot: eight
67726
70462
  * `Failed to restore device — bounded retry scheduled` lines in one day,
67727
70463
  * each one the same Zod refusal on `host` and `password`. The bound was
@@ -71031,6 +73767,27 @@ Object.freeze({
71031
73767
  access: "create",
71032
73768
  role: "viewer"
71033
73769
  },
73770
+ "displayPalette.getPalette": {
73771
+ capName: "display-palette",
73772
+ capScope: "system",
73773
+ addonId: null,
73774
+ access: "view",
73775
+ role: "viewer"
73776
+ },
73777
+ "displayPalette.listPresets": {
73778
+ capName: "display-palette",
73779
+ capScope: "system",
73780
+ addonId: null,
73781
+ access: "view",
73782
+ role: "viewer"
73783
+ },
73784
+ "displayPalette.setPalette": {
73785
+ capName: "display-palette",
73786
+ capScope: "system",
73787
+ addonId: null,
73788
+ access: "create",
73789
+ role: "admin"
73790
+ },
71034
73791
  "doorbell.getStatus": {
71035
73792
  capName: "doorbell",
71036
73793
  capScope: "device",
@@ -80948,7 +83705,7 @@ var SENSOR_CAP_VOCABULARY = {
80948
83705
  state: [{
80949
83706
  kind: "boolean",
80950
83707
  field: "on",
80951
- label: t("Active", "Attivo"),
83708
+ label: t("On", "Acceso"),
80952
83709
  whenTrue: t("When {device} turns active", "Quando {device} si attiva"),
80953
83710
  whenFalse: t("When {device} turns inactive", "Quando {device} si disattiva"),
80954
83711
  icon: "toggle-right"
@@ -81487,6 +84244,7 @@ var SYSTEM_CAP_VOCABULARY = {
81487
84244
  "device-provider": system(INTERNAL),
81488
84245
  "device-removal-hook": system(INTERNAL),
81489
84246
  "device-state": system("the runtime-state mirror every trigger already reads through"),
84247
+ "display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
81490
84248
  "embedding-encoder": system(ML),
81491
84249
  "face-gallery": system("the face gallery — curated on its own page"),
81492
84250
  "failure-contribution": system(INTERNAL),
@@ -84371,6 +87129,99 @@ Object.freeze({
84371
87129
  "smtp-provider": "email"
84372
87130
  });
84373
87131
  DeviceType.Camera;
87132
+ /**
87133
+ * A saved Customize assignment (D936). The schema is the type: callers use
87134
+ * `z.infer`, they do not restate the shape.
87135
+ */
87136
+ var OverrideSourceSchema = object({
87137
+ addonId: string().min(1),
87138
+ stableId: string().min(1),
87139
+ cap: string().min(1),
87140
+ fieldPath: string().min(1)
87141
+ });
87142
+ var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
87143
+ object({ kind: literal("identity") }),
87144
+ object({ kind: literal("invert") }),
87145
+ object({
87146
+ kind: literal("threshold"),
87147
+ comparison: _enum(["gte", "lte"]),
87148
+ threshold: number(),
87149
+ startDwellMs: number().nonnegative(),
87150
+ stopDwellMs: number().nonnegative()
87151
+ }),
87152
+ object({
87153
+ kind: literal("linear"),
87154
+ scale: number(),
87155
+ offset: number(),
87156
+ clampMin: number().optional(),
87157
+ clampMax: number().optional()
87158
+ }),
87159
+ object({
87160
+ kind: literal("enum-map"),
87161
+ mapping: record(string(), string().nullable())
87162
+ }),
87163
+ object({ kind: literal("number") })
87164
+ ]);
87165
+ var ScalarOverrideDraftSchema = object({
87166
+ kind: literal("scalar"),
87167
+ cap: string().min(1),
87168
+ targetId: string().min(1),
87169
+ source: OverrideSourceSchema,
87170
+ transform: CustomizeTransformDraftSchema
87171
+ });
87172
+ var KeyedArrayOverrideDraftSchema = object({
87173
+ kind: literal("keyedArray"),
87174
+ cap: string().min(1),
87175
+ targetId: string().min(1),
87176
+ key: string().min(1),
87177
+ label: string().min(1),
87178
+ fieldPath: string().min(1),
87179
+ source: OverrideSourceSchema,
87180
+ transform: CustomizeTransformDraftSchema
87181
+ });
87182
+ var PulseOverrideDraftSchema = object({
87183
+ kind: literal("pulse"),
87184
+ cap: string().min(1),
87185
+ targetId: string().min(1),
87186
+ enabled: boolean(),
87187
+ debounceMs: number().nonnegative(),
87188
+ edges: array(_enum([
87189
+ "rising",
87190
+ "button",
87191
+ "native-event"
87192
+ ])).min(1).optional(),
87193
+ sources: array(OverrideSourceSchema).min(1)
87194
+ });
87195
+ var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
87196
+ "in-addition",
87197
+ "confirm",
87198
+ "replace"
87199
+ ]).optional() });
87200
+ discriminatedUnion("kind", [
87201
+ ScalarOverrideDraftSchema,
87202
+ KeyedArrayOverrideDraftSchema,
87203
+ PulseOverrideDraftSchema,
87204
+ object({
87205
+ kind: literal("span"),
87206
+ cap: string().min(1),
87207
+ targetId: string().min(1),
87208
+ timeoutMs: number().nonnegative(),
87209
+ cooldownMs: number().nonnegative().optional(),
87210
+ sources: array(SpanSourceDraftSchema)
87211
+ })
87212
+ ]);
87213
+ object({
87214
+ targetId: string().min(1),
87215
+ configured: boolean(),
87216
+ source: _enum(["native", "assigned"]),
87217
+ state: _enum([
87218
+ "active",
87219
+ "stale",
87220
+ "released",
87221
+ "unavailable"
87222
+ ]),
87223
+ reason: string().nullable()
87224
+ });
84374
87225
  var G711_SCALE_CORRECTION_DB = {
84375
87226
  PCMU: 20 * Math.log10(4),
84376
87227
  PCMA: 20 * Math.log10(8)
@@ -84743,7 +87594,7 @@ var STATE_SUMMARY_SECTION_VARS = [
84743
87594
  {
84744
87595
  name: "summaryStreams",
84745
87596
  label: "Summary: streams offline",
84746
- example: "Ingresso (high) — since 06:40",
87597
+ example: "Front door (high) — since 06:40",
84747
87598
  kinds: ["stream-offline", "stream-online"]
84748
87599
  },
84749
87600
  {
@@ -84761,13 +87612,13 @@ var STATE_SUMMARY_SECTION_VARS = [
84761
87612
  {
84762
87613
  name: "summaryDetection",
84763
87614
  label: "Summary: cameras detecting nothing",
84764
- example: "Ingresso — since 05:10",
87615
+ example: "Front door — since 05:10",
84765
87616
  kinds: ["detection-blind"]
84766
87617
  },
84767
87618
  {
84768
87619
  name: "summaryNodes",
84769
87620
  label: "Summary: nodes",
84770
- example: "little-unraid — offline since 03:00",
87621
+ example: "agent-a — offline since 03:00",
84771
87622
  kinds: [
84772
87623
  "node-offline",
84773
87624
  "node-online",
@@ -188494,13 +191345,6 @@ var MowerChargingEdge = class {
188494
191345
  //#region src/devices/dreame-mower-device.ts
188495
191346
  var CAP_NAME$9 = "lawn-mower-control";
188496
191347
  var RUNNING_CAP$1 = "running-state";
188497
- var RUNNING_COLD$1 = {
188498
- running: null,
188499
- since: null,
188500
- source: "native",
188501
- phase: null,
188502
- lastFetchedAt: 0
188503
- };
188504
191348
  /**
188505
191349
  * The CMS consumable custom-action only answers while the mower is momentarily
188506
191350
  * awake and ACTIVELY charging — which it is the instant it docks with a depleted
@@ -188585,12 +191429,9 @@ var DreameMowerDevice = class extends DreameChildDevice {
188585
191429
  await this.requireMower().dock();
188586
191430
  }
188587
191431
  });
188588
- this.ctx.registerNativeCap(runningStateCapability, { getStatus: async () => this.runtimeState.getCapState(RUNNING_CAP$1) ?? RUNNING_COLD$1 });
191432
+ this.ctx.registerNativeCap(runningStateCapability, { getStatus: async () => this.runtimeState.getCapState(RUNNING_CAP$1) ?? RUNNING_STATE_COLD });
188589
191433
  this.runtimeState.setCapState(CAP_NAME$9, COLD_START);
188590
- this.runtimeState.setCapState(RUNNING_CAP$1, {
188591
- ...RUNNING_COLD$1,
188592
- lastFetchedAt: Date.now()
188593
- });
191434
+ this.runtimeState.setCapState(RUNNING_CAP$1, RUNNING_STATE_COLD);
188594
191435
  this.ctx.registerNativeCap(consumablesCapability, {
188595
191436
  getStatus: async () => this.runtimeState.getCapState("consumables") ?? CONSUMABLES_COLD_START,
188596
191437
  reset: async ({ key }) => {
@@ -188653,9 +191494,10 @@ var DreameMowerDevice = class extends DreameChildDevice {
188653
191494
  lastChangedAt: Date.now()
188654
191495
  };
188655
191496
  this.runtimeState.setCapState(CAP_NAME$9, slice);
191497
+ const fetchedAt = Date.now();
188656
191498
  const previous = this.runtimeState.getCapState(RUNNING_CAP$1);
188657
191499
  const activityForRunning = status === null ? null : mapMowerStatusToActivity(status);
188658
- this.runtimeState.setCapState(RUNNING_CAP$1, runningFromLawnMower(activityForRunning, previous, slice.lastChangedAt));
191500
+ this.runtimeState.setCapState(RUNNING_CAP$1, runningFromLawnMower(activityForRunning, previous, fetchedAt, slice.lastChangedAt));
188659
191501
  if (this.#chargingEdge.observe(status, mower.charging)) this.#consumables.refresh("charging");
188660
191502
  }
188661
191503
  /** The live typed mower handle, or throw a clear error when disconnected. */
@@ -189403,13 +192245,6 @@ function resetMeta(result) {
189403
192245
  //#region src/devices/dreame-vacuum-device.ts
189404
192246
  var CAP_NAME$1 = "vacuum-control";
189405
192247
  var RUNNING_CAP = "running-state";
189406
- var RUNNING_COLD = {
189407
- running: null,
189408
- since: null,
189409
- source: "native",
189410
- phase: null,
189411
- lastFetchedAt: 0
189412
- };
189413
192248
  var CONTROL_COLD_START = {
189414
192249
  state: "idle",
189415
192250
  batteryLevel: null,
@@ -189540,10 +192375,7 @@ var DreameVacuumDevice = class extends DreameChildDevice {
189540
192375
  });
189541
192376
  this.registerRunningCap();
189542
192377
  this.runtimeState.setCapState(CAP_NAME$1, CONTROL_COLD_START);
189543
- this.runtimeState.setCapState(RUNNING_CAP, {
189544
- ...RUNNING_COLD,
189545
- lastFetchedAt: Date.now()
189546
- });
192378
+ this.runtimeState.setCapState(RUNNING_CAP, RUNNING_STATE_COLD);
189547
192379
  this.registerConsumablesCap();
189548
192380
  }
189549
192381
  /**
@@ -189579,7 +192411,7 @@ var DreameVacuumDevice = class extends DreameChildDevice {
189579
192411
  };
189580
192412
  const toWrite = nextVacuumControlSlice(this.runtimeState.getCapState(CAP_NAME$1), controlSlice);
189581
192413
  if (toWrite !== null) this.runtimeState.setCapState(CAP_NAME$1, toWrite);
189582
- this.publishRunningSlice(miotStatus, controlSlice.lastChangedAt);
192414
+ this.publishRunningSlice(miotStatus, Date.now(), controlSlice.lastChangedAt);
189583
192415
  this.consumables.onPush(controlSlice.state, tanks);
189584
192416
  }
189585
192417
  /**
@@ -189604,11 +192436,11 @@ var DreameVacuumDevice = class extends DreameChildDevice {
189604
192436
  };
189605
192437
  }
189606
192438
  registerRunningCap() {
189607
- this.ctx.registerNativeCap(runningStateCapability, { getStatus: async () => this.runtimeState.getCapState(RUNNING_CAP) ?? RUNNING_COLD });
192439
+ this.ctx.registerNativeCap(runningStateCapability, { getStatus: async () => this.runtimeState.getCapState(RUNNING_CAP) ?? RUNNING_STATE_COLD });
189608
192440
  }
189609
- publishRunningSlice(miotStatus, sinceMs) {
192441
+ publishRunningSlice(miotStatus, fetchedAt, transitionAt) {
189610
192442
  const previous = this.runtimeState.getCapState(RUNNING_CAP);
189611
- const next = runningFromVacuumState(miotStatus === null ? null : mapMiotStateToVacuumState(miotStatus), previous, sinceMs);
192443
+ const next = runningFromVacuumState(miotStatus === null ? null : mapMiotStateToVacuumState(miotStatus), previous, fetchedAt, transitionAt);
189612
192444
  this.runtimeState.setCapState(RUNNING_CAP, next);
189613
192445
  }
189614
192446
  /** The live typed vacuum handle, or throw a clear error when disconnected. */