@camstack/addon-provider-homeassistant 1.2.89 → 1.2.91

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("./dist-D3UkTYeb.js");
2
+ const require_dist = require("./dist-DfCgRCeO.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-device-source.ts
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-COeXrW_s.mjs";
1
+ import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-DKXax7Rq.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-device-source.ts
@@ -33945,6 +33945,53 @@ var BaseDeviceProvider = class extends BaseAddon {
33945
33945
  const ids = [...this._permanentRestoreFailures.keys()].join(", ");
33946
33946
  return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) — restart the ${this.providerName} provider to retry`;
33947
33947
  }
33948
+ /**
33949
+ * A top-level persisted row with NO configuration is a leftover, not a
33950
+ * device — quarantine it instead of dialling it.
33951
+ *
33952
+ * Device 614 was deleted, resurrected as a config-less shell by a write
33953
+ * already in flight (D376), and then dialled at every single boot: eight
33954
+ * `Failed to restore device — bounded retry scheduled` lines in one day,
33955
+ * each one the same Zod refusal on `host` and `password`. The bound was
33956
+ * real, but it is a bound PER PROCESS, and the runner restarts — so nothing
33957
+ * about the row ever stopped costing attempts and log lines.
33958
+ *
33959
+ * No retry can add a configuration that is not there. The row is reported
33960
+ * once, with its `deviceId`, and set aside.
33961
+ *
33962
+ * Top-level only: an accessory child legitimately carries an empty blob (it
33963
+ * lives off its parent), and a hub-adopted child with an emptied blob is
33964
+ * repaired by `healSavedConfig` from its parent instead. Providers that
33965
+ * genuinely create configuration-free top-level devices turn this off.
33966
+ */
33967
+ quarantineConfiglessTopLevelRestores = true;
33968
+ isUnrestorableShell(saved) {
33969
+ if (!this.quarantineConfiglessTopLevelRestores) return false;
33970
+ if (saved.parentDeviceId !== null) return false;
33971
+ const config = saved.config;
33972
+ if (config === void 0) return false;
33973
+ return Object.keys(config).length === 0;
33974
+ }
33975
+ quarantineShell(saved) {
33976
+ this._permanentRestoreFailures.set(saved.id, {
33977
+ deviceId: saved.id,
33978
+ stableId: saved.stableId,
33979
+ type: saved.type,
33980
+ attempts: 0,
33981
+ lastError: "persisted row has no configuration",
33982
+ failedAt: Date.now()
33983
+ });
33984
+ this.ctx.logger.error("Persisted device row has NO configuration — quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
33985
+ tags: {
33986
+ deviceId: saved.id,
33987
+ stableId: saved.stableId
33988
+ },
33989
+ meta: {
33990
+ type: saved.type,
33991
+ provider: this.providerName
33992
+ }
33993
+ });
33994
+ }
33948
33995
  cancelRestoreRetries() {
33949
33996
  this._restoreRetryScheduler?.cancel();
33950
33997
  this._restoreRetryScheduler = null;
@@ -34129,6 +34176,10 @@ var BaseDeviceProvider = class extends BaseAddon {
34129
34176
  });
34130
34177
  return;
34131
34178
  }
34179
+ if (this.isUnrestorableShell(saved)) {
34180
+ this.quarantineShell(saved);
34181
+ return;
34182
+ }
34132
34183
  try {
34133
34184
  await attemptRestore(saved);
34134
34185
  } catch (err) {
@@ -33945,6 +33945,53 @@ var BaseDeviceProvider = class extends BaseAddon {
33945
33945
  const ids = [...this._permanentRestoreFailures.keys()].join(", ");
33946
33946
  return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) — restart the ${this.providerName} provider to retry`;
33947
33947
  }
33948
+ /**
33949
+ * A top-level persisted row with NO configuration is a leftover, not a
33950
+ * device — quarantine it instead of dialling it.
33951
+ *
33952
+ * Device 614 was deleted, resurrected as a config-less shell by a write
33953
+ * already in flight (D376), and then dialled at every single boot: eight
33954
+ * `Failed to restore device — bounded retry scheduled` lines in one day,
33955
+ * each one the same Zod refusal on `host` and `password`. The bound was
33956
+ * real, but it is a bound PER PROCESS, and the runner restarts — so nothing
33957
+ * about the row ever stopped costing attempts and log lines.
33958
+ *
33959
+ * No retry can add a configuration that is not there. The row is reported
33960
+ * once, with its `deviceId`, and set aside.
33961
+ *
33962
+ * Top-level only: an accessory child legitimately carries an empty blob (it
33963
+ * lives off its parent), and a hub-adopted child with an emptied blob is
33964
+ * repaired by `healSavedConfig` from its parent instead. Providers that
33965
+ * genuinely create configuration-free top-level devices turn this off.
33966
+ */
33967
+ quarantineConfiglessTopLevelRestores = true;
33968
+ isUnrestorableShell(saved) {
33969
+ if (!this.quarantineConfiglessTopLevelRestores) return false;
33970
+ if (saved.parentDeviceId !== null) return false;
33971
+ const config = saved.config;
33972
+ if (config === void 0) return false;
33973
+ return Object.keys(config).length === 0;
33974
+ }
33975
+ quarantineShell(saved) {
33976
+ this._permanentRestoreFailures.set(saved.id, {
33977
+ deviceId: saved.id,
33978
+ stableId: saved.stableId,
33979
+ type: saved.type,
33980
+ attempts: 0,
33981
+ lastError: "persisted row has no configuration",
33982
+ failedAt: Date.now()
33983
+ });
33984
+ this.ctx.logger.error("Persisted device row has NO configuration — quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
33985
+ tags: {
33986
+ deviceId: saved.id,
33987
+ stableId: saved.stableId
33988
+ },
33989
+ meta: {
33990
+ type: saved.type,
33991
+ provider: this.providerName
33992
+ }
33993
+ });
33994
+ }
33948
33995
  cancelRestoreRetries() {
33949
33996
  this._restoreRetryScheduler?.cancel();
33950
33997
  this._restoreRetryScheduler = null;
@@ -34129,6 +34176,10 @@ var BaseDeviceProvider = class extends BaseAddon {
34129
34176
  });
34130
34177
  return;
34131
34178
  }
34179
+ if (this.isUnrestorableShell(saved)) {
34180
+ this.quarantineShell(saved);
34181
+ return;
34182
+ }
34132
34183
  try {
34133
34184
  await attemptRestore(saved);
34134
34185
  } catch (err) {
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  //#endregion
6
- const require_dist = require("../dist-D3UkTYeb.js");
6
+ const require_dist = require("../dist-DfCgRCeO.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  //#region src/ha-export/topics.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-COeXrW_s.mjs";
1
+ import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-DKXax7Rq.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  //#region src/ha-export/topics.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.89",
3
+ "version": "1.2.91",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",