@camstack/addon-matter-broker 0.2.148 → 0.2.149
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/README.md +18 -0
- package/dist/addon.js +649 -16
- package/dist/addon.mjs +649 -16
- package/package.json +4 -2
package/dist/addon.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
|
|
|
11
11
|
import { finished } from "node:stream/promises";
|
|
12
12
|
import { createConnection, createServer as createServer$2 } from "node:net";
|
|
13
13
|
import * as dgram from "node:dgram";
|
|
14
|
-
//#region ../types/dist/event-category-
|
|
14
|
+
//#region ../types/dist/event-category-CT-hz5Rb.mjs
|
|
15
15
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
16
16
|
EventCategory["SystemBoot"] = "system.boot";
|
|
17
17
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -337,6 +337,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
337
337
|
/** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
|
|
338
338
|
EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
|
|
339
339
|
/**
|
|
340
|
+
* A camera's package LLM confirm has failed closed three times in a row
|
|
341
|
+
* (D931, 2026-10-26). One edge per camera until
|
|
342
|
+
* {@link PipelinePackageLlmAnswered}.
|
|
343
|
+
*/
|
|
344
|
+
EventCategory["PipelinePackageLlmSilent"] = "pipeline.package-llm-silent";
|
|
345
|
+
/** The recovery edge of {@link PipelinePackageLlmSilent}: a confirm returned yes or no. */
|
|
346
|
+
EventCategory["PipelinePackageLlmAnswered"] = "pipeline.package-llm-answered";
|
|
347
|
+
/**
|
|
340
348
|
* Per-camera pipeline config was mutated by the orchestrator
|
|
341
349
|
* (a settings change via `setAgentInferenceDevices` /
|
|
342
350
|
* `setCameraStepToggle` / `setCameraStepSettings`). Orchestrator
|
|
@@ -5579,7 +5587,7 @@ var ZodIssueCode = {
|
|
|
5579
5587
|
var ZodFirstPartyTypeKind;
|
|
5580
5588
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5581
5589
|
//#endregion
|
|
5582
|
-
//#region ../types/dist/sleep-
|
|
5590
|
+
//#region ../types/dist/sleep-bykKrTgu.mjs
|
|
5583
5591
|
/**
|
|
5584
5592
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5585
5593
|
* window to float samples (D455).
|
|
@@ -8360,6 +8368,53 @@ var READING_QUANTITIES = [
|
|
|
8360
8368
|
];
|
|
8361
8369
|
var ReadingQuantitySchema = _enum(READING_QUANTITIES);
|
|
8362
8370
|
new Set(READING_QUANTITIES);
|
|
8371
|
+
/**
|
|
8372
|
+
* Stored unit symbol for a quantity. `none` means the number is dimensionless
|
|
8373
|
+
* (or an index / ratio / count). `device` means the cap has no single unit.
|
|
8374
|
+
*/
|
|
8375
|
+
var QUANTITY_BASE = {
|
|
8376
|
+
temperature: "°C",
|
|
8377
|
+
pressure: "hPa",
|
|
8378
|
+
speed: "m/s",
|
|
8379
|
+
precipitation: "mm",
|
|
8380
|
+
"precipitation-rate": "mm/h",
|
|
8381
|
+
length: "m",
|
|
8382
|
+
area: "m²",
|
|
8383
|
+
illuminance: "lx",
|
|
8384
|
+
irradiance: "W/m²",
|
|
8385
|
+
power: "W",
|
|
8386
|
+
energy: "kWh",
|
|
8387
|
+
voltage: "V",
|
|
8388
|
+
current: "A",
|
|
8389
|
+
"apparent-power": "VA",
|
|
8390
|
+
humidity: "%",
|
|
8391
|
+
percentage: "%",
|
|
8392
|
+
"concentration-volume": "ppm",
|
|
8393
|
+
"concentration-mass": "µg/m³",
|
|
8394
|
+
"concentration-ppb": "ppb",
|
|
8395
|
+
volume: "L",
|
|
8396
|
+
duration: "s",
|
|
8397
|
+
"duration-ms": "ms",
|
|
8398
|
+
information: "B",
|
|
8399
|
+
"sound-level": "dBFS",
|
|
8400
|
+
"signal-level": "dBm",
|
|
8401
|
+
"colour-temperature": "mired",
|
|
8402
|
+
angle: "°",
|
|
8403
|
+
bitrate: "kbps",
|
|
8404
|
+
rate: "fps",
|
|
8405
|
+
mass: "kg",
|
|
8406
|
+
index: "none",
|
|
8407
|
+
ratio: "none",
|
|
8408
|
+
count: "none",
|
|
8409
|
+
none: "none",
|
|
8410
|
+
device: "device"
|
|
8411
|
+
};
|
|
8412
|
+
/** The stored unit, or `undefined` when the quantity has no unit symbol. */
|
|
8413
|
+
function baseUnitOf(quantity) {
|
|
8414
|
+
const symbol = QUANTITY_BASE[quantity];
|
|
8415
|
+
if (symbol === "none" || symbol === "device") return void 0;
|
|
8416
|
+
return symbol;
|
|
8417
|
+
}
|
|
8363
8418
|
function readingMeta(quantity, extras) {
|
|
8364
8419
|
return {
|
|
8365
8420
|
quantity,
|
|
@@ -8913,6 +8968,8 @@ var CAP_NAMES = Object.freeze([
|
|
|
8913
8968
|
"filesystem-browse",
|
|
8914
8969
|
"flood",
|
|
8915
8970
|
"gas",
|
|
8971
|
+
"group-commands",
|
|
8972
|
+
"group-status",
|
|
8916
8973
|
"heating-valve",
|
|
8917
8974
|
"humidifier",
|
|
8918
8975
|
"humidity-sensor",
|
|
@@ -9731,6 +9788,20 @@ Object.freeze({
|
|
|
9731
9788
|
"path": "detected",
|
|
9732
9789
|
"valueType": "boolean"
|
|
9733
9790
|
}],
|
|
9791
|
+
"group-status": [
|
|
9792
|
+
{
|
|
9793
|
+
"path": "included",
|
|
9794
|
+
"valueType": "number"
|
|
9795
|
+
},
|
|
9796
|
+
{
|
|
9797
|
+
"path": "excluded",
|
|
9798
|
+
"valueType": "number"
|
|
9799
|
+
},
|
|
9800
|
+
{
|
|
9801
|
+
"path": "total",
|
|
9802
|
+
"valueType": "number"
|
|
9803
|
+
}
|
|
9804
|
+
],
|
|
9734
9805
|
"heating-valve": [{
|
|
9735
9806
|
"path": "position",
|
|
9736
9807
|
"valueType": "number"
|
|
@@ -11072,7 +11143,7 @@ function errMsg(err) {
|
|
|
11072
11143
|
return String(err);
|
|
11073
11144
|
}
|
|
11074
11145
|
//#endregion
|
|
11075
|
-
//#region ../types/dist/composition-
|
|
11146
|
+
//#region ../types/dist/composition-OhpuespA.mjs
|
|
11076
11147
|
/**
|
|
11077
11148
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11078
11149
|
*
|
|
@@ -11827,15 +11898,74 @@ function validateExpressionSource(src) {
|
|
|
11827
11898
|
}
|
|
11828
11899
|
return null;
|
|
11829
11900
|
}
|
|
11830
|
-
/**
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11901
|
+
/**
|
|
11902
|
+
* A composition source identity: `(addonId, stableId)`, never a numeric device
|
|
11903
|
+
* id. Split out so helper schemas can name it without a cycle through
|
|
11904
|
+
* `composition.ts` (D659).
|
|
11905
|
+
*/
|
|
11834
11906
|
var CompositionSourceRefSchema = object({
|
|
11835
11907
|
/** The owning addon; `stableId` is unique only within it. */
|
|
11836
11908
|
addonId: string$2().min(1),
|
|
11837
11909
|
stableId: string$2().min(1)
|
|
11838
11910
|
});
|
|
11911
|
+
var GROUP_TEMPLATE_IDS = [
|
|
11912
|
+
"temperature",
|
|
11913
|
+
"humidity",
|
|
11914
|
+
"pressure",
|
|
11915
|
+
"illuminance",
|
|
11916
|
+
"power",
|
|
11917
|
+
"energy",
|
|
11918
|
+
"battery",
|
|
11919
|
+
"numeric",
|
|
11920
|
+
"motion",
|
|
11921
|
+
"contact",
|
|
11922
|
+
"leak",
|
|
11923
|
+
"smoke",
|
|
11924
|
+
"occupancy",
|
|
11925
|
+
"binary",
|
|
11926
|
+
"switch",
|
|
11927
|
+
"light"
|
|
11928
|
+
];
|
|
11929
|
+
var NUMERIC_AGGREGATES = [
|
|
11930
|
+
"mean",
|
|
11931
|
+
"median",
|
|
11932
|
+
"min",
|
|
11933
|
+
"max",
|
|
11934
|
+
"sum"
|
|
11935
|
+
];
|
|
11936
|
+
var BINARY_AGGREGATES = ["any", "all"];
|
|
11937
|
+
/** How an actuator group decides it is on. Unknown members never count as off. */
|
|
11938
|
+
var ACTIVE_CRITERIA = ["at-least-one", "all"];
|
|
11939
|
+
var AGGREGATE_REDUCERS = [
|
|
11940
|
+
"mean",
|
|
11941
|
+
"median",
|
|
11942
|
+
"min",
|
|
11943
|
+
"max",
|
|
11944
|
+
"sum",
|
|
11945
|
+
"any",
|
|
11946
|
+
"all"
|
|
11947
|
+
];
|
|
11948
|
+
var GroupTemplateIdSchema = _enum(GROUP_TEMPLATE_IDS);
|
|
11949
|
+
var AggregateReducerSchema = _enum(AGGREGATE_REDUCERS);
|
|
11950
|
+
var ActiveCriterionSchema = _enum(ACTIVE_CRITERIA);
|
|
11951
|
+
/** One member. The field is stored so occupancy can name motion or binary. */
|
|
11952
|
+
var HelperMemberSchema = object({
|
|
11953
|
+
source: CompositionSourceRefSchema,
|
|
11954
|
+
cap: string$2().min(1),
|
|
11955
|
+
fieldPath: string$2().min(1)
|
|
11956
|
+
});
|
|
11957
|
+
var HelperSpecSchema = discriminatedUnion("kind", [object({
|
|
11958
|
+
kind: literal("group"),
|
|
11959
|
+
templateId: GroupTemplateIdSchema,
|
|
11960
|
+
aggregate: AggregateReducerSchema,
|
|
11961
|
+
members: array(HelperMemberSchema).min(1).max(64),
|
|
11962
|
+
/** Actuator groups only. Readings leave this unset. */
|
|
11963
|
+
active: ActiveCriterionSchema.optional()
|
|
11964
|
+
})]);
|
|
11965
|
+
/** A composed device's stableId is this prefix plus the block id. */
|
|
11966
|
+
var COMPOSED_DEVICE_STABLE_ID_PREFIX = "composed-";
|
|
11967
|
+
/** Longest snippet a `code` source may carry (slice 4). */
|
|
11968
|
+
var MAX_COMPOSITION_CODE_LENGTH = 2e4;
|
|
11839
11969
|
/** One field of one capability of one source device. */
|
|
11840
11970
|
var CompositionFieldReadSchema = object({
|
|
11841
11971
|
source: CompositionSourceRefSchema,
|
|
@@ -11879,7 +12009,33 @@ var CompositionCodeSourceSchema = object({
|
|
|
11879
12009
|
var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
11880
12010
|
CompositionFromSourceSchema,
|
|
11881
12011
|
CompositionExpressionSourceSchema,
|
|
11882
|
-
CompositionCodeSourceSchema
|
|
12012
|
+
CompositionCodeSourceSchema,
|
|
12013
|
+
object({
|
|
12014
|
+
kind: literal("aggregate"),
|
|
12015
|
+
reducer: _enum([
|
|
12016
|
+
"mean",
|
|
12017
|
+
"median",
|
|
12018
|
+
"min",
|
|
12019
|
+
"max",
|
|
12020
|
+
"sum",
|
|
12021
|
+
"any",
|
|
12022
|
+
"all"
|
|
12023
|
+
]),
|
|
12024
|
+
reads: array(CompositionFieldReadSchema).min(1).max(64),
|
|
12025
|
+
/** `value` is the reading; the others are the member counts. */
|
|
12026
|
+
publish: _enum([
|
|
12027
|
+
"value",
|
|
12028
|
+
"included",
|
|
12029
|
+
"excluded",
|
|
12030
|
+
"total"
|
|
12031
|
+
]),
|
|
12032
|
+
/** What a `value` publish does when nobody is included. Counts ignore this. */
|
|
12033
|
+
empty: _enum([
|
|
12034
|
+
"null",
|
|
12035
|
+
"omit",
|
|
12036
|
+
"offline"
|
|
12037
|
+
])
|
|
12038
|
+
})
|
|
11883
12039
|
]);
|
|
11884
12040
|
var CompositionCommandTargetSchema = discriminatedUnion("kind", [object({
|
|
11885
12041
|
kind: literal("forward"),
|
|
@@ -11925,7 +12081,13 @@ var CompositionSchema = object({
|
|
|
11925
12081
|
kind: literal("existing"),
|
|
11926
12082
|
device: CompositionSourceRefSchema
|
|
11927
12083
|
})]),
|
|
11928
|
-
features: array(CompositionFeatureSchema).min(1).max(16)
|
|
12084
|
+
features: array(CompositionFeatureSchema).min(1).max(16),
|
|
12085
|
+
/**
|
|
12086
|
+
* Present when the block is a helper template. Absent on a free
|
|
12087
|
+
* composition (the room example, device 4603). The editor reads this,
|
|
12088
|
+
* never the compiled features.
|
|
12089
|
+
*/
|
|
12090
|
+
helper: HelperSpecSchema.optional()
|
|
11929
12091
|
}).superRefine((composition, ctx) => {
|
|
11930
12092
|
const seen = /* @__PURE__ */ new Set();
|
|
11931
12093
|
composition.features.forEach((feature, index) => {
|
|
@@ -18183,7 +18345,10 @@ var CompositionProblemSchema = object({
|
|
|
18183
18345
|
"target-missing",
|
|
18184
18346
|
"target-unreadable",
|
|
18185
18347
|
"not-replaceable",
|
|
18186
|
-
"native-capability-replace"
|
|
18348
|
+
"native-capability-replace",
|
|
18349
|
+
"mixed-quantity",
|
|
18350
|
+
"helper-mismatch",
|
|
18351
|
+
"member-constraint"
|
|
18187
18352
|
]),
|
|
18188
18353
|
path: string$2(),
|
|
18189
18354
|
message: string$2()
|
|
@@ -18204,7 +18369,8 @@ var CompositionUnavailableModeSchema = _enum([
|
|
|
18204
18369
|
"null",
|
|
18205
18370
|
"offline",
|
|
18206
18371
|
"unknown",
|
|
18207
|
-
"release"
|
|
18372
|
+
"release",
|
|
18373
|
+
"omit"
|
|
18208
18374
|
]);
|
|
18209
18375
|
/**
|
|
18210
18376
|
* `derived` reads a source · `clock` reads only `now`, recomputed when a sibling
|
|
@@ -18418,6 +18584,275 @@ Object.freeze({
|
|
|
18418
18584
|
result: ["number", "null"]
|
|
18419
18585
|
}
|
|
18420
18586
|
});
|
|
18587
|
+
/**
|
|
18588
|
+
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18589
|
+
* Data, not a form default written into the block.
|
|
18590
|
+
*/
|
|
18591
|
+
var NOW = {
|
|
18592
|
+
fieldPath: "lastFetchedAt",
|
|
18593
|
+
expr: "now"
|
|
18594
|
+
};
|
|
18595
|
+
var CHANGED = {
|
|
18596
|
+
fieldPath: "lastChangedAt",
|
|
18597
|
+
expr: "now"
|
|
18598
|
+
};
|
|
18599
|
+
function numeric(input) {
|
|
18600
|
+
return {
|
|
18601
|
+
...input,
|
|
18602
|
+
family: "numeric",
|
|
18603
|
+
deviceType: DeviceType.Sensor,
|
|
18604
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18605
|
+
commandCaps: [],
|
|
18606
|
+
baseUnit: baseUnitOf(input.quantity),
|
|
18607
|
+
aggregates: NUMERIC_AGGREGATES,
|
|
18608
|
+
accept: [{
|
|
18609
|
+
cap: input.outputCap,
|
|
18610
|
+
fieldPath: input.outputField
|
|
18611
|
+
}]
|
|
18612
|
+
};
|
|
18613
|
+
}
|
|
18614
|
+
function binary(input) {
|
|
18615
|
+
return {
|
|
18616
|
+
...input,
|
|
18617
|
+
family: "binary",
|
|
18618
|
+
deviceType: DeviceType.Sensor,
|
|
18619
|
+
memberDeviceType: DeviceType.Sensor,
|
|
18620
|
+
commandCaps: [],
|
|
18621
|
+
quantity: "none",
|
|
18622
|
+
baseUnit: void 0,
|
|
18623
|
+
aggregates: BINARY_AGGREGATES,
|
|
18624
|
+
empty: "offline"
|
|
18625
|
+
};
|
|
18626
|
+
}
|
|
18627
|
+
var GROUP_TEMPLATES = [
|
|
18628
|
+
numeric({
|
|
18629
|
+
id: "temperature",
|
|
18630
|
+
summary: "Mean, median, min, max or sum of temperatures. Offline and unknown members are left out, never read as 0 °C.",
|
|
18631
|
+
role: DeviceRole.TemperatureSensor,
|
|
18632
|
+
outputCap: "temperature-sensor",
|
|
18633
|
+
outputField: "celsius",
|
|
18634
|
+
quantity: "temperature",
|
|
18635
|
+
defaultAggregate: "mean",
|
|
18636
|
+
empty: "null",
|
|
18637
|
+
companions: [NOW]
|
|
18638
|
+
}),
|
|
18639
|
+
numeric({
|
|
18640
|
+
id: "humidity",
|
|
18641
|
+
summary: "Humidity in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18642
|
+
role: DeviceRole.HumiditySensor,
|
|
18643
|
+
outputCap: "humidity-sensor",
|
|
18644
|
+
outputField: "percent",
|
|
18645
|
+
quantity: "humidity",
|
|
18646
|
+
defaultAggregate: "mean",
|
|
18647
|
+
empty: "null",
|
|
18648
|
+
companions: [NOW]
|
|
18649
|
+
}),
|
|
18650
|
+
numeric({
|
|
18651
|
+
id: "pressure",
|
|
18652
|
+
summary: "Pressure in hectopascals. Offline and unknown members are left out, never read as 0 hPa.",
|
|
18653
|
+
role: DeviceRole.PressureSensor,
|
|
18654
|
+
outputCap: "pressure-sensor",
|
|
18655
|
+
outputField: "hpa",
|
|
18656
|
+
quantity: "pressure",
|
|
18657
|
+
defaultAggregate: "mean",
|
|
18658
|
+
empty: "null",
|
|
18659
|
+
companions: [NOW]
|
|
18660
|
+
}),
|
|
18661
|
+
numeric({
|
|
18662
|
+
id: "illuminance",
|
|
18663
|
+
summary: "Illuminance in lux. Offline and unknown members are left out, never read as 0 lx.",
|
|
18664
|
+
role: DeviceRole.AmbientLightSensor,
|
|
18665
|
+
outputCap: "ambient-light-sensor",
|
|
18666
|
+
outputField: "lux",
|
|
18667
|
+
quantity: "illuminance",
|
|
18668
|
+
defaultAggregate: "mean",
|
|
18669
|
+
empty: "null",
|
|
18670
|
+
companions: [NOW]
|
|
18671
|
+
}),
|
|
18672
|
+
numeric({
|
|
18673
|
+
id: "power",
|
|
18674
|
+
summary: "Power in watts, summed by default. Nobody reporting omits the key rather than writing 0 W.",
|
|
18675
|
+
role: DeviceRole.PowerSensor,
|
|
18676
|
+
outputCap: "power-meter",
|
|
18677
|
+
outputField: "watts",
|
|
18678
|
+
quantity: "power",
|
|
18679
|
+
defaultAggregate: "sum",
|
|
18680
|
+
empty: "omit",
|
|
18681
|
+
companions: [NOW]
|
|
18682
|
+
}),
|
|
18683
|
+
numeric({
|
|
18684
|
+
id: "energy",
|
|
18685
|
+
summary: "Energy in kilowatt-hours, summed by default. Nobody reporting omits the key rather than writing 0 kWh.",
|
|
18686
|
+
role: DeviceRole.EnergySensor,
|
|
18687
|
+
outputCap: "power-meter",
|
|
18688
|
+
outputField: "kwhTotal",
|
|
18689
|
+
quantity: "energy",
|
|
18690
|
+
defaultAggregate: "sum",
|
|
18691
|
+
empty: "omit",
|
|
18692
|
+
companions: [NOW]
|
|
18693
|
+
}),
|
|
18694
|
+
numeric({
|
|
18695
|
+
id: "battery",
|
|
18696
|
+
summary: "Battery charge in percent. Offline and unknown members are left out, never read as 0 %.",
|
|
18697
|
+
role: DeviceRole.BatterySensor,
|
|
18698
|
+
outputCap: "battery",
|
|
18699
|
+
outputField: "percentage",
|
|
18700
|
+
quantity: "percentage",
|
|
18701
|
+
defaultAggregate: "mean",
|
|
18702
|
+
empty: "null",
|
|
18703
|
+
companions: [
|
|
18704
|
+
{
|
|
18705
|
+
fieldPath: "charging",
|
|
18706
|
+
expr: "\"unknown\""
|
|
18707
|
+
},
|
|
18708
|
+
{
|
|
18709
|
+
fieldPath: "sleeping",
|
|
18710
|
+
expr: "false"
|
|
18711
|
+
},
|
|
18712
|
+
{
|
|
18713
|
+
fieldPath: "lastUpdated",
|
|
18714
|
+
expr: "now"
|
|
18715
|
+
}
|
|
18716
|
+
]
|
|
18717
|
+
}),
|
|
18718
|
+
numeric({
|
|
18719
|
+
id: "numeric",
|
|
18720
|
+
summary: "A numeric reading in the members’ shared quantity. Mixed quantities are refused. Nobody reporting publishes null, not 0.",
|
|
18721
|
+
role: DeviceRole.NumericSensor,
|
|
18722
|
+
outputCap: "numeric-sensor",
|
|
18723
|
+
outputField: "value",
|
|
18724
|
+
quantity: "device",
|
|
18725
|
+
defaultAggregate: "mean",
|
|
18726
|
+
empty: "null",
|
|
18727
|
+
companions: [NOW]
|
|
18728
|
+
}),
|
|
18729
|
+
binary({
|
|
18730
|
+
id: "motion",
|
|
18731
|
+
summary: "Any or all motion. Offline and unknown members are left out, never read as off. Nobody reporting takes the device offline.",
|
|
18732
|
+
role: DeviceRole.MotionSensor,
|
|
18733
|
+
outputCap: "motion",
|
|
18734
|
+
outputField: "detected",
|
|
18735
|
+
defaultAggregate: "any",
|
|
18736
|
+
accept: [{
|
|
18737
|
+
cap: "motion",
|
|
18738
|
+
fieldPath: "detected"
|
|
18739
|
+
}],
|
|
18740
|
+
companions: [{
|
|
18741
|
+
fieldPath: "lastDetectedAt",
|
|
18742
|
+
expr: "null"
|
|
18743
|
+
}, {
|
|
18744
|
+
fieldPath: "autoClearAfterMs",
|
|
18745
|
+
expr: "null"
|
|
18746
|
+
}]
|
|
18747
|
+
}),
|
|
18748
|
+
binary({
|
|
18749
|
+
id: "contact",
|
|
18750
|
+
summary: "Any or all open contacts. Offline and unknown members are left out, never read as closed.",
|
|
18751
|
+
role: DeviceRole.ContactSensor,
|
|
18752
|
+
outputCap: "contact",
|
|
18753
|
+
outputField: "entryOpen",
|
|
18754
|
+
defaultAggregate: "any",
|
|
18755
|
+
accept: [{
|
|
18756
|
+
cap: "contact",
|
|
18757
|
+
fieldPath: "entryOpen"
|
|
18758
|
+
}],
|
|
18759
|
+
companions: [CHANGED]
|
|
18760
|
+
}),
|
|
18761
|
+
binary({
|
|
18762
|
+
id: "leak",
|
|
18763
|
+
summary: "Any or all leak detections. Offline and unknown members are left out, never read as dry.",
|
|
18764
|
+
role: DeviceRole.LeakSensor,
|
|
18765
|
+
outputCap: "flood",
|
|
18766
|
+
outputField: "flooded",
|
|
18767
|
+
defaultAggregate: "any",
|
|
18768
|
+
accept: [{
|
|
18769
|
+
cap: "flood",
|
|
18770
|
+
fieldPath: "flooded"
|
|
18771
|
+
}],
|
|
18772
|
+
companions: [CHANGED]
|
|
18773
|
+
}),
|
|
18774
|
+
binary({
|
|
18775
|
+
id: "smoke",
|
|
18776
|
+
summary: "Any or all smoke detections. Offline and unknown members are left out, never read as clear.",
|
|
18777
|
+
role: DeviceRole.SmokeSensor,
|
|
18778
|
+
outputCap: "smoke",
|
|
18779
|
+
outputField: "detected",
|
|
18780
|
+
defaultAggregate: "any",
|
|
18781
|
+
accept: [{
|
|
18782
|
+
cap: "smoke",
|
|
18783
|
+
fieldPath: "detected"
|
|
18784
|
+
}],
|
|
18785
|
+
companions: [CHANGED]
|
|
18786
|
+
}),
|
|
18787
|
+
binary({
|
|
18788
|
+
id: "occupancy",
|
|
18789
|
+
summary: "Any or all of motion or binary sensors, published as a binary. Presence zones are not aggregated. Nobody reporting is offline, not off.",
|
|
18790
|
+
role: DeviceRole.BinarySensor,
|
|
18791
|
+
outputCap: "binary",
|
|
18792
|
+
outputField: "on",
|
|
18793
|
+
defaultAggregate: "any",
|
|
18794
|
+
accept: [{
|
|
18795
|
+
cap: "motion",
|
|
18796
|
+
fieldPath: "detected"
|
|
18797
|
+
}, {
|
|
18798
|
+
cap: "binary",
|
|
18799
|
+
fieldPath: "on"
|
|
18800
|
+
}],
|
|
18801
|
+
companions: [CHANGED]
|
|
18802
|
+
}),
|
|
18803
|
+
binary({
|
|
18804
|
+
id: "binary",
|
|
18805
|
+
summary: "Any or all generic binary sensors. Offline and unknown members are left out, never read as off.",
|
|
18806
|
+
role: DeviceRole.BinarySensor,
|
|
18807
|
+
outputCap: "binary",
|
|
18808
|
+
outputField: "on",
|
|
18809
|
+
defaultAggregate: "any",
|
|
18810
|
+
accept: [{
|
|
18811
|
+
cap: "binary",
|
|
18812
|
+
fieldPath: "on"
|
|
18813
|
+
}],
|
|
18814
|
+
companions: [CHANGED]
|
|
18815
|
+
}),
|
|
18816
|
+
actuator({
|
|
18817
|
+
id: "switch",
|
|
18818
|
+
summary: "On when at least one switch is on, or when all of them are. Offline and unknown members are left out of that decision, never read as off, and still receive the command.",
|
|
18819
|
+
deviceType: DeviceType.Switch,
|
|
18820
|
+
outputCap: "switch",
|
|
18821
|
+
commandCaps: ["switch"]
|
|
18822
|
+
}),
|
|
18823
|
+
actuator({
|
|
18824
|
+
id: "light",
|
|
18825
|
+
summary: "On when at least one light is on, or when all of them are. Brightness and colour are offered only when every member has them. A command is not sent to a member that lacks it.",
|
|
18826
|
+
deviceType: DeviceType.Light,
|
|
18827
|
+
outputCap: "switch",
|
|
18828
|
+
commandCaps: [
|
|
18829
|
+
"switch",
|
|
18830
|
+
"brightness",
|
|
18831
|
+
"color"
|
|
18832
|
+
]
|
|
18833
|
+
})
|
|
18834
|
+
];
|
|
18835
|
+
function actuator(input) {
|
|
18836
|
+
return {
|
|
18837
|
+
...input,
|
|
18838
|
+
family: "actuator",
|
|
18839
|
+
role: void 0,
|
|
18840
|
+
memberDeviceType: input.deviceType,
|
|
18841
|
+
outputField: "on",
|
|
18842
|
+
quantity: "none",
|
|
18843
|
+
baseUnit: void 0,
|
|
18844
|
+
aggregates: BINARY_AGGREGATES,
|
|
18845
|
+
defaultAggregate: "any",
|
|
18846
|
+
empty: "offline",
|
|
18847
|
+
accept: [{
|
|
18848
|
+
cap: "switch",
|
|
18849
|
+
fieldPath: "on"
|
|
18850
|
+
}],
|
|
18851
|
+
companions: [CHANGED]
|
|
18852
|
+
};
|
|
18853
|
+
}
|
|
18854
|
+
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
18855
|
+
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
18421
18856
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
18422
18857
|
/**
|
|
18423
18858
|
* What a composition may BUILD on a device type (G2, D676): the caps a new
|
|
@@ -45237,6 +45672,8 @@ var NcSystemEventKindSchema = _enum([
|
|
|
45237
45672
|
"detection-blind",
|
|
45238
45673
|
"motion-noisy",
|
|
45239
45674
|
"motion-calm",
|
|
45675
|
+
"package-llm-silent",
|
|
45676
|
+
"package-llm-answered",
|
|
45240
45677
|
"recording-stalled",
|
|
45241
45678
|
"recording-healthy",
|
|
45242
45679
|
"recording-degraded",
|
|
@@ -56328,6 +56765,28 @@ var PackageVersionInfoSchema = object({
|
|
|
56328
56765
|
deprecated: string$2().optional(),
|
|
56329
56766
|
distTags: array(string$2()).readonly()
|
|
56330
56767
|
});
|
|
56768
|
+
/**
|
|
56769
|
+
* One published document. `ok` is markdown from the registry. `missing` means
|
|
56770
|
+
* the registry answered and the file was not there. `error` is a registry or
|
|
56771
|
+
* tarball failure — never an empty string standing in for either.
|
|
56772
|
+
*/
|
|
56773
|
+
var PackageDocBodySchema = discriminatedUnion("status", [
|
|
56774
|
+
object({
|
|
56775
|
+
status: literal("ok"),
|
|
56776
|
+
markdown: string$2()
|
|
56777
|
+
}),
|
|
56778
|
+
object({ status: literal("missing") }),
|
|
56779
|
+
object({
|
|
56780
|
+
status: literal("error"),
|
|
56781
|
+
message: string$2()
|
|
56782
|
+
})
|
|
56783
|
+
]);
|
|
56784
|
+
var PackageDocsSchema = object({
|
|
56785
|
+
name: string$2(),
|
|
56786
|
+
version: string$2(),
|
|
56787
|
+
readme: PackageDocBodySchema,
|
|
56788
|
+
changelog: PackageDocBodySchema
|
|
56789
|
+
});
|
|
56331
56790
|
var SearchResultSchema = object({
|
|
56332
56791
|
name: string$2(),
|
|
56333
56792
|
version: string$2(),
|
|
@@ -56546,7 +57005,10 @@ method(object({ nodeId: string$2().optional() }).optional(), array(AddonListItem
|
|
|
56546
57005
|
}), object({ success: literal(true) }), {
|
|
56547
57006
|
kind: "mutation",
|
|
56548
57007
|
auth: "admin"
|
|
56549
|
-
}), method(object({ name: string$2() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57008
|
+
}), method(object({ name: string$2() }), array(PackageVersionInfoSchema).readonly()), method(object({
|
|
57009
|
+
name: string$2().min(1),
|
|
57010
|
+
version: string$2().min(1).optional()
|
|
57011
|
+
}), PackageDocsSchema, { auth: "admin" }), method(object({ addonId: string$2() }), RestartAddonResultSchema, {
|
|
56550
57012
|
kind: "mutation",
|
|
56551
57013
|
auth: "admin"
|
|
56552
57014
|
}), method(object({ packageName: string$2() }), object({ success: literal(true) }), {
|
|
@@ -59882,6 +60344,88 @@ var gasCapability = {
|
|
|
59882
60344
|
* whether persisting is worth a SQLite commit. */
|
|
59883
60345
|
volatileStateFields: ["lastChangedAt"]
|
|
59884
60346
|
};
|
|
60347
|
+
var GroupCommandsSchema = object({
|
|
60348
|
+
/** One row per member that has been commanded. A later command replaces that member's row. */
|
|
60349
|
+
results: array(object({
|
|
60350
|
+
deviceId: number().int().nonnegative(),
|
|
60351
|
+
cap: string$2().min(1),
|
|
60352
|
+
method: string$2().min(1),
|
|
60353
|
+
ok: boolean(),
|
|
60354
|
+
error: string$2().optional(),
|
|
60355
|
+
/** Ms epoch of the attempt. */
|
|
60356
|
+
at: number()
|
|
60357
|
+
})) });
|
|
60358
|
+
var groupCommandsCapability = {
|
|
60359
|
+
name: "group-commands",
|
|
60360
|
+
scope: "device",
|
|
60361
|
+
deviceNative: true,
|
|
60362
|
+
mode: "singleton",
|
|
60363
|
+
deviceTypes: [DeviceType.Switch, DeviceType.Light],
|
|
60364
|
+
methods: {},
|
|
60365
|
+
status: {
|
|
60366
|
+
schema: GroupCommandsSchema,
|
|
60367
|
+
kind: "push"
|
|
60368
|
+
},
|
|
60369
|
+
runtimeState: GroupCommandsSchema,
|
|
60370
|
+
/**
|
|
60371
|
+
* Runtime-state durability: **session** — the last attempt. A restored
|
|
60372
|
+
* failure would outlive the command that caused it.
|
|
60373
|
+
*
|
|
60374
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60375
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60376
|
+
*/
|
|
60377
|
+
durability: "session",
|
|
60378
|
+
history: "none"
|
|
60379
|
+
};
|
|
60380
|
+
/**
|
|
60381
|
+
* How many members of a helper group answered (D944). Counts are integers,
|
|
60382
|
+
* not measurements: zero included is a real count, never a stand-in reading.
|
|
60383
|
+
* The reading itself stays on the output capability. History is none — the
|
|
60384
|
+
* series that later statistics read is the output cap's own history block.
|
|
60385
|
+
*/
|
|
60386
|
+
var GroupStatusSchema = object({
|
|
60387
|
+
/** Members whose current value entered the aggregate. */
|
|
60388
|
+
included: number().int().nonnegative().meta(readingMeta("count", {
|
|
60389
|
+
precision: 0,
|
|
60390
|
+
label: "Reporting"
|
|
60391
|
+
})),
|
|
60392
|
+
/** Members left out: offline, unknown, or not a finite reading (D393). */
|
|
60393
|
+
excluded: number().int().nonnegative().meta(readingMeta("count", {
|
|
60394
|
+
precision: 0,
|
|
60395
|
+
label: "Excluded"
|
|
60396
|
+
})),
|
|
60397
|
+
/** `included` + `excluded`. */
|
|
60398
|
+
total: number().int().nonnegative().meta(readingMeta("count", {
|
|
60399
|
+
precision: 0,
|
|
60400
|
+
label: "Members"
|
|
60401
|
+
}))
|
|
60402
|
+
});
|
|
60403
|
+
var groupStatusCapability = {
|
|
60404
|
+
name: "group-status",
|
|
60405
|
+
scope: "device",
|
|
60406
|
+
deviceNative: true,
|
|
60407
|
+
mode: "singleton",
|
|
60408
|
+
deviceTypes: [
|
|
60409
|
+
DeviceType.Sensor,
|
|
60410
|
+
DeviceType.Switch,
|
|
60411
|
+
DeviceType.Light
|
|
60412
|
+
],
|
|
60413
|
+
methods: {},
|
|
60414
|
+
status: {
|
|
60415
|
+
schema: GroupStatusSchema,
|
|
60416
|
+
kind: "push"
|
|
60417
|
+
},
|
|
60418
|
+
runtimeState: GroupStatusSchema,
|
|
60419
|
+
/**
|
|
60420
|
+
* Runtime-state durability: **session** — recomputed from members on the
|
|
60421
|
+
* next source event; a restored count would outlive the readings it named.
|
|
60422
|
+
*
|
|
60423
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
60424
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
60425
|
+
*/
|
|
60426
|
+
durability: "session",
|
|
60427
|
+
history: "none"
|
|
60428
|
+
};
|
|
59885
60429
|
var HeatingValveStatusSchema = object({
|
|
59886
60430
|
/** Radiator valve opening 0 (closed) .. 100 (open). Null = not yet known. */
|
|
59887
60431
|
position: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
@@ -61651,12 +62195,18 @@ var motionCapability = {
|
|
|
61651
62195
|
methods: {
|
|
61652
62196
|
/**
|
|
61653
62197
|
* Pull the current motion state synchronously. Convenience shortcut
|
|
61654
|
-
* for consumers that don't need the full status object
|
|
61655
|
-
*
|
|
61656
|
-
* `getStatus` once the auto-injected status surface lands in every
|
|
61657
|
-
* consumer.
|
|
62198
|
+
* for consumers that don't need the full status object. A composed
|
|
62199
|
+
* group answers from its slice (D944): unknown throws, it is not off.
|
|
61658
62200
|
*/
|
|
61659
62201
|
isDetected: method(object({ deviceId: number() }), boolean()) },
|
|
62202
|
+
/**
|
|
62203
|
+
* A composed motion group serves `isDetected` from `detected` (D944).
|
|
62204
|
+
* Without this the cap stays uncomposable (`has-commands`).
|
|
62205
|
+
*/
|
|
62206
|
+
composedMethods: { isDetected: {
|
|
62207
|
+
kind: "slice",
|
|
62208
|
+
field: "detected"
|
|
62209
|
+
} },
|
|
61660
62210
|
events: {
|
|
61661
62211
|
/**
|
|
61662
62212
|
* Fires every time the runner transitions a camera between
|
|
@@ -69464,6 +70014,8 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
69464
70014
|
featureProbe: featureProbeCapability,
|
|
69465
70015
|
flood: floodCapability,
|
|
69466
70016
|
gas: gasCapability,
|
|
70017
|
+
groupCommands: groupCommandsCapability,
|
|
70018
|
+
groupStatus: groupStatusCapability,
|
|
69467
70019
|
heatingValve: heatingValveCapability,
|
|
69468
70020
|
humidifier: humidifierCapability,
|
|
69469
70021
|
humiditySensor: humiditySensorCapability,
|
|
@@ -70840,6 +71392,13 @@ Object.freeze({
|
|
|
70840
71392
|
access: "view",
|
|
70841
71393
|
role: "admin"
|
|
70842
71394
|
},
|
|
71395
|
+
"addons.getPackageDocs": {
|
|
71396
|
+
capName: "addons",
|
|
71397
|
+
capScope: "system",
|
|
71398
|
+
addonId: null,
|
|
71399
|
+
access: "view",
|
|
71400
|
+
role: "admin"
|
|
71401
|
+
},
|
|
70843
71402
|
"addons.getVersions": {
|
|
70844
71403
|
capName: "addons",
|
|
70845
71404
|
capScope: "system",
|
|
@@ -73948,6 +74507,20 @@ Object.freeze({
|
|
|
73948
74507
|
access: "view",
|
|
73949
74508
|
role: "viewer"
|
|
73950
74509
|
},
|
|
74510
|
+
"groupCommands.getStatus": {
|
|
74511
|
+
capName: "group-commands",
|
|
74512
|
+
capScope: "device",
|
|
74513
|
+
addonId: null,
|
|
74514
|
+
access: "view",
|
|
74515
|
+
role: "viewer"
|
|
74516
|
+
},
|
|
74517
|
+
"groupStatus.getStatus": {
|
|
74518
|
+
capName: "group-status",
|
|
74519
|
+
capScope: "device",
|
|
74520
|
+
addonId: null,
|
|
74521
|
+
access: "view",
|
|
74522
|
+
role: "viewer"
|
|
74523
|
+
},
|
|
73951
74524
|
"heatingValve.getStatus": {
|
|
73952
74525
|
capName: "heating-valve",
|
|
73953
74526
|
capScope: "device",
|
|
@@ -83770,6 +84343,37 @@ var SENSOR_CAP_VOCABULARY = {
|
|
|
83770
84343
|
icon: "flame"
|
|
83771
84344
|
}]
|
|
83772
84345
|
},
|
|
84346
|
+
"group-commands": {
|
|
84347
|
+
scope: "device",
|
|
84348
|
+
noun: t("Group command", "Comando di gruppo")
|
|
84349
|
+
},
|
|
84350
|
+
"group-status": {
|
|
84351
|
+
scope: "device",
|
|
84352
|
+
noun: t("Group", "Gruppo"),
|
|
84353
|
+
state: [
|
|
84354
|
+
{
|
|
84355
|
+
kind: "numeric",
|
|
84356
|
+
field: "included",
|
|
84357
|
+
quantity: t("the members reporting", "i membri che rispondono"),
|
|
84358
|
+
label: t("Reporting", "Rispondono"),
|
|
84359
|
+
icon: "users"
|
|
84360
|
+
},
|
|
84361
|
+
{
|
|
84362
|
+
kind: "numeric",
|
|
84363
|
+
field: "excluded",
|
|
84364
|
+
quantity: t("the members left out", "i membri esclusi"),
|
|
84365
|
+
label: t("Excluded", "Esclusi"),
|
|
84366
|
+
icon: "users"
|
|
84367
|
+
},
|
|
84368
|
+
{
|
|
84369
|
+
kind: "numeric",
|
|
84370
|
+
field: "total",
|
|
84371
|
+
quantity: t("the member count", "il numero di membri"),
|
|
84372
|
+
label: t("Members", "Membri"),
|
|
84373
|
+
icon: "sigma"
|
|
84374
|
+
}
|
|
84375
|
+
]
|
|
84376
|
+
},
|
|
83773
84377
|
"humidity-sensor": {
|
|
83774
84378
|
scope: "device",
|
|
83775
84379
|
noun: t("Humidity", "Umidità"),
|
|
@@ -85235,6 +85839,16 @@ Object.freeze({
|
|
|
85235
85839
|
form: "single",
|
|
85236
85840
|
optional: false
|
|
85237
85841
|
}],
|
|
85842
|
+
"groupCommands.getStatus": [{
|
|
85843
|
+
name: "deviceId",
|
|
85844
|
+
form: "single",
|
|
85845
|
+
optional: false
|
|
85846
|
+
}],
|
|
85847
|
+
"groupStatus.getStatus": [{
|
|
85848
|
+
name: "deviceId",
|
|
85849
|
+
form: "single",
|
|
85850
|
+
optional: false
|
|
85851
|
+
}],
|
|
85238
85852
|
"heatingValve.getStatus": [{
|
|
85239
85853
|
name: "deviceId",
|
|
85240
85854
|
form: "single",
|
|
@@ -87219,6 +87833,8 @@ new Map(Object.entries({
|
|
|
87219
87833
|
"detection-blind": "device-events",
|
|
87220
87834
|
"motion-noisy": "device-events",
|
|
87221
87835
|
"motion-calm": "device-events",
|
|
87836
|
+
"package-llm-silent": "device-events",
|
|
87837
|
+
"package-llm-answered": "device-events",
|
|
87222
87838
|
"recording-stalled": "device-events",
|
|
87223
87839
|
"recording-healthy": "device-events",
|
|
87224
87840
|
"recording-degraded": "device-events",
|
|
@@ -87302,6 +87918,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
|
|
|
87302
87918
|
label: "Motion without a subject",
|
|
87303
87919
|
kinds: ["motion-noisy", "motion-calm"]
|
|
87304
87920
|
},
|
|
87921
|
+
{
|
|
87922
|
+
id: "package-llm",
|
|
87923
|
+
family: "device-events",
|
|
87924
|
+
label: "Package confirm",
|
|
87925
|
+
kinds: ["package-llm-silent", "package-llm-answered"]
|
|
87926
|
+
},
|
|
87305
87927
|
{
|
|
87306
87928
|
id: "recording",
|
|
87307
87929
|
family: "device-events",
|
|
@@ -87483,6 +88105,8 @@ var DEVICE_EVENTS = [
|
|
|
87483
88105
|
"detection-blind",
|
|
87484
88106
|
"motion-noisy",
|
|
87485
88107
|
"motion-calm",
|
|
88108
|
+
"package-llm-silent",
|
|
88109
|
+
"package-llm-answered",
|
|
87486
88110
|
"recording-stalled",
|
|
87487
88111
|
"recording-healthy",
|
|
87488
88112
|
"recording-degraded",
|
|
@@ -87751,6 +88375,15 @@ new Map([
|
|
|
87751
88375
|
snapshotLabel: "Cameras with constant motion now",
|
|
87752
88376
|
snapshotSection: null
|
|
87753
88377
|
},
|
|
88378
|
+
{
|
|
88379
|
+
id: "package-llm-confirm",
|
|
88380
|
+
family: "device-events",
|
|
88381
|
+
label: "Package confirm (not answering / answering again)",
|
|
88382
|
+
bad: ["package-llm-silent"],
|
|
88383
|
+
recovery: ["package-llm-answered"],
|
|
88384
|
+
snapshotLabel: "Cameras whose package confirm is not answering",
|
|
88385
|
+
snapshotSection: null
|
|
88386
|
+
},
|
|
87754
88387
|
{
|
|
87755
88388
|
id: "recording-health",
|
|
87756
88389
|
family: "device-events",
|