@camstack/addon-provider-wyze 0.2.127 → 0.2.128

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.
Files changed (3) hide show
  1. package/dist/addon.js +121 -58
  2. package/dist/addon.mjs +121 -58
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -10517,6 +10517,57 @@ var ClipSearchStrictnessSchema = _enum([
10517
10517
  "balanced",
10518
10518
  "strict"
10519
10519
  ]);
10520
+ new Set([
10521
+ {
10522
+ id: "person",
10523
+ name: "Person"
10524
+ },
10525
+ {
10526
+ id: "vehicle",
10527
+ name: "Vehicle"
10528
+ },
10529
+ {
10530
+ id: "animal",
10531
+ name: "Animal"
10532
+ },
10533
+ {
10534
+ id: "package",
10535
+ name: "Package"
10536
+ }
10537
+ ].map((l) => l.id));
10538
+ var COCO_TO_MACRO = {
10539
+ mapping: {
10540
+ person: "person",
10541
+ bicycle: "vehicle",
10542
+ car: "vehicle",
10543
+ motorcycle: "vehicle",
10544
+ airplane: "vehicle",
10545
+ bus: "vehicle",
10546
+ train: "vehicle",
10547
+ truck: "vehicle",
10548
+ boat: "vehicle",
10549
+ bird: "animal",
10550
+ cat: "animal",
10551
+ dog: "animal",
10552
+ horse: "animal",
10553
+ sheep: "animal",
10554
+ cow: "animal",
10555
+ elephant: "animal",
10556
+ bear: "animal",
10557
+ zebra: "animal",
10558
+ giraffe: "animal",
10559
+ suitcase: "package",
10560
+ backpack: "package",
10561
+ handbag: "package"
10562
+ },
10563
+ preserveOriginal: false
10564
+ };
10565
+ /** Steps a root detector may declare it fills. */
10566
+ var FILLABLE_STEP_IDS = [
10567
+ "animal-classifier",
10568
+ "vehicle-classifier",
10569
+ "package-detection"
10570
+ ];
10520
10571
  var MODEL_FORMATS = [
10521
10572
  "onnx",
10522
10573
  "coreml",
@@ -10649,6 +10700,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
10649
10700
  /** True when the weights or their data forbid commercial use. */
10650
10701
  nonCommercial: boolean().optional()
10651
10702
  }));
