@camstack/addon-provider-onvif 1.1.20 → 1.1.21

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
@@ -6937,10 +6937,18 @@ var ModelVariantGroupSchema = object({
6937
6937
  precision: _enum(["fp32", "int8"]).optional(),
6938
6938
  /**
6939
6939
  * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
6940
- * latency-optimized export (e.g. ReLU-activation / reduced-input variant)
6941
- * — the slot the future performance variants plug into.
6940
+ * latency-optimized export (e.g. ReLU-activation variant) the slot the
6941
+ * future performance variants plug into.
6942
6942
  */
6943
- optimization: _enum(["standard", "fast"]).optional()
6943
+ optimization: _enum(["standard", "fast"]).optional(),
6944
+ /**
6945
+ * Input-resolution axis (square input side, px). Omit ⇒ the family's native
6946
+ * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
6947
+ * cheap latency lever — especially on Apple ANE and the Intel N100 — at a
6948
+ * small-object accuracy cost. Mirrors the model's `inputSize` but lifted onto
6949
+ * the group so the selector can offer it as a variant axis.
6950
+ */
6951
+ resolution: number().int().positive().optional()
6944
6952
  });
6945
6953
  var ModelCatalogEntrySchema = object({
6946
6954
  id: string(),
@@ -8430,6 +8438,72 @@ var DeviceConfig = class DeviceConfig {
8430
8438
  }));
8431
8439
  }
8432
8440
  };
8441
+ /** Reject after `ms`; always clears its own timer. */
8442
+ async function withTimeout(promise, ms, label) {
8443
+ let timer;
8444
+ const timeout = new Promise((_resolve, reject) => {
8445
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`${label} timed out after ${String(ms)}ms`)), ms);
8446
+ });
8447
+ try {
8448
+ return await Promise.race([promise, timeout]);
8449
+ } finally {
8450
+ if (timer !== void 0) clearTimeout(timer);
8451
+ }
8452
+ }
8453
+ /**
8454
+ * Start the reachability poll loop. Returns a handle whose `stop()` clears the
8455
+ * timer and prevents any further ticks. Start on device activation, stop on
8456
+ * device teardown (`removeDevice`) so no timer leaks.
8457
+ */
8458
+ function startReachabilityPoll(options) {
8459
+ const intervalMs = options.intervalMs ?? 3e4;
8460
+ const failuresToOffline = options.failuresToOffline ?? 3;
8461
+ const probeTimeoutMs = options.probeTimeoutMs ?? 1e4;
8462
+ const runImmediately = options.runImmediately ?? true;
8463
+ let stopped = false;
8464
+ let running = false;
8465
+ let consecutiveFailures = 0;
8466
+ let timer;
8467
+ const tick = async () => {
8468
+ if (stopped) return;
8469
+ if (running) return;
8470
+ if (options.isEnabled && !options.isEnabled()) return;
8471
+ running = true;
8472
+ try {
8473
+ const reachable = await withTimeout(Promise.resolve().then(options.probe), probeTimeoutMs, "reachability probe");
8474
+ if (stopped) return;
8475
+ if (reachable) {
8476
+ consecutiveFailures = 0;
8477
+ options.setOnline(true);
8478
+ } else registerFailure("probe resolved unreachable");
8479
+ } catch (error) {
8480
+ if (stopped) return;
8481
+ registerFailure(error instanceof Error ? error.message : "probe threw");
8482
+ } finally {
8483
+ running = false;
8484
+ }
8485
+ };
8486
+ const registerFailure = (reason) => {
8487
+ consecutiveFailures += 1;
8488
+ options.logger?.debug("reachability probe failed", {
8489
+ reason,
8490
+ consecutiveFailures,
8491
+ failuresToOffline
8492
+ });
8493
+ if (consecutiveFailures >= failuresToOffline) options.setOnline(false);
8494
+ };
8495
+ timer = setInterval(() => {
8496
+ tick();
8497
+ }, intervalMs);
8498
+ if (typeof timer === "object" && timer !== null && "unref" in timer) timer.unref();
8499
+ if (runImmediately) tick();
8500
+ return { stop: () => {
8501
+ if (stopped) return;
8502
+ stopped = true;
8503
+ if (timer !== void 0) clearInterval(timer);
8504
+ timer = void 0;
8505
+ } };
8506
+ }
8433
8507
  /**
8434
8508
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
8435
8509
  * for every device, regardless of provider — the kernel needs a uniform
@@ -10725,6 +10799,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
10725
10799
  })) }), object({ success: literal(true) }), {
10726
10800
  kind: "mutation",
10727
10801
  auth: "admin"
10802
+ }), method(object({ nodeId: string() }), object({
10803
+ success: literal(true),
10804
+ regeneratedModelId: string().nullable()
10805
+ }), {
10806
+ kind: "mutation",
10807
+ auth: "admin"
10728
10808
  }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({ steps: array(PipelineStepInputSchema) }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
10729
10809
  name: string(),
10730
10810
  steps: array(PipelineTemplateStepSchema).readonly(),
@@ -21696,6 +21776,12 @@ Object.freeze({
21696
21776
  addonId: null,
21697
21777
  access: "create"
21698
21778
  },
21779
+ "pipelineExecutor.resetToDefault": {
21780
+ capName: "pipeline-executor",
21781
+ capScope: "system",
21782
+ addonId: null,
21783
+ access: "delete"
21784
+ },
21699
21785
  "pipelineExecutor.runAudioTest": {
21700
21786
  capName: "pipeline-executor",
21701
21787
  capScope: "system",
@@ -23378,6 +23464,10 @@ var OnvifCamera = class {
23378
23464
  * `null` when the camera is being restored from DB without a live connection.
23379
23465
  */
