@camstack/types 1.2.417 → 1.2.418
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/capabilities/capability-definition.d.ts +5 -0
- package/dist/capabilities/composer.cap.d.ts +198 -0
- package/dist/capabilities/core-blocks.cap.d.ts +1420 -0
- package/dist/capabilities/group-status.cap.d.ts +46 -0
- package/dist/capabilities/index.d.ts +3 -1
- package/dist/capabilities/motion.cap.d.ts +12 -4
- package/dist/client.js +3 -0
- package/dist/client.mjs +3 -0
- package/dist/composition/composition-report.d.ts +72 -0
- package/dist/composition/composition.d.ts +285 -5
- package/dist/composition/helpers/aggregate.d.ts +41 -0
- package/dist/composition/helpers/catalog.d.ts +42 -0
- package/dist/composition/helpers/compile.d.ts +22 -0
- package/dist/composition/helpers/index.d.ts +6 -0
- package/dist/composition/helpers/save.d.ts +18 -0
- package/dist/composition/helpers/source-pick.d.ts +40 -0
- package/dist/composition/helpers/spec.d.ts +38 -0
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/source-ref.d.ts +11 -0
- package/dist/composition/validate-composition.d.ts +5 -0
- package/dist/{composition-kEl9mevu.mjs → composition-B85l9j1M.mjs} +114 -8
- package/dist/{composition-DsmkwP9-.js → composition-OJKOJJD-.js} +179 -7
- package/dist/device/cap-vocabulary/entries/sensors.d.ts +1 -1
- package/dist/generated/addon-api.d.ts +14 -0
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/cap-status-types.d.ts +3 -1
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/device-local-state.d.ts +3 -0
- package/dist/generated/device-proxy.d.ts +3 -0
- package/dist/generated/history-catalog.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/generated/runtime-state-durability.d.ts +1 -1
- package/dist/index.js +706 -12
- package/dist/index.mjs +686 -13
- package/dist/node.js +1 -1
- package/dist/node.mjs +1 -1
- package/dist/{sleep-gtskVoMw.js → sleep-7Gw3GJ4n.js} +18 -0
- package/dist/{sleep-CARd6wZF.mjs → sleep-B81gwQuR.mjs} +18 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-7Gw3GJ4n.js");
|
|
3
3
|
const require_event_category = require("./event-category-DXZ3f9Q5.js");
|
|
4
|
-
const require_composition = require("./composition-
|
|
4
|
+
const require_composition = require("./composition-OJKOJJD-.js");
|
|
5
5
|
const require_node_color = require("./node-color.js");
|
|
6
6
|
const require_err_msg = require("./err-msg-BhVbr0NX.js");
|
|
7
7
|
const require_enums = require("./enums.js");
|
|
@@ -12624,7 +12624,10 @@ var CompositionProblemCodeSchema = zod.z.enum([
|
|
|
12624
12624
|
"target-missing",
|
|
12625
12625
|
"target-unreadable",
|
|
12626
12626
|
"not-replaceable",
|
|
12627
|
-
"native-capability-replace"
|
|
12627
|
+
"native-capability-replace",
|
|
12628
|
+
"mixed-quantity",
|
|
12629
|
+
"helper-mismatch",
|
|
12630
|
+
"member-constraint"
|
|
12628
12631
|
]);
|
|
12629
12632
|
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
|
|
12630
12633
|
var CompositionProblemSchema = zod.z.object({
|
|
@@ -12648,7 +12651,8 @@ var CompositionUnavailableModeSchema = zod.z.enum([
|
|
|
12648
12651
|
"null",
|
|
12649
12652
|
"offline",
|
|
12650
12653
|
"unknown",
|
|
12651
|
-
"release"
|
|
12654
|
+
"release",
|
|
12655
|
+
"omit"
|
|
12652
12656
|
]);
|
|
12653
12657
|
/**
|
|
12654
12658
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -13019,6 +13023,24 @@ function inferExpressionKinds(input) {
|
|
|
13019
13023
|
* planner (`composition-items.ts`). Internal to the composition module — NOT
|
|
13020
13024
|
* in the barrel: these are planner internals, not a published contract.
|
|
13021
13025
|
*/
|
|
13026
|
+
function aggregateKinds(source) {
|
|
13027
|
+
if (source.publish !== "value") return {
|
|
13028
|
+
ok: true,
|
|
13029
|
+
kinds: new Set(["number"])
|
|
13030
|
+
};
|
|
13031
|
+
if (source.reducer === "any" || source.reducer === "all") return {
|
|
13032
|
+
ok: true,
|
|
13033
|
+
kinds: new Set(["boolean"])
|
|
13034
|
+
};
|
|
13035
|
+
if (source.empty === "null") return {
|
|
13036
|
+
ok: true,
|
|
13037
|
+
kinds: new Set(["number", "null"])
|
|
13038
|
+
};
|
|
13039
|
+
return {
|
|
13040
|
+
ok: true,
|
|
13041
|
+
kinds: new Set(["number"])
|
|
13042
|
+
};
|
|
13043
|
+
}
|
|
13022
13044
|
function readKinds(read, lookupCap) {
|
|
13023
13045
|
const def = lookupCap(read.cap);
|
|
13024
13046
|
const schema = def?.runtimeState ?? def?.status?.schema;
|
|
@@ -13046,6 +13068,7 @@ function sourceKinds(source, lookupCap) {
|
|
|
13046
13068
|
code: "reserved-variant",
|
|
13047
13069
|
message: "code fields arrive in slice 4"
|
|
13048
13070
|
};
|
|
13071
|
+
if (source.kind === "aggregate") return aggregateKinds(source);
|
|
13049
13072
|
const bindingKinds = /* @__PURE__ */ new Map();
|
|
13050
13073
|
for (const [name, binding] of Object.entries(source.bindings)) {
|
|
13051
13074
|
if (binding.kind === "literal") {
|
|
@@ -13242,6 +13265,388 @@ function planItems(def, feature, featureIndex, lookupCap, mode = "new") {
|
|
|
13242
13265
|
};
|
|
13243
13266
|
}
|
|
13244
13267
|
//#endregion
|
|
13268
|
+
//#region src/composition/helpers/catalog.ts
|
|
13269
|
+
/**
|
|
13270
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
13271
|
+
* Data, not a form default written into the block.
|
|
13272
|
+
*/
|
|
13273
|
+
var NOW = {
|
|
13274
|
+
fieldPath: "lastFetchedAt",
|
|
13275
|
+
expr: "now"
|
|
13276
|
+
};
|
|
13277
|
+
var CHANGED = {
|
|
13278
|
+
fieldPath: "lastChangedAt",
|
|
13279
|
+
expr: "now"
|
|
13280
|
+
};
|
|
13281
|
+
function numeric(input) {
|
|
13282
|
+
return {
|
|
13283
|
+
...input,
|
|
13284
|
+
family: "numeric",
|
|
13285
|
+
deviceType: require_err_msg.DeviceType.Sensor,
|
|
13286
|
+
memberDeviceType: require_err_msg.DeviceType.Sensor,
|
|
13287
|
+
baseUnit: require_sleep.baseUnitOf(input.quantity),
|
|
13288
|
+
aggregates: require_composition.NUMERIC_AGGREGATES,
|
|
13289
|
+
accept: [{
|
|
13290
|
+
cap: input.outputCap,
|
|
13291
|
+
fieldPath: input.outputField
|
|
13292
|
+
}]
|
|
13293
|
+
};
|
|
13294
|
+
}
|
|
13295
|
+
function binary(input) {
|
|
13296
|
+
return {
|
|
13297
|
+
...input,
|
|
13298
|
+
family: "binary",
|
|
13299
|
+
deviceType: require_err_msg.DeviceType.Sensor,
|
|
13300
|
+
memberDeviceType: require_err_msg.DeviceType.Sensor,
|
|
13301
|
+
quantity: "none",
|
|
13302
|
+
baseUnit: void 0,
|
|
13303
|
+
aggregates: require_composition.BINARY_AGGREGATES,
|
|
13304
|
+
empty: "offline"
|
|
13305
|
+
};
|
|
13306
|
+
}
|
|
13307
|
+
var GROUP_TEMPLATES = [
|
|
13308
|
+
numeric({
|
|
13309
|
+
id: "temperature",
|
|
13310
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
13311
|
+
role: require_err_msg.DeviceRole.TemperatureSensor,
|
|
13312
|
+
outputCap: "temperature-sensor",
|
|
13313
|
+
outputField: "celsius",
|
|
13314
|
+
quantity: "temperature",
|
|
13315
|
+
defaultAggregate: "mean",
|
|
13316
|
+
empty: "null",
|
|
13317
|
+
companions: [NOW]
|
|
13318
|
+
}),
|
|
13319
|
+
numeric({
|
|
13320
|
+
id: "humidity",
|
|
13321
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
13322
|
+
role: require_err_msg.DeviceRole.HumiditySensor,
|
|
13323
|
+
outputCap: "humidity-sensor",
|
|
13324
|
+
outputField: "percent",
|
|
13325
|
+
quantity: "humidity",
|
|
13326
|
+
defaultAggregate: "mean",
|
|
13327
|
+
empty: "null",
|
|
13328
|
+
companions: [NOW]
|
|
13329
|
+
}),
|
|
13330
|
+
numeric({
|
|
13331
|
+
id: "pressure",
|
|
13332
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
13333
|
+
role: require_err_msg.DeviceRole.PressureSensor,
|
|
13334
|
+
outputCap: "pressure-sensor",
|
|
13335
|
+
outputField: "hpa",
|
|
13336
|
+
quantity: "pressure",
|
|
13337
|
+
defaultAggregate: "mean",
|
|
13338
|
+
empty: "null",
|
|
13339
|
+
companions: [NOW]
|
|
13340
|
+
}),
|
|
13341
|
+
numeric({
|
|
13342
|
+
id: "illuminance",
|
|
13343
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
13344
|
+
role: require_err_msg.DeviceRole.AmbientLightSensor,
|
|
13345
|
+
outputCap: "ambient-light-sensor",
|
|
13346
|
+
outputField: "lux",
|
|
13347
|
+
quantity: "illuminance",
|
|
13348
|
+
defaultAggregate: "mean",
|
|
13349
|
+
empty: "null",
|
|
13350
|
+
companions: [NOW]
|
|
13351
|
+
}),
|
|
13352
|
+
numeric({
|
|
13353
|
+
id: "power",
|
|
13354
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
13355
|
+
role: require_err_msg.DeviceRole.PowerSensor,
|
|
13356
|
+
outputCap: "power-meter",
|
|
13357
|
+
outputField: "watts",
|
|
13358
|
+
quantity: "power",
|
|
13359
|
+
defaultAggregate: "sum",
|
|
13360
|
+
empty: "omit",
|
|
13361
|
+
companions: [NOW]
|
|
13362
|
+
}),
|
|
13363
|
+
numeric({
|
|
13364
|
+
id: "energy",
|
|
13365
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
13366
|
+
role: require_err_msg.DeviceRole.EnergySensor,
|
|
13367
|
+
outputCap: "power-meter",
|
|
13368
|
+
outputField: "kwhTotal",
|
|
13369
|
+
quantity: "energy",
|
|
13370
|
+
defaultAggregate: "sum",
|
|
13371
|
+
empty: "omit",
|
|
13372
|
+
companions: [NOW]
|
|
13373
|
+
}),
|
|
13374
|
+
numeric({
|
|
13375
|
+
id: "battery",
|
|
13376
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
13377
|
+
role: require_err_msg.DeviceRole.BatterySensor,
|
|
13378
|
+
outputCap: "battery",
|
|
13379
|
+
outputField: "percentage",
|
|
13380
|
+
quantity: "percentage",
|
|
13381
|
+
defaultAggregate: "mean",
|
|
13382
|
+
empty: "null",
|
|
13383
|
+
companions: [
|
|
13384
|
+
{
|
|
13385
|
+
fieldPath: "charging",
|
|
13386
|
+
expr: "\"unknown\""
|
|
13387
|
+
},
|
|
13388
|
+
{
|
|
13389
|
+
fieldPath: "sleeping",
|
|
13390
|
+
expr: "false"
|
|
13391
|
+
},
|
|
13392
|
+
{
|
|
13393
|
+
fieldPath: "lastUpdated",
|
|
13394
|
+
expr: "now"
|
|
13395
|
+
}
|
|
13396
|
+
]
|
|
13397
|
+
}),
|
|
13398
|
+
numeric({
|
|
13399
|
+
id: "numeric",
|
|
13400
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
13401
|
+
role: require_err_msg.DeviceRole.NumericSensor,
|
|
13402
|
+
outputCap: "numeric-sensor",
|
|
13403
|
+
outputField: "value",
|
|
13404
|
+
quantity: "device",
|
|
13405
|
+
defaultAggregate: "mean",
|
|
13406
|
+
empty: "null",
|
|
13407
|
+
companions: [NOW]
|
|
13408
|
+
}),
|
|
13409
|
+
binary({
|
|
13410
|
+
id: "motion",
|
|
13411
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
13412
|
+
role: require_err_msg.DeviceRole.MotionSensor,
|
|
13413
|
+
outputCap: "motion",
|
|
13414
|
+
outputField: "detected",
|
|
13415
|
+
defaultAggregate: "any",
|
|
13416
|
+
accept: [{
|
|
13417
|
+
cap: "motion",
|
|
13418
|
+
fieldPath: "detected"
|
|
13419
|
+
}],
|
|
13420
|
+
companions: [{
|
|
13421
|
+
fieldPath: "lastDetectedAt",
|
|
13422
|
+
expr: "null"
|
|
13423
|
+
}, {
|
|
13424
|
+
fieldPath: "autoClearAfterMs",
|
|
13425
|
+
expr: "null"
|
|
13426
|
+
}]
|
|
13427
|
+
}),
|
|
13428
|
+
binary({
|
|
13429
|
+
id: "contact",
|
|
13430
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
13431
|
+
role: require_err_msg.DeviceRole.ContactSensor,
|
|
13432
|
+
outputCap: "contact",
|
|
13433
|
+
outputField: "entryOpen",
|
|
13434
|
+
defaultAggregate: "any",
|
|
13435
|
+
accept: [{
|
|
13436
|
+
cap: "contact",
|
|
13437
|
+
fieldPath: "entryOpen"
|
|
13438
|
+
}],
|
|
13439
|
+
companions: [CHANGED]
|
|
13440
|
+
}),
|
|
13441
|
+
binary({
|
|
13442
|
+
id: "leak",
|
|
13443
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
13444
|
+
role: require_err_msg.DeviceRole.LeakSensor,
|
|
13445
|
+
outputCap: "flood",
|
|
13446
|
+
outputField: "flooded",
|
|
13447
|
+
defaultAggregate: "any",
|
|
13448
|
+
accept: [{
|
|
13449
|
+
cap: "flood",
|
|
13450
|
+
fieldPath: "flooded"
|
|
13451
|
+
}],
|
|
13452
|
+
companions: [CHANGED]
|
|
13453
|
+
}),
|
|
13454
|
+
binary({
|
|
13455
|
+
id: "smoke",
|
|
13456
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
13457
|
+
role: require_err_msg.DeviceRole.SmokeSensor,
|
|
13458
|
+
outputCap: "smoke",
|
|
13459
|
+
outputField: "detected",
|
|
13460
|
+
defaultAggregate: "any",
|
|
13461
|
+
accept: [{
|
|
13462
|
+
cap: "smoke",
|
|
13463
|
+
fieldPath: "detected"
|
|
13464
|
+
}],
|
|
13465
|
+
companions: [CHANGED]
|
|
13466
|
+
}),
|
|
13467
|
+
binary({
|
|
13468
|
+
id: "occupancy",
|
|
13469
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
13470
|
+
role: require_err_msg.DeviceRole.BinarySensor,
|
|
13471
|
+
outputCap: "binary",
|
|
13472
|
+
outputField: "on",
|
|
13473
|
+
defaultAggregate: "any",
|
|
13474
|
+
accept: [{
|
|
13475
|
+
cap: "motion",
|
|
13476
|
+
fieldPath: "detected"
|
|
13477
|
+
}, {
|
|
13478
|
+
cap: "binary",
|
|
13479
|
+
fieldPath: "on"
|
|
13480
|
+
}],
|
|
13481
|
+
companions: [CHANGED]
|
|
13482
|
+
}),
|
|
13483
|
+
binary({
|
|
13484
|
+
id: "binary",
|
|
13485
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
13486
|
+
role: require_err_msg.DeviceRole.BinarySensor,
|
|
13487
|
+
outputCap: "binary",
|
|
13488
|
+
outputField: "on",
|
|
13489
|
+
defaultAggregate: "any",
|
|
13490
|
+
accept: [{
|
|
13491
|
+
cap: "binary",
|
|
13492
|
+
fieldPath: "on"
|
|
13493
|
+
}],
|
|
13494
|
+
companions: [CHANGED]
|
|
13495
|
+
})
|
|
13496
|
+
];
|
|
13497
|
+
var BY_ID = new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
13498
|
+
function groupTemplate(id) {
|
|
13499
|
+
return BY_ID.get(id) ?? null;
|
|
13500
|
+
}
|
|
13501
|
+
//#endregion
|
|
13502
|
+
//#region src/composition/helpers/compile.ts
|
|
13503
|
+
function sameSource(a, b) {
|
|
13504
|
+
return a.addonId === b.addonId && a.stableId === b.stableId;
|
|
13505
|
+
}
|
|
13506
|
+
function sameMember(a, b) {
|
|
13507
|
+
return sameSource(a.source, b.source) && a.cap === b.cap && a.fieldPath === b.fieldPath;
|
|
13508
|
+
}
|
|
13509
|
+
function accepted(template, member) {
|
|
13510
|
+
return template.accept.some((field) => field.cap === member.cap && field.fieldPath === member.fieldPath);
|
|
13511
|
+
}
|
|
13512
|
+
function memberProblems(template, spec) {
|
|
13513
|
+
return spec.members.flatMap((member, index) => {
|
|
13514
|
+
const at = `helper.members[${index}]`;
|
|
13515
|
+
const problems = [];
|
|
13516
|
+
if (!accepted(template, member)) {
|
|
13517
|
+
const allowed = template.accept.map((field) => `${field.cap}.${field.fieldPath}`).join(" or ");
|
|
13518
|
+
problems.push(problem("member-constraint", at, `a ${template.id} group reads ${allowed}; this member is ${member.cap}.${member.fieldPath}`));
|
|
13519
|
+
}
|
|
13520
|
+
if (spec.members.slice(0, index).some((other) => sameMember(other, member))) problems.push(problem("member-constraint", at, "this member is already in the group"));
|
|
13521
|
+
return problems;
|
|
13522
|
+
});
|
|
13523
|
+
}
|
|
13524
|
+
function aggregateSource(template, spec, reads, publish) {
|
|
13525
|
+
return {
|
|
13526
|
+
kind: "aggregate",
|
|
13527
|
+
reducer: spec.aggregate,
|
|
13528
|
+
reads: [...reads],
|
|
13529
|
+
publish,
|
|
13530
|
+
empty: template.empty
|
|
13531
|
+
};
|
|
13532
|
+
}
|
|
13533
|
+
function expressionSource(expr) {
|
|
13534
|
+
return {
|
|
13535
|
+
kind: "expression",
|
|
13536
|
+
expr,
|
|
13537
|
+
bindings: {}
|
|
13538
|
+
};
|
|
13539
|
+
}
|
|
13540
|
+
function draftOf$1(template, spec) {
|
|
13541
|
+
const reads = spec.members.map((member) => ({
|
|
13542
|
+
source: member.source,
|
|
13543
|
+
cap: member.cap,
|
|
13544
|
+
fieldPath: member.fieldPath
|
|
13545
|
+
}));
|
|
13546
|
+
const companions = Object.fromEntries(template.companions.map((companion) => [companion.fieldPath, expressionSource(companion.expr)]));
|
|
13547
|
+
return {
|
|
13548
|
+
target: {
|
|
13549
|
+
kind: "new",
|
|
13550
|
+
type: template.deviceType,
|
|
13551
|
+
role: template.role
|
|
13552
|
+
},
|
|
13553
|
+
helper: spec,
|
|
13554
|
+
features: [{
|
|
13555
|
+
kind: "fields",
|
|
13556
|
+
cap: template.outputCap,
|
|
13557
|
+
fields: {
|
|
13558
|
+
[template.outputField]: aggregateSource(template, spec, reads, "value"),
|
|
13559
|
+
...companions
|
|
13560
|
+
}
|
|
13561
|
+
}, {
|
|
13562
|
+
kind: "fields",
|
|
13563
|
+
cap: "group-status",
|
|
13564
|
+
fields: {
|
|
13565
|
+
included: aggregateSource(template, spec, reads, "included"),
|
|
13566
|
+
excluded: aggregateSource(template, spec, reads, "excluded"),
|
|
13567
|
+
total: aggregateSource(template, spec, reads, "total")
|
|
13568
|
+
}
|
|
13569
|
+
}]
|
|
13570
|
+
};
|
|
13571
|
+
}
|
|
13572
|
+
function parseDraft(draft) {
|
|
13573
|
+
const parsed = require_composition.CompositionSchema.safeParse(draft);
|
|
13574
|
+
if (parsed.success) return {
|
|
13575
|
+
ok: true,
|
|
13576
|
+
composition: parsed.data
|
|
13577
|
+
};
|
|
13578
|
+
return {
|
|
13579
|
+
ok: false,
|
|
13580
|
+
problems: [problem("helper-mismatch", "helper", `the template did not compile: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`)]
|
|
13581
|
+
};
|
|
13582
|
+
}
|
|
13583
|
+
/** Compile a group template to a new-device composition. Refusals are named. */
|
|
13584
|
+
function compileHelper(spec) {
|
|
13585
|
+
const template = groupTemplate(spec.templateId);
|
|
13586
|
+
if (template === null) return {
|
|
13587
|
+
ok: false,
|
|
13588
|
+
problems: [problem("member-constraint", "helper.templateId", `unknown template \`${spec.templateId}\``)]
|
|
13589
|
+
};
|
|
13590
|
+
if (!template.aggregates.includes(spec.aggregate)) {
|
|
13591
|
+
const allowed = template.aggregates.join(", ");
|
|
13592
|
+
return {
|
|
13593
|
+
ok: false,
|
|
13594
|
+
problems: [problem("kind-mismatch", "helper.aggregate", `a ${template.id} group aggregates by ${allowed}, not \`${spec.aggregate}\``)]
|
|
13595
|
+
};
|
|
13596
|
+
}
|
|
13597
|
+
const members = memberProblems(template, spec);
|
|
13598
|
+
if (members.length > 0) return {
|
|
13599
|
+
ok: false,
|
|
13600
|
+
problems: members
|
|
13601
|
+
};
|
|
13602
|
+
return parseDraft(draftOf$1(template, spec));
|
|
13603
|
+
}
|
|
13604
|
+
/** The built body, ignoring `helper`, so a save can demand one writer. */
|
|
13605
|
+
function sameHelperBody(stored, compiled) {
|
|
13606
|
+
return JSON.stringify(stored.target) === JSON.stringify(compiled.target) && JSON.stringify(stored.features) === JSON.stringify(compiled.features);
|
|
13607
|
+
}
|
|
13608
|
+
function templateDeviceType(spec) {
|
|
13609
|
+
return groupTemplate(spec.templateId)?.memberDeviceType ?? null;
|
|
13610
|
+
}
|
|
13611
|
+
//#endregion
|
|
13612
|
+
//#region src/composition/helpers/save.ts
|
|
13613
|
+
function quantityProblems(spec, facts) {
|
|
13614
|
+
const template = groupTemplate(spec.templateId);
|
|
13615
|
+
if (template === null || template.family !== "numeric") return [];
|
|
13616
|
+
const known = spec.members.flatMap((member, index) => {
|
|
13617
|
+
const quantity = facts.get(require_composition.compositionSourceKey(member.source))?.quantity;
|
|
13618
|
+
return quantity === void 0 ? [] : [{
|
|
13619
|
+
index,
|
|
13620
|
+
quantity
|
|
13621
|
+
}];
|
|
13622
|
+
});
|
|
13623
|
+
if (template.quantity !== "device") return known.flatMap((member) => member.quantity === template.quantity ? [] : [problem("mixed-quantity", `helper.members[${member.index}]`, `a ${template.id} group is ${template.quantity}${template.baseUnit === void 0 ? "" : ` (${template.baseUnit})`}; this member is ${member.quantity}`)]);
|
|
13624
|
+
const distinct = [...new Set(known.map((member) => member.quantity))];
|
|
13625
|
+
if (distinct.length <= 1) return [];
|
|
13626
|
+
return [problem("mixed-quantity", "helper.members", `a numeric group requires one quantity; members report ${distinct.join(" and ")}`)];
|
|
13627
|
+
}
|
|
13628
|
+
function deviceTypeProblems(spec, facts) {
|
|
13629
|
+
const template = groupTemplate(spec.templateId);
|
|
13630
|
+
if (template === null) return [];
|
|
13631
|
+
return spec.members.flatMap((member, index) => {
|
|
13632
|
+
const deviceType = facts.get(require_composition.compositionSourceKey(member.source))?.deviceType;
|
|
13633
|
+
if (deviceType === void 0 || deviceType === template.memberDeviceType) return [];
|
|
13634
|
+
return [problem("member-constraint", `helper.members[${index}]`, `a ${template.id} group takes ${template.memberDeviceType} devices; this member is a ${deviceType}`)];
|
|
13635
|
+
});
|
|
13636
|
+
}
|
|
13637
|
+
/**
|
|
13638
|
+
* Problems that refuse a save. No `helper` key means a free composition: this
|
|
13639
|
+
* returns nothing, and expression semantics stay as they are.
|
|
13640
|
+
*/
|
|
13641
|
+
function helperSaveProblems(composition, facts) {
|
|
13642
|
+
const spec = composition.helper;
|
|
13643
|
+
if (spec === void 0) return [];
|
|
13644
|
+
const compiled = compileHelper(spec);
|
|
13645
|
+
if (!compiled.ok) return compiled.problems;
|
|
13646
|
+
if (!sameHelperBody(composition, compiled.composition)) return [problem("helper-mismatch", "helper", "the stored features are not this template — the helper spec is the only writer")];
|
|
13647
|
+
return [...quantityProblems(spec, facts), ...deviceTypeProblems(spec, facts)];
|
|
13648
|
+
}
|
|
13649
|
+
//#endregion
|
|
13245
13650
|
//#region src/composition/composition-graph.ts
|
|
13246
13651
|
/**
|
|
13247
13652
|
* The field graph across every composition, and the cycles in it (D659).
|
|
@@ -13472,6 +13877,7 @@ function planTopLevelField({ def, fields }, field, mode, lookupCap) {
|
|
|
13472
13877
|
const role = roleOf(source);
|
|
13473
13878
|
const unavailable = unavailableFor(tf, role, mode, def.name, fieldAt);
|
|
13474
13879
|
if (!unavailable.ok) return refused(unavailable.problem);
|
|
13880
|
+
const omitEmpty = source.kind === "aggregate" && source.publish === "value" && source.empty === "omit";
|
|
13475
13881
|
const plan = {
|
|
13476
13882
|
cap: def.name,
|
|
13477
13883
|
path,
|
|
@@ -13479,7 +13885,7 @@ function planTopLevelField({ def, fields }, field, mode, lookupCap) {
|
|
|
13479
13885
|
kind: tf.kind,
|
|
13480
13886
|
nullable: tf.nullable,
|
|
13481
13887
|
required: tf.required,
|
|
13482
|
-
unavailable: unavailable.unavailable,
|
|
13888
|
+
unavailable: omitEmpty ? "omit" : unavailable.unavailable,
|
|
13483
13889
|
role,
|
|
13484
13890
|
source,
|
|
13485
13891
|
reads: [...require_composition.fieldReads(source)]
|
|
@@ -13744,10 +14150,15 @@ function validateComposition(composition, ctx) {
|
|
|
13744
14150
|
if (refusedFeatures.some((at) => item.path === at || item.path.startsWith(`${at}.`))) return false;
|
|
13745
14151
|
return refusedFeatures.length === 0 || item.path !== "features";
|
|
13746
14152
|
});
|
|
14153
|
+
const facts = new Map([...ctx.sources].flatMap(([key, source]) => source.kind === "found" ? [[key, {
|
|
14154
|
+
deviceType: source.deviceType,
|
|
14155
|
+
quantity: source.quantity
|
|
14156
|
+
}]] : []));
|
|
13747
14157
|
const problems = [
|
|
13748
14158
|
...plan.problems,
|
|
13749
14159
|
...sourceProblems(plan.fields, ctx, self),
|
|
13750
|
-
...cycles
|
|
14160
|
+
...cycles,
|
|
14161
|
+
...helperSaveProblems(composition, facts)
|
|
13751
14162
|
];
|
|
13752
14163
|
return {
|
|
13753
14164
|
ok: problems.length === 0,
|
|
@@ -64307,6 +64718,53 @@ var gasCapability = {
|
|
|
64307
64718
|
volatileStateFields: ["lastChangedAt"]
|
|
64308
64719
|
};
|
|
64309
64720
|
//#endregion
|
|
64721
|
+
//#region src/capabilities/group-status.cap.ts
|
|
64722
|
+
/**
|
|
64723
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
64724
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
64725
|
+
* The reading itself stays on the output capability. History is none — the
|
|
64726
|
+
* series that later statistics read is the output cap's own history block.
|
|
64727
|
+
*/
|
|
64728
|
+
var GroupStatusSchema = zod.z.object({
|
|
64729
|
+
/** Members whose current value entered the aggregate. */
|
|
64730
|
+
included: zod.z.number().int().nonnegative().meta(require_sleep.readingMeta("count", {
|
|
64731
|
+
precision: 0,
|
|
64732
|
+
label: "Reporting"
|
|
64733
|
+
})),
|
|
64734
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
64735
|
+
excluded: zod.z.number().int().nonnegative().meta(require_sleep.readingMeta("count", {
|
|
64736
|
+
precision: 0,
|
|
64737
|
+
label: "Excluded"
|
|
64738
|
+
})),
|
|
64739
|
+
/** `included` + `excluded`. */
|
|
64740
|
+
total: zod.z.number().int().nonnegative().meta(require_sleep.readingMeta("count", {
|
|
64741
|
+
precision: 0,
|
|
64742
|
+
label: "Members"
|
|
64743
|
+
}))
|
|
64744
|
+
});
|
|
64745
|
+
var groupStatusCapability = {
|
|
64746
|
+
name: "group-status",
|
|
64747
|
+
scope: "device",
|
|
64748
|
+
deviceNative: true,
|
|
64749
|
+
mode: "singleton",
|
|
64750
|
+
deviceTypes: [require_err_msg.DeviceType.Sensor],
|
|
64751
|
+
methods: {},
|
|
64752
|
+
status: {
|
|
64753
|
+
schema: GroupStatusSchema,
|
|
64754
|
+
kind: "push"
|
|
64755
|
+
},
|
|
64756
|
+
runtimeState: GroupStatusSchema,
|
|
64757
|
+
/**
|
|
64758
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
64759
|
+
* next source event; a restored count would outlive the readings it named.
|
|
64760
|
+
*
|
|
64761
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
64762
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
64763
|
+
*/
|
|
64764
|
+
durability: "session",
|
|
64765
|
+
history: "none"
|
|
64766
|
+
};
|
|
64767
|
+
//#endregion
|
|
64310
64768
|
//#region src/capabilities/heating-valve.cap.ts
|
|
64311
64769
|
var HeatingValveStatusSchema = zod.z.object({
|
|
64312
64770
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
@@ -66402,12 +66860,18 @@ var motionCapability = {
|
|
|
66402
66860
|
methods: {
|
|
66403
66861
|
/**
|
|
66404
66862
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
66405
|
-
* for consumers that don't need the full status object
|
|
66406
|
-
*
|
|
66407
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
66408
|
-
* consumer.
|
|
66863
|
+
* for consumers that don't need the full status object. A composed
|
|
66864
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
66409
66865
|
*/
|
|
66410
66866
|
isDetected: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.boolean()) },
|
|
66867
|
+
/**
|
|
66868
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
66869
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
66870
|
+
*/
|
|
66871
|
+
composedMethods: { isDetected: {
|
|
66872
|
+
kind: "slice",
|
|
66873
|
+
field: "detected"
|
|
66874
|
+
} },
|
|
66411
66875
|
events: {
|
|
66412
66876
|
/**
|
|
66413
66877
|
* Fires every time the runner transitions a camera between
|
|
@@ -77154,6 +77618,127 @@ function createDeviceExtensionProvider(options) {
|
|
|
77154
77618
|
};
|
|
77155
77619
|
}
|
|
77156
77620
|
//#endregion
|
|
77621
|
+
//#region src/composition/helpers/aggregate.ts
|
|
77622
|
+
function isBinaryReducer(reducer) {
|
|
77623
|
+
return reducer === "any" || reducer === "all";
|
|
77624
|
+
}
|
|
77625
|
+
function includedValue(reducer, member) {
|
|
77626
|
+
if (member.state !== "fresh") return null;
|
|
77627
|
+
if (isBinaryReducer(reducer)) return typeof member.value === "boolean" ? member.value : null;
|
|
77628
|
+
return typeof member.value === "number" && Number.isFinite(member.value) ? member.value : null;
|
|
77629
|
+
}
|
|
77630
|
+
function median$1(values) {
|
|
77631
|
+
const sorted = [...values].toSorted((a, b) => a - b);
|
|
77632
|
+
const mid = Math.floor(sorted.length / 2);
|
|
77633
|
+
const right = sorted[mid];
|
|
77634
|
+
const left = sorted[mid - 1];
|
|
77635
|
+
if (right === void 0) throw new Error("median requires at least one finite number");
|
|
77636
|
+
if (sorted.length % 2 === 1) return right;
|
|
77637
|
+
if (left === void 0) throw new Error("median requires at least one finite number");
|
|
77638
|
+
return (left + right) / 2;
|
|
77639
|
+
}
|
|
77640
|
+
function reduceNumbers(reducer, values) {
|
|
77641
|
+
if (reducer === "min") return Math.min(...values);
|
|
77642
|
+
if (reducer === "max") return Math.max(...values);
|
|
77643
|
+
if (reducer === "sum") return values.reduce((sum, value) => sum + value, 0);
|
|
77644
|
+
if (reducer === "median") return median$1(values);
|
|
77645
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
77646
|
+
}
|
|
77647
|
+
function reduceBooleans(reducer, values) {
|
|
77648
|
+
return reducer === "all" ? values.every((value) => value) : values.some((value) => value);
|
|
77649
|
+
}
|
|
77650
|
+
function countsOf(included, total) {
|
|
77651
|
+
return {
|
|
77652
|
+
included,
|
|
77653
|
+
excluded: total - included,
|
|
77654
|
+
total
|
|
77655
|
+
};
|
|
77656
|
+
}
|
|
77657
|
+
function fatalReason(members) {
|
|
77658
|
+
const reasons = members.flatMap((member) => member.state === "unavailable" && member.fatal === true ? [member.reason ?? "source gone"] : []);
|
|
77659
|
+
return reasons.length === 0 ? null : reasons.join("; ");
|
|
77660
|
+
}
|
|
77661
|
+
function emptyOutcome(empty, counts) {
|
|
77662
|
+
if (empty === "null") return {
|
|
77663
|
+
kind: "value",
|
|
77664
|
+
value: null,
|
|
77665
|
+
counts
|
|
77666
|
+
};
|
|
77667
|
+
return {
|
|
77668
|
+
kind: "unavailable",
|
|
77669
|
+
fatal: false,
|
|
77670
|
+
reason: "no member included — unknown is not 0 or off",
|
|
77671
|
+
counts
|
|
77672
|
+
};
|
|
77673
|
+
}
|
|
77674
|
+
/** Pure. `members` is not mutated. An empty included set is null or unavailable, never 0 or false. */
|
|
77675
|
+
function evaluateAggregate(input) {
|
|
77676
|
+
const included = input.members.flatMap((member) => {
|
|
77677
|
+
const value = includedValue(input.reducer, member);
|
|
77678
|
+
return value === null ? [] : [value];
|
|
77679
|
+
});
|
|
77680
|
+
const counts = countsOf(included.length, input.members.length);
|
|
77681
|
+
const gone = fatalReason(input.members);
|
|
77682
|
+
if (gone !== null) return {
|
|
77683
|
+
kind: "unavailable",
|
|
77684
|
+
fatal: true,
|
|
77685
|
+
reason: gone,
|
|
77686
|
+
counts
|
|
77687
|
+
};
|
|
77688
|
+
if (input.publish === "included") return {
|
|
77689
|
+
kind: "value",
|
|
77690
|
+
value: counts.included,
|
|
77691
|
+
counts
|
|
77692
|
+
};
|
|
77693
|
+
if (input.publish === "excluded") return {
|
|
77694
|
+
kind: "value",
|
|
77695
|
+
value: counts.excluded,
|
|
77696
|
+
counts
|
|
77697
|
+
};
|
|
77698
|
+
if (input.publish === "total") return {
|
|
77699
|
+
kind: "value",
|
|
77700
|
+
value: counts.total,
|
|
77701
|
+
counts
|
|
77702
|
+
};
|
|
77703
|
+
if (included.length === 0) return emptyOutcome(input.empty, counts);
|
|
77704
|
+
if (isBinaryReducer(input.reducer)) {
|
|
77705
|
+
const flags = included.filter((value) => typeof value === "boolean");
|
|
77706
|
+
return {
|
|
77707
|
+
kind: "value",
|
|
77708
|
+
value: reduceBooleans(input.reducer, flags),
|
|
77709
|
+
counts
|
|
77710
|
+
};
|
|
77711
|
+
}
|
|
77712
|
+
const numbers = included.filter((value) => typeof value === "number");
|
|
77713
|
+
return {
|
|
77714
|
+
kind: "value",
|
|
77715
|
+
value: reduceNumbers(input.reducer, numbers),
|
|
77716
|
+
counts
|
|
77717
|
+
};
|
|
77718
|
+
}
|
|
77719
|
+
//#endregion
|
|
77720
|
+
//#region src/composition/helpers/source-pick.ts
|
|
77721
|
+
/** What the member step asks the selector for this template. */
|
|
77722
|
+
function sourcePickForTemplate(template) {
|
|
77723
|
+
const valueKind = template.family === "numeric" ? "number" : "boolean";
|
|
77724
|
+
return {
|
|
77725
|
+
purpose: "member",
|
|
77726
|
+
multiple: true,
|
|
77727
|
+
max: 64,
|
|
77728
|
+
deviceTypes: [template.memberDeviceType],
|
|
77729
|
+
accept: template.accept.map((field) => ({
|
|
77730
|
+
...field,
|
|
77731
|
+
valueKind
|
|
77732
|
+
})),
|
|
77733
|
+
history: {
|
|
77734
|
+
required: false,
|
|
77735
|
+
minRetentionMs: null
|
|
77736
|
+
},
|
|
77737
|
+
mustBindCaps: [],
|
|
77738
|
+
exclude: []
|
|
77739
|
+
};
|
|
77740
|
+
}
|
|
77741
|
+
//#endregion
|
|
77157
77742
|
//#region src/units/unit-table.ts
|
|
77158
77743
|
/**
|
|
77159
77744
|
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
@@ -77740,11 +78325,45 @@ function expressionOutcome(source, read, now, stateful) {
|
|
|
77740
78325
|
deadline: deadlines.length > 0 ? Math.min(...deadlines) : null
|
|
77741
78326
|
};
|
|
77742
78327
|
}
|
|
78328
|
+
function aggregateRead(reading) {
|
|
78329
|
+
if (reading.state === "unavailable") return {
|
|
78330
|
+
state: "unavailable",
|
|
78331
|
+
fatal: reading.fatal,
|
|
78332
|
+
reason: reading.reason
|
|
78333
|
+
};
|
|
78334
|
+
return {
|
|
78335
|
+
state: reading.state,
|
|
78336
|
+
value: reading.value,
|
|
78337
|
+
...reading.state === "stale" ? { reason: reading.reason } : {}
|
|
78338
|
+
};
|
|
78339
|
+
}
|
|
78340
|
+
function aggregateField(source, read) {
|
|
78341
|
+
const outcome = evaluateAggregate({
|
|
78342
|
+
reducer: source.reducer,
|
|
78343
|
+
members: source.reads.map((item) => aggregateRead(read(item))),
|
|
78344
|
+
publish: source.publish,
|
|
78345
|
+
empty: source.empty
|
|
78346
|
+
});
|
|
78347
|
+
if (outcome.kind === "value") return {
|
|
78348
|
+
state: "fresh",
|
|
78349
|
+
value: outcome.value,
|
|
78350
|
+
reason: null,
|
|
78351
|
+
deadline: null
|
|
78352
|
+
};
|
|
78353
|
+
return {
|
|
78354
|
+
state: "unavailable",
|
|
78355
|
+
value: null,
|
|
78356
|
+
reason: outcome.reason,
|
|
78357
|
+
fatal: outcome.fatal,
|
|
78358
|
+
confirmed: true
|
|
78359
|
+
};
|
|
78360
|
+
}
|
|
77743
78361
|
function evaluateCompositionField(input) {
|
|
77744
78362
|
const { source } = input;
|
|
77745
78363
|
switch (source.kind) {
|
|
77746
78364
|
case "from": return fromReading(input.read(source), source);
|
|
77747
78365
|
case "expression": return expressionOutcome(source, input.read, input.now, input.stateful);
|
|
78366
|
+
case "aggregate": return aggregateField(source, input.read);
|
|
77748
78367
|
case "code": return {
|
|
77749
78368
|
state: "unavailable",
|
|
77750
78369
|
value: null,
|
|
@@ -80600,6 +81219,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
80600
81219
|
featureProbe: featureProbeCapability,
|
|
80601
81220
|
flood: floodCapability,
|
|
80602
81221
|
gas: gasCapability,
|
|
81222
|
+
groupStatus: groupStatusCapability,
|
|
80603
81223
|
heatingValve: heatingValveCapability,
|
|
80604
81224
|
humidifier: humidifierCapability,
|
|
80605
81225
|
humiditySensor: humiditySensorCapability,
|
|
@@ -85925,6 +86545,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
85925
86545
|
access: "view",
|
|
85926
86546
|
role: "viewer"
|
|
85927
86547
|
},
|
|
86548
|
+
"groupStatus.getStatus": {
|
|
86549
|
+
capName: "group-status",
|
|
86550
|
+
capScope: "device",
|
|
86551
|
+
addonId: null,
|
|
86552
|
+
access: "view",
|
|
86553
|
+
role: "viewer"
|
|
86554
|
+
},
|
|
85928
86555
|
"heatingValve.getStatus": {
|
|
85929
86556
|
capName: "heating-valve",
|
|
85930
86557
|
capScope: "device",
|
|
@@ -92463,6 +93090,7 @@ var KNOWN_CAP_NAMES = [
|
|
|
92463
93090
|
"filesystem-browse",
|
|
92464
93091
|
"flood",
|
|
92465
93092
|
"gas",
|
|
93093
|
+
"group-status",
|
|
92466
93094
|
"heating-valve",
|
|
92467
93095
|
"humidifier",
|
|
92468
93096
|
"humidity-sensor",
|
|
@@ -92611,6 +93239,7 @@ var DEVICE_CAP_NAMES = [
|
|
|
92611
93239
|
"feature-probe",
|
|
92612
93240
|
"flood",
|
|
92613
93241
|
"gas",
|
|
93242
|
+
"group-status",
|
|
92614
93243
|
"heating-valve",
|
|
92615
93244
|
"humidifier",
|
|
92616
93245
|
"humidity-sensor",
|
|
@@ -96128,6 +96757,33 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
96128
96757
|
icon: "flame"
|
|
96129
96758
|
}]
|
|
96130
96759
|
},
|
|
96760
|
+
"group-status": {
|
|
96761
|
+
scope: "device",
|
|
96762
|
+
noun: t("Group", "Gruppo"),
|
|
96763
|
+
state: [
|
|
96764
|
+
{
|
|
96765
|
+
kind: "numeric",
|
|
96766
|
+
field: "included",
|
|
96767
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
96768
|
+
label: t("Reporting", "Rispondono"),
|
|
96769
|
+
icon: "users"
|
|
96770
|
+
},
|
|
96771
|
+
{
|
|
96772
|
+
kind: "numeric",
|
|
96773
|
+
field: "excluded",
|
|
96774
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
96775
|
+
label: t("Excluded", "Esclusi"),
|
|
96776
|
+
icon: "users"
|
|
96777
|
+
},
|
|
96778
|
+
{
|
|
96779
|
+
kind: "numeric",
|
|
96780
|
+
field: "total",
|
|
96781
|
+
quantity: t("the member count", "il numero di membri"),
|
|
96782
|
+
label: t("Members", "Membri"),
|
|
96783
|
+
icon: "sigma"
|
|
96784
|
+
}
|
|
96785
|
+
]
|
|
96786
|
+
},
|
|
96131
96787
|
"humidity-sensor": {
|
|
96132
96788
|
scope: "device",
|
|
96133
96789
|
noun: t("Humidity", "Umidità"),
|
|
@@ -98265,6 +98921,7 @@ var CAP_NAMES_WITH_STATUS = [
|
|
|
98265
98921
|
"feature-probe",
|
|
98266
98922
|
"flood",
|
|
98267
98923
|
"gas",
|
|
98924
|
+
"group-status",
|
|
98268
98925
|
"heating-valve",
|
|
98269
98926
|
"humidifier",
|
|
98270
98927
|
"humidity-sensor",
|
|
@@ -98387,6 +99044,7 @@ var CAPABILITY_NAMES = {
|
|
|
98387
99044
|
filesystemBrowse: "filesystem-browse",
|
|
98388
99045
|
flood: "flood",
|
|
98389
99046
|
gas: "gas",
|
|
99047
|
+
groupStatus: "group-status",
|
|
98390
99048
|
heatingValve: "heating-valve",
|
|
98391
99049
|
humidifier: "humidifier",
|
|
98392
99050
|
humiditySensor: "humidity-sensor",
|
|
@@ -98793,6 +99451,10 @@ var CAPABILITY_ROUTER_KEYS = [
|
|
|
98793
99451
|
key: "gas",
|
|
98794
99452
|
name: "gas"
|
|
98795
99453
|
},
|
|
99454
|
+
{
|
|
99455
|
+
key: "groupStatus",
|
|
99456
|
+
name: "group-status"
|
|
99457
|
+
},
|
|
98796
99458
|
{
|
|
98797
99459
|
key: "heatingValve",
|
|
98798
99460
|
name: "heating-valve"
|
|
@@ -99306,6 +99968,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
|
|
|
99306
99968
|
filesystemBrowseCapability,
|
|
99307
99969
|
floodCapability,
|
|
99308
99970
|
gasCapability,
|
|
99971
|
+
groupStatusCapability,
|
|
99309
99972
|
heatingValveCapability,
|
|
99310
99973
|
humidifierCapability,
|
|
99311
99974
|
humiditySensorCapability,
|
|
@@ -100382,6 +101045,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
|
|
|
100382
101045
|
form: "single",
|
|
100383
101046
|
optional: false
|
|
100384
101047
|
}],
|
|
101048
|
+
"groupStatus.getStatus": [{
|
|
101049
|
+
name: "deviceId",
|
|
101050
|
+
form: "single",
|
|
101051
|
+
optional: false
|
|
101052
|
+
}],
|
|
100385
101053
|
"heatingValve.getStatus": [{
|
|
100386
101054
|
name: "deviceId",
|
|
100387
101055
|
form: "single",
|
|
@@ -102393,7 +103061,7 @@ function getCapsByProviderKind(kind) {
|
|
|
102393
103061
|
//#region src/generated/runtime-state-durability.ts
|
|
102394
103062
|
/**
|
|
102395
103063
|
* Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
|
|
102396
|
-
* `runtimeState`.
|
|
103064
|
+
* `runtimeState`. 73 caps: 38 `restored`, 35 `session`.
|
|
102397
103065
|
*
|
|
102398
103066
|
* A cap absent from this map has no runtime-state slice at all. A cap PRESENT
|
|
102399
103067
|
* with `durability: 'session'` has one and has decided not to keep it.
|
|
@@ -102511,6 +103179,10 @@ var RUNTIME_STATE_POLICY = {
|
|
|
102511
103179
|
durability: "restored",
|
|
102512
103180
|
volatileFields: ["lastChangedAt"]
|
|
102513
103181
|
},
|
|
103182
|
+
"group-status": {
|
|
103183
|
+
durability: "session",
|
|
103184
|
+
volatileFields: []
|
|
103185
|
+
},
|
|
102514
103186
|
"heating-valve": {
|
|
102515
103187
|
durability: "session",
|
|
102516
103188
|
volatileFields: ["lastFetchedAt"]
|
|
@@ -102853,7 +103525,7 @@ var BucketAccumulator = class {
|
|
|
102853
103525
|
//#region src/generated/history-catalog.ts
|
|
102854
103526
|
/**
|
|
102855
103527
|
* Cap history catalog, projected from every `*.cap.ts` `history` block.
|
|
102856
|
-
* 41 caps with series (75 series),
|
|
103528
|
+
* 41 caps with series (75 series), 31 caps answered `'none'`.
|
|
102857
103529
|
* Field keys are `runtimeState` paths (`a.b` into fixed objects only).
|
|
102858
103530
|
*/
|
|
102859
103531
|
var HISTORY_CATALOG = {
|
|
@@ -103254,6 +103926,7 @@ var HISTORY_NONE_CAPS = [
|
|
|
103254
103926
|
"doorbell",
|
|
103255
103927
|
"event-emitter",
|
|
103256
103928
|
"feature-probe",
|
|
103929
|
+
"group-status",
|
|
103257
103930
|
"image",
|
|
103258
103931
|
"image-settings",
|
|
103259
103932
|
"intercom",
|
|
@@ -114509,6 +115182,7 @@ exports.ADMIN_SCOPE = ADMIN_SCOPE;
|
|
|
114509
115182
|
exports.AGENT_MDNS_QUERY_NAME = AGENT_MDNS_QUERY_NAME;
|
|
114510
115183
|
exports.AGENT_MDNS_SERVICE_TYPE = AGENT_MDNS_SERVICE_TYPE;
|
|
114511
115184
|
exports.AGENT_MDNS_TXT_KEYS = AGENT_MDNS_TXT_KEYS;
|
|
115185
|
+
exports.AGGREGATE_REDUCERS = require_composition.AGGREGATE_REDUCERS;
|
|
114512
115186
|
exports.AGGREGATE_THROUGHPUT_BY_KIND = AGGREGATE_THROUGHPUT_BY_KIND;
|
|
114513
115187
|
exports.ALEXA_EGRESS_PROFILE = ALEXA_EGRESS_PROFILE;
|
|
114514
115188
|
exports.ALL_CAPABILITY_DEFINITIONS = ALL_CAPABILITY_DEFINITIONS;
|
|
@@ -114563,6 +115237,7 @@ exports.AdoptionOutcomeSchema = AdoptionOutcomeSchema;
|
|
|
114563
115237
|
exports.AdoptionReleaseInputSchema = ReleaseInputSchema;
|
|
114564
115238
|
exports.AdoptionStatusSchema = AdoptionStatusSchema;
|
|
114565
115239
|
exports.AgentLoadSummarySchema = AgentLoadSummarySchema;
|
|
115240
|
+
exports.AggregateReducerSchema = require_composition.AggregateReducerSchema;
|
|
114566
115241
|
exports.AirQualitySensorStatusSchema = AirQualitySensorStatusSchema;
|
|
114567
115242
|
exports.AlarmArmModeSchema = AlarmArmModeSchema;
|
|
114568
115243
|
exports.AlarmPanelStatusSchema = AlarmPanelStatusSchema;
|
|
@@ -114629,6 +115304,7 @@ exports.BASE_LIVE_EGRESS_PROFILE = BASE_LIVE_EGRESS_PROFILE;
|
|
|
114629
115304
|
exports.BATTERY_DEVICE_PROFILE = BATTERY_DEVICE_PROFILE;
|
|
114630
115305
|
exports.BATTERY_UNREACHABLE_AFTER_MS = BATTERY_UNREACHABLE_AFTER_MS;
|
|
114631
115306
|
exports.BENCH_ROOT_STEP_ID = BENCH_ROOT_STEP_ID;
|
|
115307
|
+
exports.BINARY_AGGREGATES = require_composition.BINARY_AGGREGATES;
|
|
114632
115308
|
exports.BIRTH_DECISION_DEFAULT_LIMIT = BIRTH_DECISION_DEFAULT_LIMIT;
|
|
114633
115309
|
exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
|
|
114634
115310
|
exports.BUILTIN_RESULT_KINDS = BUILTIN_RESULT_KINDS;
|
|
@@ -114839,6 +115515,7 @@ exports.ComposerApplyResultSchema = ComposerApplyResultSchema;
|
|
|
114839
115515
|
exports.ComposerBlockSchema = ComposerBlockSchema;
|
|
114840
115516
|
exports.ComposerBlockVerdictSchema = ComposerBlockVerdictSchema;
|
|
114841
115517
|
exports.ComposerUnreadableBlockSchema = ComposerUnreadableBlockSchema;
|
|
115518
|
+
exports.CompositionAggregateSourceSchema = require_composition.CompositionAggregateSourceSchema;
|
|
114842
115519
|
exports.CompositionBindingSchema = require_composition.CompositionBindingSchema;
|
|
114843
115520
|
exports.CompositionBlockInputSchema = CompositionBlockInputSchema;
|
|
114844
115521
|
exports.CompositionBlockStateSchema = CompositionBlockStateSchema;
|
|
@@ -115215,12 +115892,17 @@ exports.FrameInputSchema = FrameInputSchema;
|
|
|
115215
115892
|
exports.FrameLazyCountersSchema = FrameLazyCountersSchema;
|
|
115216
115893
|
exports.FrameLazyMetricsSchema = FrameLazyMetricsSchema;
|
|
115217
115894
|
exports.G711_SCALE_CORRECTION_DB = G711_SCALE_CORRECTION_DB;
|
|
115895
|
+
exports.GROUP_TEMPLATES = GROUP_TEMPLATES;
|
|
115896
|
+
exports.GROUP_TEMPLATE_IDS = require_composition.GROUP_TEMPLATE_IDS;
|
|
115218
115897
|
exports.GasStatusSchema = GasStatusSchema;
|
|
115219
115898
|
exports.GetLoggingSettingsInputSchema = GetLoggingSettingsInputSchema;
|
|
115220
115899
|
exports.GetStreamWithCodecInputSchema = GetStreamWithCodecInputSchema;
|
|
115221
115900
|
exports.GlobalMetricsSchema = GlobalMetricsSchema;
|
|
115222
115901
|
exports.GridLayoutPatchSchema = GridLayoutPatchSchema;
|
|
115223
115902
|
exports.GridLayoutViewSchema = GridLayoutViewSchema;
|
|
115903
|
+
exports.GroupHelperSpecSchema = require_composition.GroupHelperSpecSchema;
|
|
115904
|
+
exports.GroupStatusSchema = GroupStatusSchema;
|
|
115905
|
+
exports.GroupTemplateIdSchema = require_composition.GroupTemplateIdSchema;
|
|
115224
115906
|
exports.HAP_AUDIO_BASE = HAP_AUDIO_BASE;
|
|
115225
115907
|
exports.HAP_AUDIO_BITRATE_KBPS = HAP_AUDIO_BITRATE_KBPS;
|
|
115226
115908
|
exports.HAP_AUDIO_VBV_KBITS = HAP_AUDIO_VBV_KBITS;
|
|
@@ -115244,6 +115926,8 @@ exports.HWACCEL_OPTIONS = HWACCEL_OPTIONS;
|
|
|
115244
115926
|
exports.HardwareClassIdSchema = HardwareClassIdSchema;
|
|
115245
115927
|
exports.HealthStatusSchema = HealthStatusSchema;
|
|
115246
115928
|
exports.HeatingValveStatusSchema = HeatingValveStatusSchema;
|
|
115929
|
+
exports.HelperMemberSchema = require_composition.HelperMemberSchema;
|
|
115930
|
+
exports.HelperSpecSchema = require_composition.HelperSpecSchema;
|
|
115247
115931
|
exports.HfModelResolutionSchema = HfModelResolutionSchema;
|
|
115248
115932
|
exports.HistoryPointSchema = HistoryPointSchema;
|
|
115249
115933
|
exports.HistoryResolutionEnum = HistoryResolutionEnum;
|
|
@@ -115418,6 +116102,7 @@ exports.MAX_EXPRESSION_BINDINGS = require_composition.MAX_EXPRESSION_BINDINGS;
|
|
|
115418
116102
|
exports.MAX_EXPRESSION_CALL_ARGS = require_composition.MAX_EXPRESSION_CALL_ARGS;
|
|
115419
116103
|
exports.MAX_EXPRESSION_EVAL_STEPS = require_composition.MAX_EXPRESSION_EVAL_STEPS;
|
|
115420
116104
|
exports.MAX_EXPRESSION_SOURCE_LENGTH = require_composition.MAX_EXPRESSION_SOURCE_LENGTH;
|
|
116105
|
+
exports.MAX_HELPER_MEMBERS = require_composition.MAX_HELPER_MEMBERS;
|
|
115421
116106
|
exports.MAX_KEYS = MAX_KEYS;
|
|
115422
116107
|
exports.MAX_REASONS_PER_KEY = MAX_REASONS_PER_KEY;
|
|
115423
116108
|
exports.MAX_REQUEUED_BUCKETS_PER_SERIES = MAX_REQUEUED_BUCKETS_PER_SERIES;
|
|
@@ -115609,6 +116294,7 @@ exports.NETWORK_LINK_UNKNOWN = NETWORK_LINK_UNKNOWN;
|
|
|
115609
116294
|
exports.NODE_BENCHMARK_DEFAULTS = NODE_BENCHMARK_DEFAULTS;
|
|
115610
116295
|
exports.NODE_COLOR_IDS = require_node_color.NODE_COLOR_IDS;
|
|
115611
116296
|
exports.NO_MEASURED_CAPACITY = NO_MEASURED_CAPACITY;
|
|
116297
|
+
exports.NUMERIC_AGGREGATES = require_composition.NUMERIC_AGGREGATES;
|
|
115612
116298
|
exports.NativeCropBboxSchema = NativeCropBboxSchema;
|
|
115613
116299
|
exports.NativeCropRefSchema = NativeCropRefSchema;
|
|
115614
116300
|
exports.NativeCropResultSchema = NativeCropResultSchema;
|
|
@@ -116663,6 +117349,7 @@ exports.commitWatchdogRestart = commitWatchdogRestart;
|
|
|
116663
117349
|
exports.compareToTarget = compareToTarget;
|
|
116664
117350
|
exports.compileExpression = require_composition.compileExpression;
|
|
116665
117351
|
exports.compileExpressionSafe = require_composition.compileExpressionSafe;
|
|
117352
|
+
exports.compileHelper = compileHelper;
|
|
116666
117353
|
exports.compileKeyedArrayOverride = compileKeyedArrayOverride;
|
|
116667
117354
|
exports.compilePulseOverride = compilePulseOverride;
|
|
116668
117355
|
exports.compileScalarOverride = compileScalarOverride;
|
|
@@ -116825,6 +117512,7 @@ exports.enumerateItemArrayFields = enumerateItemArrayFields;
|
|
|
116825
117512
|
exports.enumerateSchemaFields = enumerateSchemaFields;
|
|
116826
117513
|
exports.errMsg = require_err_msg.errMsg;
|
|
116827
117514
|
exports.estimateNodeBenchmarkDurationMs = estimateNodeBenchmarkDurationMs;
|
|
117515
|
+
exports.evaluateAggregate = evaluateAggregate;
|
|
116828
117516
|
exports.evaluateAst = require_composition.evaluateAst;
|
|
116829
117517
|
exports.evaluateCompositionField = evaluateCompositionField;
|
|
116830
117518
|
exports.evaluateCount = require_composition.evaluateCount;
|
|
@@ -116898,10 +117586,13 @@ exports.gifFilterComplex = gifFilterComplex;
|
|
|
116898
117586
|
exports.gifFromMp4Args = gifFromMp4Args;
|
|
116899
117587
|
exports.globalSecretScope = require_sleep.globalSecretScope;
|
|
116900
117588
|
exports.grantRowsOf = grantRowsOf;
|
|
117589
|
+
exports.groupStatusCapability = groupStatusCapability;
|
|
117590
|
+
exports.groupTemplate = groupTemplate;
|
|
116901
117591
|
exports.hasModelBoundOverrides = hasModelBoundOverrides;
|
|
116902
117592
|
exports.hasMotionTrigger = hasMotionTrigger;
|
|
116903
117593
|
exports.hasUrlScheme = hasUrlScheme;
|
|
116904
117594
|
exports.heatingValveCapability = heatingValveCapability;
|
|
117595
|
+
exports.helperSaveProblems = helperSaveProblems;
|
|
116905
117596
|
exports.hfModelUrl = require_sleep.hfModelUrl;
|
|
116906
117597
|
exports.historyFieldsFor = historyFieldsFor;
|
|
116907
117598
|
exports.historyItemFieldPath = require_sleep.historyItemFieldPath;
|
|
@@ -117329,6 +118020,7 @@ exports.runtimeDevices = runtimeDevices;
|
|
|
117329
118020
|
exports.runtimeFieldUnit = runtimeFieldUnit;
|
|
117330
118021
|
exports.runtimeStatePolicyFor = runtimeStatePolicyFor;
|
|
117331
118022
|
exports.sameDoFamily = sameDoFamily;
|
|
118023
|
+
exports.sameHelperBody = sameHelperBody;
|
|
117332
118024
|
exports.sameRead = sameRead;
|
|
117333
118025
|
exports.sceneMonitorCapability = sceneMonitorCapability;
|
|
117334
118026
|
exports.scheduleForSendTimes = scheduleForSendTimes;
|
|
@@ -117378,6 +118070,7 @@ exports.sliceChangedAt = require_composition.sliceChangedAt;
|
|
|
117378
118070
|
exports.smokeCapability = smokeCapability;
|
|
117379
118071
|
exports.smtpProviderCapability = smtpProviderCapability;
|
|
117380
118072
|
exports.snapshotCapability = snapshotCapability;
|
|
118073
|
+
exports.sourcePickForTemplate = sourcePickForTemplate;
|
|
117381
118074
|
exports.splitTranslationRef = splitTranslationRef;
|
|
117382
118075
|
exports.squareAround = squareAround;
|
|
117383
118076
|
exports.ssoBridgeCapability = ssoBridgeCapability;
|
|
@@ -117440,6 +118133,7 @@ exports.taskPhaseSchema = taskPhaseSchema;
|
|
|
117440
118133
|
exports.taskTargetSchema = taskTargetSchema;
|
|
117441
118134
|
exports.temperatureSensorCapability = temperatureSensorCapability;
|
|
117442
118135
|
exports.templateCarriesSummary = templateCarriesSummary;
|
|
118136
|
+
exports.templateDeviceType = templateDeviceType;
|
|
117443
118137
|
exports.templateVarDeliveryApplies = templateVarDeliveryApplies;
|
|
117444
118138
|
exports.templateVarKindApplies = templateVarKindApplies;
|
|
117445
118139
|
exports.templateVarSystemEventApplies = templateVarSystemEventApplies;
|