@camstack/addon-provider-onvif 1.2.64 → 1.2.66

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
@@ -7552,7 +7552,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
7552
7552
  var CameraSwitchUnavailableReasonSchema = _enum([
7553
7553
  "no-provider",
7554
7554
  "source-unreachable",
7555
- "not-configured"
7555
+ "not-configured",
7556
+ "device-disabled"
7556
7557
  ]);
7557
7558
  /**
7558
7559
  * One switch, resolved for one camera.
@@ -23260,12 +23261,20 @@ var BatteryStatusSchema = object({
23260
23261
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23261
23262
  * Reolink-specific for the Solar Panel 2 accessory (will become
23262
23263
  * common on other battery cams). `'none'` means running on battery
23263
- * alone.
23264
+ * alone — a NEGATIVE the firmware actually reported.
23265
+ *
23266
+ * `'unknown'` is the absence of an answer: the provider has not read the
23267
+ * power fields yet, or the firmware reported neither. Before it existed,
23268
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
23269
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
23270
+ * by going nullable. Consumers SKIP it (no charger state published, no
23271
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
23264
23272
  */
23265
23273
  charging: _enum([
23266
23274
  "dc",
23267
23275
  "solar",
23268
- "none"
23276
+ "none",
23277
+ "unknown"
23269
23278
  ]),
23270
23279
  /**
23271
23280
  * True when the camera firmware has gone into low-power mode. Battery
@@ -29867,13 +29876,30 @@ var BaseDeviceProvider = class extends BaseAddon {
29867
29876
  async onRestoreDevices(savedDevices) {
29868
29877
  const restored = /* @__PURE__ */ new Set();
29869
29878
  const failures = [];
29879
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
29870
29880
  const attemptRestore = async (saved) => {
29871
29881
  if (restored.has(saved.id)) return;
29882
+ if (liveStableIds.has(saved.stableId)) {
29883
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
29884
+ deviceId: saved.id,
29885
+ stableId: saved.stableId
29886
+ } });
29887
+ restored.add(saved.id);
29888
+ return;
29889
+ }
29872
29890
  const Class = this.deviceClasses[saved.type];
29873
29891
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
29874
29892
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
29875
29893
  await this.healSavedConfig(saved, savedDevices);
29876
- await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
29894
+ try {
29895
+ await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
29896
+ } catch (err) {
29897
+ if (!(await this.ctx.kernel.devices.getAll()).some((device) => device.stableId === saved.stableId)) throw err;
29898
+ this.ctx.logger.debug("Restore row came to life during its own dial — kept", { tags: {
29899
+ deviceId: saved.id,
29900
+ stableId: saved.stableId
29901
+ } });
29902
+ }
29877
29903
  restored.add(saved.id);
29878
29904
  };
29879
29905
  const topLevel = savedDevices.filter((saved) => saved.parentDeviceId === null);
package/dist/addon.mjs CHANGED
@@ -7553,7 +7553,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
7553
7553
  var CameraSwitchUnavailableReasonSchema = _enum([
7554
7554
  "no-provider",
7555
7555
  "source-unreachable",
7556
- "not-configured"
7556
+ "not-configured",
7557
+ "device-disabled"
7557
7558
  ]);
7558
7559
  /**
7559
7560
  * One switch, resolved for one camera.
@@ -23261,12 +23262,20 @@ var BatteryStatusSchema = object({
23261
23262
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23262
23263
  * Reolink-specific for the Solar Panel 2 accessory (will become
23263
23264
  * common on other battery cams). `'none'` means running on battery
23264
- * alone.
23265
+ * alone — a NEGATIVE the firmware actually reported.
23266
+ *
23267
+ * `'unknown'` is the absence of an answer: the provider has not read the
23268
+ * power fields yet, or the firmware reported neither. Before it existed,
23269
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
23270
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
23271
+ * by going nullable. Consumers SKIP it (no charger state published, no
23272
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
23265
23273
  */
23266
23274
  charging: _enum([
23267
23275
  "dc",
23268
23276
  "solar",
23269
- "none"
23277
+ "none",
23278
+ "unknown"
23270
23279
  ]),
23271
23280
  /**
23272
23281
  * True when the camera firmware has gone into low-power mode. Battery
@@ -29868,13 +29877,30 @@ var BaseDeviceProvider = class extends BaseAddon {
29868
29877
  async onRestoreDevices(savedDevices) {
29869
29878
  const restored = /* @__PURE__ */ new Set();
29870
29879
  const failures = [];
29880
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
29871
29881
  const attemptRestore = async (saved) => {
29872
29882
  if (restored.has(saved.id)) return;
29883
+ if (liveStableIds.has(saved.stableId)) {
29884
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
29885
+ deviceId: saved.id,
29886
+ stableId: saved.stableId
29887
+ } });
29888
+ restored.add(saved.id);
29889
+ return;
29890
+ }
29873
29891
  const Class = this.deviceClasses[saved.type];
29874
29892
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
29875
29893
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
29876
29894
  await this.healSavedConfig(saved, savedDevices);
29877
- await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
29895
+ try {
29896
+ await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
29897
+ } catch (err) {
29898
+ if (!(await this.ctx.kernel.devices.getAll()).some((device) => device.stableId === saved.stableId)) throw err;
29899
+ this.ctx.logger.debug("Restore row came to life during its own dial — kept", { tags: {
29900
+ deviceId: saved.id,
29901
+ stableId: saved.stableId
29902
+ } });
29903
+ }
29878
29904
  restored.add(saved.id);
29879
29905
  };
29880
29906
  const topLevel = savedDevices.filter((saved) => saved.parentDeviceId === null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-onvif",
3
- "version": "1.2.64",
3
+ "version": "1.2.66",
4
4
  "description": "ONVIF camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",