23380
23466
  client;
23467
+ /** Control-plane reachability poll — drives `online` from ONVIF
23468
+ * `getDeviceInformation` liveness, decoupled from stream-broker video
23469
+ * health. Started on `attachClient`, stopped on `removeDevice`. */
23470
+ reachabilityPoll = null;
23381
23471
  constructor(ctx, initialData, client = null) {
23382
23472
  this.ctx = ctx;
23383
23473
  this.id = ctx.id;
@@ -23562,8 +23652,32 @@ var OnvifCamera = class {
23562
23652
  attachClient(client) {
23563
23653
  this.client = client;
23564
23654
  this.online = true;
23655
+ this.startReachabilityPolling();
23656
+ }
23657
+ /** Start the control-plane reachability poll: an ONVIF
23658
+ * `getDeviceInformation` round-trip every 30s drives `online`, with
23659
+ * hysteresis. Replaces the old stream-health→online coupling so a
23660
+ * reachable on-demand camera still reports ONLINE. Re-armed on each
23661
+ * `attachClient` (reconnect) — the prior poll is stopped first. */
23662
+ startReachabilityPolling() {
23663
+ this.reachabilityPoll?.stop();
23664
+ this.reachabilityPoll = startReachabilityPoll({
23665
+ probe: async () => {
23666
+ const client = this.client;
23667
+ if (!client) return false;
23668
+ await client.getDeviceInfo();
23669
+ return true;
23670
+ },
23671
+ setOnline: (online) => {
23672
+ this.markOnline(online);
23673
+ },
23674
+ isEnabled: () => !this.disabled && this.client !== null,
23675
+ logger: this.ctx.logger
23676
+ });
23565
23677
  }
23566
23678
  async removeDevice() {
23679
+ this.reachabilityPoll?.stop();
23680
+ this.reachabilityPoll = null;
23567
23681
  this.client?.disconnect();
23568
23682
  this.client = null;
23569
23683
  this.online = false;
package/dist/addon.mjs CHANGED
@@ -6938,10 +6938,18 @@ var ModelVariantGroupSchema = object({
6938
6938
  precision: _enum(["fp32", "int8"]).optional(),
6939
6939
  /**
6940
6940
  * Speed-optimization axis. Omit ⇒ the standard build. `fast` marks a
6941
- * latency-optimized export (e.g. ReLU-activation / reduced-input variant)
6942
- * — the slot the future performance variants plug into.
6941
+ * latency-optimized export (e.g. ReLU-activation variant) the slot the
6942
+ * future performance variants plug into.
6943
6943
  */
6944
- optimization: _enum(["standard", "fast"]).optional()
6944
+ optimization: _enum(["standard", "fast"]).optional(),
6945
+ /**
6946
+ * Input-resolution axis (square input side, px). Omit ⇒ the family's native
6947
+ * resolution (640 for yolo26). Reduced-input builds (320 / 256) are a big,
6948
+ * cheap latency lever — especially on Apple ANE and the Intel N100 — at a
6949
+ * small-object accuracy cost. Mirrors the model's `inputSize` but lifted onto
6950
+ * the group so the selector can offer it as a variant axis.
6951
+ */
6952
+ resolution: number().int().positive().optional()
6945
6953
  });
6946
6954
  var ModelCatalogEntrySchema = object({
6947
6955
  id: string(),
@@ -8431,6 +8439,72 @@ var DeviceConfig = class DeviceConfig {
8431
8439
  }));
8432
8440
  }
8433
8441
  };
8442
+ /** Reject after `ms`; always clears its own timer. */
8443
+ async function withTimeout(promise, ms, label) {
8444
+ let timer;
8445
+ const timeout = new Promise((_resolve, reject) => {
8446
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`${label} timed out after ${String(ms)}ms`)), ms);
8447
+ });
8448
+ try {
8449
+ return await Promise.race([promise, timeout]);
8450
+ } finally {
8451
+ if (timer !== void 0) clearTimeout(timer);
8452
+ }
8453
+ }
8454
+ /**
8455
+ * Start the reachability poll loop. Returns a handle whose `stop()` clears the
8456
+ * timer and prevents any further ticks. Start on device activation, stop on
8457
+ * device teardown (`removeDevice`) so no timer leaks.
8458
+ */
8459
+ function startReachabilityPoll(options) {
8460
+ const intervalMs = options.intervalMs ?? 3e4;
8461
+ const failuresToOffline = options.failuresToOffline ?? 3;
8462
+ const probeTimeoutMs = options.probeTimeoutMs ?? 1e4;
8463
+ const runImmediately = options.runImmediately ?? true;
8464
+ let stopped = false;
8465
+ let running = false;
8466
+ let consecutiveFailures = 0;
8467
+ let timer;
8468
+ const tick = async () => {
8469
+ if (stopped) return;
8470
+ if (running) return;
8471
+ if (options.isEnabled && !options.isEnabled()) return;
8472
+ running = true;
8473
+ try {
8474
+ const reachable = await withTimeout(Promise.resolve().then(options.probe), probeTimeoutMs, "reachability probe");
8475
+ if (stopped) return;
8476
+ if (reachable) {
8477
+ consecutiveFailures = 0;
8478
+ options.setOnline(true);
8479
+ } else registerFailure("probe resolved unreachable");
8480
+ } catch (error) {
8481
+ if (stopped) return;
8482
+ registerFailure(error instanceof Error ? error.message : "probe threw");
8483
+ } finally {
8484
+ running = false;
8485
+ }
8486
+ };
8487
+ const registerFailure = (reason) => {
8488
+ consecutiveFailures += 1;
8489
+ options.logger?.debug("reachability probe failed", {
8490
+ reason,
8491
+ consecutiveFailures,
8492
+ failuresToOffline
8493
+ });
8494
+ if (consecutiveFailures >= failuresToOffline) options.setOnline(false);
8495
+ };
8496
+ timer = setInterval(() => {
8497
+ tick();
8498
+ }, intervalMs);
8499
+ if (typeof timer === "object" && timer !== null && "unref" in timer) timer.unref();
8500
+ if (runImmediately) tick();
8501
+ return { stop: () => {
8502
+ if (stopped) return;
8503
+ stopped = true;
8504
+ if (timer !== void 0) clearInterval(timer);
8505
+ timer = void 0;
8506
+ } };
8507
+ }
8434
8508
  /**
8435
8509
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
8436
8510
  * for every device, regardless of provider — the kernel needs a uniform
@@ -10726,6 +10800,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
10726
10800
  })) }), object({ success: literal(true) }), {
10727
10801
  kind: "mutation",
10728
10802
  auth: "admin"
10803
+ }), method(object({ nodeId: string() }), object({
10804
+ success: literal(true),
10805
+ regeneratedModelId: string().nullable()
10806
+ }), {
10807
+ kind: "mutation",
10808
+ auth: "admin"
10729
10809
  }), method(_void(), PipelineSchemaSchema), method(_void(), array(PipelineDefaultStepSchema).readonly().nullable()), method(_void(), PipelineConfigBridge), method(_void(), ConfigUISchemaBridge), method(object({ steps: array(PipelineStepInputSchema) }), PipelineValidationResultSchema), method(_void(), array(PipelineTemplateSchema$1).readonly()), method(object({
10730
10810
  name: string(),
10731
10811
  steps: array(PipelineTemplateStepSchema).readonly(),
@@ -21697,6 +21777,12 @@ Object.freeze({
21697
21777
  addonId: null,
21698
21778
  access: "create"
21699
21779
  },
21780
+ "pipelineExecutor.resetToDefault": {
21781
+ capName: "pipeline-executor",
21782
+ capScope: "system",
21783
+ addonId: null,
21784
+ access: "delete"
21785
+ },
21700
21786
  "pipelineExecutor.runAudioTest": {
21701
21787
  capName: "pipeline-executor",
21702
21788
  capScope: "system",
@@ -23379,6 +23465,10 @@ var OnvifCamera = class {
23379
23465
  * `null` when the camera is being restored from DB without a live connection.
23380
23466
  */
