@camstack/types 1.2.419 → 1.2.421
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/composer.cap.d.ts +36 -0
- package/dist/capabilities/core-blocks.cap.d.ts +252 -0
- package/dist/capabilities/power-meter.cap.d.ts +1 -1
- package/dist/capabilities/running-state.cap.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +166 -1
- package/dist/client.mjs +166 -2
- package/dist/composition/composition.d.ts +12 -0
- package/dist/composition/helpers/appliance.d.ts +28 -0
- package/dist/composition/helpers/compile.d.ts +1 -1
- package/dist/composition/helpers/index.d.ts +2 -1
- package/dist/composition/helpers/save.d.ts +1 -1
- package/dist/composition/helpers/spec.d.ts +21 -1
- package/dist/{composition-OhpuespA.mjs → composition-B2rw5L29.mjs} +88 -3
- package/dist/{composition-re1aezX9.js → composition-B3Hkb6v7.js} +135 -2
- package/dist/device/appliance-export.d.ts +25 -0
- package/dist/device/cap-vocabulary/types.d.ts +10 -0
- package/dist/device/device-type.d.ts +8 -2
- package/dist/{err-msg-BXKzRBwg.mjs → err-msg-DIorGYeC.mjs} +7 -1
- package/dist/{err-msg-BhVbr0NX.js → err-msg-U7lLUMNz.js} +7 -1
- package/dist/generated/customize-catalog.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +318 -118
- package/dist/index.mjs +307 -119
- package/dist/node.js +2 -2
- package/dist/node.mjs +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_sleep = require("./sleep-YJ6FVsUu.js");
|
|
3
3
|
const require_event_category = require("./event-category-Ave2VSxY.js");
|
|
4
|
-
const require_composition = require("./composition-
|
|
4
|
+
const require_composition = require("./composition-B3Hkb6v7.js");
|
|
5
5
|
const require_node_color = require("./node-color.js");
|
|
6
|
-
const require_err_msg = require("./err-msg-
|
|
6
|
+
const require_err_msg = require("./err-msg-U7lLUMNz.js");
|
|
7
7
|
const require_enums = require("./enums.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/media/media-owner-key.ts
|
|
@@ -13538,6 +13538,102 @@ function groupTemplate(id) {
|
|
|
13538
13538
|
return BY_ID.get(id) ?? null;
|
|
13539
13539
|
}
|
|
13540
13540
|
//#endregion
|
|
13541
|
+
//#region src/composition/customize/scalar-expr.ts
|
|
13542
|
+
var UNSIGNED = /^\d+(?:\.\d+)?$/;
|
|
13543
|
+
var SIGNED = /^-?\d+(?:\.\d+)?$/;
|
|
13544
|
+
var DWELL = /^dwell\(x (>=|<=) (\d+(?:\.\d+)?), (\d+(?:\.\d+)?), (\d+(?:\.\d+)?)\)$/;
|
|
13545
|
+
var LINEAR_CLAMP = /^clamp\((x|number\(x\)) \* (-?\d+(?:\.\d+)?) \+ (-?\d+(?:\.\d+)?), (-?\d+(?:\.\d+)?), (-?\d+(?:\.\d+)?)\)$/;
|
|
13546
|
+
var LINEAR_BARE = /^(x|number\(x\)) \* (-?\d+(?:\.\d+)?) \+ (-?\d+(?:\.\d+)?)$/;
|
|
13547
|
+
var IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
13548
|
+
function unsignedToken(value) {
|
|
13549
|
+
return token(value, UNSIGNED);
|
|
13550
|
+
}
|
|
13551
|
+
function signedToken(value) {
|
|
13552
|
+
return token(value, SIGNED);
|
|
13553
|
+
}
|
|
13554
|
+
function constantExpr(value) {
|
|
13555
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
13556
|
+
if (typeof value === "number") return signedToken(value);
|
|
13557
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
13558
|
+
return "null";
|
|
13559
|
+
}
|
|
13560
|
+
function isIdentifier(path) {
|
|
13561
|
+
return IDENT.test(path);
|
|
13562
|
+
}
|
|
13563
|
+
function dwellExpr(comparison, threshold, start, stop) {
|
|
13564
|
+
return `dwell(x ${comparison === "gte" ? ">=" : "<="} ${threshold}, ${start}, ${stop})`;
|
|
13565
|
+
}
|
|
13566
|
+
function linearExpr(inner, scale, offset, clampMin, clampMax) {
|
|
13567
|
+
const arithmetic = `${inner} * ${scale} + ${offset}`;
|
|
13568
|
+
if (clampMin === null || clampMax === null) return arithmetic;
|
|
13569
|
+
return `clamp(${arithmetic}, ${clampMin}, ${clampMax})`;
|
|
13570
|
+
}
|
|
13571
|
+
function parseDwell(expr) {
|
|
13572
|
+
const match = DWELL.exec(expr);
|
|
13573
|
+
if (match === null) return null;
|
|
13574
|
+
const threshold = Number(match[2]);
|
|
13575
|
+
const startDwellMs = Number(match[3]);
|
|
13576
|
+
const stopDwellMs = Number(match[4]);
|
|
13577
|
+
if (!Number.isFinite(threshold) || !Number.isFinite(startDwellMs) || !Number.isFinite(stopDwellMs)) return null;
|
|
13578
|
+
return {
|
|
13579
|
+
comparison: match[1] === "<=" ? "lte" : "gte",
|
|
13580
|
+
threshold,
|
|
13581
|
+
startDwellMs,
|
|
13582
|
+
stopDwellMs
|
|
13583
|
+
};
|
|
13584
|
+
}
|
|
13585
|
+
function parseLinear(expr) {
|
|
13586
|
+
const clamped = LINEAR_CLAMP.exec(expr);
|
|
13587
|
+
if (clamped !== null) return linearFrom(clamped[1], clamped[2], clamped[3], clamped[4], clamped[5]);
|
|
13588
|
+
const bare = LINEAR_BARE.exec(expr);
|
|
13589
|
+
if (bare === null) return null;
|
|
13590
|
+
return linearFrom(bare[1], bare[2], bare[3], void 0, void 0);
|
|
13591
|
+
}
|
|
13592
|
+
function singleFrom(source) {
|
|
13593
|
+
if (source.kind === "from") return {
|
|
13594
|
+
cap: source.cap,
|
|
13595
|
+
fieldPath: source.fieldPath,
|
|
13596
|
+
addonId: source.source.addonId,
|
|
13597
|
+
stableId: source.source.stableId
|
|
13598
|
+
};
|
|
13599
|
+
if (source.kind !== "expression" || Object.keys(source.bindings).length !== 1) return null;
|
|
13600
|
+
const bound = source.bindings["x"];
|
|
13601
|
+
if (bound === void 0 || bound.kind !== "from") return null;
|
|
13602
|
+
return {
|
|
13603
|
+
cap: bound.cap,
|
|
13604
|
+
fieldPath: bound.fieldPath,
|
|
13605
|
+
addonId: bound.source.addonId,
|
|
13606
|
+
stableId: bound.source.stableId
|
|
13607
|
+
};
|
|
13608
|
+
}
|
|
13609
|
+
function token(value, pattern) {
|
|
13610
|
+
if (!Number.isFinite(value)) return null;
|
|
13611
|
+
const text = Object.is(value, -0) ? "0" : String(value);
|
|
13612
|
+
return pattern.test(text) ? text : null;
|
|
13613
|
+
}
|
|
13614
|
+
function linearFrom(inner, scale, offset, clampMin, clampMax) {
|
|
13615
|
+
if (inner !== "x" && inner !== "number(x)") return null;
|
|
13616
|
+
if (scale === void 0 || offset === void 0) return null;
|
|
13617
|
+
const parsedScale = Number(scale);
|
|
13618
|
+
const parsedOffset = Number(offset);
|
|
13619
|
+
if (!Number.isFinite(parsedScale) || !Number.isFinite(parsedOffset)) return null;
|
|
13620
|
+
if (clampMin === void 0 || clampMax === void 0) return {
|
|
13621
|
+
inner,
|
|
13622
|
+
scale: parsedScale,
|
|
13623
|
+
offset: parsedOffset
|
|
13624
|
+
};
|
|
13625
|
+
const parsedMin = Number(clampMin);
|
|
13626
|
+
const parsedMax = Number(clampMax);
|
|
13627
|
+
if (!Number.isFinite(parsedMin) || !Number.isFinite(parsedMax)) return null;
|
|
13628
|
+
return {
|
|
13629
|
+
inner,
|
|
13630
|
+
scale: parsedScale,
|
|
13631
|
+
offset: parsedOffset,
|
|
13632
|
+
clampMin: parsedMin,
|
|
13633
|
+
clampMax: parsedMax
|
|
13634
|
+
};
|
|
13635
|
+
}
|
|
13636
|
+
//#endregion
|
|
13541
13637
|
//#region src/composition/helpers/actuator.ts
|
|
13542
13638
|
/**
|
|
13543
13639
|
* Actuator groups (D944 phase 1b). The active boolean is the binary reducer
|
|
@@ -13658,13 +13754,6 @@ function aggregateSource(template, spec, reads, publish) {
|
|
|
13658
13754
|
empty: template.empty
|
|
13659
13755
|
};
|
|
13660
13756
|
}
|
|
13661
|
-
function expressionSource(expr) {
|
|
13662
|
-
return {
|
|
13663
|
-
kind: "expression",
|
|
13664
|
-
expr,
|
|
13665
|
-
bindings: {}
|
|
13666
|
-
};
|
|
13667
|
-
}
|
|
13668
13757
|
function draftOf$1(template, spec) {
|
|
13669
13758
|
const reads = spec.members.map((member) => ({
|
|
13670
13759
|
source: member.source,
|
|
@@ -13718,8 +13807,67 @@ function parseDraft(draft) {
|
|
|
13718
13807
|
problems: [problem("helper-mismatch", "helper", `the template did not compile: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`)]
|
|
13719
13808
|
};
|
|
13720
13809
|
}
|
|
13721
|
-
|
|
13810
|
+
function expressionSource(expr, bindings = {}) {
|
|
13811
|
+
return {
|
|
13812
|
+
kind: "expression",
|
|
13813
|
+
expr,
|
|
13814
|
+
bindings
|
|
13815
|
+
};
|
|
13816
|
+
}
|
|
13817
|
+
function compileAppliance(spec) {
|
|
13818
|
+
const member = spec.member;
|
|
13819
|
+
if (member.cap !== "power-meter" || member.fieldPath !== "watts") return {
|
|
13820
|
+
ok: false,
|
|
13821
|
+
problems: [problem("member-constraint", "helper.member", "an appliance helper reads power-meter.watts")]
|
|
13822
|
+
};
|
|
13823
|
+
const threshold = unsignedToken(spec.thresholdWatts);
|
|
13824
|
+
const start = unsignedToken(spec.startDwellMs);
|
|
13825
|
+
const stop = unsignedToken(spec.stopDwellMs);
|
|
13826
|
+
if (threshold === null || spec.thresholdWatts <= 0) return {
|
|
13827
|
+
ok: false,
|
|
13828
|
+
problems: [problem("kind-mismatch", "helper.thresholdWatts", "the threshold is watts above which the appliance is running")]
|
|
13829
|
+
};
|
|
13830
|
+
if (start === null || stop === null) return {
|
|
13831
|
+
ok: false,
|
|
13832
|
+
problems: [problem("kind-mismatch", "helper.startDwellMs", "start and stop dwells are a non-negative number of milliseconds")]
|
|
13833
|
+
};
|
|
13834
|
+
const read = {
|
|
13835
|
+
kind: "from",
|
|
13836
|
+
source: member.source,
|
|
13837
|
+
cap: member.cap,
|
|
13838
|
+
fieldPath: member.fieldPath
|
|
13839
|
+
};
|
|
13840
|
+
const dwell = dwellExpr("gte", threshold, start, stop);
|
|
13841
|
+
const clock = expressionSource("now");
|
|
13842
|
+
return parseDraft({
|
|
13843
|
+
target: {
|
|
13844
|
+
kind: "new",
|
|
13845
|
+
type: require_composition.applianceDeviceType(spec.appliance)
|
|
13846
|
+
},
|
|
13847
|
+
helper: spec,
|
|
13848
|
+
features: [{
|
|
13849
|
+
kind: "fields",
|
|
13850
|
+
cap: "running-state",
|
|
13851
|
+
fields: {
|
|
13852
|
+
running: expressionSource(dwell, { x: read }),
|
|
13853
|
+
source: expressionSource("\"assigned\""),
|
|
13854
|
+
phase: expressionSource("null"),
|
|
13855
|
+
lastFetchedAt: clock,
|
|
13856
|
+
since: expressionSource(`latchedAt(${dwell})`, { x: read })
|
|
13857
|
+
}
|
|
13858
|
+
}, {
|
|
13859
|
+
kind: "fields",
|
|
13860
|
+
cap: "power-meter",
|
|
13861
|
+
fields: {
|
|
13862
|
+
watts: read,
|
|
13863
|
+
lastFetchedAt: clock
|
|
13864
|
+
}
|
|
13865
|
+
}]
|
|
13866
|
+
});
|
|
13867
|
+
}
|
|
13868
|
+
/** Compile a helper template to a new-device composition. Refusals are named. */
|
|
13722
13869
|
function compileHelper(spec) {
|
|
13870
|
+
if (spec.kind === "appliance") return compileAppliance(spec);
|
|
13723
13871
|
const template = groupTemplate(spec.templateId);
|
|
13724
13872
|
if (template === null) return {
|
|
13725
13873
|
ok: false,
|
|
@@ -13749,10 +13897,15 @@ function sameHelperBody(stored, compiled) {
|
|
|
13749
13897
|
return JSON.stringify(stored.target) === JSON.stringify(compiled.target) && JSON.stringify(stored.features) === JSON.stringify(compiled.features);
|
|
13750
13898
|
}
|
|
13751
13899
|
function templateDeviceType(spec) {
|
|
13900
|
+
if (spec.kind === "appliance") return require_composition.applianceDeviceType(spec.appliance);
|
|
13752
13901
|
return groupTemplate(spec.templateId)?.memberDeviceType ?? null;
|
|
13753
13902
|
}
|
|
13754
13903
|
//#endregion
|
|
13755
13904
|
//#region src/composition/helpers/save.ts
|
|
13905
|
+
/**
|
|
13906
|
+
* Save-time checks a pure compile cannot make: the compiled features must be
|
|
13907
|
+
* this spec's, and members that report a quantity must share one (D944 §4).
|
|
13908
|
+
*/
|
|
13756
13909
|
function quantityProblems(spec, facts) {
|
|
13757
13910
|
const template = groupTemplate(spec.templateId);
|
|
13758
13911
|
if (template === null || template.family !== "numeric") return [];
|
|
@@ -13787,8 +13940,17 @@ function helperSaveProblems(composition, facts) {
|
|
|
13787
13940
|
const compiled = compileHelper(spec);
|
|
13788
13941
|
if (!compiled.ok) return compiled.problems;
|
|
13789
13942
|
if (!sameHelperBody(composition, compiled.composition)) return [problem("helper-mismatch", "helper", "the stored features are not this template — the helper spec is the only writer")];
|
|
13943
|
+
if (spec.kind === "appliance") return applianceMemberProblems(spec.member, facts);
|
|
13790
13944
|
return [...quantityProblems(spec, facts), ...deviceTypeProblems(spec, facts)];
|
|
13791
13945
|
}
|
|
13946
|
+
function applianceMemberProblems(member, facts) {
|
|
13947
|
+
const fact = facts.get(require_composition.compositionSourceKey(member.source));
|
|
13948
|
+
if (fact === void 0) return [];
|
|
13949
|
+
const problems = [];
|
|
13950
|
+
if (fact.deviceType !== void 0 && fact.deviceType !== require_err_msg.DeviceType.Sensor && fact.deviceType !== require_err_msg.DeviceType.Switch) problems.push(problem("member-constraint", "helper.member", `an appliance helper reads a sensor or a switch; this member is a ${fact.deviceType}`));
|
|
13951
|
+
if (fact.quantity !== void 0 && fact.quantity !== "power") problems.push(problem("mixed-quantity", "helper.member", `an appliance helper reads power (W); this member is ${fact.quantity}`));
|
|
13952
|
+
return problems;
|
|
13953
|
+
}
|
|
13792
13954
|
//#endregion
|
|
13793
13955
|
//#region src/composition/composition-graph.ts
|
|
13794
13956
|
/**
|
|
@@ -14002,7 +14164,7 @@ function composableCap(feature, at, lookupCap) {
|
|
|
14002
14164
|
*/
|
|
14003
14165
|
function actuatorCommandCaps(composition) {
|
|
14004
14166
|
const spec = composition.helper;
|
|
14005
|
-
if (spec === void 0) return /* @__PURE__ */ new Set();
|
|
14167
|
+
if (spec === void 0 || spec.kind !== "group") return /* @__PURE__ */ new Set();
|
|
14006
14168
|
const template = groupTemplate(spec.templateId);
|
|
14007
14169
|
if (template === null || template.family !== "actuator") return /* @__PURE__ */ new Set();
|
|
14008
14170
|
return new Set(template.commandCaps);
|
|
@@ -70385,7 +70547,12 @@ var powerMeterCapability = {
|
|
|
70385
70547
|
scope: "device",
|
|
70386
70548
|
deviceNative: true,
|
|
70387
70549
|
mode: "singleton",
|
|
70388
|
-
deviceTypes: [
|
|
70550
|
+
deviceTypes: [
|
|
70551
|
+
require_err_msg.DeviceType.Sensor,
|
|
70552
|
+
require_err_msg.DeviceType.Washer,
|
|
70553
|
+
require_err_msg.DeviceType.Dryer,
|
|
70554
|
+
require_err_msg.DeviceType.Dishwasher
|
|
70555
|
+
],
|
|
70389
70556
|
methods: {},
|
|
70390
70557
|
status: {
|
|
70391
70558
|
schema: PowerMeterStatusSchema,
|
|
@@ -71293,6 +71460,8 @@ var runningCustomize = {
|
|
|
71293
71460
|
stateField: "running"
|
|
71294
71461
|
},
|
|
71295
71462
|
deviceTypes: [
|
|
71463
|
+
require_err_msg.DeviceType.Washer,
|
|
71464
|
+
require_err_msg.DeviceType.Dryer,
|
|
71296
71465
|
require_err_msg.DeviceType.Dishwasher,
|
|
71297
71466
|
require_err_msg.DeviceType.Vacuum,
|
|
71298
71467
|
require_err_msg.DeviceType.LawnMower,
|
|
@@ -79138,7 +79307,9 @@ var CAP_CUSTOMIZE_CATALOG = {
|
|
|
79138
79307
|
require_err_msg.DeviceType.Container,
|
|
79139
79308
|
require_err_msg.DeviceType.Image,
|
|
79140
79309
|
require_err_msg.DeviceType.PetFeeder,
|
|
79141
|
-
require_err_msg.DeviceType.Dishwasher
|
|
79310
|
+
require_err_msg.DeviceType.Dishwasher,
|
|
79311
|
+
require_err_msg.DeviceType.Washer,
|
|
79312
|
+
require_err_msg.DeviceType.Dryer
|
|
79142
79313
|
],
|
|
79143
79314
|
apply: "add",
|
|
79144
79315
|
vocabularyCap: "consumables",
|
|
@@ -79312,6 +79483,8 @@ var CAP_CUSTOMIZE_CATALOG = {
|
|
|
79312
79483
|
id: "running",
|
|
79313
79484
|
cardinality: "scalar",
|
|
79314
79485
|
deviceTypes: [
|
|
79486
|
+
require_err_msg.DeviceType.Washer,
|
|
79487
|
+
require_err_msg.DeviceType.Dryer,
|
|
79315
79488
|
require_err_msg.DeviceType.Dishwasher,
|
|
79316
79489
|
require_err_msg.DeviceType.Vacuum,
|
|
79317
79490
|
require_err_msg.DeviceType.LawnMower,
|
|
@@ -79430,102 +79603,6 @@ function isLiteral(source, expr) {
|
|
|
79430
79603
|
return source?.kind === "expression" && source.expr === expr && Object.keys(source.bindings).length === 0;
|
|
79431
79604
|
}
|
|
79432
79605
|
//#endregion
|
|
79433
|
-
//#region src/composition/customize/scalar-expr.ts
|
|
79434
|
-
var UNSIGNED = /^\d+(?:\.\d+)?$/;
|
|
79435
|
-
var SIGNED = /^-?\d+(?:\.\d+)?$/;
|
|
79436
|
-
var DWELL = /^dwell\(x (>=|<=) (\d+(?:\.\d+)?), (\d+(?:\.\d+)?), (\d+(?:\.\d+)?)\)$/;
|
|
79437
|
-
var LINEAR_CLAMP = /^clamp\((x|number\(x\)) \* (-?\d+(?:\.\d+)?) \+ (-?\d+(?:\.\d+)?), (-?\d+(?:\.\d+)?), (-?\d+(?:\.\d+)?)\)$/;
|
|
79438
|
-
var LINEAR_BARE = /^(x|number\(x\)) \* (-?\d+(?:\.\d+)?) \+ (-?\d+(?:\.\d+)?)$/;
|
|
79439
|
-
var IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
79440
|
-
function unsignedToken(value) {
|
|
79441
|
-
return token(value, UNSIGNED);
|
|
79442
|
-
}
|
|
79443
|
-
function signedToken(value) {
|
|
79444
|
-
return token(value, SIGNED);
|
|
79445
|
-
}
|
|
79446
|
-
function constantExpr(value) {
|
|
79447
|
-
if (typeof value === "string") return JSON.stringify(value);
|
|
79448
|
-
if (typeof value === "number") return signedToken(value);
|
|
79449
|
-
if (typeof value === "boolean") return value ? "true" : "false";
|
|
79450
|
-
return "null";
|
|
79451
|
-
}
|
|
79452
|
-
function isIdentifier(path) {
|
|
79453
|
-
return IDENT.test(path);
|
|
79454
|
-
}
|
|
79455
|
-
function dwellExpr(comparison, threshold, start, stop) {
|
|
79456
|
-
return `dwell(x ${comparison === "gte" ? ">=" : "<="} ${threshold}, ${start}, ${stop})`;
|
|
79457
|
-
}
|
|
79458
|
-
function linearExpr(inner, scale, offset, clampMin, clampMax) {
|
|
79459
|
-
const arithmetic = `${inner} * ${scale} + ${offset}`;
|
|
79460
|
-
if (clampMin === null || clampMax === null) return arithmetic;
|
|
79461
|
-
return `clamp(${arithmetic}, ${clampMin}, ${clampMax})`;
|
|
79462
|
-
}
|
|
79463
|
-
function parseDwell(expr) {
|
|
79464
|
-
const match = DWELL.exec(expr);
|
|
79465
|
-
if (match === null) return null;
|
|
79466
|
-
const threshold = Number(match[2]);
|
|
79467
|
-
const startDwellMs = Number(match[3]);
|
|
79468
|
-
const stopDwellMs = Number(match[4]);
|
|
79469
|
-
if (!Number.isFinite(threshold) || !Number.isFinite(startDwellMs) || !Number.isFinite(stopDwellMs)) return null;
|
|
79470
|
-
return {
|
|
79471
|
-
comparison: match[1] === "<=" ? "lte" : "gte",
|
|
79472
|
-
threshold,
|
|
79473
|
-
startDwellMs,
|
|
79474
|
-
stopDwellMs
|
|
79475
|
-
};
|
|
79476
|
-
}
|
|
79477
|
-
function parseLinear(expr) {
|
|
79478
|
-
const clamped = LINEAR_CLAMP.exec(expr);
|
|
79479
|
-
if (clamped !== null) return linearFrom(clamped[1], clamped[2], clamped[3], clamped[4], clamped[5]);
|
|
79480
|
-
const bare = LINEAR_BARE.exec(expr);
|
|
79481
|
-
if (bare === null) return null;
|
|
79482
|
-
return linearFrom(bare[1], bare[2], bare[3], void 0, void 0);
|
|
79483
|
-
}
|
|
79484
|
-
function singleFrom(source) {
|
|
79485
|
-
if (source.kind === "from") return {
|
|
79486
|
-
cap: source.cap,
|
|
79487
|
-
fieldPath: source.fieldPath,
|
|
79488
|
-
addonId: source.source.addonId,
|
|
79489
|
-
stableId: source.source.stableId
|
|
79490
|
-
};
|
|
79491
|
-
if (source.kind !== "expression" || Object.keys(source.bindings).length !== 1) return null;
|
|
79492
|
-
const bound = source.bindings["x"];
|
|
79493
|
-
if (bound === void 0 || bound.kind !== "from") return null;
|
|
79494
|
-
return {
|
|
79495
|
-
cap: bound.cap,
|
|
79496
|
-
fieldPath: bound.fieldPath,
|
|
79497
|
-
addonId: bound.source.addonId,
|
|
79498
|
-
stableId: bound.source.stableId
|
|
79499
|
-
};
|
|
79500
|
-
}
|
|
79501
|
-
function token(value, pattern) {
|
|
79502
|
-
if (!Number.isFinite(value)) return null;
|
|
79503
|
-
const text = Object.is(value, -0) ? "0" : String(value);
|
|
79504
|
-
return pattern.test(text) ? text : null;
|
|
79505
|
-
}
|
|
79506
|
-
function linearFrom(inner, scale, offset, clampMin, clampMax) {
|
|
79507
|
-
if (inner !== "x" && inner !== "number(x)") return null;
|
|
79508
|
-
if (scale === void 0 || offset === void 0) return null;
|
|
79509
|
-
const parsedScale = Number(scale);
|
|
79510
|
-
const parsedOffset = Number(offset);
|
|
79511
|
-
if (!Number.isFinite(parsedScale) || !Number.isFinite(parsedOffset)) return null;
|
|
79512
|
-
if (clampMin === void 0 || clampMax === void 0) return {
|
|
79513
|
-
inner,
|
|
79514
|
-
scale: parsedScale,
|
|
79515
|
-
offset: parsedOffset
|
|
79516
|
-
};
|
|
79517
|
-
const parsedMin = Number(clampMin);
|
|
79518
|
-
const parsedMax = Number(clampMax);
|
|
79519
|
-
if (!Number.isFinite(parsedMin) || !Number.isFinite(parsedMax)) return null;
|
|
79520
|
-
return {
|
|
79521
|
-
inner,
|
|
79522
|
-
scale: parsedScale,
|
|
79523
|
-
offset: parsedOffset,
|
|
79524
|
-
clampMin: parsedMin,
|
|
79525
|
-
clampMax: parsedMax
|
|
79526
|
-
};
|
|
79527
|
-
}
|
|
79528
|
-
//#endregion
|
|
79529
79606
|
//#region src/composition/customize/event-compile.ts
|
|
79530
79607
|
var catalog$4 = CAP_CUSTOMIZE_CATALOG;
|
|
79531
79608
|
function compilePulseOverride(input) {
|
|
@@ -82857,6 +82934,8 @@ var CONTAINER_CHILD_PRIORITY = [
|
|
|
82857
82934
|
"fan",
|
|
82858
82935
|
"vacuum",
|
|
82859
82936
|
"lawn-mower",
|
|
82937
|
+
"washer",
|
|
82938
|
+
"dryer",
|
|
82860
82939
|
"dishwasher",
|
|
82861
82940
|
"light",
|
|
82862
82941
|
"switch",
|
|
@@ -83471,7 +83550,9 @@ var DEVICE_TYPE_CONTROL_KIND = {
|
|
|
83471
83550
|
[require_err_msg.DeviceType.Container]: "dummy",
|
|
83472
83551
|
[require_err_msg.DeviceType.Image]: "image",
|
|
83473
83552
|
[require_err_msg.DeviceType.PetFeeder]: "pet-feeder",
|
|
83474
|
-
[require_err_msg.DeviceType.Dishwasher]: "dishwasher"
|
|
83553
|
+
[require_err_msg.DeviceType.Dishwasher]: "dishwasher",
|
|
83554
|
+
[require_err_msg.DeviceType.Washer]: "dummy",
|
|
83555
|
+
[require_err_msg.DeviceType.Dryer]: "dummy"
|
|
83475
83556
|
};
|
|
83476
83557
|
var DEVICE_TYPE_VALUES = new Set(Object.values(require_err_msg.DeviceType));
|
|
83477
83558
|
/**
|
|
@@ -96244,7 +96325,39 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
96244
96325
|
phrase: t("When {device} finishes", "Quando {device} finisce"),
|
|
96245
96326
|
icon: "square"
|
|
96246
96327
|
}
|
|
96247
|
-
}
|
|
96328
|
+
},
|
|
96329
|
+
overrides: { byType: {
|
|
96330
|
+
[require_err_msg.DeviceType.Washer]: {
|
|
96331
|
+
state: { running: {
|
|
96332
|
+
whenTrue: t("When the washing machine starts", "Quando la lavatrice inizia"),
|
|
96333
|
+
whenFalse: t("When the washing machine has finished", "Quando la lavatrice ha finito")
|
|
96334
|
+
} },
|
|
96335
|
+
events: {
|
|
96336
|
+
onStarted: { phrase: t("When the washing machine starts", "Quando la lavatrice inizia") },
|
|
96337
|
+
onFinished: { phrase: t("When the washing machine has finished", "Quando la lavatrice ha finito") }
|
|
96338
|
+
}
|
|
96339
|
+
},
|
|
96340
|
+
[require_err_msg.DeviceType.Dryer]: {
|
|
96341
|
+
state: { running: {
|
|
96342
|
+
whenTrue: t("When the dryer starts", "Quando l'asciugatrice inizia"),
|
|
96343
|
+
whenFalse: t("When the dryer has finished", "Quando l'asciugatrice ha finito")
|
|
96344
|
+
} },
|
|
96345
|
+
events: {
|
|
96346
|
+
onStarted: { phrase: t("When the dryer starts", "Quando l'asciugatrice inizia") },
|
|
96347
|
+
onFinished: { phrase: t("When the dryer has finished", "Quando l'asciugatrice ha finito") }
|
|
96348
|
+
}
|
|
96349
|
+
},
|
|
96350
|
+
[require_err_msg.DeviceType.Dishwasher]: {
|
|
96351
|
+
state: { running: {
|
|
96352
|
+
whenTrue: t("When the dishwasher starts", "Quando la lavastoviglie inizia"),
|
|
96353
|
+
whenFalse: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito")
|
|
96354
|
+
} },
|
|
96355
|
+
events: {
|
|
96356
|
+
onStarted: { phrase: t("When the dishwasher starts", "Quando la lavastoviglie inizia") },
|
|
96357
|
+
onFinished: { phrase: t("When the dishwasher has finished", "Quando la lavastoviglie ha finito") }
|
|
96358
|
+
}
|
|
96359
|
+
}
|
|
96360
|
+
} }
|
|
96248
96361
|
},
|
|
96249
96362
|
update: {
|
|
96250
96363
|
scope: "device",
|
|
@@ -97669,7 +97782,9 @@ var DEVICE_TYPE_DO_CAPS = {
|
|
|
97669
97782
|
[require_err_msg.DeviceType.Container]: [],
|
|
97670
97783
|
[require_err_msg.DeviceType.Image]: [],
|
|
97671
97784
|
[require_err_msg.DeviceType.PetFeeder]: ["pet-feeder"],
|
|
97672
|
-
[require_err_msg.DeviceType.Dishwasher]: ["dishwasher"]
|
|
97785
|
+
[require_err_msg.DeviceType.Dishwasher]: ["dishwasher"],
|
|
97786
|
+
[require_err_msg.DeviceType.Washer]: [],
|
|
97787
|
+
[require_err_msg.DeviceType.Dryer]: []
|
|
97673
97788
|
};
|
|
97674
97789
|
/**
|
|
97675
97790
|
* Whether a device type belongs in a Do / automation action device picker.
|
|
@@ -97866,6 +97981,12 @@ function stateWording(wordings, field) {
|
|
|
97866
97981
|
...w.state?.[field]
|
|
97867
97982
|
}), {});
|
|
97868
97983
|
}
|
|
97984
|
+
function eventWording(wordings, name) {
|
|
97985
|
+
return wordings.reduce((acc, w) => ({
|
|
97986
|
+
...acc,
|
|
97987
|
+
...w.events?.[name]
|
|
97988
|
+
}), {});
|
|
97989
|
+
}
|
|
97869
97990
|
function accessOf(cap, method) {
|
|
97870
97991
|
return METHOD_ACCESS_MAP[`${kebabToCamel(cap)}.${method}`]?.access;
|
|
97871
97992
|
}
|
|
@@ -97976,18 +98097,19 @@ function resolveState(cap, trigger, wordings) {
|
|
|
97976
98097
|
offer: trigger.offer ?? null
|
|
97977
98098
|
};
|
|
97978
98099
|
}
|
|
97979
|
-
function eventTriggersOf(cap, entry) {
|
|
98100
|
+
function eventTriggersOf(cap, entry, wordings) {
|
|
97980
98101
|
const out = [];
|
|
97981
|
-
for (const ev of Object.
|
|
98102
|
+
for (const [name, ev] of Object.entries(entry.events ?? {})) {
|
|
97982
98103
|
if ("notOperatorFacing" in ev) continue;
|
|
98104
|
+
const wording = eventWording(wordings, name);
|
|
97983
98105
|
out.push({
|
|
97984
98106
|
kind: "event",
|
|
97985
98107
|
id: `${cap}.event.${ev.category}`,
|
|
97986
98108
|
cap,
|
|
97987
98109
|
category: ev.category,
|
|
97988
|
-
label: ev.label,
|
|
97989
|
-
phrase: ev.phrase,
|
|
97990
|
-
icon: ev.icon
|
|
98110
|
+
label: wording.label ?? ev.label,
|
|
98111
|
+
phrase: wording.phrase ?? ev.phrase,
|
|
98112
|
+
icon: wording.icon ?? ev.icon
|
|
97991
98113
|
});
|
|
97992
98114
|
}
|
|
97993
98115
|
for (const ev of entry.extraEvents ?? []) out.push({
|
|
@@ -98011,7 +98133,7 @@ function triggersForDevice(bindings, deviceType, role) {
|
|
|
98011
98133
|
for (const [cap, entry] of boundEntries(bindings)) {
|
|
98012
98134
|
const wordings = wordingsFor(entry, deviceType, role);
|
|
98013
98135
|
for (const trigger of entry.state ?? []) state.push(resolveState(cap, trigger, wordings));
|
|
98014
|
-
events.push(...eventTriggersOf(cap, entry));
|
|
98136
|
+
events.push(...eventTriggersOf(cap, entry, wordings));
|
|
98015
98137
|
}
|
|
98016
98138
|
return [...state, ...events];
|
|
98017
98139
|
}
|
|
@@ -98064,6 +98186,72 @@ function resolveDeviceProfile(features) {
|
|
|
98064
98186
|
return null;
|
|
98065
98187
|
}
|
|
98066
98188
|
//#endregion
|
|
98189
|
+
//#region src/device/appliance-export.ts
|
|
98190
|
+
/**
|
|
98191
|
+
* How a washer, dryer or dishwasher leaves CamStack.
|
|
98192
|
+
*
|
|
98193
|
+
* Home Assistant has no laundry domain: the device is offered, and what
|
|
98194
|
+
* travels is its power reading. The others have a laundry type that this
|
|
98195
|
+
* export cannot honour yet, so they are named and withheld.
|
|
98196
|
+
*/
|
|
98197
|
+
var PLUG_APPLIANCE_TYPES = [
|
|
98198
|
+
require_err_msg.DeviceType.Washer,
|
|
98199
|
+
require_err_msg.DeviceType.Dryer,
|
|
98200
|
+
require_err_msg.DeviceType.Dishwasher
|
|
98201
|
+
];
|
|
98202
|
+
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|
|
98203
|
+
var HOMEKIT_REASON = "HomeKit has no laundry-appliance service. The export tab would pair an accessory with nothing on it: running-state is withheld until a null reading can be unavailable, and power is not a HomeKit service this export honours.";
|
|
98204
|
+
var ALEXA_REASON = "Alexa has no laundry category in this export, and neither power nor running has an Alexa interface.";
|
|
98205
|
+
var GOOGLE_REASON = "Google WASHER, DRYER and DISHWASHER require RunCycle. A power threshold is not that trait, and this export does not publish RunCycle.";
|
|
98206
|
+
var MATTER_REASON = "No Matter export is built. The closest device types are Laundry Washer (0x0073) and Laundry Dryer (0x0074); a power threshold is not the Laundry Washer Mode cluster.";
|
|
98207
|
+
function withheld(reason) {
|
|
98208
|
+
return {
|
|
98209
|
+
[require_err_msg.DeviceType.Washer]: {
|
|
98210
|
+
exported: false,
|
|
98211
|
+
reason
|
|
98212
|
+
},
|
|
98213
|
+
[require_err_msg.DeviceType.Dryer]: {
|
|
98214
|
+
exported: false,
|
|
98215
|
+
reason
|
|
98216
|
+
},
|
|
98217
|
+
[require_err_msg.DeviceType.Dishwasher]: {
|
|
98218
|
+
exported: false,
|
|
98219
|
+
reason
|
|
98220
|
+
}
|
|
98221
|
+
};
|
|
98222
|
+
}
|
|
98223
|
+
function offered(received) {
|
|
98224
|
+
return {
|
|
98225
|
+
[require_err_msg.DeviceType.Washer]: {
|
|
98226
|
+
exported: true,
|
|
98227
|
+
as: received
|
|
98228
|
+
},
|
|
98229
|
+
[require_err_msg.DeviceType.Dryer]: {
|
|
98230
|
+
exported: true,
|
|
98231
|
+
as: received
|
|
98232
|
+
},
|
|
98233
|
+
[require_err_msg.DeviceType.Dishwasher]: {
|
|
98234
|
+
exported: true,
|
|
98235
|
+
as: received
|
|
98236
|
+
}
|
|
98237
|
+
};
|
|
98238
|
+
}
|
|
98239
|
+
var APPLIANCE_EXPORT = {
|
|
98240
|
+
ha: offered(HA_AS),
|
|
98241
|
+
homekit: withheld(HOMEKIT_REASON),
|
|
98242
|
+
alexa: withheld(ALEXA_REASON),
|
|
98243
|
+
google: withheld(GOOGLE_REASON),
|
|
98244
|
+
matter: withheld(MATTER_REASON)
|
|
98245
|
+
};
|
|
98246
|
+
function isPlugApplianceType(deviceType) {
|
|
98247
|
+
return PLUG_APPLIANCE_TYPES.some((type) => type === deviceType);
|
|
98248
|
+
}
|
|
98249
|
+
/** The decision for this ecosystem, or null when the type is not an appliance. */
|
|
98250
|
+
function applianceExport(ecosystem, deviceType) {
|
|
98251
|
+
if (!isPlugApplianceType(deviceType)) return null;
|
|
98252
|
+
return APPLIANCE_EXPORT[ecosystem][deviceType];
|
|
98253
|
+
}
|
|
98254
|
+
//#endregion
|
|
98067
98255
|
//#region src/device/path-util.ts
|
|
98068
98256
|
/** Returns true when `x` is a non-null, non-array plain object. */
|
|
98069
98257
|
function isRecord$1(x) {
|
|
@@ -115501,6 +115689,10 @@ exports.APPEARANCE_BLOCKS = APPEARANCE_BLOCKS;
|
|
|
115501
115689
|
exports.APPEARANCE_DESCRIPTOR_VERSION = APPEARANCE_DESCRIPTOR_VERSION;
|
|
115502
115690
|
exports.APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT = APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT;
|
|
115503
115691
|
exports.APPLE_SA_TO_MACRO = APPLE_SA_TO_MACRO;
|
|
115692
|
+
exports.APPLIANCE_DEFAULTS = require_composition.APPLIANCE_DEFAULTS;
|
|
115693
|
+
exports.APPLIANCE_EXPORT = APPLIANCE_EXPORT;
|
|
115694
|
+
exports.APPLIANCE_KINDS = require_composition.APPLIANCE_KINDS;
|
|
115695
|
+
exports.APPLIANCE_TEMPLATE_ID = require_composition.APPLIANCE_TEMPLATE_ID;
|
|
115504
115696
|
exports.APP_AUTH_CALLBACK_MAX_LENGTH = APP_AUTH_CALLBACK_MAX_LENGTH;
|
|
115505
115697
|
exports.APP_AUTH_CALLBACK_URLS = APP_AUTH_CALLBACK_URLS;
|
|
115506
115698
|
exports.APP_FLOW_DEFAULT_REDIRECT = APP_FLOW_DEFAULT_REDIRECT;
|
|
@@ -115564,6 +115756,7 @@ exports.AppLoginPathSchema = AppLoginPathSchema;
|
|
|
115564
115756
|
exports.AppPageLangSchema = AppPageLangSchema;
|
|
115565
115757
|
exports.AppleFmAvailabilitySchema = AppleFmAvailabilitySchema;
|
|
115566
115758
|
exports.AppleFmUnavailableReasonSchema = AppleFmUnavailableReasonSchema;
|
|
115759
|
+
exports.ApplianceHelperSpecSchema = require_composition.ApplianceHelperSpecSchema;
|
|
115567
115760
|
exports.ArchiveEntrySchema = ArchiveEntrySchema;
|
|
115568
115761
|
exports.ArchiveManifestSchema = ArchiveManifestSchema;
|
|
115569
115762
|
exports.ArchiveSqliteSnapshotSchema = ArchiveSqliteSnapshotSchema;
|
|
@@ -116836,6 +117029,7 @@ exports.PIPELINE_ANALYTICS_CAP_NAME = PIPELINE_ANALYTICS_CAP_NAME;
|
|
|
116836
117029
|
exports.PIPELINE_FLOW_CAPABILITY_NAMES = PIPELINE_FLOW_CAPABILITY_NAMES;
|
|
116837
117030
|
exports.PIPELINE_OWNER_CAPABILITY_NAMES = PIPELINE_OWNER_CAPABILITY_NAMES;
|
|
116838
117031
|
exports.PIPELINE_RAMP = PIPELINE_RAMP;
|
|
117032
|
+
exports.PLUG_APPLIANCE_TYPES = PLUG_APPLIANCE_TYPES;
|
|
116839
117033
|
exports.PLUS_CATALOG_CLASS_FLOORS = PLUS_CATALOG_CLASS_FLOORS;
|
|
116840
117034
|
exports.PLUS_CATALOG_STOCK_CLASS_FLOORS = PLUS_CATALOG_STOCK_CLASS_FLOORS;
|
|
116841
117035
|
exports.PLUS_CATALOG_TO_MACRO = PLUS_CATALOG_TO_MACRO;
|
|
@@ -117538,6 +117732,8 @@ exports.allowedSuppliedEffect = allowedSuppliedEffect;
|
|
|
117538
117732
|
exports.ambientLightSensorCapability = ambientLightSensorCapability;
|
|
117539
117733
|
exports.annotateClipsWithEventLabels = annotateClipsWithEventLabels;
|
|
117540
117734
|
exports.appFlowLocation = appFlowLocation;
|
|
117735
|
+
exports.applianceDeviceType = require_composition.applianceDeviceType;
|
|
117736
|
+
exports.applianceExport = applianceExport;
|
|
117541
117737
|
exports.applyBlockingEdit = applyBlockingEdit;
|
|
117542
117738
|
exports.applyCropClassFloors = applyCropClassFloors;
|
|
117543
117739
|
exports.applyModeDelaysEdits = applyModeDelaysEdits;
|
|
@@ -117909,6 +118105,7 @@ exports.hasModelBoundOverrides = hasModelBoundOverrides;
|
|
|
117909
118105
|
exports.hasMotionTrigger = hasMotionTrigger;
|
|
117910
118106
|
exports.hasUrlScheme = hasUrlScheme;
|
|
117911
118107
|
exports.heatingValveCapability = heatingValveCapability;
|
|
118108
|
+
exports.helperMembers = require_composition.helperMembers;
|
|
117912
118109
|
exports.helperSaveProblems = helperSaveProblems;
|
|
117913
118110
|
exports.hfModelUrl = require_sleep.hfModelUrl;
|
|
117914
118111
|
exports.historyFieldsFor = historyFieldsFor;
|
|
@@ -117943,6 +118140,7 @@ exports.isAlertEpisodeOpen = isAlertEpisodeOpen;
|
|
|
117943
118140
|
exports.isAlertEpisodeSeverity = isAlertEpisodeSeverity;
|
|
117944
118141
|
exports.isAppLinkBase = isAppLinkBase;
|
|
117945
118142
|
exports.isAppStartRefusal = isAppStartRefusal;
|
|
118143
|
+
exports.isApplianceKind = require_composition.isApplianceKind;
|
|
117946
118144
|
exports.isArrayOutputSchema = isArrayOutputSchema;
|
|
117947
118145
|
exports.isAudioChunkFormat = require_sleep.isAudioChunkFormat;
|
|
117948
118146
|
exports.isAudioClassName = isAudioClassName;
|
|
@@ -117983,6 +118181,7 @@ exports.isOauthLandingReason = isOauthLandingReason;
|
|
|
117983
118181
|
exports.isObjectInput = isObjectInput;
|
|
117984
118182
|
exports.isOccupancyRule = isOccupancyRule;
|
|
117985
118183
|
exports.isOwnerOnlyEventCategory = require_event_category.isOwnerOnlyEventCategory;
|
|
118184
|
+
exports.isPlugApplianceType = isPlugApplianceType;
|
|
117986
118185
|
exports.isReadingQuantity = require_sleep.isReadingQuantity;
|
|
117987
118186
|
exports.isRemovedModelId = isRemovedModelId;
|
|
117988
118187
|
exports.isRestoredCap = isRestoredCap;
|
|
@@ -118392,6 +118591,7 @@ exports.sliceChangedAt = require_composition.sliceChangedAt;
|
|
|
118392
118591
|
exports.smokeCapability = smokeCapability;
|
|
118393
118592
|
exports.smtpProviderCapability = smtpProviderCapability;
|
|
118394
118593
|
exports.snapshotCapability = snapshotCapability;
|
|
118594
|
+
exports.sourcePickForAppliance = require_composition.sourcePickForAppliance;
|
|
118395
118595
|
exports.sourcePickForTemplate = sourcePickForTemplate;
|
|
118396
118596
|
exports.splitTranslationRef = splitTranslationRef;
|
|
118397
118597
|
exports.squareAround = squareAround;
|