@camstack/addon-provider-wyze 0.2.64 → 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
@@ -12805,7 +12805,26 @@ var DiscoveryCandidateSchema = object({
12805
12805
  * identity ahead of adoption. Rendering metadata (unit, precision)
12806
12806
  * flows live through the cap STATUS SLICE after adoption.
12807
12807
  */
12808
- sourceInfo: SourceInfoSchema.optional()
12808
+ sourceInfo: SourceInfoSchema.optional(),
12809
+ /**
12810
+ * Set when this candidate is a device the provider ALREADY owns.
12811
+ *
12812
+ * A scan cannot generally produce the identity a device was onboarded under
12813
+ * (Reolink keys on `mac-<mac>`, learned at adopt time), so a stableId
12814
+ * comparison never matches and an owned device looks addable. Re-adopting one
12815
+ * overwrites its config with scan-derived values — that is how a Home Hub's
12816
+ * Baichuan port was overwritten with its ONVIF port, taking the hub and its
12817
+ * three child cameras offline for four hours.
12818
+ *
12819
+ * A provider that can recognise its own devices says so here. Absent means
12820
+ * "not recognised", which is not the same as "known to be new" — a provider
12821
+ * that cannot tell simply never sets it.
12822
+ */
12823
+ alreadyOnboarded: boolean().optional(),
12824
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
12825
+ onboardedDeviceId: number().optional(),
12826
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
12827
+ onboardedName: string().optional()
12809
12828
  });
12810
12829
  /**
12811
12830
  * Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
@@ -33155,6 +33174,22 @@ var BaseDeviceProvider = class extends BaseAddon {
33155
33174
  * failed — logged at ERROR with `tags.deviceId` and surfaced via
33156
33175
  * `getStatus().error`.
33157
33176
  */
33177
+ /**
33178
+ * Repair a row's PERSISTED config blob immediately before it is restored.
33179
+ * Default: no-op — most providers have nothing to heal.
33180
+ *
33181
+ * This exists because a restored device self-hydrates from the DB: `create()`
33182
+ * passes `{}` and `BaseDevice` parses the stored blob against the device
33183
+ * schema. A blob that lost a REQUIRED field therefore fails restore forever,
33184
+ * and no later pass revisits it — a hub-adopted Reolink camera whose blob had
33185
+ * been emptied failed all four bounded attempts against fields
33186
+ * (`host`, `password`) it inherits from its parent and never dials itself.
33187
+ *
33188
+ * Implementations get every saved row, so a child can read its parent's blob.
33189
+ * A heal that throws is treated like any other restore failure: retried under
33190
+ * the bound, then reported — never swallowed.
33191
+ */
33192
+ async healSavedConfig(_saved, _allSaved) {}
33158
33193
  async onRestoreDevices(savedDevices) {
33159
33194
  const restored = /* @__PURE__ */ new Set();
33160
33195
  const failures = [];
@@ -33163,6 +33198,7 @@ var BaseDeviceProvider = class extends BaseAddon {
33163
33198
  const Class = this.deviceClasses[saved.type];
33164
33199
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
33165
33200
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
33201
+ await this.healSavedConfig(saved, savedDevices);
33166
33202
  await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
33167
33203
  restored.add(saved.id);
33168
33204
  };
package/dist/addon.mjs CHANGED
@@ -12784,7 +12784,26 @@ var DiscoveryCandidateSchema = object({
12784
12784
  * identity ahead of adoption. Rendering metadata (unit, precision)
12785
12785
  * flows live through the cap STATUS SLICE after adoption.
12786
12786
  */
12787
- sourceInfo: SourceInfoSchema.optional()
12787
+ sourceInfo: SourceInfoSchema.optional(),
12788
+ /**
12789
+ * Set when this candidate is a device the provider ALREADY owns.
12790
+ *
12791
+ * A scan cannot generally produce the identity a device was onboarded under
12792
+ * (Reolink keys on `mac-<mac>`, learned at adopt time), so a stableId
12793
+ * comparison never matches and an owned device looks addable. Re-adopting one
12794
+ * overwrites its config with scan-derived values — that is how a Home Hub's
12795
+ * Baichuan port was overwritten with its ONVIF port, taking the hub and its
12796
+ * three child cameras offline for four hours.
12797
+ *
12798
+ * A provider that can recognise its own devices says so here. Absent means
12799
+ * "not recognised", which is not the same as "known to be new" — a provider
12800
+ * that cannot tell simply never sets it.
12801
+ */
12802
+ alreadyOnboarded: boolean().optional(),
12803
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
12804
+ onboardedDeviceId: number().optional(),
12805
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
12806
+ onboardedName: string().optional()
12788
12807
  });
12789
12808
  /**
12790
12809
  * Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
@@ -33134,6 +33153,22 @@ var BaseDeviceProvider = class extends BaseAddon {
33134
33153
  * failed — logged at ERROR with `tags.deviceId` and surfaced via
33135
33154
  * `getStatus().error`.
33136
33155
  */
33156
+ /**
33157
+ * Repair a row's PERSISTED config blob immediately before it is restored.
33158
+ * Default: no-op — most providers have nothing to heal.
33159
+ *
33160
+ * This exists because a restored device self-hydrates from the DB: `create()`
33161
+ * passes `{}` and `BaseDevice` parses the stored blob against the device
33162
+ * schema. A blob that lost a REQUIRED field therefore fails restore forever,
33163
+ * and no later pass revisits it — a hub-adopted Reolink camera whose blob had
33164
+ * been emptied failed all four bounded attempts against fields
33165
+ * (`host`, `password`) it inherits from its parent and never dials itself.
33166
+ *
33167
+ * Implementations get every saved row, so a child can read its parent's blob.
33168
+ * A heal that throws is treated like any other restore failure: retried under
33169
+ * the bound, then reported — never swallowed.
33170
+ */
33171
+ async healSavedConfig(_saved, _allSaved) {}
33137
33172
  async onRestoreDevices(savedDevices) {
33138
33173
  const restored = /* @__PURE__ */ new Set();
33139
33174
  const failures = [];
@@ -33142,6 +33177,7 @@ var BaseDeviceProvider = class extends BaseAddon {
33142
33177
  const Class = this.deviceClasses[saved.type];
33143
33178
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
33144
33179
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
33180
+ await this.healSavedConfig(saved, savedDevices);
33145
33181
  await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
33146
33182
  restored.add(saved.id);
33147
33183
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-wyze",
3
- "version": "0.2.64",
3
+ "version": "0.2.65",
4
4
  "description": "Wyze camera device-provider addon for CamStack — wraps the @apocaliss92/wyze-bridge-js P2P/DTLS client, feeding the stream-broker via the pull-rfc4571 lazy-publish path (a structural twin of addon-provider-reolink)",
5
5
  "keywords": [
6
6
  "camstack",