23381
23467
  client;
23468
+ /** Control-plane reachability poll — drives `online` from ONVIF
23469
+ * `getDeviceInformation` liveness, decoupled from stream-broker video
23470
+ * health. Started on `attachClient`, stopped on `removeDevice`. */
23471
+ reachabilityPoll = null;
23382
23472
  constructor(ctx, initialData, client = null) {
23383
23473
  this.ctx = ctx;
23384
23474
  this.id = ctx.id;
@@ -23563,8 +23653,32 @@ var OnvifCamera = class {
23563
23653
  attachClient(client) {
23564
23654
  this.client = client;
23565
23655
  this.online = true;
23656
+ this.startReachabilityPolling();
23657
+ }
23658
+ /** Start the control-plane reachability poll: an ONVIF
23659
+ * `getDeviceInformation` round-trip every 30s drives `online`, with
23660
+ * hysteresis. Replaces the old stream-health→online coupling so a
23661
+ * reachable on-demand camera still reports ONLINE. Re-armed on each
23662
+ * `attachClient` (reconnect) — the prior poll is stopped first. */
23663
+ startReachabilityPolling() {
23664
+ this.reachabilityPoll?.stop();
23665
+ this.reachabilityPoll = startReachabilityPoll({
23666
+ probe: async () => {
23667
+ const client = this.client;
23668
+ if (!client) return false;
23669
+ await client.getDeviceInfo();
23670
+ return true;
23671
+ },
23672
+ setOnline: (online) => {
23673
+ this.markOnline(online);
23674
+ },
23675
+ isEnabled: () => !this.disabled && this.client !== null,
23676
+ logger: this.ctx.logger
23677
+ });
23566
23678
  }
23567
23679
  async removeDevice() {
23680
+ this.reachabilityPoll?.stop();
23681
+ this.reachabilityPoll = null;
23568
23682
  this.client?.disconnect();
23569
23683
  this.client = null;
23570
23684
  this.online = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-onvif",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "description": "ONVIF camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",