@camstack/types 1.2.425 → 1.2.426

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/index.js CHANGED
@@ -71593,9 +71593,9 @@ var PowerMeterStatusSchema = zod.z.object({
71593
71593
  /** Cumulative energy in kilowatt-hours since the meter was reset. */
71594
71594
  kwhTotal: zod.z.number().optional().meta(require_sleep.readingMeta("energy", { label: "Energy" })),
71595
71595
  /** Voltage in volts. */
71596
- volts: zod.z.number().optional().meta(require_sleep.readingMeta("voltage")),
71596
+ volts: zod.z.number().optional().meta(require_sleep.readingMeta("voltage", { label: "Voltage" })),
71597
71597
  /** Current in amperes. */
71598
- amps: zod.z.number().optional().meta(require_sleep.readingMeta("current")),
71598
+ amps: zod.z.number().optional().meta(require_sleep.readingMeta("current", { label: "Current" })),
71599
71599
  /** Apparent power in volt-amperes. */
71600
71600
  va: zod.z.number().optional().meta(require_sleep.readingMeta("apparent-power")),
71601
71601
  /** Power factor (0..1) if reported. */
@@ -71603,17 +71603,74 @@ var PowerMeterStatusSchema = zod.z.object({
71603
71603
  /** Ms epoch when the slice was last updated. */
71604
71604
  lastFetchedAt: zod.z.number()
71605
71605
  });
71606
+ /**
71607
+ * Loads that draw metered mains power (D951). The reading is a feature of the
71608
+ * device itself — a plug, a lamp, a fan, an air conditioner, a boiler, a
71609
+ * vacuum dock — not a separate sensor beside it. A `Sensor` stays: a clamp
71610
+ * meter or a standalone energy monitor IS the device. Cover, lock, valve,
71611
+ * camera and the like are left out: their draw is not what anyone meters.
71612
+ */
71613
+ var POWER_METER_DEVICE_TYPES = [
71614
+ require_err_msg.DeviceType.Sensor,
71615
+ require_err_msg.DeviceType.Switch,
71616
+ require_err_msg.DeviceType.Light,
71617
+ require_err_msg.DeviceType.Fan,
71618
+ require_err_msg.DeviceType.Climate,
71619
+ require_err_msg.DeviceType.Thermostat,
71620
+ require_err_msg.DeviceType.Humidifier,
71621
+ require_err_msg.DeviceType.WaterHeater,
71622
+ require_err_msg.DeviceType.MediaPlayer,
71623
+ require_err_msg.DeviceType.Washer,
71624
+ require_err_msg.DeviceType.Dryer,
71625
+ require_err_msg.DeviceType.Dishwasher,
71626
+ require_err_msg.DeviceType.Vacuum,
71627
+ require_err_msg.DeviceType.LawnMower,
71628
+ require_err_msg.DeviceType.PetFeeder
71629
+ ];
71630
+ /** Everything but a bare `Sensor`: a sensor that takes its reading from another sensor adds nothing. */
71631
+ var POWER_METER_CUSTOMIZE_DEVICE_TYPES = POWER_METER_DEVICE_TYPES.filter((type) => type !== require_err_msg.DeviceType.Sensor);
71632
+ /** One scalar target per reading; each is sourced from a device of its own (D951). */
71633
+ function powerTarget(id, unit) {
71634
+ return {
71635
+ id,
71636
+ cardinality: "scalar",
71637
+ vocabulary: {
71638
+ cap: "power-meter",
71639
+ stateField: id
71640
+ },
71641
+ deviceTypes: POWER_METER_CUSTOMIZE_DEVICE_TYPES,
71642
+ apply: "add",
71643
+ path: id,
71644
+ sources: [{
71645
+ kind: "numeric",
71646
+ requiredUnit: unit,
71647
+ transforms: [{ kind: "identity" }]
71648
+ }],
71649
+ companions: [{
71650
+ kind: "clock",
71651
+ path: "lastFetchedAt",
71652
+ when: "always"
71653
+ }],
71654
+ sourceReport: { status: "assignment-status" },
71655
+ advancedExpression: true
71656
+ };
71657
+ }
71658
+ /** "Power and energy" extension: watts, energy, voltage and current from other devices (D951). */
71659
+ var powerMeterCustomize = {
71660
+ version: 1,
71661
+ targets: [
71662
+ powerTarget("watts", "W"),
71663
+ powerTarget("kwhTotal", "kWh"),
71664
+ powerTarget("volts", "V"),
71665
+ powerTarget("amps", "A")
71666
+ ]
71667
+ };
71606
71668
  var powerMeterCapability = {
71607
71669
  name: "power-meter",
71608
71670
  scope: "device",
71609
71671
  deviceNative: true,
71610
71672
  mode: "singleton",
71611
- deviceTypes: [
71612
- require_err_msg.DeviceType.Sensor,
71613
- require_err_msg.DeviceType.Washer,
71614
- require_err_msg.DeviceType.Dryer,
71615
- require_err_msg.DeviceType.Dishwasher
71616
- ],
71673
+ deviceTypes: POWER_METER_DEVICE_TYPES,
71617
71674
  methods: {},
71618
71675
  status: {
71619
71676
  schema: PowerMeterStatusSchema,
@@ -71670,7 +71727,8 @@ var powerMeterCapability = {
71670
71727
  } },
71671
71728
  /** Clock fields: written, but excluded from the compare that decides
71672
71729
  * whether persisting is worth a SQLite commit. */
71673
- volatileStateFields: ["lastFetchedAt"]
71730
+ volatileStateFields: ["lastFetchedAt"],
71731
+ customize: powerMeterCustomize
71674
71732
  };
71675
71733
  //#endregion
71676
71734
  //#region src/capabilities/presence.cap.ts
@@ -80443,7 +80501,7 @@ function convertUnitTargets(from) {
80443
80501
  //#region src/generated/customize-catalog.ts
80444
80502
  /**
80445
80503
  * Customize catalog, projected from every `*.cap.ts` `customize` block.
80446
- * 5 caps. Field keys are `runtimeState` paths. No Zod.
80504
+ * 6 caps. Field keys are `runtimeState` paths. No Zod.
80447
80505
  */
80448
80506
  var CAP_CUSTOMIZE_CATALOG = {
80449
80507
  "battery": {
@@ -80708,6 +80766,167 @@ var CAP_CUSTOMIZE_CATALOG = {
80708
80766
  ]
80709
80767
  }]
80710
80768
  },
80769
+ "power-meter": {
80770
+ version: 1,
80771
+ targets: [
80772
+ {
80773
+ id: "watts",
80774
+ cardinality: "scalar",
80775
+ deviceTypes: [
80776
+ require_err_msg.DeviceType.Switch,
80777
+ require_err_msg.DeviceType.Light,
80778
+ require_err_msg.DeviceType.Fan,
80779
+ require_err_msg.DeviceType.Climate,
80780
+ require_err_msg.DeviceType.Thermostat,
80781
+ require_err_msg.DeviceType.Humidifier,
80782
+ require_err_msg.DeviceType.WaterHeater,
80783
+ require_err_msg.DeviceType.MediaPlayer,
80784
+ require_err_msg.DeviceType.Washer,
80785
+ require_err_msg.DeviceType.Dryer,
80786
+ require_err_msg.DeviceType.Dishwasher,
80787
+ require_err_msg.DeviceType.Vacuum,
80788
+ require_err_msg.DeviceType.LawnMower,
80789
+ require_err_msg.DeviceType.PetFeeder
80790
+ ],
80791
+ apply: "add",
80792
+ vocabularyCap: "power-meter",
80793
+ vocabularyStateField: "watts",
80794
+ sources: [{
80795
+ kind: "numeric",
80796
+ requiredUnit: "W",
80797
+ transformKinds: ["identity"],
80798
+ transforms: [{ kind: "identity" }]
80799
+ }],
80800
+ sourceReport: { status: "assignment-status" },
80801
+ advancedExpression: true,
80802
+ path: "watts",
80803
+ valueKind: "number",
80804
+ nullable: false,
80805
+ companions: [{
80806
+ kind: "clock",
80807
+ path: "lastFetchedAt",
80808
+ when: "always"
80809
+ }]
80810
+ },
80811
+ {
80812
+ id: "kwhTotal",
80813
+ cardinality: "scalar",
80814
+ deviceTypes: [
80815
+ require_err_msg.DeviceType.Switch,
80816
+ require_err_msg.DeviceType.Light,
80817
+ require_err_msg.DeviceType.Fan,
80818
+ require_err_msg.DeviceType.Climate,
80819
+ require_err_msg.DeviceType.Thermostat,
80820
+ require_err_msg.DeviceType.Humidifier,
80821
+ require_err_msg.DeviceType.WaterHeater,
80822
+ require_err_msg.DeviceType.MediaPlayer,
80823
+ require_err_msg.DeviceType.Washer,
80824
+ require_err_msg.DeviceType.Dryer,
80825
+ require_err_msg.DeviceType.Dishwasher,
80826
+ require_err_msg.DeviceType.Vacuum,
80827
+ require_err_msg.DeviceType.LawnMower,
80828
+ require_err_msg.DeviceType.PetFeeder
80829
+ ],
80830
+ apply: "add",
80831
+ vocabularyCap: "power-meter",
80832
+ vocabularyStateField: "kwhTotal",
80833
+ sources: [{
80834
+ kind: "numeric",
80835
+ requiredUnit: "kWh",
80836
+ transformKinds: ["identity"],
80837
+ transforms: [{ kind: "identity" }]
80838
+ }],
80839
+ sourceReport: { status: "assignment-status" },
80840
+ advancedExpression: true,
80841
+ path: "kwhTotal",
80842
+ valueKind: "number",
80843
+ nullable: false,
80844
+ companions: [{
80845
+ kind: "clock",
80846
+ path: "lastFetchedAt",
80847
+ when: "always"
80848
+ }]
80849
+ },
80850
+ {
80851
+ id: "volts",
80852
+ cardinality: "scalar",
80853
+ deviceTypes: [
80854
+ require_err_msg.DeviceType.Switch,
80855
+ require_err_msg.DeviceType.Light,
80856
+ require_err_msg.DeviceType.Fan,
80857
+ require_err_msg.DeviceType.Climate,
80858
+ require_err_msg.DeviceType.Thermostat,
80859
+ require_err_msg.DeviceType.Humidifier,
80860
+ require_err_msg.DeviceType.WaterHeater,
80861
+ require_err_msg.DeviceType.MediaPlayer,
80862
+ require_err_msg.DeviceType.Washer,
80863
+ require_err_msg.DeviceType.Dryer,
80864
+ require_err_msg.DeviceType.Dishwasher,
80865
+ require_err_msg.DeviceType.Vacuum,
80866
+ require_err_msg.DeviceType.LawnMower,
80867
+ require_err_msg.DeviceType.PetFeeder
80868
+ ],
80869
+ apply: "add",
80870
+ vocabularyCap: "power-meter",
80871
+ vocabularyStateField: "volts",
80872
+ sources: [{
80873
+ kind: "numeric",
80874
+ requiredUnit: "V",
80875
+ transformKinds: ["identity"],
80876
+ transforms: [{ kind: "identity" }]
80877
+ }],
80878
+ sourceReport: { status: "assignment-status" },
80879
+ advancedExpression: true,
80880
+ path: "volts",
80881
+ valueKind: "number",
80882
+ nullable: false,
80883
+ companions: [{
80884
+ kind: "clock",
80885
+ path: "lastFetchedAt",
80886
+ when: "always"
80887
+ }]
80888
+ },
80889
+ {
80890
+ id: "amps",
80891
+ cardinality: "scalar",
80892
+ deviceTypes: [
80893
+ require_err_msg.DeviceType.Switch,
80894
+ require_err_msg.DeviceType.Light,
80895
+ require_err_msg.DeviceType.Fan,
80896
+ require_err_msg.DeviceType.Climate,
80897
+ require_err_msg.DeviceType.Thermostat,
80898
+ require_err_msg.DeviceType.Humidifier,
80899
+ require_err_msg.DeviceType.WaterHeater,
80900
+ require_err_msg.DeviceType.MediaPlayer,
80901
+ require_err_msg.DeviceType.Washer,
80902
+ require_err_msg.DeviceType.Dryer,
80903
+ require_err_msg.DeviceType.Dishwasher,
80904
+ require_err_msg.DeviceType.Vacuum,
80905
+ require_err_msg.DeviceType.LawnMower,
80906
+ require_err_msg.DeviceType.PetFeeder
80907
+ ],
80908
+ apply: "add",
80909
+ vocabularyCap: "power-meter",
80910
+ vocabularyStateField: "amps",
80911
+ sources: [{
80912
+ kind: "numeric",
80913
+ requiredUnit: "A",
80914
+ transformKinds: ["identity"],
80915
+ transforms: [{ kind: "identity" }]
80916
+ }],
80917
+ sourceReport: { status: "assignment-status" },
80918
+ advancedExpression: true,
80919
+ path: "amps",
80920
+ valueKind: "number",
80921
+ nullable: false,
80922
+ companions: [{
80923
+ kind: "clock",
80924
+ path: "lastFetchedAt",
80925
+ when: "always"
80926
+ }]
80927
+ }
80928
+ ]
80929
+ },
80711
80930
  "running-state": {
80712
80931
  version: 1,
80713
80932
  targets: [{
@@ -80806,7 +81025,9 @@ var CAP_RUNTIME_FIELD_UNITS = {
80806
81025
  "humidity-sensor": { percent: "%" },
80807
81026
  "power-meter": {
80808
81027
  watts: "W",
80809
- kwhTotal: "kWh"
81028
+ kwhTotal: "kWh",
81029
+ volts: "V",
81030
+ amps: "A"
80810
81031
  },
80811
81032
  "temperature-sensor": { celsius: "°C" }
80812
81033
  };
@@ -80835,7 +81056,7 @@ function isLiteral(source, expr) {
80835
81056
  }
80836
81057
  //#endregion
80837
81058
  //#region src/composition/customize/event-compile.ts
80838
- var catalog$4 = CAP_CUSTOMIZE_CATALOG;
81059
+ var catalog$5 = CAP_CUSTOMIZE_CATALOG;
80839
81060
  function compilePulseOverride(input) {
80840
81061
  const target = catalogTarget$4(input.draft.cap, input.draft.targetId);
80841
81062
  if (target === null || target.shape !== "pulse") return fail$2("target");
@@ -80967,7 +81188,7 @@ function sensorEntries(sources, device, modes) {
80967
81188
  };
80968
81189
  }
80969
81190
  function catalogTarget$4(cap, targetId) {
80970
- const entry = catalog$4[cap];
81191
+ const entry = catalog$5[cap];
80971
81192
  if (entry === void 0) return null;
80972
81193
  return entry.targets.find((target) => target.id === targetId) ?? null;
80973
81194
  }
@@ -81092,7 +81313,7 @@ function wrap$2(feature) {
81092
81313
  }
81093
81314
  //#endregion
81094
81315
  //#region src/composition/customize/scalar-compile.ts
81095
- var catalog$3 = CAP_CUSTOMIZE_CATALOG;
81316
+ var catalog$4 = CAP_CUSTOMIZE_CATALOG;
81096
81317
  function compileScalarOverride(input) {
81097
81318
  const target = catalogTarget$3(input.draft.cap, input.draft.targetId);
81098
81319
  if (target === null || target.cardinality !== "scalar" || target.path === void 0) return fail$1("target");
@@ -81122,7 +81343,7 @@ function fail$1(reason) {
81122
81343
  };
81123
81344
  }
81124
81345
  function catalogTarget$3(cap, targetId) {
81125
- const entry = catalog$3[cap];
81346
+ const entry = catalog$4[cap];
81126
81347
  if (entry === void 0) return null;
81127
81348
  return entry.targets.find((target) => target.id === targetId) ?? null;
81128
81349
  }
@@ -81259,6 +81480,83 @@ function refOf$1(draft) {
81259
81480
  };
81260
81481
  }
81261
81482
  //#endregion
81483
+ //#region src/composition/customize/scalar-merge.ts
81484
+ var catalog$3 = CAP_CUSTOMIZE_CATALOG;
81485
+ function scalarTargets(cap) {
81486
+ return (catalog$3[cap]?.targets ?? []).filter((target) => target.cardinality === "scalar" && target.path !== void 0);
81487
+ }
81488
+ /** How many scalar targets the cap declares: above one, the cap's feature is shared. */
81489
+ function scalarTargetCount(cap) {
81490
+ return scalarTargets(cap).length;
81491
+ }
81492
+ function valuePath(target) {
81493
+ return target.path ?? target.id;
81494
+ }
81495
+ function ownedPaths(target) {
81496
+ return [valuePath(target), ...(target.companions ?? []).map((companion) => companion.path)];
81497
+ }
81498
+ function find(cap, targetId) {
81499
+ return scalarTargets(cap).find((target) => target.id === targetId) ?? null;
81500
+ }
81501
+ function without(fields, paths) {
81502
+ return Object.fromEntries(Object.entries(fields).filter(([path]) => !paths.has(path)));
81503
+ }
81504
+ /**
81505
+ * The cap's feature with `compiled` (one target's own feature) merged in. A cap
81506
+ * with one scalar target is replaced whole, as before.
81507
+ */
81508
+ function mergeScalarTarget(current, compiled, cap, targetId) {
81509
+ const target = find(cap, targetId);
81510
+ if (current === null || target === null || scalarTargetCount(cap) < 2) return compiled;
81511
+ const kept = without(current.fields, new Set(ownedPaths(target)));
81512
+ return {
81513
+ ...current,
81514
+ ...compiled,
81515
+ fields: {
81516
+ ...kept,
81517
+ ...compiled.fields
81518
+ }
81519
+ };
81520
+ }
81521
+ /** The cap's feature without `targetId`'s paths; null when no target value is left. */
81522
+ function removeScalarTarget(current, cap, targetId) {
81523
+ if (current === null) return null;
81524
+ const target = find(cap, targetId);
81525
+ if (target === null || scalarTargetCount(cap) < 2) return null;
81526
+ const stillAssigned = scalarTargets(cap).filter((row) => row.id !== targetId).filter((row) => current.fields[valuePath(row)] !== void 0);
81527
+ if (stillAssigned.length === 0) return null;
81528
+ const needed = new Set(stillAssigned.flatMap((row) => ownedPaths(row)));
81529
+ const drop = new Set(ownedPaths(target).filter((path) => !needed.has(path)));
81530
+ return {
81531
+ ...current,
81532
+ fields: without(current.fields, drop)
81533
+ };
81534
+ }
81535
+ /**
81536
+ * The part of a stored feature one target owns — what a decode compares with
81537
+ * its recompiled feature. A cap with one target compares the whole feature.
81538
+ */
81539
+ function ownedSlice(stored, cap, targetId) {
81540
+ const target = find(cap, targetId);
81541
+ if (target === null || scalarTargetCount(cap) < 2) return stored;
81542
+ const owned = new Set(ownedPaths(target));
81543
+ return {
81544
+ ...stored,
81545
+ fields: Object.fromEntries(Object.entries(stored.fields).filter(([path]) => owned.has(path)))
81546
+ };
81547
+ }
81548
+ /**
81549
+ * The stored feature as ONE target sees it: null when the cap's feature holds
81550
+ * only its neighbours' readings (no assignment of this target), else the whole
81551
+ * feature. A cap with one target sees what is stored.
81552
+ */
81553
+ function targetFeature(stored, cap, targetId) {
81554
+ if (stored === null) return null;
81555
+ const target = find(cap, targetId);
81556
+ if (target === null || scalarTargetCount(cap) < 2) return stored;
81557
+ return stored.fields[valuePath(target)] === void 0 ? null : stored;
81558
+ }
81559
+ //#endregion
81262
81560
  //#region src/composition/customize/scalar-decode.ts
81263
81561
  var catalog$2 = CAP_CUSTOMIZE_CATALOG;
81264
81562
  function decodeScalarOverride(input) {
@@ -81369,7 +81667,7 @@ function reproduces$1(decoded, device, stored) {
81369
81667
  sourceUnit: decoded.sourceUnit
81370
81668
  });
81371
81669
  if (!compiled.ok) return false;
81372
- return sameFeature$1(compiled.value, stored);
81670
+ return sameFeature$1(compiled.value, ownedSlice(stored, decoded.draft.cap, decoded.draft.targetId));
81373
81671
  }
81374
81672
  function sameFeature$1(compiled, stored) {
81375
81673
  return sameStored(wrap$1(withoutEnabled(compiled)), wrap$1(withoutEnabled(stored)));
@@ -119179,6 +119477,7 @@ exports.memoizePinnedFfmpeg = memoizePinnedFfmpeg;
119179
119477
  exports.mergeClipLabels = mergeClipLabels;
119180
119478
  exports.mergeKeyedArrayItem = mergeKeyedArrayItem;
119181
119479
  exports.mergeOverrides = mergeOverrides;
119480
+ exports.mergeScalarTarget = mergeScalarTarget;
119182
119481
  exports.mergeSecretStatePaths = require_sleep.mergeSecretStatePaths;
119183
119482
  exports.mergeSettingsBags = mergeSettingsBags;
119184
119483
  exports.mergeSourceInfo = mergeSourceInfo;
@@ -119245,6 +119544,7 @@ exports.optionalMethod = require_sleep.optionalMethod;
119245
119544
  exports.osdCapability = osdCapability;
119246
119545
  exports.osdManagerCapability = osdManagerCapability;
119247
119546
  exports.overlayClusterStepSettings = overlayClusterStepSettings;
119547
+ exports.ownedSlice = ownedSlice;
119248
119548
  exports.packagePickerItems = packagePickerItems;
119249
119549
  exports.paintHex = paintHex;
119250
119550
  exports.paletteEntryLabel = paletteEntryLabel;
@@ -119375,6 +119675,7 @@ exports.reducePoints = reducePoints;
119375
119675
  exports.reducerForActive = reducerForActive;
119376
119676
  exports.registerKnownSecret = require_sleep.registerKnownSecret;
119377
119677
  exports.remapCropDetections = remapCropDetections;
119678
+ exports.removeScalarTarget = removeScalarTarget;
119378
119679
  exports.renameAlarmProfile = renameAlarmProfile;
119379
119680
  exports.renderVocabPhrase = renderVocabPhrase;
119380
119681
  exports.replacedFieldKeys = replacedFieldKeys;
@@ -119463,6 +119764,7 @@ exports.runtimeStatePolicyFor = runtimeStatePolicyFor;
119463
119764
  exports.sameDoFamily = sameDoFamily;
119464
119765
  exports.sameHelperBody = sameHelperBody;
119465
119766
  exports.sameRead = sameRead;
119767
+ exports.scalarTargetCount = scalarTargetCount;
119466
119768
  exports.sceneMonitorCapability = sceneMonitorCapability;
119467
119769
  exports.scheduleForSendTimes = scheduleForSendTimes;
119468
119770
  exports.schemaDeclaresAnyField = require_sleep.schemaDeclaresAnyField;
@@ -119578,6 +119880,7 @@ exports.systemEventSummarySplitOf = systemEventSummarySplitOf;
119578
119880
  exports.systemFamilyOfKind = systemFamilyOfKind;
119579
119881
  exports.systemRuleKindOf = systemRuleKindOf;
119580
119882
  exports.tamperCapability = tamperCapability;
119883
+ exports.targetFeature = targetFeature;
119581
119884
  exports.taskLogEntrySchema = taskLogEntrySchema;
119582
119885
  exports.taskPhaseSchema = taskPhaseSchema;
119583
119886
  exports.taskTargetSchema = taskTargetSchema;