@camstack/addon-provider-hikvision 1.2.72 → 1.2.74

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
@@ -7548,7 +7548,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
7548
7548
  var CameraSwitchUnavailableReasonSchema = _enum([
7549
7549
  "no-provider",
7550
7550
  "source-unreachable",
7551
- "not-configured"
7551
+ "not-configured",
7552
+ "device-disabled"
7552
7553
  ]);
7553
7554
  /**
7554
7555
  * One switch, resolved for one camera.
@@ -13331,7 +13332,12 @@ var ConfigEntrySchema = object({
13331
13332
  value: unknown(),
13332
13333
  description: string().optional()
13333
13334
  });
13334
- var LinkedDevicesModeSchema = _enum(["auto", "manual"]);
13335
+ /**
13336
+ * Only `manual` since D356: the operator picks, nothing links itself. The
13337
+ * field survives on the wire because a viewer already OTA'd parses it —
13338
+ * drop it once no shipped client reads `mode`.
13339
+ */
13340
+ var LinkedDevicesModeSchema = _enum(["manual"]);
13335
13341
  /** One resolved linked device — the compact projection consumers need. */
13336
13342
  var LinkedDeviceSchema = object({
13337
13343
  deviceId: number(),
@@ -23982,12 +23988,20 @@ var BatteryStatusSchema = object({
23982
23988
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23983
23989
  * Reolink-specific for the Solar Panel 2 accessory (will become
23984
23990
  * common on other battery cams). `'none'` means running on battery
23985
- * alone.
23991
+ * alone — a NEGATIVE the firmware actually reported.
23992
+ *
23993
+ * `'unknown'` is the absence of an answer: the provider has not read the
23994
+ * power fields yet, or the firmware reported neither. Before it existed,
23995
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
23996
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
23997
+ * by going nullable. Consumers SKIP it (no charger state published, no
23998
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
23986
23999
  */
23987
24000
  charging: _enum([
23988
24001
  "dc",
23989
24002
  "solar",
23990
- "none"
24003
+ "none",
24004
+ "unknown"
23991
24005
  ]),
23992
24006
  /**
23993
24007
  * True when the camera firmware has gone into low-power mode. Battery
@@ -24077,7 +24091,7 @@ onStatusChanged: { data: object({
24077
24091
  kind: "push",
24078
24092
  empty: {
24079
24093
  percentage: 0,
24080
- charging: "none",
24094
+ charging: "unknown",
24081
24095
  sleeping: false,
24082
24096
  lastUpdated: 0
24083
24097
  }
@@ -33831,8 +33845,17 @@ var BaseDeviceProvider = class extends BaseAddon {
33831
33845
  async onRestoreDevices(savedDevices) {
33832
33846
  const restored = /* @__PURE__ */ new Set();
33833
33847
  const failures = [];
33848
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
33834
33849
  const attemptRestore = async (saved) => {
33835
33850
  if (restored.has(saved.id)) return;
33851
+ if (liveStableIds.has(saved.stableId)) {
33852
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
33853
+ deviceId: saved.id,
33854
+ stableId: saved.stableId
33855
+ } });
33856
+ restored.add(saved.id);
33857
+ return;
33858
+ }
33836
33859
  const Class = this.deviceClasses[saved.type];
33837
33860
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
33838
33861
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
package/dist/addon.mjs CHANGED
@@ -7549,7 +7549,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
7549
7549
  var CameraSwitchUnavailableReasonSchema = _enum([
7550
7550
  "no-provider",
7551
7551
  "source-unreachable",
7552
- "not-configured"
7552
+ "not-configured",
7553
+ "device-disabled"
7553
7554
  ]);
7554
7555
  /**
7555
7556
  * One switch, resolved for one camera.
@@ -13332,7 +13333,12 @@ var ConfigEntrySchema = object({
13332
13333
  value: unknown(),
13333
13334
  description: string().optional()
13334
13335
  });
13335
- var LinkedDevicesModeSchema = _enum(["auto", "manual"]);
13336
+ /**
13337
+ * Only `manual` since D356: the operator picks, nothing links itself. The
13338
+ * field survives on the wire because a viewer already OTA'd parses it —
13339
+ * drop it once no shipped client reads `mode`.
13340
+ */
13341
+ var LinkedDevicesModeSchema = _enum(["manual"]);
13336
13342
  /** One resolved linked device — the compact projection consumers need. */
13337
13343
  var LinkedDeviceSchema = object({
13338
13344
  deviceId: number(),
@@ -23983,12 +23989,20 @@ var BatteryStatusSchema = object({
23983
23989
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
23984
23990
  * Reolink-specific for the Solar Panel 2 accessory (will become
23985
23991
  * common on other battery cams). `'none'` means running on battery
23986
- * alone.
23992
+ * alone — a NEGATIVE the firmware actually reported.
23993
+ *
23994
+ * `'unknown'` is the absence of an answer: the provider has not read the
23995
+ * power fields yet, or the firmware reported neither. Before it existed,
23996
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
23997
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
23998
+ * by going nullable. Consumers SKIP it (no charger state published, no
23999
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
23987
24000
  */
23988
24001
  charging: _enum([
23989
24002
  "dc",
23990
24003
  "solar",
23991
- "none"
24004
+ "none",
24005
+ "unknown"
23992
24006
  ]),
23993
24007
  /**
23994
24008
  * True when the camera firmware has gone into low-power mode. Battery
@@ -24078,7 +24092,7 @@ onStatusChanged: { data: object({
24078
24092
  kind: "push",
24079
24093
  empty: {
24080
24094
  percentage: 0,
24081
- charging: "none",
24095
+ charging: "unknown",
24082
24096
  sleeping: false,
24083
24097
  lastUpdated: 0
24084
24098
  }
@@ -33832,8 +33846,17 @@ var BaseDeviceProvider = class extends BaseAddon {
33832
33846
  async onRestoreDevices(savedDevices) {
33833
33847
  const restored = /* @__PURE__ */ new Set();
33834
33848
  const failures = [];
33849
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
33835
33850
  const attemptRestore = async (saved) => {
33836
33851
  if (restored.has(saved.id)) return;
33852
+ if (liveStableIds.has(saved.stableId)) {
33853
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
33854
+ deviceId: saved.id,
33855
+ stableId: saved.stableId
33856
+ } });
33857
+ restored.add(saved.id);
33858
+ return;
33859
+ }
33837
33860
  const Class = this.deviceClasses[saved.type];
33838
33861
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
33839
33862
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-hikvision",
3
- "version": "1.2.72",
3
+ "version": "1.2.74",
4
4
  "description": "Hikvision camera device provider addon for CamStack — ISAPI over HTTP(S) with digest auth (snapshot, alarm stream, RTSP discovery)",
5
5
  "keywords": [
6
6
  "camstack",