@camstack/addon-provider-rademacher 0.2.63 → 0.2.65

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
@@ -8538,7 +8538,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
8538
8538
  var CameraSwitchUnavailableReasonSchema = _enum([
8539
8539
  "no-provider",
8540
8540
  "source-unreachable",
8541
- "not-configured"
8541
+ "not-configured",
8542
+ "device-disabled"
8542
8543
  ]);
8543
8544
  /**
8544
8545
  * One switch, resolved for one camera.
@@ -14028,7 +14029,12 @@ var ConfigEntrySchema = object({
14028
14029
  value: unknown(),
14029
14030
  description: string().optional()
14030
14031
  });
14031
- var LinkedDevicesModeSchema = _enum(["auto", "manual"]);
14032
+ /**
14033
+ * Only `manual` since D356: the operator picks, nothing links itself. The
14034
+ * field survives on the wire because a viewer already OTA'd parses it —
14035
+ * drop it once no shipped client reads `mode`.
14036
+ */
14037
+ var LinkedDevicesModeSchema = _enum(["manual"]);
14032
14038
  /** One resolved linked device — the compact projection consumers need. */
14033
14039
  var LinkedDeviceSchema = object({
14034
14040
  deviceId: number(),
@@ -24556,12 +24562,20 @@ var BatteryStatusSchema = object({
24556
24562
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24557
24563
  * Reolink-specific for the Solar Panel 2 accessory (will become
24558
24564
  * common on other battery cams). `'none'` means running on battery
24559
- * alone.
24565
+ * alone — a NEGATIVE the firmware actually reported.
24566
+ *
24567
+ * `'unknown'` is the absence of an answer: the provider has not read the
24568
+ * power fields yet, or the firmware reported neither. Before it existed,
24569
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
24570
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
24571
+ * by going nullable. Consumers SKIP it (no charger state published, no
24572
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
24560
24573
  */
24561
24574
  charging: _enum([
24562
24575
  "dc",
24563
24576
  "solar",
24564
- "none"
24577
+ "none",
24578
+ "unknown"
24565
24579
  ]),
24566
24580
  /**
24567
24581
  * True when the camera firmware has gone into low-power mode. Battery
@@ -24651,7 +24665,7 @@ onStatusChanged: { data: object({
24651
24665
  kind: "push",
24652
24666
  empty: {
24653
24667
  percentage: 0,
24654
- charging: "none",
24668
+ charging: "unknown",
24655
24669
  sleeping: false,
24656
24670
  lastUpdated: 0
24657
24671
  }
@@ -34059,8 +34073,17 @@ var BaseDeviceProvider = class extends BaseAddon {
34059
34073
  async onRestoreDevices(savedDevices) {
34060
34074
  const restored = /* @__PURE__ */ new Set();
34061
34075
  const failures = [];
34076
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
34062
34077
  const attemptRestore = async (saved) => {
34063
34078
  if (restored.has(saved.id)) return;
34079
+ if (liveStableIds.has(saved.stableId)) {
34080
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
34081
+ deviceId: saved.id,
34082
+ stableId: saved.stableId
34083
+ } });
34084
+ restored.add(saved.id);
34085
+ return;
34086
+ }
34064
34087
  const Class = this.deviceClasses[saved.type];
34065
34088
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
34066
34089
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
package/dist/addon.mjs CHANGED
@@ -8537,7 +8537,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
8537
8537
  var CameraSwitchUnavailableReasonSchema = _enum([
8538
8538
  "no-provider",
8539
8539
  "source-unreachable",
8540
- "not-configured"
8540
+ "not-configured",
8541
+ "device-disabled"
8541
8542
  ]);
8542
8543
  /**
8543
8544
  * One switch, resolved for one camera.
@@ -14027,7 +14028,12 @@ var ConfigEntrySchema = object({
14027
14028
  value: unknown(),
14028
14029
  description: string().optional()
14029
14030
  });
14030
- var LinkedDevicesModeSchema = _enum(["auto", "manual"]);
14031
+ /**
14032
+ * Only `manual` since D356: the operator picks, nothing links itself. The
14033
+ * field survives on the wire because a viewer already OTA'd parses it —
14034
+ * drop it once no shipped client reads `mode`.
14035
+ */
14036
+ var LinkedDevicesModeSchema = _enum(["manual"]);
14031
14037
  /** One resolved linked device — the compact projection consumers need. */
14032
14038
  var LinkedDeviceSchema = object({
14033
14039
  deviceId: number(),
@@ -24555,12 +24561,20 @@ var BatteryStatusSchema = object({
24555
24561
  * Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
24556
24562
  * Reolink-specific for the Solar Panel 2 accessory (will become
24557
24563
  * common on other battery cams). `'none'` means running on battery
24558
- * alone.
24564
+ * alone — a NEGATIVE the firmware actually reported.
24565
+ *
24566
+ * `'unknown'` is the absence of an answer: the provider has not read the
24567
+ * power fields yet, or the firmware reported neither. Before it existed,
24568
+ * two unreadable fields produced `'none'`, and a camera nobody had reached
24569
+ * was drawn "on battery alone" — the same D315 defect `percentage` closed
24570
+ * by going nullable. Consumers SKIP it (no charger state published, no
24571
+ * glyph, no HomeKit ChargingState) rather than coerce it either way.
24559
24572
  */
24560
24573
  charging: _enum([
24561
24574
  "dc",
24562
24575
  "solar",
24563
- "none"
24576
+ "none",
24577
+ "unknown"
24564
24578
  ]),
24565
24579
  /**
24566
24580
  * True when the camera firmware has gone into low-power mode. Battery
@@ -24650,7 +24664,7 @@ onStatusChanged: { data: object({
24650
24664
  kind: "push",
24651
24665
  empty: {
24652
24666
  percentage: 0,
24653
- charging: "none",
24667
+ charging: "unknown",
24654
24668
  sleeping: false,
24655
24669
  lastUpdated: 0
24656
24670
  }
@@ -34058,8 +34072,17 @@ var BaseDeviceProvider = class extends BaseAddon {
34058
34072
  async onRestoreDevices(savedDevices) {
34059
34073
  const restored = /* @__PURE__ */ new Set();
34060
34074
  const failures = [];
34075
+ const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
34061
34076
  const attemptRestore = async (saved) => {
34062
34077
  if (restored.has(saved.id)) return;
34078
+ if (liveStableIds.has(saved.stableId)) {
34079
+ this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
34080
+ deviceId: saved.id,
34081
+ stableId: saved.stableId
34082
+ } });
34083
+ restored.add(saved.id);
34084
+ return;
34085
+ }
34063
34086
  const Class = this.deviceClasses[saved.type];
34064
34087
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
34065
34088
  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-rademacher",
3
- "version": "0.2.63",
3
+ "version": "0.2.65",
4
4
  "description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
5
5
  "keywords": [
6
6
  "camstack",