@camstack/addon-provider-bosch 0.1.17 → 0.1.19

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.
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../dist-D6D2JO8x.js");
3
- const require_account_integration_offline = require("../account-integration-offline-pY2Ojv8k.js");
2
+ const require_dist = require("../dist-C5fLGNXK.js");
3
+ const require_account_integration_offline = require("../account-integration-offline-D5EEH5Xn.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_tls = require("node:tls");
6
6
  let node_zlib = require("node:zlib");
@@ -3826,8 +3826,6 @@ var COLD_DISHWASHER_STATUS = {
3826
3826
  localControlActive: null,
3827
3827
  powerOn: null,
3828
3828
  powerState: null,
3829
- saltLevel: null,
3830
- rinseAidLevel: null,
3831
3829
  filterCleaningDue: null,
3832
3830
  machineCareDue: null,
3833
3831
  machineCareRemainingRuns: null,
@@ -3885,8 +3883,6 @@ function dishwasherStatusFromFeatures(input) {
3885
3883
  localControlActive: boolOf(valueOf(input, findEntity(description, ["status"], ["LocalControlActive"]))),
3886
3884
  powerOn: powerRaw === null ? null : powerRaw === "On",
3887
3885
  powerState: powerRaw,
3888
- saltLevel: consumableFromEvents(input, ["SaltNearlyEmpty"], ["SaltEmpty", "SaltLack"]),
3889
- rinseAidLevel: consumableFromEvents(input, ["RinseAidNearlyEmpty"], ["RinseAidEmpty", "RinseAidLack"]),
3890
3886
  filterCleaningDue: reminderDue(input, [
3891
3887
  "SmartFilterCleaningReminder",
3892
3888
  "CheckFilterSystem",
@@ -3987,6 +3983,44 @@ function dishwasherOptionsFromDescription(input) {
3987
3983
  var HC_COMMAND_PAUSE = "PauseProgram";
3988
3984
  var HC_COMMAND_RESUME = "ResumeProgram";
3989
3985
  var HC_COMMAND_STOP = "AbortProgram";
3986
+ /** The dishwasher supplies, by the events that report them. */
3987
+ var DISHWASHER_SUPPLIES = [{
3988
+ key: "salt",
3989
+ label: "Salt",
3990
+ nearlyEmpty: ["SaltNearlyEmpty"],
3991
+ empty: ["SaltEmpty", "SaltLack"]
3992
+ }, {
3993
+ key: "rinseAid",
3994
+ label: "Rinse aid",
3995
+ nearlyEmpty: ["RinseAidNearlyEmpty"],
3996
+ empty: ["RinseAidEmpty", "RinseAidLack"]
3997
+ }];
3998
+ /**
3999
+ * The dishwasher's `consumables` items (D915): salt and rinse aid as `supply`
4000
+ * items, for each the appliance's description lists an event for. Their
4001
+ * status comes from those events (`consumableFromEvents`); none reported is
4002
+ * `null` (unknown), never `ok`. Neither is resettable — refilling is the reset.
4003
+ *
4004
+ * `null` while the appliance is offline or undescribed: nothing is known NOW,
4005
+ * and the `consumables` slice is restored — the last observation stays rather
4006
+ * than being overwritten with unknowns. Pure.
4007
+ */
4008
+ function dishwasherConsumablesFromFeatures(view) {
4009
+ if (availabilityOf(view) !== "available") return null;
4010
+ return DISHWASHER_SUPPLIES.flatMap(({ key, label, nearlyEmpty, empty }) => {
4011
+ if (eventStates(view, [...nearlyEmpty, ...empty]).length === 0) return [];
4012
+ return [{
4013
+ key,
4014
+ label,
4015
+ level: null,
4016
+ status: consumableFromEvents(view, nearlyEmpty, empty),
4017
+ kind: "supply",
4018
+ form: "product",
4019
+ lastResetAt: null,
4020
+ resettable: false
4021
+ }];
4022
+ });
4023
+ }
3990
4024
  //#endregion
3991
4025
  //#region src/home-connect/home-connect-child-bindings.ts
3992
4026
  /** The capability a bound child registers. */
@@ -4577,6 +4611,15 @@ var homeConnectDishwasherSchema = require_dist.object({
4577
4611
  integrationId: require_dist.string().optional()
4578
4612
  });
4579
4613
  var DISH_CAP = "dishwasher";
4614
+ var CONSUMABLES_CAP = "consumables";
4615
+ var CONSUMABLES_EMPTY = {
4616
+ items: [],
4617
+ lastChangedAt: 0,
4618
+ lastFetchedAt: 0
4619
+ };
4620
+ function sameItems(a, b) {
4621
+ return JSON.stringify(a) === JSON.stringify(b);
4622
+ }
4580
4623
  /** The option short names of the boolean setters, in the spellings an appliance uses. */
4581
4624
  var OPTION_NAMES = {
4582
4625
  halfLoad: ["HalfLoad"],
@@ -4603,6 +4646,7 @@ var HomeConnectDishwasherDevice = class extends require_dist.BaseDevice {
4603
4646
  async onActivate() {
4604
4647
  await super.onActivate();
4605
4648
  this.registerDishwasherCap();
4649
+ this.registerConsumablesCap();
4606
4650
  this.runtimeState.setCapState(DISH_CAP, COLD_DISHWASHER_STATUS);
4607
4651
  this.markOnline(false);
4608
4652
  this.#unwatch = homeConnectConnections.watch(this.#brokerId, this.#haId, (event) => this.recomputeSlice(event));
@@ -4627,13 +4671,41 @@ var HomeConnectDishwasherDevice = class extends require_dist.BaseDevice {
4627
4671
  recomputeSlice(event) {
4628
4672
  const previous = this.runtimeState.getCapState(DISH_CAP);
4629
4673
  const lastValueAt = event.kind === "feature" && !event.key.startsWith("HomeConnect.Info.") && !event.key.startsWith("HomeConnect.Network.") ? Date.now() : previous?.lastFetchedAt ?? 0;
4674
+ const view = this.view();
4630
4675
  const slice = dishwasherStatusFromFeatures({
4631
- ...this.view(),
4676
+ ...view,
4632
4677
  lastValueAt
4633
4678
  });
4634
4679
  this.runtimeState.setCapState(DISH_CAP, slice);
4680
+ this.writeConsumables(dishwasherConsumablesFromFeatures(view));
4635
4681
  this.markOnline(slice.availability !== "offline");
4636
4682
  }
4683
+ /**
4684
+ * Salt and rinse aid, as `consumables` items (D915). Written only when they
4685
+ * changed; `null` (offline / undescribed) and an empty list write nothing —
4686
+ * the slice is restored, and "nothing known now" must not erase the last
4687
+ * observation.
4688
+ */
4689
+ writeConsumables(items) {
4690
+ if (items === null || items.length === 0) return;
4691
+ const previous = this.runtimeState.getCapState(CONSUMABLES_CAP);
4692
+ if (previous !== void 0 && sameItems(previous.items, items)) return;
4693
+ const now = Date.now();
4694
+ const next = {
4695
+ items,
4696
+ lastChangedAt: now,
4697
+ lastFetchedAt: now
4698
+ };
4699
+ this.runtimeState.setCapState(CONSUMABLES_CAP, next);
4700
+ }
4701
+ registerConsumablesCap() {
4702
+ this.ctx.registerNativeCap(require_dist.consumablesCapability, {
4703
+ getStatus: async () => this.runtimeState.getCapState(CONSUMABLES_CAP) ?? CONSUMABLES_EMPTY,
4704
+ reset: async ({ key }) => {
4705
+ throw new Error(`"${key}" has no reset on a dishwasher — refilling it is the reset`);
4706
+ }
4707
+ });
4708
+ }
4637
4709
  requireClient() {
4638
4710
  const client = this.client();
4639
4711
  if (!client) throw new Error("Home Connect client unavailable — the integration is not connected");
@@ -1,5 +1,5 @@
1
- import { A as object, C as defineCustomActions, D as array, E as _enum, F as EventCategory, M as string, N as union, O as literal, P as unknown, S as customAction, T as isSecretMarkerLike, a as binaryCapability, b as errMsg, c as deviceAdoptionCapability, d as eventEmitterCapability, j as record, l as dishwasherCapability, m as powerMeterCapability, n as BaseDeviceProvider, p as numericSensorCapability, r as DishwasherOperationStateSchema, s as connectionTestCapability, t as BaseDevice, u as enumSensorCapability, v as DeviceRole, w as isSecretMarker, x as createEvent, y as DeviceType } from "../dist-C8QaBSuL.mjs";
2
- import { n as cascadeRemoveDevicesForIntegration, r as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-W-dxoTT1.mjs";
1
+ import { C as customAction, D as _enum, E as isSecretMarkerLike, F as unknown, I as EventCategory, M as record, N as string, O as array, P as union, S as createEvent, T as isSecretMarker, a as binaryCapability, b as DeviceType, c as consumablesCapability, d as enumSensorCapability, f as eventEmitterCapability, h as powerMeterCapability, j as object, k as literal, l as deviceAdoptionCapability, m as numericSensorCapability, n as BaseDeviceProvider, r as DishwasherOperationStateSchema, s as connectionTestCapability, t as BaseDevice, u as dishwasherCapability, w as defineCustomActions, x as errMsg, y as DeviceRole } from "../dist-LGjOHvFG.mjs";
2
+ import { n as cascadeRemoveDevicesForIntegration, r as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-B9spxppg.mjs";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  import { connect } from "node:tls";
5
5
  import { inflateRawSync } from "node:zlib";
@@ -3825,8 +3825,6 @@ var COLD_DISHWASHER_STATUS = {
3825
3825
  localControlActive: null,
3826
3826
  powerOn: null,
3827
3827
  powerState: null,
3828
- saltLevel: null,
3829
- rinseAidLevel: null,
3830
3828
  filterCleaningDue: null,
3831
3829
  machineCareDue: null,
3832
3830
  machineCareRemainingRuns: null,
@@ -3884,8 +3882,6 @@ function dishwasherStatusFromFeatures(input) {
3884
3882
  localControlActive: boolOf(valueOf(input, findEntity(description, ["status"], ["LocalControlActive"]))),
3885
3883
  powerOn: powerRaw === null ? null : powerRaw === "On",
3886
3884
  powerState: powerRaw,
3887
- saltLevel: consumableFromEvents(input, ["SaltNearlyEmpty"], ["SaltEmpty", "SaltLack"]),
3888
- rinseAidLevel: consumableFromEvents(input, ["RinseAidNearlyEmpty"], ["RinseAidEmpty", "RinseAidLack"]),
3889
3885
  filterCleaningDue: reminderDue(input, [
3890
3886
  "SmartFilterCleaningReminder",
3891
3887
  "CheckFilterSystem",
@@ -3986,6 +3982,44 @@ function dishwasherOptionsFromDescription(input) {
3986
3982
  var HC_COMMAND_PAUSE = "PauseProgram";
3987
3983
  var HC_COMMAND_RESUME = "ResumeProgram";
3988
3984
  var HC_COMMAND_STOP = "AbortProgram";
3985
+ /** The dishwasher supplies, by the events that report them. */
3986
+ var DISHWASHER_SUPPLIES = [{
3987
+ key: "salt",
3988
+ label: "Salt",
3989
+ nearlyEmpty: ["SaltNearlyEmpty"],
3990
+ empty: ["SaltEmpty", "SaltLack"]
3991
+ }, {
3992
+ key: "rinseAid",
3993
+ label: "Rinse aid",
3994
+ nearlyEmpty: ["RinseAidNearlyEmpty"],
3995
+ empty: ["RinseAidEmpty", "RinseAidLack"]
3996
+ }];
3997
+ /**
3998
+ * The dishwasher's `consumables` items (D915): salt and rinse aid as `supply`
3999
+ * items, for each the appliance's description lists an event for. Their
4000
+ * status comes from those events (`consumableFromEvents`); none reported is
4001
+ * `null` (unknown), never `ok`. Neither is resettable — refilling is the reset.
4002
+ *
4003
+ * `null` while the appliance is offline or undescribed: nothing is known NOW,
4004
+ * and the `consumables` slice is restored — the last observation stays rather
4005
+ * than being overwritten with unknowns. Pure.
4006
+ */
4007
+ function dishwasherConsumablesFromFeatures(view) {
4008
+ if (availabilityOf(view) !== "available") return null;
4009
+ return DISHWASHER_SUPPLIES.flatMap(({ key, label, nearlyEmpty, empty }) => {
4010
+ if (eventStates(view, [...nearlyEmpty, ...empty]).length === 0) return [];
4011
+ return [{
4012
+ key,
4013
+ label,
4014
+ level: null,
4015
+ status: consumableFromEvents(view, nearlyEmpty, empty),
4016
+ kind: "supply",
4017
+ form: "product",
4018
+ lastResetAt: null,
4019
+ resettable: false
4020
+ }];
4021
+ });
4022
+ }
3989
4023
  //#endregion
3990
4024
  //#region src/home-connect/home-connect-child-bindings.ts
3991
4025
  /** The capability a bound child registers. */
@@ -4576,6 +4610,15 @@ var homeConnectDishwasherSchema = object({
4576
4610
  integrationId: string().optional()
4577
4611
  });
4578
4612
  var DISH_CAP = "dishwasher";
4613
+ var CONSUMABLES_CAP = "consumables";
4614
+ var CONSUMABLES_EMPTY = {
4615
+ items: [],
4616
+ lastChangedAt: 0,
4617
+ lastFetchedAt: 0
4618
+ };
4619
+ function sameItems(a, b) {
4620
+ return JSON.stringify(a) === JSON.stringify(b);
4621
+ }
4579
4622
  /** The option short names of the boolean setters, in the spellings an appliance uses. */
4580
4623
  var OPTION_NAMES = {
4581
4624
  halfLoad: ["HalfLoad"],
@@ -4602,6 +4645,7 @@ var HomeConnectDishwasherDevice = class extends BaseDevice {
4602
4645
  async onActivate() {
4603
4646
  await super.onActivate();
4604
4647
  this.registerDishwasherCap();
4648
+ this.registerConsumablesCap();
4605
4649
  this.runtimeState.setCapState(DISH_CAP, COLD_DISHWASHER_STATUS);
4606
4650
  this.markOnline(false);
4607
4651
  this.#unwatch = homeConnectConnections.watch(this.#brokerId, this.#haId, (event) => this.recomputeSlice(event));
@@ -4626,13 +4670,41 @@ var HomeConnectDishwasherDevice = class extends BaseDevice {
4626
4670
  recomputeSlice(event) {
4627
4671
  const previous = this.runtimeState.getCapState(DISH_CAP);
4628
4672
  const lastValueAt = event.kind === "feature" && !event.key.startsWith("HomeConnect.Info.") && !event.key.startsWith("HomeConnect.Network.") ? Date.now() : previous?.lastFetchedAt ?? 0;
4673
+ const view = this.view();
4629
4674
  const slice = dishwasherStatusFromFeatures({
4630
- ...this.view(),
4675
+ ...view,
4631
4676
  lastValueAt
4632
4677
  });
4633
4678
  this.runtimeState.setCapState(DISH_CAP, slice);
4679
+ this.writeConsumables(dishwasherConsumablesFromFeatures(view));
4634
4680
  this.markOnline(slice.availability !== "offline");
4635
4681
  }
4682
+ /**
4683
+ * Salt and rinse aid, as `consumables` items (D915). Written only when they
4684
+ * changed; `null` (offline / undescribed) and an empty list write nothing —
4685
+ * the slice is restored, and "nothing known now" must not erase the last
4686
+ * observation.
4687
+ */
4688
+ writeConsumables(items) {
4689
+ if (items === null || items.length === 0) return;
4690
+ const previous = this.runtimeState.getCapState(CONSUMABLES_CAP);
4691
+ if (previous !== void 0 && sameItems(previous.items, items)) return;
4692
+ const now = Date.now();
4693
+ const next = {
4694
+ items,
4695
+ lastChangedAt: now,
4696
+ lastFetchedAt: now
4697
+ };
4698
+ this.runtimeState.setCapState(CONSUMABLES_CAP, next);
4699
+ }
4700
+ registerConsumablesCap() {
4701
+ this.ctx.registerNativeCap(consumablesCapability, {
4702
+ getStatus: async () => this.runtimeState.getCapState(CONSUMABLES_CAP) ?? CONSUMABLES_EMPTY,
4703
+ reset: async ({ key }) => {
4704
+ throw new Error(`"${key}" has no reset on a dishwasher — refilling it is the reset`);
4705
+ }
4706
+ });
4707
+ }
4636
4708
  requireClient() {
4637
4709
  const client = this.client();
4638
4710
  if (!client) throw new Error("Home Connect client unavailable — the integration is not connected");
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("../dist-D6D2JO8x.js");
3
- const require_account_integration_offline = require("../account-integration-offline-pY2Ojv8k.js");
2
+ const require_dist = require("../dist-C5fLGNXK.js");
3
+ const require_account_integration_offline = require("../account-integration-offline-D5EEH5Xn.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  //#region src/homecom/custom-actions.ts
6
6
  var homeComActions = require_dist.defineCustomActions({
@@ -1,5 +1,5 @@
1
- import { A as object, C as defineCustomActions, E as _enum, F as EventCategory, M as string, O as literal, S as customAction, T as isSecretMarkerLike, _ as waterHeaterCapability, b as errMsg, c as deviceAdoptionCapability, n as BaseDeviceProvider, o as climateControlCapability, s as connectionTestCapability, t as BaseDevice, w as isSecretMarker, y as DeviceType } from "../dist-C8QaBSuL.mjs";
2
- import { n as cascadeRemoveDevicesForIntegration, r as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-W-dxoTT1.mjs";
1
+ import { C as customAction, D as _enum, E as isSecretMarkerLike, I as EventCategory, N as string, T as isSecretMarker, b as DeviceType, j as object, k as literal, l as deviceAdoptionCapability, n as BaseDeviceProvider, o as climateControlCapability, s as connectionTestCapability, t as BaseDevice, v as waterHeaterCapability, w as defineCustomActions, x as errMsg } from "../dist-LGjOHvFG.mjs";
2
+ import { n as cascadeRemoveDevicesForIntegration, r as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-B9spxppg.mjs";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  //#region src/homecom/custom-actions.ts
5
5
  var homeComActions = defineCustomActions({
package/dist/shc/addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region \0rolldown/runtime.js
3
3
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
4
  //#endregion
5
- const require_dist = require("../dist-D6D2JO8x.js");
5
+ const require_dist = require("../dist-C5fLGNXK.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  let node_https = require("node:https");
8
8
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { A as object, C as defineCustomActions, D as array, E as _enum, F as EventCategory, M as string, O as literal, S as customAction, b as errMsg, c as deviceAdoptionCapability, f as heatingValveCapability, g as temperatureSensorCapability, h as switchCapability, i as batteryCapability, k as number, n as BaseDeviceProvider, o as climateControlCapability, s as connectionTestCapability, t as BaseDevice, y as DeviceType } from "../dist-C8QaBSuL.mjs";
1
+ import { A as number, C as customAction, D as _enum, I as EventCategory, N as string, O as array, _ as temperatureSensorCapability, b as DeviceType, g as switchCapability, i as batteryCapability, j as object, k as literal, l as deviceAdoptionCapability, n as BaseDeviceProvider, o as climateControlCapability, p as heatingValveCapability, s as connectionTestCapability, t as BaseDevice, w as defineCustomActions, x as errMsg } from "../dist-LGjOHvFG.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { request } from "node:https";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-bosch",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Bosch smart-home device-provider addons for CamStack — SHC, Home Connect, and HomeCom cloud integrations (scaffold)",
5
5
  "keywords": [
6
6
  "camstack",
@@ -81,6 +81,9 @@
81
81
  },
82
82
  {
83
83
  "name": "dishwasher"
84
+ },
85
+ {
86
+ "name": "consumables"
84
87
  }
85
88
  ]
86
89
  },