10703
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
10704
+ var FillsClassifierEffectSchema = object({
10705
+ stepId: _enum(FILLABLE_STEP_IDS),
10706
+ labelToEffect: record(string(), string()),
10707
+ uncovered: array(string()).readonly()
10708
+ });
10652
10709
  var ModelCatalogEntrySchema = object({
10653
10710
  id: string(),
10654
10711
  name: string(),
@@ -10775,6 +10832,16 @@ var ModelCatalogEntrySchema = object({
10775
10832
  */
10776
10833
  classMap: DetectionCatalogClassMapSchema.optional(),
10777
10834
  /**
10835
+ * The pipeline steps this ROOT detector already does the work of (D715):
10836
+ * its labels name the effect the step exists to produce (`deer` for
10837
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
10838
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
10839
+ * declares none. Whether a declaration is honoured is the step's own
10840
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
10841
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
10842
+ */
10843
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
10844
+ /**
10778
10845
  * The model's CLIP feature-space contract (text encoder, dimension, vector
10779
10846
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
10780
10847
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -18002,51 +18069,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
18002
18069
  kind: "mutation",
18003
18070
  auth: "admin"
18004
18071
  });
18005
- new Set([
18006
- {
18007
- id: "person",
18008
- name: "Person"
18009
- },
18010
- {
18011
- id: "vehicle",
18012
- name: "Vehicle"
18013
- },
18014
- {
18015
- id: "animal",
18016
- name: "Animal"
18017
- },
18018
- {
18019
- id: "package",
18020
- name: "Package"
18021
- }
18022
- ].map((l) => l.id));
18023
- var COCO_TO_MACRO = {
18024
- mapping: {
18025
- person: "person",
18026
- bicycle: "vehicle",
18027
- car: "vehicle",
18028
- motorcycle: "vehicle",
18029
- airplane: "vehicle",
18030
- bus: "vehicle",
18031
- train: "vehicle",
18032
- truck: "vehicle",
18033
- boat: "vehicle",
18034
- bird: "animal",
18035
- cat: "animal",
18036
- dog: "animal",
18037
- horse: "animal",
18038
- sheep: "animal",
18039
- cow: "animal",
18040
- elephant: "animal",
18041
- bear: "animal",
18042
- zebra: "animal",
18043
- giraffe: "animal",
18044
- suitcase: "package",
18045
- backpack: "package",
18046
- handbag: "package"
18047
- },
18048
- preserveOriginal: false
18049
- };
18050
18072
  var AUDIO_MACRO_LABELS = [
18051
18073
  {
18052
18074
  id: "speech",
@@ -18842,6 +18864,8 @@ var NcSystemEventKindSchema = _enum([
18842
18864
  "stream-offline",
18843
18865
  "node-online",
18844
18866
  "node-offline",
18867
+ "node-restarting",
18868
+ "node-updating",
18845
18869
  "node-inference-unavailable",
18846
18870
  "detection-blind",
18847
18871
  "addon-crash-loop",
@@ -23488,7 +23512,8 @@ var PipelineModelOptionSchema = object({
23488
23512
  group: ModelVariantGroupSchema.optional(),
23489
23513
  legacy: boolean().optional(),
23490
23514
  provider: ModelProviderIdSchema.optional(),
23491
- defaultConfidence: number().optional()
23515
+ defaultConfidence: number().optional(),
23516
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23492
23517
  });
23493
23518
  var ConfigFieldBridge = custom();
23494
23519
  var PipelineAddonSchemaSchema = object({
@@ -32757,7 +32782,8 @@ var MotionStatusSchema = object({
32757
32782
  * writes this slice (not even a boot seed), and neither does the runner's
32758
32783
  * phase machine: its phase is "a session is attached" for every on-motion
32759
32784
  * session, not motion, and it now has its own `DetectionPhaseTransition`.
32760
- * A provider's `isDetected` answers from the hub's slice.
32785
+ * A provider's `isDetected` and `getStatus` answer from the hub's slice
32786
+ * (`hubMotionNativeProvider`).
32761
32787
  * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
32762
32788
  * imports) — the provider pushes both edges itself, from the upstream
32763
32789
  * system's own state change. That is the sensor's own fact.
@@ -52227,6 +52253,8 @@ new Map(Object.entries({
52227
52253
  "detection-blind": "device-events",
52228
52254
  "node-online": "system",
52229
52255
  "node-offline": "system",
52256
+ "node-restarting": "system",
52257
+ "node-updating": "system",
52230
52258
  "node-inference-unavailable": "system",
52231
52259
  "addon-crash-loop": "system",
52232
52260
  "addon-update-available": "system",
@@ -52304,6 +52332,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52304
52332
  kinds: [
52305
52333
  "node-offline",
52306
52334
  "node-online",
52335
+ "node-restarting",
52307
52336
  "node-inference-unavailable"
52308
52337
  ]
52309
52338
  },
@@ -52325,6 +52354,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52325
52354
  label: "Server & container updates",
52326
52355
  kinds: [
52327
52356
  "server-update-available",
52357
+ "node-updating",
52328
52358
  "server-updated",
52329
52359
  "wrapper-update-available"
52330
52360
  ]
@@ -52472,6 +52502,7 @@ var STATE_SUMMARY_SECTION_VARS = [
52472
52502
  kinds: [
52473
52503
  "node-offline",
52474
52504
  "node-online",
52505
+ "node-restarting",
52475
52506
  "node-inference-unavailable"
52476
52507
  ]
52477
52508
  },
@@ -52493,6 +52524,7 @@ var STATE_SUMMARY_SECTION_VARS = [
52493
52524
  example: "server 1.2.377 → 1.2.378",
52494
52525
  kinds: [
52495
52526
  "server-update-available",
52527
+ "node-updating",
52496
52528
  "server-updated",
52497
52529
  "wrapper-update-available"
52498
52530
  ]
@@ -52948,10 +52980,9 @@ TimelapseRuleInputSchema.extend({
52948
52980
  createdAt: number(),
52949
52981
  updatedAt: number()
52950
52982
  });
52951
- async function readHubMotionDetected(deviceState, deviceId) {
52952
- let slice;
52983
+ async function readSlice(deviceState, deviceId) {
52953
52984
  try {
52954
- slice = await deviceState.getCapSlice.query({
52985
+ return await deviceState.getCapSlice.query({
52955
52986
  deviceId,
52956
52987
  capName: "motion"
52957
52988
  });
@@ -52959,10 +52990,44 @@ async function readHubMotionDetected(deviceState, deviceId) {
52959
52990
  const reason = err instanceof Error ? err.message : String(err);
52960
52991
  throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
52961
52992
  }
52962
- const detected = slice?.["detected"];
52993
+ }
52994
+ /**
52995
+ * The hub's `motion` slice as a `MotionStatus`, or `null` when nobody has
52996
+ * published it since the hub started. Throws when the hub does not answer or
52997
+ * the slice is malformed — never a made-up "no motion".
52998
+ */
52999
+ async function readHubMotionStatus(deviceState, deviceId) {
53000
+ const slice = await readSlice(deviceState, deviceId);
53001
+ if (slice === null) return null;
53002
+ const parsed = MotionStatusSchema.safeParse(slice);
53003
+ if (!parsed.success) throw new Error(`motion state of device ${deviceId} is malformed on the hub: ${parsed.error.message}`);
53004
+ return parsed.data;
53005
+ }
53006
+ async function readHubMotionDetected(deviceState, deviceId) {
53007
+ const detected = (await readSlice(deviceState, deviceId))?.["detected"];
52963
53008
  if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
52964
53009
  return detected;
52965
53010
  }
53011
+ /**
53012
+ * The native `motion` provider of a camera whose slice the orchestrator writes
53013
+ * (D696): `isDetected` AND `getStatus`, both from the hub. `owner` names the
53014
+ * provider class in the deviceId-mismatch error.
53015
+ */
53016
+ function hubMotionNativeProvider(deviceState, deviceId, owner) {
53017
+ const ownDevice = (asked) => {
53018
+ if (asked !== deviceId) throw new Error(`${owner}: motion deviceId mismatch, expected ${deviceId}, got ${asked}`);
53019
+ };
53020
+ return {
53021
+ isDetected: async ({ deviceId: asked }) => {
53022
+ ownDevice(asked);
53023
+ return readHubMotionDetected(deviceState, deviceId);
53024
+ },
53025
+ getStatus: async ({ deviceId: asked }) => {
53026
+ ownDevice(asked);
53027
+ return readHubMotionStatus(deviceState, deviceId);
53028
+ }
53029
+ };
53030
+ }
52966
53031
  MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
52967
53032
  function providerMotionEvent(source, data) {
52968
53033
  return createEvent(EventCategory.ProviderMotion, source, data);
@@ -57438,15 +57503,13 @@ var WyzeCamera = class extends BaseDevice {
57438
57503
  /**
57439
57504
  * The native `motion` cap. This provider writes NO `motion` slice (D696): the
57440
57505
  * orchestrator is its only writer, with the EFFECTIVE motion, on the hub.
57441
- * `isDetected` answers from the HUB's slice; an unreadable hub, or a slice
57442
- * nobody has published yet, fails the call — never `false` for unknown
57443
- * (D49, D393).
57506
+ * `isDetected` and `getStatus` answer from the HUB's slice
57507
+ * (`hubMotionNativeProvider`); an unreadable hub fails both — never `false`
57508
+ * for unknown (D49, D393).
57444
57509
  */
57445
57510
  registerMotionProvider() {
57446
- this.ctx.registerNativeCap(motionCapability, { isDetected: async ({ deviceId }) => {
57447
- if (deviceId !== this.id) throw new Error(`WyzeCamera: deviceId mismatch, expected ${this.id}, got ${deviceId}`);
57448
- return readHubMotionDetected(this.ctx.api.deviceState, this.id);
57449
- } });
57511
+ const provider = hubMotionNativeProvider(this.ctx.api.deviceState, this.id, "WyzeCamera");
57512
+ this.ctx.registerNativeCap(motionCapability, provider);
57450
57513
  }
57451
57514
  /**
57452
57515
  * Start the configured motion source. `cloud` polls the Wyze events API
package/dist/addon.mjs CHANGED
@@ -10496,6 +10496,57 @@ var ClipSearchStrictnessSchema = _enum([
10496
10496
  "balanced",
10497
10497
  "strict"
10498
10498
  ]);
10499
+ new Set([
10500
+ {
10501
+ id: "person",
10502
+ name: "Person"
10503
+ },
10504
+ {
10505
+ id: "vehicle",
10506
+ name: "Vehicle"
10507
+ },
10508
+ {
10509
+ id: "animal",
10510
+ name: "Animal"
10511
+ },
10512
+ {
10513
+ id: "package",
10514
+ name: "Package"
10515
+ }
10516
+ ].map((l) => l.id));
10517
+ var COCO_TO_MACRO = {
10518
+ mapping: {
10519
+ person: "person",
10520
+ bicycle: "vehicle",
10521
+ car: "vehicle",
10522
+ motorcycle: "vehicle",
10523
+ airplane: "vehicle",
10524
+ bus: "vehicle",
10525
+ train: "vehicle",
10526
+ truck: "vehicle",
10527
+ boat: "vehicle",
10528
+ bird: "animal",
10529
+ cat: "animal",
10530
+ dog: "animal",
10531
+ horse: "animal",
10532
+ sheep: "animal",
10533
+ cow: "animal",
10534
+ elephant: "animal",
10535
+ bear: "animal",
10536
+ zebra: "animal",
10537
+ giraffe: "animal",
10538
+ suitcase: "package",
10539
+ backpack: "package",
10540
+ handbag: "package"
10541
+ },
10542
+ preserveOriginal: false
10543
+ };
10544
+ /** Steps a root detector may declare it fills. */
10545
+ var FILLABLE_STEP_IDS = [
10546
+ "animal-classifier",
10547
+ "vehicle-classifier",
10548
+ "package-detection"
10549
+ ];
10499
10550
  var MODEL_FORMATS = [
10500
10551
  "onnx",
10501
10552
  "coreml",
@@ -10628,6 +10679,12 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
10628
10679
  /** True when the weights or their data forbid commercial use. */
10629
10680
  nonCommercial: boolean().optional()
10630
10681
  }));
10682
+ /** One `fillsClassifierEffects` entry — see `ModelCatalogEntry.fillsClassifierEffects`. */
10683
+ var FillsClassifierEffectSchema = object({
10684
+ stepId: _enum(FILLABLE_STEP_IDS),
10685
+ labelToEffect: record(string(), string()),
10686
+ uncovered: array(string()).readonly()
10687
+ });
10631
10688
  var ModelCatalogEntrySchema = object({
10632
10689
  id: string(),
10633
10690
  name: string(),
@@ -10754,6 +10811,16 @@ var ModelCatalogEntrySchema = object({
10754
10811
  */
10755
10812
  classMap: DetectionCatalogClassMapSchema.optional(),
10756
10813
  /**
10814
+ * The pipeline steps this ROOT detector already does the work of (D715):
10815
+ * its labels name the effect the step exists to produce (`deer` for
10816
+ * `animal-classifier`, `package` for `package-detection`). Derived from the
10817
+ * labelmap by `deriveClassifierFills`, never hand-written; a COCO model
10818
+ * declares none. Whether a declaration is honoured is the step's own
10819
+ * `labelLink` policy (`resolveLabelLink`). `labelToEffect` values are in
10820
+ * `FILLABLE_STEP_VOCABULARIES` (guard `check-label-link-vocabulary`).
10821
+ */
10822
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional(),
10823
+ /**
10757
10824
  * The model's CLIP feature-space contract (text encoder, dimension, vector
10758
10825
  * index, token window, search floor) — see `clip-model.ts`. Present ONLY on a
10759
10826
  * CLIP image encoder; its absence is what "not a CLIP model" means to the
@@ -17981,51 +18048,6 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
17981
18048
  kind: "mutation",
17982
18049
  auth: "admin"
17983
18050
  });
17984
- new Set([
17985
- {
17986
- id: "person",
17987
- name: "Person"
17988
- },
17989
- {
17990
- id: "vehicle",
17991
- name: "Vehicle"
17992
- },
17993
- {
17994
- id: "animal",
17995
- name: "Animal"
17996
- },
17997
- {
17998
- id: "package",
17999
- name: "Package"
18000
- }
18001
- ].map((l) => l.id));
18002
- var COCO_TO_MACRO = {
18003
- mapping: {
18004
- person: "person",
18005
- bicycle: "vehicle",
18006
- car: "vehicle",
18007
- motorcycle: "vehicle",
18008
- airplane: "vehicle",
18009
- bus: "vehicle",
18010
- train: "vehicle",
18011
- truck: "vehicle",
18012
- boat: "vehicle",
18013
- bird: "animal",
18014
- cat: "animal",
18015
- dog: "animal",
18016
- horse: "animal",
18017
- sheep: "animal",
18018
- cow: "animal",
18019
- elephant: "animal",
18020
- bear: "animal",
18021
- zebra: "animal",
18022
- giraffe: "animal",
18023
- suitcase: "package",
18024
- backpack: "package",
18025
- handbag: "package"
18026
- },
18027
- preserveOriginal: false
18028
- };
18029
18051
  var AUDIO_MACRO_LABELS = [
18030
18052
  {
18031
18053
  id: "speech",
@@ -18821,6 +18843,8 @@ var NcSystemEventKindSchema = _enum([
18821
18843
  "stream-offline",
18822
18844
  "node-online",
18823
18845
  "node-offline",
18846
+ "node-restarting",
18847
+ "node-updating",
18824
18848
  "node-inference-unavailable",
18825
18849
  "detection-blind",
18826
18850
  "addon-crash-loop",
@@ -23467,7 +23491,8 @@ var PipelineModelOptionSchema = object({
23467
23491
  group: ModelVariantGroupSchema.optional(),
23468
23492
  legacy: boolean().optional(),
23469
23493
  provider: ModelProviderIdSchema.optional(),
23470
- defaultConfidence: number().optional()
23494
+ defaultConfidence: number().optional(),
23495
+ fillsClassifierEffects: array(FillsClassifierEffectSchema).readonly().optional()
23471
23496
  });
23472
23497
  var ConfigFieldBridge = custom();
23473
23498
  var PipelineAddonSchemaSchema = object({
@@ -32736,7 +32761,8 @@ var MotionStatusSchema = object({
32736
32761
  * writes this slice (not even a boot seed), and neither does the runner's
32737
32762
  * phase machine: its phase is "a session is attached" for every on-motion
32738
32763
  * session, not motion, and it now has its own `DetectionPhaseTransition`.
32739
- * A provider's `isDetected` answers from the hub's slice.
32764
+ * A provider's `isDetected` and `getStatus` answer from the hub's slice
32765
+ * (`hubMotionNativeProvider`).
32740
32766
  * - **Sensors** (Home Assistant binary sensors, Homematic, Matter, Alexa
32741
32767
  * imports) — the provider pushes both edges itself, from the upstream
32742
32768
  * system's own state change. That is the sensor's own fact.
@@ -52206,6 +52232,8 @@ new Map(Object.entries({
52206
52232
  "detection-blind": "device-events",
52207
52233
  "node-online": "system",
52208
52234
  "node-offline": "system",
52235
+ "node-restarting": "system",
52236
+ "node-updating": "system",
52209
52237
  "node-inference-unavailable": "system",
52210
52238
  "addon-crash-loop": "system",
52211
52239
  "addon-update-available": "system",
@@ -52283,6 +52311,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52283
52311
  kinds: [
52284
52312
  "node-offline",
52285
52313
  "node-online",
52314
+ "node-restarting",
52286
52315
  "node-inference-unavailable"
52287
52316
  ]
52288
52317
  },
@@ -52304,6 +52333,7 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
52304
52333
  label: "Server & container updates",
52305
52334
  kinds: [
52306
52335
  "server-update-available",
52336
+ "node-updating",
52307
52337
  "server-updated",
52308
52338
  "wrapper-update-available"
52309
52339
  ]
@@ -52451,6 +52481,7 @@ var STATE_SUMMARY_SECTION_VARS = [
52451
52481
  kinds: [
52452
52482
  "node-offline",
52453
52483
  "node-online",
52484
+ "node-restarting",
52454
52485
  "node-inference-unavailable"
52455
52486
  ]
52456
52487
  },
@@ -52472,6 +52503,7 @@ var STATE_SUMMARY_SECTION_VARS = [
52472
52503
  example: "server 1.2.377 → 1.2.378",
52473
52504
  kinds: [
52474
52505
  "server-update-available",
52506
+ "node-updating",
52475
52507
  "server-updated",
52476
52508
  "wrapper-update-available"
52477
52509
  ]
@@ -52927,10 +52959,9 @@ TimelapseRuleInputSchema.extend({
52927
52959
  createdAt: number(),
52928
52960
  updatedAt: number()
52929
52961
  });
52930
- async function readHubMotionDetected(deviceState, deviceId) {
52931
- let slice;
52962
+ async function readSlice(deviceState, deviceId) {
52932
52963
  try {
52933
- slice = await deviceState.getCapSlice.query({
52964
+ return await deviceState.getCapSlice.query({
52934
52965
  deviceId,
52935
52966
  capName: "motion"
52936
52967
  });
@@ -52938,10 +52969,44 @@ async function readHubMotionDetected(deviceState, deviceId) {
52938
52969
  const reason = err instanceof Error ? err.message : String(err);
52939
52970
  throw new Error(`motion state of device ${deviceId} is unreadable: ${reason}`, { cause: err });
52940
52971
  }
52941
- const detected = slice?.["detected"];
52972
+ }
52973
+ /**
52974
+ * The hub's `motion` slice as a `MotionStatus`, or `null` when nobody has
52975
+ * published it since the hub started. Throws when the hub does not answer or
52976
+ * the slice is malformed — never a made-up "no motion".
52977
+ */
52978
+ async function readHubMotionStatus(deviceState, deviceId) {
52979
+ const slice = await readSlice(deviceState, deviceId);
52980
+ if (slice === null) return null;
52981
+ const parsed = MotionStatusSchema.safeParse(slice);
52982
+ if (!parsed.success) throw new Error(`motion state of device ${deviceId} is malformed on the hub: ${parsed.error.message}`);
52983
+ return parsed.data;
52984
+ }
52985
+ async function readHubMotionDetected(deviceState, deviceId) {
52986
+ const detected = (await readSlice(deviceState, deviceId))?.["detected"];
52942
52987
  if (typeof detected !== "boolean") throw new Error(`motion state of device ${deviceId} is not published yet (unknown)`);
52943
52988
  return detected;
52944
52989
  }
52990
+ /**
52991
+ * The native `motion` provider of a camera whose slice the orchestrator writes
52992
+ * (D696): `isDetected` AND `getStatus`, both from the hub. `owner` names the
52993
+ * provider class in the deviceId-mismatch error.
52994
+ */
52995
+ function hubMotionNativeProvider(deviceState, deviceId, owner) {
52996
+ const ownDevice = (asked) => {
52997
+ if (asked !== deviceId) throw new Error(`${owner}: motion deviceId mismatch, expected ${deviceId}, got ${asked}`);
52998
+ };
52999
+ return {
53000
+ isDetected: async ({ deviceId: asked }) => {
53001
+ ownDevice(asked);
53002
+ return readHubMotionDetected(deviceState, deviceId);
53003
+ },
53004
+ getStatus: async ({ deviceId: asked }) => {
53005
+ ownDevice(asked);
53006
+ return readHubMotionStatus(deviceState, deviceId);
53007
+ }
53008
+ };
53009
+ }
52945
53010
  MotionOnMotionChangedDataSchema.omit({ triggeredBy: true });
52946
53011
  function providerMotionEvent(source, data) {
52947
53012
  return createEvent(EventCategory.ProviderMotion, source, data);
@@ -57417,15 +57482,13 @@ var WyzeCamera = class extends BaseDevice {
57417
57482
  /**
57418
57483
  * The native `motion` cap. This provider writes NO `motion` slice (D696): the
57419
57484
  * orchestrator is its only writer, with the EFFECTIVE motion, on the hub.
57420
- * `isDetected` answers from the HUB's slice; an unreadable hub, or a slice
57421
- * nobody has published yet, fails the call — never `false` for unknown
57422
- * (D49, D393).
57485
+ * `isDetected` and `getStatus` answer from the HUB's slice
57486
+ * (`hubMotionNativeProvider`); an unreadable hub fails both — never `false`
57487
+ * for unknown (D49, D393).
57423
57488
  */
57424
57489
  registerMotionProvider() {
57425
- this.ctx.registerNativeCap(motionCapability, { isDetected: async ({ deviceId }) => {
57426
- if (deviceId !== this.id) throw new Error(`WyzeCamera: deviceId mismatch, expected ${this.id}, got ${deviceId}`);
57427
- return readHubMotionDetected(this.ctx.api.deviceState, this.id);
57428
- } });
57490
+ const provider = hubMotionNativeProvider(this.ctx.api.deviceState, this.id, "WyzeCamera");
57491
+ this.ctx.registerNativeCap(motionCapability, provider);
57429
57492
  }
57430
57493
  /**
57431
57494
  * Start the configured motion source. `cloud` polls the Wyze events API
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-wyze",
3
- "version": "0.2.127",
3
+ "version": "0.2.128",
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",