@camstack/addon-model-studio 1.1.322 → 1.1.324
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/{MotionZonesSettings-DIoKHy61.mjs → MotionZonesSettings-BFSzpDlc.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-SkRUYyni.mjs → PrivacyMaskSettings-bzbS1q77.mjs} +4 -4
- package/dist/{SceneMonitorEditor-CB_GHDb6.mjs → SceneMonitorEditor-5jtlWR_n.mjs} +3 -3
- package/dist/_stub.js +1298 -1264
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-onE-V79z.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DMLYtwXQ.mjs} +3 -3
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D8h8qfbd.mjs +26 -0
- package/dist/{hostInit-DvZygcN-.mjs → hostInit-BQhIepOe.mjs} +2 -2
- package/dist/model-studio.addon.js +803 -64
- package/dist/model-studio.addon.mjs +803 -64
- package/dist/{player-overlays-_zERIZfO.mjs → player-overlays-DwnklNvS.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-CFFPG77U.mjs → responsive-DFhiWOST.mjs} +1 -1
- package/dist/{scene-monitor-copy-DEJ23ZZg.mjs → scene-monitor-copy-DVaiZyk_.mjs} +1 -1
- package/dist/{square-Prn9rHwz.mjs → square-CL1GZCDy.mjs} +1 -1
- package/dist/{trash-2-Ddf3KFsK.mjs → trash-2-Bs4Zqar1.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-DDvX_rph.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-B3z4_zyV.mjs} +1 -1
- package/package.json +1 -1
- package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Dt_IlI_h.mjs +0 -26
|
@@ -5824,7 +5824,7 @@ var ZodIssueCode = {
|
|
|
5824
5824
|
var ZodFirstPartyTypeKind;
|
|
5825
5825
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5826
5826
|
//#endregion
|
|
5827
|
-
//#region ../types/dist/sleep-
|
|
5827
|
+
//#region ../types/dist/sleep-63gM_1JR.mjs
|
|
5828
5828
|
/**
|
|
5829
5829
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5830
5830
|
* window to float samples (D455).
|
|
@@ -9185,6 +9185,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9185
9185
|
"recording-signal",
|
|
9186
9186
|
"records",
|
|
9187
9187
|
"remote",
|
|
9188
|
+
"remote-layout-components",
|
|
9188
9189
|
"running-state",
|
|
9189
9190
|
"scene-monitor",
|
|
9190
9191
|
"script-runner",
|
|
@@ -16042,6 +16043,478 @@ object({
|
|
|
16042
16043
|
path: ["expr"]
|
|
16043
16044
|
});
|
|
16044
16045
|
});
|
|
16046
|
+
/**
|
|
16047
|
+
* Identity envelope for a device's upstream-system metadata.
|
|
16048
|
+
*
|
|
16049
|
+
* Two jobs:
|
|
16050
|
+
*
|
|
16051
|
+
* 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
|
|
16052
|
+
* uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
|
|
16053
|
+
* WS-Discovery endpoint UUID, …). Provider code keeps a
|
|
16054
|
+
* `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
|
|
16055
|
+
* without round-tripping through `stableId` / `id` mappings.
|
|
16056
|
+
*
|
|
16057
|
+
* 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
|
|
16058
|
+
* one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
|
|
16059
|
+
* for vendors where MAC is the natural key). For systems where the
|
|
16060
|
+
* live dispatch key can be renamed (HA `entity_id` can be edited),
|
|
16061
|
+
* providers detect renames by matching `uniqueId` and patch `id`
|
|
16062
|
+
* in-place so dispatch keeps working.
|
|
16063
|
+
*
|
|
16064
|
+
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
16065
|
+
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
16066
|
+
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
16067
|
+
* neither is repeated on each sample. The `device_class` tag is an
|
|
16068
|
+
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
16069
|
+
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
16070
|
+
*
|
|
16071
|
+
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
16072
|
+
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
16073
|
+
* details, …). Providers control what lands here.
|
|
16074
|
+
*/
|
|
16075
|
+
var SourceInfoSchema = object({
|
|
16076
|
+
/** Live dispatch key — mutable when the source system allows rename. */
|
|
16077
|
+
id: string(),
|
|
16078
|
+
/** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
|
|
16079
|
+
system: string(),
|
|
16080
|
+
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
16081
|
+
* Used to detect rename when `id` changes. */
|
|
16082
|
+
uniqueId: string().optional(),
|
|
16083
|
+
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
16084
|
+
quantity: ReadingQuantitySchema.optional(),
|
|
16085
|
+
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
16086
|
+
dateTimeShape: _enum([
|
|
16087
|
+
"date",
|
|
16088
|
+
"time",
|
|
16089
|
+
"datetime"
|
|
16090
|
+
]).optional(),
|
|
16091
|
+
/** Provider-specific extras that don't fit the structured slots.
|
|
16092
|
+
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
16093
|
+
* attribute blobs (would explode the meta JSON column). */
|
|
16094
|
+
raw: record(string(), unknown()).optional()
|
|
16095
|
+
});
|
|
16096
|
+
/**
|
|
16097
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
16098
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
16099
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
16100
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
16101
|
+
*/
|
|
16102
|
+
var UNIT_TABLE = {
|
|
16103
|
+
"°C": {
|
|
16104
|
+
dimension: "temperature",
|
|
16105
|
+
factor: 1,
|
|
16106
|
+
offset: 0
|
|
16107
|
+
},
|
|
16108
|
+
"°F": {
|
|
16109
|
+
dimension: "temperature",
|
|
16110
|
+
factor: 5 / 9,
|
|
16111
|
+
offset: -160 / 9
|
|
16112
|
+
},
|
|
16113
|
+
K: {
|
|
16114
|
+
dimension: "temperature",
|
|
16115
|
+
factor: 1,
|
|
16116
|
+
offset: -273.15
|
|
16117
|
+
},
|
|
16118
|
+
hPa: {
|
|
16119
|
+
dimension: "pressure",
|
|
16120
|
+
factor: 1,
|
|
16121
|
+
offset: 0
|
|
16122
|
+
},
|
|
16123
|
+
kPa: {
|
|
16124
|
+
dimension: "pressure",
|
|
16125
|
+
factor: 10,
|
|
16126
|
+
offset: 0
|
|
16127
|
+
},
|
|
16128
|
+
Pa: {
|
|
16129
|
+
dimension: "pressure",
|
|
16130
|
+
factor: .01,
|
|
16131
|
+
offset: 0
|
|
16132
|
+
},
|
|
16133
|
+
mbar: {
|
|
16134
|
+
dimension: "pressure",
|
|
16135
|
+
factor: 1,
|
|
16136
|
+
offset: 0
|
|
16137
|
+
},
|
|
16138
|
+
bar: {
|
|
16139
|
+
dimension: "pressure",
|
|
16140
|
+
factor: 1e3,
|
|
16141
|
+
offset: 0
|
|
16142
|
+
},
|
|
16143
|
+
inHg: {
|
|
16144
|
+
dimension: "pressure",
|
|
16145
|
+
factor: 33.8639,
|
|
16146
|
+
offset: 0
|
|
16147
|
+
},
|
|
16148
|
+
mmHg: {
|
|
16149
|
+
dimension: "pressure",
|
|
16150
|
+
factor: 1.33322,
|
|
16151
|
+
offset: 0
|
|
16152
|
+
},
|
|
16153
|
+
psi: {
|
|
16154
|
+
dimension: "pressure",
|
|
16155
|
+
factor: 68.9476,
|
|
16156
|
+
offset: 0
|
|
16157
|
+
},
|
|
16158
|
+
"m/s": {
|
|
16159
|
+
dimension: "speed",
|
|
16160
|
+
factor: 1,
|
|
16161
|
+
offset: 0
|
|
16162
|
+
},
|
|
16163
|
+
"km/h": {
|
|
16164
|
+
dimension: "speed",
|
|
16165
|
+
factor: 1 / 3.6,
|
|
16166
|
+
offset: 0
|
|
16167
|
+
},
|
|
16168
|
+
mph: {
|
|
16169
|
+
dimension: "speed",
|
|
16170
|
+
factor: .44704,
|
|
16171
|
+
offset: 0
|
|
16172
|
+
},
|
|
16173
|
+
kn: {
|
|
16174
|
+
dimension: "speed",
|
|
16175
|
+
factor: .514444,
|
|
16176
|
+
offset: 0
|
|
16177
|
+
},
|
|
16178
|
+
"mm/h": {
|
|
16179
|
+
dimension: "precipitation-rate",
|
|
16180
|
+
factor: 1,
|
|
16181
|
+
offset: 0
|
|
16182
|
+
},
|
|
16183
|
+
"in/h": {
|
|
16184
|
+
dimension: "precipitation-rate",
|
|
16185
|
+
factor: 25.4,
|
|
16186
|
+
offset: 0
|
|
16187
|
+
},
|
|
16188
|
+
m: {
|
|
16189
|
+
dimension: "length",
|
|
16190
|
+
factor: 1,
|
|
16191
|
+
offset: 0
|
|
16192
|
+
},
|
|
16193
|
+
mm: {
|
|
16194
|
+
dimension: "length",
|
|
16195
|
+
factor: .001,
|
|
16196
|
+
offset: 0
|
|
16197
|
+
},
|
|
16198
|
+
cm: {
|
|
16199
|
+
dimension: "length",
|
|
16200
|
+
factor: .01,
|
|
16201
|
+
offset: 0
|
|
16202
|
+
},
|
|
16203
|
+
km: {
|
|
16204
|
+
dimension: "length",
|
|
16205
|
+
factor: 1e3,
|
|
16206
|
+
offset: 0
|
|
16207
|
+
},
|
|
16208
|
+
in: {
|
|
16209
|
+
dimension: "length",
|
|
16210
|
+
factor: .0254,
|
|
16211
|
+
offset: 0
|
|
16212
|
+
},
|
|
16213
|
+
ft: {
|
|
16214
|
+
dimension: "length",
|
|
16215
|
+
factor: .3048,
|
|
16216
|
+
offset: 0
|
|
16217
|
+
},
|
|
16218
|
+
mi: {
|
|
16219
|
+
dimension: "length",
|
|
16220
|
+
factor: 1609.344,
|
|
16221
|
+
offset: 0
|
|
16222
|
+
},
|
|
16223
|
+
"m²": {
|
|
16224
|
+
dimension: "area",
|
|
16225
|
+
factor: 1,
|
|
16226
|
+
offset: 0
|
|
16227
|
+
},
|
|
16228
|
+
lx: {
|
|
16229
|
+
dimension: "illuminance",
|
|
16230
|
+
factor: 1,
|
|
16231
|
+
offset: 0
|
|
16232
|
+
},
|
|
16233
|
+
"W/m²": {
|
|
16234
|
+
dimension: "irradiance",
|
|
16235
|
+
factor: 1,
|
|
16236
|
+
offset: 0
|
|
16237
|
+
},
|
|
16238
|
+
W: {
|
|
16239
|
+
dimension: "power",
|
|
16240
|
+
factor: 1,
|
|
16241
|
+
offset: 0
|
|
16242
|
+
},
|
|
16243
|
+
kW: {
|
|
16244
|
+
dimension: "power",
|
|
16245
|
+
factor: 1e3,
|
|
16246
|
+
offset: 0
|
|
16247
|
+
},
|
|
16248
|
+
VA: {
|
|
16249
|
+
dimension: "apparent-power",
|
|
16250
|
+
factor: 1,
|
|
16251
|
+
offset: 0
|
|
16252
|
+
},
|
|
16253
|
+
Wh: {
|
|
16254
|
+
dimension: "energy",
|
|
16255
|
+
factor: 1,
|
|
16256
|
+
offset: 0
|
|
16257
|
+
},
|
|
16258
|
+
kWh: {
|
|
16259
|
+
dimension: "energy",
|
|
16260
|
+
factor: 1e3,
|
|
16261
|
+
offset: 0
|
|
16262
|
+
},
|
|
16263
|
+
MWh: {
|
|
16264
|
+
dimension: "energy",
|
|
16265
|
+
factor: 1e6,
|
|
16266
|
+
offset: 0
|
|
16267
|
+
},
|
|
16268
|
+
V: {
|
|
16269
|
+
dimension: "voltage",
|
|
16270
|
+
factor: 1,
|
|
16271
|
+
offset: 0
|
|
16272
|
+
},
|
|
16273
|
+
mV: {
|
|
16274
|
+
dimension: "voltage",
|
|
16275
|
+
factor: .001,
|
|
16276
|
+
offset: 0
|
|
16277
|
+
},
|
|
16278
|
+
A: {
|
|
16279
|
+
dimension: "current",
|
|
16280
|
+
factor: 1,
|
|
16281
|
+
offset: 0
|
|
16282
|
+
},
|
|
16283
|
+
mA: {
|
|
16284
|
+
dimension: "current",
|
|
16285
|
+
factor: .001,
|
|
16286
|
+
offset: 0
|
|
16287
|
+
},
|
|
16288
|
+
ppm: {
|
|
16289
|
+
dimension: "concentration-volume",
|
|
16290
|
+
factor: 1,
|
|
16291
|
+
offset: 0
|
|
16292
|
+
},
|
|
16293
|
+
ppb: {
|
|
16294
|
+
dimension: "concentration-volume",
|
|
16295
|
+
factor: .001,
|
|
16296
|
+
offset: 0
|
|
16297
|
+
},
|
|
16298
|
+
"µg/m³": {
|
|
16299
|
+
dimension: "concentration-mass",
|
|
16300
|
+
factor: 1,
|
|
16301
|
+
offset: 0
|
|
16302
|
+
},
|
|
16303
|
+
"mg/m³": {
|
|
16304
|
+
dimension: "concentration-mass",
|
|
16305
|
+
factor: 1e3,
|
|
16306
|
+
offset: 0
|
|
16307
|
+
},
|
|
16308
|
+
kg: {
|
|
16309
|
+
dimension: "mass",
|
|
16310
|
+
factor: 1,
|
|
16311
|
+
offset: 0
|
|
16312
|
+
},
|
|
16313
|
+
g: {
|
|
16314
|
+
dimension: "mass",
|
|
16315
|
+
factor: .001,
|
|
16316
|
+
offset: 0
|
|
16317
|
+
},
|
|
16318
|
+
lb: {
|
|
16319
|
+
dimension: "mass",
|
|
16320
|
+
factor: .453592,
|
|
16321
|
+
offset: 0
|
|
16322
|
+
},
|
|
16323
|
+
oz: {
|
|
16324
|
+
dimension: "mass",
|
|
16325
|
+
factor: .0283495,
|
|
16326
|
+
offset: 0
|
|
16327
|
+
},
|
|
16328
|
+
"%": {
|
|
16329
|
+
dimension: "percentage",
|
|
16330
|
+
factor: 1,
|
|
16331
|
+
offset: 0
|
|
16332
|
+
},
|
|
16333
|
+
L: {
|
|
16334
|
+
dimension: "volume",
|
|
16335
|
+
factor: 1,
|
|
16336
|
+
offset: 0
|
|
16337
|
+
},
|
|
16338
|
+
mL: {
|
|
16339
|
+
dimension: "volume",
|
|
16340
|
+
factor: .001,
|
|
16341
|
+
offset: 0
|
|
16342
|
+
},
|
|
16343
|
+
gal: {
|
|
16344
|
+
dimension: "volume",
|
|
16345
|
+
factor: 3.785411784,
|
|
16346
|
+
offset: 0
|
|
16347
|
+
},
|
|
16348
|
+
s: {
|
|
16349
|
+
dimension: "duration",
|
|
16350
|
+
factor: 1,
|
|
16351
|
+
offset: 0
|
|
16352
|
+
},
|
|
16353
|
+
ms: {
|
|
16354
|
+
dimension: "duration",
|
|
16355
|
+
factor: .001,
|
|
16356
|
+
offset: 0
|
|
16357
|
+
},
|
|
16358
|
+
min: {
|
|
16359
|
+
dimension: "duration",
|
|
16360
|
+
factor: 60,
|
|
16361
|
+
offset: 0
|
|
16362
|
+
},
|
|
16363
|
+
h: {
|
|
16364
|
+
dimension: "duration",
|
|
16365
|
+
factor: 3600,
|
|
16366
|
+
offset: 0
|
|
16367
|
+
},
|
|
16368
|
+
d: {
|
|
16369
|
+
dimension: "duration",
|
|
16370
|
+
factor: 86400,
|
|
16371
|
+
offset: 0
|
|
16372
|
+
},
|
|
16373
|
+
B: {
|
|
16374
|
+
dimension: "information",
|
|
16375
|
+
factor: 1,
|
|
16376
|
+
offset: 0
|
|
16377
|
+
},
|
|
16378
|
+
KiB: {
|
|
16379
|
+
dimension: "information",
|
|
16380
|
+
factor: 1024,
|
|
16381
|
+
offset: 0
|
|
16382
|
+
},
|
|
16383
|
+
MiB: {
|
|
16384
|
+
dimension: "information",
|
|
16385
|
+
factor: 1024 ** 2,
|
|
16386
|
+
offset: 0
|
|
16387
|
+
},
|
|
16388
|
+
GiB: {
|
|
16389
|
+
dimension: "information",
|
|
16390
|
+
factor: 1024 ** 3,
|
|
16391
|
+
offset: 0
|
|
16392
|
+
},
|
|
16393
|
+
TiB: {
|
|
16394
|
+
dimension: "information",
|
|
16395
|
+
factor: 1024 ** 4,
|
|
16396
|
+
offset: 0
|
|
16397
|
+
},
|
|
16398
|
+
kB: {
|
|
16399
|
+
dimension: "information",
|
|
16400
|
+
factor: 1e3,
|
|
16401
|
+
offset: 0
|
|
16402
|
+
},
|
|
16403
|
+
MB: {
|
|
16404
|
+
dimension: "information",
|
|
16405
|
+
factor: 1e6,
|
|
16406
|
+
offset: 0
|
|
16407
|
+
},
|
|
16408
|
+
GB: {
|
|
16409
|
+
dimension: "information",
|
|
16410
|
+
factor: 1e9,
|
|
16411
|
+
offset: 0
|
|
16412
|
+
},
|
|
16413
|
+
"°": {
|
|
16414
|
+
dimension: "angle",
|
|
16415
|
+
factor: 1,
|
|
16416
|
+
offset: 0
|
|
16417
|
+
},
|
|
16418
|
+
dBFS: {
|
|
16419
|
+
dimension: "sound-level",
|
|
16420
|
+
factor: 1,
|
|
16421
|
+
offset: 0
|
|
16422
|
+
},
|
|
16423
|
+
dBm: {
|
|
16424
|
+
dimension: "signal-level",
|
|
16425
|
+
factor: 1,
|
|
16426
|
+
offset: 0
|
|
16427
|
+
},
|
|
16428
|
+
mired: {
|
|
16429
|
+
dimension: "colour-temperature",
|
|
16430
|
+
factor: 1,
|
|
16431
|
+
offset: 0
|
|
16432
|
+
},
|
|
16433
|
+
kbps: {
|
|
16434
|
+
dimension: "bitrate",
|
|
16435
|
+
factor: 1,
|
|
16436
|
+
offset: 0
|
|
16437
|
+
},
|
|
16438
|
+
Mbps: {
|
|
16439
|
+
dimension: "bitrate",
|
|
16440
|
+
factor: 1e3,
|
|
16441
|
+
offset: 0
|
|
16442
|
+
},
|
|
16443
|
+
fps: {
|
|
16444
|
+
dimension: "rate",
|
|
16445
|
+
factor: 1,
|
|
16446
|
+
offset: 0
|
|
16447
|
+
}
|
|
16448
|
+
};
|
|
16449
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
16450
|
+
function specFor(unit) {
|
|
16451
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
16452
|
+
}
|
|
16453
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
16454
|
+
function toCanonical(value, spec) {
|
|
16455
|
+
return value * spec.factor + spec.offset;
|
|
16456
|
+
}
|
|
16457
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
16458
|
+
function fromCanonical(canonical, spec) {
|
|
16459
|
+
return (canonical - spec.offset) / spec.factor;
|
|
16460
|
+
}
|
|
16461
|
+
/**
|
|
16462
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
16463
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
16464
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
16465
|
+
*/
|
|
16466
|
+
function tryConvertUnit(value, from, to) {
|
|
16467
|
+
if (from === to) return value;
|
|
16468
|
+
const fromSpec = specFor(from);
|
|
16469
|
+
if (!fromSpec) return void 0;
|
|
16470
|
+
const toSpec = specFor(to);
|
|
16471
|
+
if (!toSpec) return void 0;
|
|
16472
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
16473
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
16474
|
+
}
|
|
16475
|
+
/**
|
|
16476
|
+
* A number a person types for a physical quantity — the input side of the
|
|
16477
|
+
* value + unit contract (D972).
|
|
16478
|
+
*
|
|
16479
|
+
* Readings are stored in the base unit of their quantity (D944); a cap method
|
|
16480
|
+
* param is stored in the unit its input schema DECLARES (`paramMeta`). The
|
|
16481
|
+
* wire pair {@link QuantityValue} says "this number is expressed in this
|
|
16482
|
+
* unit"; {@link convertQuantityInput} brings it to the stored unit and refuses,
|
|
16483
|
+
* with a typed {@link QuantityUnitError}, a unit that cannot be that quantity.
|
|
16484
|
+
*/
|
|
16485
|
+
/** A unit that cannot be applied to the number it was given with. */
|
|
16486
|
+
var QuantityUnitError = class extends Error {
|
|
16487
|
+
code;
|
|
16488
|
+
constructor(code, message) {
|
|
16489
|
+
super(`[${code}] ${message}`);
|
|
16490
|
+
this.name = "QuantityUnitError";
|
|
16491
|
+
this.code = code;
|
|
16492
|
+
}
|
|
16493
|
+
};
|
|
16494
|
+
/** The wire pair: `value` is expressed in `unit`. */
|
|
16495
|
+
var QuantityValueSchema = object({
|
|
16496
|
+
value: number(),
|
|
16497
|
+
unit: string().min(1)
|
|
16498
|
+
});
|
|
16499
|
+
/**
|
|
16500
|
+
* Zod `.meta()` bag for a cap METHOD param that is a physical quantity — the
|
|
16501
|
+
* input-side twin of `readingMeta`. The value is carried in `unit` (a gram
|
|
16502
|
+
* portion stays in grams); the unit must belong to the quantity, checked once
|
|
16503
|
+
* when the cap is declared.
|
|
16504
|
+
*/
|
|
16505
|
+
function paramMeta(declared) {
|
|
16506
|
+
const base = baseUnitOf(declared.quantity);
|
|
16507
|
+
if (base === void 0) throw new QuantityUnitError("unknown-unit", `quantity "${declared.quantity}" has no unit`);
|
|
16508
|
+
if (tryConvertUnit(1, declared.unit, base) === void 0) throw new QuantityUnitError("cross-dimension", `"${declared.unit}" is not a unit of ${declared.quantity}`);
|
|
16509
|
+
return {
|
|
16510
|
+
quantity: declared.quantity,
|
|
16511
|
+
unit: declared.unit
|
|
16512
|
+
};
|
|
16513
|
+
}
|
|
16514
|
+
object({
|
|
16515
|
+
quantity: ReadingQuantitySchema,
|
|
16516
|
+
unit: string().min(1)
|
|
16517
|
+
});
|
|
16045
16518
|
/** How a leaf compares a device field to a value. Derived from the field's
|
|
16046
16519
|
* `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
|
|
16047
16520
|
var AutomationConditionOperatorSchema = _enum([
|
|
@@ -16064,8 +16537,10 @@ var AutomationConditionLeafSchema = object({
|
|
|
16064
16537
|
string(),
|
|
16065
16538
|
number(),
|
|
16066
16539
|
boolean(),
|
|
16067
|
-
array(union([string(), number()]))
|
|
16068
|
-
|
|
16540
|
+
array(union([string(), number()])),
|
|
16541
|
+
QuantityValueSchema
|
|
16542
|
+
]),
|
|
16543
|
+
unit: string().min(1).optional()
|
|
16069
16544
|
});
|
|
16070
16545
|
var AutomationConditionStationaryPresentSchema = object({
|
|
16071
16546
|
kind: literal("stationary-present"),
|
|
@@ -16218,7 +16693,13 @@ var AutomationCapStepSchema = object({
|
|
|
16218
16693
|
/** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
|
|
16219
16694
|
* SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
|
|
16220
16695
|
* the expression leaf. */
|
|
16221
|
-
args: record(string(), unknown()).optional()
|
|
16696
|
+
args: record(string(), unknown()).optional(),
|
|
16697
|
+
/**
|
|
16698
|
+
* The unit the person picked per arg (display only). `args` always hold the
|
|
16699
|
+
* value in the unit the method's input DECLARES (`paramMeta`); on a write an
|
|
16700
|
+
* arg may be a {@link QuantityValue}, which the save boundary converts.
|
|
16701
|
+
*/
|
|
16702
|
+
argUnits: record(string(), string().min(1)).optional()
|
|
16222
16703
|
});
|
|
16223
16704
|
/**
|
|
16224
16705
|
* The steps an internal Action may contain: cap and wait, and nothing that can
|
|
@@ -16598,6 +17079,16 @@ object({
|
|
|
16598
17079
|
lastRunAt: number().nullable(),
|
|
16599
17080
|
lastError: string().nullable()
|
|
16600
17081
|
});
|
|
17082
|
+
/** A bare number accepted as a base unit — the save succeeded, say so. */
|
|
17083
|
+
var UnitWarningSchema = object({
|
|
17084
|
+
/** Where in the saved record, e.g. `conditions.children.0` or `steps.2.args.grams`. */
|
|
17085
|
+
path: string(),
|
|
17086
|
+
deviceId: number().int().optional(),
|
|
17087
|
+
field: string(),
|
|
17088
|
+
value: number(),
|
|
17089
|
+
assumedUnit: string(),
|
|
17090
|
+
message: string()
|
|
17091
|
+
});
|
|
16601
17092
|
/**
|
|
16602
17093
|
* notification-output — canonical, capability-gated notification delivery.
|
|
16603
17094
|
*
|
|
@@ -21970,56 +22461,6 @@ var DeviceAdminLinkSchema = object({
|
|
|
21970
22461
|
});
|
|
21971
22462
|
method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema.nullable(), { auth: "admin" });
|
|
21972
22463
|
/**
|
|
21973
|
-
* Identity envelope for a device's upstream-system metadata.
|
|
21974
|
-
*
|
|
21975
|
-
* Two jobs:
|
|
21976
|
-
*
|
|
21977
|
-
* 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
|
|
21978
|
-
* uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
|
|
21979
|
-
* WS-Discovery endpoint UUID, …). Provider code keeps a
|
|
21980
|
-
* `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
|
|
21981
|
-
* without round-tripping through `stableId` / `id` mappings.
|
|
21982
|
-
*
|
|
21983
|
-
* 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
|
|
21984
|
-
* one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
|
|
21985
|
-
* for vendors where MAC is the natural key). For systems where the
|
|
21986
|
-
* live dispatch key can be renamed (HA `entity_id` can be edited),
|
|
21987
|
-
* providers detect renames by matching `uniqueId` and patch `id`
|
|
21988
|
-
* in-place so dispatch keeps working.
|
|
21989
|
-
*
|
|
21990
|
-
* **Display unit and precision are NOT stored here.** They are a read-time
|
|
21991
|
-
* preference (D944). A polymorphic reading stores its `quantity` here once,
|
|
21992
|
-
* at adopt, and a date/time value stores `dateTimeShape` the same way —
|
|
21993
|
-
* neither is repeated on each sample. The `device_class` tag is an
|
|
21994
|
-
* HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
|
|
21995
|
-
* to derive the CamStack `DeviceRole`; it is never stored after that point.
|
|
21996
|
-
*
|
|
21997
|
-
* The `raw` escape hatch carries provider-specific attributes that don't
|
|
21998
|
-
* fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
|
|
21999
|
-
* details, …). Providers control what lands here.
|
|
22000
|
-
*/
|
|
22001
|
-
var SourceInfoSchema = object({
|
|
22002
|
-
/** Live dispatch key — mutable when the source system allows rename. */
|
|
22003
|
-
id: string(),
|
|
22004
|
-
/** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
|
|
22005
|
-
system: string(),
|
|
22006
|
-
/** Immutable upstream identifier when available (HA `unique_id`, … ).
|
|
22007
|
-
* Used to detect rename when `id` changes. */
|
|
22008
|
-
uniqueId: string().optional(),
|
|
22009
|
-
/** Quantity of a polymorphic reading, written once at adopt (D944). */
|
|
22010
|
-
quantity: ReadingQuantitySchema.optional(),
|
|
22011
|
-
/** Date / time / datetime shape of a string reading, written once at adopt. */
|
|
22012
|
-
dateTimeShape: _enum([
|
|
22013
|
-
"date",
|
|
22014
|
-
"time",
|
|
22015
|
-
"datetime"
|
|
22016
|
-
]).optional(),
|
|
22017
|
-
/** Provider-specific extras that don't fit the structured slots.
|
|
22018
|
-
* Whitelist what goes here per provider — do NOT dump entire HA
|
|
22019
|
-
* attribute blobs (would explode the meta JSON column). */
|
|
22020
|
-
raw: record(string(), unknown()).optional()
|
|
22021
|
-
});
|
|
22022
|
-
/**
|
|
22023
22464
|
* device-discovery — device-scoped capability for parents that host /
|
|
22024
22465
|
* enumerate child devices (Reolink Hub / NVR, ONVIF gateway, future
|
|
22025
22466
|
* integrations). The parent advertises a list of discoverable children,
|
|
@@ -58032,13 +58473,19 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
|
|
|
58032
58473
|
}), method(ActionIdInput, _void(), {
|
|
58033
58474
|
kind: "mutation",
|
|
58034
58475
|
auth: "admin"
|
|
58035
|
-
}), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({
|
|
58476
|
+
}), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({
|
|
58477
|
+
action: ActionEntrySchema,
|
|
58478
|
+
warnings: array(UnitWarningSchema).optional()
|
|
58479
|
+
}), {
|
|
58036
58480
|
kind: "mutation",
|
|
58037
58481
|
auth: "admin"
|
|
58038
58482
|
}), method(object({
|
|
58039
58483
|
actionId: string().min(1),
|
|
58040
58484
|
action: ActionInputSchema.partial()
|
|
58041
|
-
}), object({
|
|
58485
|
+
}), object({
|
|
58486
|
+
action: ActionEntrySchema,
|
|
58487
|
+
warnings: array(UnitWarningSchema).optional()
|
|
58488
|
+
}), {
|
|
58042
58489
|
kind: "mutation",
|
|
58043
58490
|
auth: "admin"
|
|
58044
58491
|
}), method(ActionIdInput, _void(), {
|
|
@@ -58344,6 +58791,30 @@ object({
|
|
|
58344
58791
|
at: number()
|
|
58345
58792
|
}).nullable()
|
|
58346
58793
|
});
|
|
58794
|
+
var RemoteButtonShapeSchema = _enum([
|
|
58795
|
+
"rect",
|
|
58796
|
+
"rounded",
|
|
58797
|
+
"round",
|
|
58798
|
+
"pill"
|
|
58799
|
+
]);
|
|
58800
|
+
var RemoteButtonToneSchema = _enum([
|
|
58801
|
+
"neutral",
|
|
58802
|
+
"accent",
|
|
58803
|
+
"danger",
|
|
58804
|
+
"red",
|
|
58805
|
+
"green",
|
|
58806
|
+
"yellow",
|
|
58807
|
+
"blue"
|
|
58808
|
+
]);
|
|
58809
|
+
var RemoteGroupFrameSchema = _enum([
|
|
58810
|
+
"none",
|
|
58811
|
+
"panel",
|
|
58812
|
+
"divider",
|
|
58813
|
+
"dpad",
|
|
58814
|
+
"rocker-v",
|
|
58815
|
+
"rocker-h",
|
|
58816
|
+
"keypad"
|
|
58817
|
+
]);
|
|
58347
58818
|
var RemoteLayoutButtonSchema = object({
|
|
58348
58819
|
id: string().min(1).max(40),
|
|
58349
58820
|
/** 0-based grid position. */
|
|
@@ -58353,12 +58824,94 @@ var RemoteLayoutButtonSchema = object({
|
|
|
58353
58824
|
colSpan: number().int().min(1).max(24),
|
|
58354
58825
|
icon: string().min(1).max(60).optional(),
|
|
58355
58826
|
label: string().min(1).max(40).optional(),
|
|
58356
|
-
role: RemoteRoleSchema
|
|
58827
|
+
role: RemoteRoleSchema,
|
|
58828
|
+
/** Absent = the plain rendering every layout had before shapes existed. */
|
|
58829
|
+
shape: RemoteButtonShapeSchema.optional(),
|
|
58830
|
+
tone: RemoteButtonToneSchema.optional(),
|
|
58831
|
+
/** The group this button belongs to; it must lie inside that group's rectangle. */
|
|
58832
|
+
groupId: string().min(1).max(40).optional()
|
|
58833
|
+
});
|
|
58834
|
+
/**
|
|
58835
|
+
* A rectangle of the grid that moves as ONE thing and is drawn with a frame: a
|
|
58836
|
+
* titled panel, a section divider, a D-pad ring. `componentId` names the palette
|
|
58837
|
+
* entry it came from (informational: the layout is self-contained).
|
|
58838
|
+
*/
|
|
58839
|
+
var RemoteLayoutGroupSchema = object({
|
|
58840
|
+
id: string().min(1).max(40),
|
|
58841
|
+
componentId: string().min(1).max(80),
|
|
58842
|
+
frame: RemoteGroupFrameSchema,
|
|
58843
|
+
row: number().int().min(0).max(24),
|
|
58844
|
+
col: number().int().min(0).max(24),
|
|
58845
|
+
rowSpan: number().int().min(1).max(24),
|
|
58846
|
+
colSpan: number().int().min(1).max(24),
|
|
58847
|
+
title: string().min(1).max(40).optional()
|
|
58357
58848
|
});
|
|
58849
|
+
function rectsOverlap(a, b) {
|
|
58850
|
+
return a.row < b.row + b.rowSpan && b.row < a.row + a.rowSpan && a.col < b.col + b.colSpan && b.col < a.col + a.colSpan;
|
|
58851
|
+
}
|
|
58852
|
+
function rectContains(outer, inner) {
|
|
58853
|
+
return inner.row >= outer.row && inner.col >= outer.col && inner.row + inner.rowSpan <= outer.row + outer.rowSpan && inner.col + inner.colSpan <= outer.col + outer.colSpan;
|
|
58854
|
+
}
|
|
58855
|
+
/**
|
|
58856
|
+
* The group rules of a layout: inside the grid, no two groups overlap, a
|
|
58857
|
+
* member lies inside its group, a divider holds nothing, and a button that is
|
|
58858
|
+
* not a member never sits inside someone else's rectangle (a group moves as
|
|
58859
|
+
* one thing, so a stray key under it would be left behind).
|
|
58860
|
+
*/
|
|
58861
|
+
function refineGroups(grid, ctx) {
|
|
58862
|
+
const groups = grid.groups ?? [];
|
|
58863
|
+
const byId = /* @__PURE__ */ new Map();
|
|
58864
|
+
const fail = (message, path) => {
|
|
58865
|
+
ctx.addIssue({
|
|
58866
|
+
code: "custom",
|
|
58867
|
+
message,
|
|
58868
|
+
path
|
|
58869
|
+
});
|
|
58870
|
+
};
|
|
58871
|
+
groups.forEach((group, index) => {
|
|
58872
|
+
if (byId.has(group.id)) fail(`group id "${group.id}" is used twice`, [
|
|
58873
|
+
"groups",
|
|
58874
|
+
index,
|
|
58875
|
+
"id"
|
|
58876
|
+
]);
|
|
58877
|
+
byId.set(group.id, group);
|
|
58878
|
+
if (group.row + group.rowSpan > grid.rows || group.col + group.colSpan > grid.columns) fail(`group "${group.id}" leaves the grid`, ["groups", index]);
|
|
58879
|
+
for (let other = 0; other < index; other += 1) {
|
|
58880
|
+
const earlier = groups[other];
|
|
58881
|
+
if (earlier !== void 0 && rectsOverlap(earlier, group)) {
|
|
58882
|
+
fail(`groups "${earlier.id}" and "${group.id}" overlap`, ["groups", index]);
|
|
58883
|
+
return;
|
|
58884
|
+
}
|
|
58885
|
+
}
|
|
58886
|
+
});
|
|
58887
|
+
grid.buttons.forEach((button, index) => {
|
|
58888
|
+
if (button.groupId !== void 0) {
|
|
58889
|
+
const group = byId.get(button.groupId);
|
|
58890
|
+
if (group === void 0) {
|
|
58891
|
+
fail(`button "${button.id}" names the unknown group "${button.groupId}"`, [
|
|
58892
|
+
"buttons",
|
|
58893
|
+
index,
|
|
58894
|
+
"groupId"
|
|
58895
|
+
]);
|
|
58896
|
+
return;
|
|
58897
|
+
}
|
|
58898
|
+
if (group.frame === "divider") fail(`a divider group ("${group.id}") holds no buttons`, [
|
|
58899
|
+
"buttons",
|
|
58900
|
+
index,
|
|
58901
|
+
"groupId"
|
|
58902
|
+
]);
|
|
58903
|
+
if (!rectContains(group, button)) fail(`button "${button.id}" lies outside its group "${group.id}"`, ["buttons", index]);
|
|
58904
|
+
return;
|
|
58905
|
+
}
|
|
58906
|
+
const foreign = groups.find((group) => rectsOverlap(group, button));
|
|
58907
|
+
if (foreign !== void 0) fail(`button "${button.id}" lies inside group "${foreign.id}" but is not a member`, ["buttons", index]);
|
|
58908
|
+
});
|
|
58909
|
+
}
|
|
58358
58910
|
object({
|
|
58359
58911
|
columns: number().int().min(1).max(24),
|
|
58360
58912
|
rows: number().int().min(1).max(24),
|
|
58361
|
-
buttons: array(RemoteLayoutButtonSchema).max(200)
|
|
58913
|
+
buttons: array(RemoteLayoutButtonSchema).max(200),
|
|
58914
|
+
groups: array(RemoteLayoutGroupSchema).max(50).optional()
|
|
58362
58915
|
}).superRefine((grid, ctx) => {
|
|
58363
58916
|
const ids = /* @__PURE__ */ new Set();
|
|
58364
58917
|
const taken = /* @__PURE__ */ new Map();
|
|
@@ -58395,6 +58948,7 @@ object({
|
|
|
58395
58948
|
taken.set(cell, button.id);
|
|
58396
58949
|
}
|
|
58397
58950
|
});
|
|
58951
|
+
refineGroups(grid, ctx);
|
|
58398
58952
|
});
|
|
58399
58953
|
var RemoteBoundCommandSchema = object({
|
|
58400
58954
|
role: RemoteRoleSchema,
|
|
@@ -58526,6 +59080,91 @@ method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSche
|
|
|
58526
59080
|
kind: "mutation",
|
|
58527
59081
|
auth: "admin"
|
|
58528
59082
|
});
|
|
59083
|
+
var RemoteComponentCategorySchema = _enum([
|
|
59084
|
+
"power",
|
|
59085
|
+
"navigation",
|
|
59086
|
+
"volume",
|
|
59087
|
+
"numbers",
|
|
59088
|
+
"media",
|
|
59089
|
+
"colour",
|
|
59090
|
+
"apps",
|
|
59091
|
+
"layout"
|
|
59092
|
+
]);
|
|
59093
|
+
/** `<namespace>:<name>`, both lowercase slugs — `core:dpad`, `<addonId>:<name>`. */
|
|
59094
|
+
var COMPONENT_ID_RE = /^[a-z0-9][a-z0-9_.-]*:[a-z0-9][a-z0-9_-]*$/;
|
|
59095
|
+
var RemoteComponentButtonSchema = object({
|
|
59096
|
+
/** Joined to the instance id when the component is inserted. */
|
|
59097
|
+
idSuffix: string().regex(/^[a-z0-9][a-z0-9_-]{0,19}$/, { message: "a short lowercase slug" }),
|
|
59098
|
+
row: number().int().min(0).max(24),
|
|
59099
|
+
col: number().int().min(0).max(24),
|
|
59100
|
+
rowSpan: number().int().min(1).max(24),
|
|
59101
|
+
colSpan: number().int().min(1).max(24),
|
|
59102
|
+
role: RemoteRoleSchema,
|
|
59103
|
+
icon: string().min(1).max(60).optional(),
|
|
59104
|
+
label: string().min(1).max(40).optional(),
|
|
59105
|
+
shape: RemoteButtonShapeSchema.optional(),
|
|
59106
|
+
tone: RemoteButtonToneSchema.optional()
|
|
59107
|
+
});
|
|
59108
|
+
var RemoteLayoutComponentSchema = object({
|
|
59109
|
+
id: string().max(80).regex(COMPONENT_ID_RE, { message: "<namespace>:<name>, lowercase" }),
|
|
59110
|
+
name: string().min(1).max(60),
|
|
59111
|
+
nameI18n: object({
|
|
59112
|
+
en: string().min(1).max(60),
|
|
59113
|
+
it: string().min(1).max(60)
|
|
59114
|
+
}).optional(),
|
|
59115
|
+
/** A display icon key, resolved by the UI like a button icon. */
|
|
59116
|
+
icon: string().min(1).max(60),
|
|
59117
|
+
category: RemoteComponentCategorySchema,
|
|
59118
|
+
size: object({
|
|
59119
|
+
rows: number().int().min(1).max(24),
|
|
59120
|
+
cols: number().int().min(1).max(24)
|
|
59121
|
+
}),
|
|
59122
|
+
/** The frame drawn around the whole component, or null for loose buttons. */
|
|
59123
|
+
group: object({
|
|
59124
|
+
frame: RemoteGroupFrameSchema,
|
|
59125
|
+
title: string().min(1).max(40).optional()
|
|
59126
|
+
}).nullable(),
|
|
59127
|
+
buttons: array(RemoteComponentButtonSchema).max(40)
|
|
59128
|
+
}).superRefine((component, ctx) => {
|
|
59129
|
+
const suffixes = /* @__PURE__ */ new Set();
|
|
59130
|
+
component.buttons.forEach((button, index) => {
|
|
59131
|
+
if (suffixes.has(button.idSuffix)) ctx.addIssue({
|
|
59132
|
+
code: "custom",
|
|
59133
|
+
message: `button "${button.idSuffix}" is listed twice`,
|
|
59134
|
+
path: [
|
|
59135
|
+
"buttons",
|
|
59136
|
+
index,
|
|
59137
|
+
"idSuffix"
|
|
59138
|
+
]
|
|
59139
|
+
});
|
|
59140
|
+
suffixes.add(button.idSuffix);
|
|
59141
|
+
if (button.row + button.rowSpan > component.size.rows || button.col + button.colSpan > component.size.cols) {
|
|
59142
|
+
ctx.addIssue({
|
|
59143
|
+
code: "custom",
|
|
59144
|
+
message: `button "${button.idSuffix}" leaves the component`,
|
|
59145
|
+
path: ["buttons", index]
|
|
59146
|
+
});
|
|
59147
|
+
return;
|
|
59148
|
+
}
|
|
59149
|
+
for (let other = 0; other < index; other += 1) {
|
|
59150
|
+
const earlier = component.buttons[other];
|
|
59151
|
+
if (earlier !== void 0 && rectsOverlap(earlier, button)) {
|
|
59152
|
+
ctx.addIssue({
|
|
59153
|
+
code: "custom",
|
|
59154
|
+
message: `buttons "${earlier.idSuffix}" and "${button.idSuffix}" overlap`,
|
|
59155
|
+
path: ["buttons", index]
|
|
59156
|
+
});
|
|
59157
|
+
return;
|
|
59158
|
+
}
|
|
59159
|
+
}
|
|
59160
|
+
});
|
|
59161
|
+
if (component.group?.frame === "divider" && component.buttons.length > 0) ctx.addIssue({
|
|
59162
|
+
code: "custom",
|
|
59163
|
+
message: "a divider component holds no buttons",
|
|
59164
|
+
path: ["buttons"]
|
|
59165
|
+
});
|
|
59166
|
+
});
|
|
59167
|
+
method(object({}), array(RemoteLayoutComponentSchema), { auth: "protected" });
|
|
58529
59168
|
DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
|
|
58530
59169
|
kind: "mutation",
|
|
58531
59170
|
auth: "protected"
|
|
@@ -62685,6 +63324,14 @@ var PetFeederDeviceStatusSchema = _enum([
|
|
|
62685
63324
|
"on_batteries"
|
|
62686
63325
|
]);
|
|
62687
63326
|
var gramsPortion = number().int().min(4).max(200);
|
|
63327
|
+
/** A portion REQUESTED of the feeder is a mass the method takes in GRAMS (the
|
|
63328
|
+
* hardware's own unit). The bounds are grams; a caller entering another unit
|
|
63329
|
+
* converts to grams first (`paramMeta`, D972). The STATUS fields above stay
|
|
63330
|
+
* plain grams — they are not readings in the kilogram base. */
|
|
63331
|
+
var gramsParam = gramsPortion.meta(paramMeta({
|
|
63332
|
+
quantity: "mass",
|
|
63333
|
+
unit: "g"
|
|
63334
|
+
}));
|
|
62688
63335
|
object({
|
|
62689
63336
|
/** Food in the TANK (hopper), as the feeder's own sensor reports it
|
|
62690
63337
|
* (`state.food`). A coarse level code, not grams — `0` is empty. The
|
|
@@ -62759,9 +63406,9 @@ object({
|
|
|
62759
63406
|
});
|
|
62760
63407
|
DeviceType.PetFeeder, method(object({
|
|
62761
63408
|
deviceId: number().int().nonnegative(),
|
|
62762
|
-
grams:
|
|
62763
|
-
hopper1:
|
|
62764
|
-
hopper2:
|
|
63409
|
+
grams: gramsParam.optional(),
|
|
63410
|
+
hopper1: gramsParam.optional(),
|
|
63411
|
+
hopper2: gramsParam.optional()
|
|
62765
63412
|
}), _void(), {
|
|
62766
63413
|
kind: "mutation",
|
|
62767
63414
|
auth: "protected"
|
|
@@ -67453,6 +68100,87 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
|
|
|
67453
68100
|
kind: "mutation",
|
|
67454
68101
|
auth: "admin"
|
|
67455
68102
|
});
|
|
68103
|
+
var btn = (idSuffix, row, col, init) => ({
|
|
68104
|
+
idSuffix,
|
|
68105
|
+
row,
|
|
68106
|
+
col,
|
|
68107
|
+
rowSpan: 1,
|
|
68108
|
+
colSpan: 1,
|
|
68109
|
+
...init
|
|
68110
|
+
});
|
|
68111
|
+
function rocker(id, name, it, frame, title, buttons, size) {
|
|
68112
|
+
return {
|
|
68113
|
+
id,
|
|
68114
|
+
name,
|
|
68115
|
+
nameI18n: {
|
|
68116
|
+
en: name,
|
|
68117
|
+
it
|
|
68118
|
+
},
|
|
68119
|
+
icon: frame === "rocker-v" ? "chevrons-up-down" : "chevrons-left-right",
|
|
68120
|
+
category: id.includes("channel") || id.includes("volume") ? "volume" : "navigation",
|
|
68121
|
+
size,
|
|
68122
|
+
group: title === null ? { frame } : {
|
|
68123
|
+
frame,
|
|
68124
|
+
title
|
|
68125
|
+
},
|
|
68126
|
+
buttons
|
|
68127
|
+
};
|
|
68128
|
+
}
|
|
68129
|
+
btn("power", 0, 0, {
|
|
68130
|
+
role: "power",
|
|
68131
|
+
shape: "round",
|
|
68132
|
+
tone: "danger"
|
|
68133
|
+
}), btn("up", 0, 1, { role: "up" }), btn("left", 1, 0, { role: "left" }), btn("ok", 1, 1, {
|
|
68134
|
+
role: "ok",
|
|
68135
|
+
shape: "round",
|
|
68136
|
+
tone: "accent"
|
|
68137
|
+
}), btn("right", 1, 2, { role: "right" }), btn("down", 2, 1, { role: "down" }), rocker("core:rocker-volume-v", "Volume rocker", "Bilanciere volume", "rocker-v", "VOL", [btn("up", 0, 0, {
|
|
68138
|
+
role: "volume_up",
|
|
68139
|
+
shape: "pill"
|
|
68140
|
+
}), btn("down", 1, 0, {
|
|
68141
|
+
role: "volume_down",
|
|
68142
|
+
shape: "pill"
|
|
68143
|
+
})], {
|
|
68144
|
+
rows: 2,
|
|
68145
|
+
cols: 1
|
|
68146
|
+
}), rocker("core:rocker-channel-v", "Channel rocker", "Bilanciere canali", "rocker-v", "CH", [btn("up", 0, 0, {
|
|
68147
|
+
role: "channel_up",
|
|
68148
|
+
shape: "pill"
|
|
68149
|
+
}), btn("down", 1, 0, {
|
|
68150
|
+
role: "channel_down",
|
|
68151
|
+
shape: "pill"
|
|
68152
|
+
})], {
|
|
68153
|
+
rows: 2,
|
|
68154
|
+
cols: 1
|
|
68155
|
+
}), rocker("core:rocker-h", "Minus / plus rocker", "Bilanciere meno / più", "rocker-h", null, [btn("minus", 0, 0, {
|
|
68156
|
+
role: "custom:minus",
|
|
68157
|
+
label: "−",
|
|
68158
|
+
shape: "pill"
|
|
68159
|
+
}), btn("plus", 0, 1, {
|
|
68160
|
+
role: "custom:plus",
|
|
68161
|
+
label: "+",
|
|
68162
|
+
shape: "pill"
|
|
68163
|
+
})], {
|
|
68164
|
+
rows: 1,
|
|
68165
|
+
cols: 2
|
|
68166
|
+
}), [...Array.from({ length: 9 }, (_, i) => btn(`d${i + 1}`, Math.floor(i / 3), i % 3, { role: `digit_${i + 1}` })), btn("d0", 3, 1, { role: "digit_0" })], btn("red", 0, 0, {
|
|
68167
|
+
role: "custom:color_red",
|
|
68168
|
+
tone: "red"
|
|
68169
|
+
}), btn("green", 0, 1, {
|
|
68170
|
+
role: "custom:color_green",
|
|
68171
|
+
tone: "green"
|
|
68172
|
+
}), btn("yellow", 0, 2, {
|
|
68173
|
+
role: "custom:color_yellow",
|
|
68174
|
+
tone: "yellow"
|
|
68175
|
+
}), btn("blue", 0, 3, {
|
|
68176
|
+
role: "custom:color_blue",
|
|
68177
|
+
tone: "blue"
|
|
68178
|
+
}), btn("rewind", 0, 0, { role: "rewind" }), btn("play", 0, 1, { role: "play" }), btn("pause", 0, 2, { role: "pause" }), btn("forward", 0, 3, { role: "fast_forward" }), btn("stop", 0, 4, { role: "stop" }), [
|
|
68179
|
+
1,
|
|
68180
|
+
2,
|
|
68181
|
+
3,
|
|
68182
|
+
4
|
|
68183
|
+
].map((n) => btn(`app${n}`, 0, n - 1, { role: `custom:app_slot_${n}` })), btn("back", 0, 0, { role: "back" }), btn("home", 0, 1, { role: "home" }), btn("menu", 0, 2, { role: "menu" });
|
|
67456
68184
|
discriminatedUnion("kind", [object({
|
|
67457
68185
|
kind: literal("raw"),
|
|
67458
68186
|
timings: array(number().int()),
|
|
@@ -75415,6 +76143,13 @@ Object.freeze({
|
|
|
75415
76143
|
access: "create",
|
|
75416
76144
|
role: "admin"
|
|
75417
76145
|
},
|
|
76146
|
+
"remoteLayoutComponents.listComponents": {
|
|
76147
|
+
capName: "remote-layout-components",
|
|
76148
|
+
capScope: "system",
|
|
76149
|
+
addonId: null,
|
|
76150
|
+
access: "view",
|
|
76151
|
+
role: "admin"
|
|
76152
|
+
},
|
|
75418
76153
|
"runningState.getStatus": {
|
|
75419
76154
|
capName: "running-state",
|
|
75420
76155
|
capScope: "device",
|
|
@@ -79458,7 +80193,8 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
79458
80193
|
min: 4,
|
|
79459
80194
|
max: 200,
|
|
79460
80195
|
step: 1,
|
|
79461
|
-
unit: "g"
|
|
80196
|
+
unit: "g",
|
|
80197
|
+
quantity: "mass"
|
|
79462
80198
|
},
|
|
79463
80199
|
optional: true
|
|
79464
80200
|
}]
|
|
@@ -79477,7 +80213,8 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
79477
80213
|
min: 4,
|
|
79478
80214
|
max: 200,
|
|
79479
80215
|
step: 1,
|
|
79480
|
-
unit: "g"
|
|
80216
|
+
unit: "g",
|
|
80217
|
+
quantity: "mass"
|
|
79481
80218
|
},
|
|
79482
80219
|
optional: true
|
|
79483
80220
|
}, {
|
|
@@ -79488,7 +80225,8 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
79488
80225
|
min: 4,
|
|
79489
80226
|
max: 200,
|
|
79490
80227
|
step: 1,
|
|
79491
|
-
unit: "g"
|
|
80228
|
+
unit: "g",
|
|
80229
|
+
quantity: "mass"
|
|
79492
80230
|
},
|
|
79493
80231
|
optional: true
|
|
79494
80232
|
}]
|
|
@@ -81588,6 +82326,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
81588
82326
|
"recording-export": system("recording exports — requested from the timeline, not an automation step"),
|
|
81589
82327
|
records: system(INTERNAL),
|
|
81590
82328
|
remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
|
|
82329
|
+
"remote-layout-components": system("the palette of the remote template editor — read-only data, never actuated"),
|
|
81591
82330
|
"server-management": system(CLUSTER),
|
|
81592
82331
|
"settings-store": system(INTERNAL),
|
|
81593
82332
|
"smtp-provider": system(INTERNAL),
|