@apocaliss92/nodelink-js 0.4.18 → 0.4.20

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.
@@ -3,7 +3,7 @@ import {
3
3
  BaichuanRtspServer,
4
4
  ReolinkBaichuanApi,
5
5
  autoDetectDeviceType
6
- } from "../chunk-EF6BCSCZ.js";
6
+ } from "../chunk-XUL2Y2AL.js";
7
7
  import "../chunk-S2UTGNFN.js";
8
8
  import {
9
9
  __require
package/dist/index.cjs CHANGED
@@ -16858,6 +16858,9 @@ function computeDeviceCapabilities(params) {
16858
16858
  const isDoorbellFromModel = typeof params.model === "string" && /doorbell/i.test(params.model);
16859
16859
  const lightTypeRaw = supportItem ? supportItem.lightType : void 0;
16860
16860
  const lightType = typeof lightTypeRaw === "number" ? lightTypeRaw : typeof lightTypeRaw === "string" ? Number(lightTypeRaw) : void 0;
16861
+ const ledCtrlRaw = supportItem ? supportItem.ledCtrl : void 0;
16862
+ const ledCtrl = typeof ledCtrlRaw === "number" ? ledCtrlRaw : typeof ledCtrlRaw === "string" ? Number(ledCtrlRaw) : void 0;
16863
+ const hasFloodlightFromLedCtrl = typeof ledCtrl === "number" && Number.isFinite(ledCtrl) && ledCtrl > 1;
16861
16864
  const hasPtzFromSupport = hasPtzFromSupportItem || (ptzMode ? ptzMode !== "none" && ptzMode !== "0" : false);
16862
16865
  const hasPanTiltFromSupport = ptzMode ? ptzMode.includes("pt") || ptzMode === "pt" || ptzMode === "ptz" : false;
16863
16866
  const hasZoomFromSupport = ptzMode ? ptzMode.includes("z") : false;
@@ -16900,8 +16903,10 @@ function computeDeviceCapabilities(params) {
16900
16903
  hasBattery,
16901
16904
  hasIntercom: hasIntercomFromSupport,
16902
16905
  hasSiren: hasSirenFromSupport || hasSirenFromAbilities,
16903
- // lightType >= 2 indicates controllable white LED / floodlight (1 = IR only)
16904
- hasFloodlight: Number.isFinite(lightType) ? lightType >= 2 : hasFloodlightFromAbilities,
16906
+ // lightType >= 2 indicates controllable white LED / floodlight (1 = IR only).
16907
+ // ledCtrl > 1 is a secondary signal that rescues firmwares like the Duo 3
16908
+ // WiFi which under-report lightType (=1) despite having a real spotlight.
16909
+ hasFloodlight: Number.isFinite(lightType) ? lightType >= 2 || hasFloodlightFromLedCtrl : hasFloodlightFromAbilities || hasFloodlightFromLedCtrl,
16905
16910
  hasPir: hasPirFromAbilities || hasPirFromSupport,
16906
16911
  isDoorbell,
16907
16912
  hasAutotracking: ptzDisabledBySupport ? false : hasAutotrackingFromSupport || hasAutotrackingFromAbilities,
@@ -19586,9 +19591,11 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
19586
19591
  if (!this.sessionGuardIntervalTimer) {
19587
19592
  client.once("push", () => {
19588
19593
  void this.logActiveSessionsOnStartup();
19589
- this.sessionGuardIntervalTimer = setInterval(() => {
19590
- void this.maybeRebootOnTooManySessions();
19591
- }, 6e4);
19594
+ if (this.sessionGuardEnabled) {
19595
+ this.sessionGuardIntervalTimer = setInterval(() => {
19596
+ void this.maybeRebootOnTooManySessions();
19597
+ }, 6e4);
19598
+ }
19592
19599
  });
19593
19600
  }
19594
19601
  }
@@ -19621,6 +19628,19 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
19621
19628
  _isMultiFocal;
19622
19629
  /** Maximum dedicated sessions allowed before triggering a reboot (default: 7). */
19623
19630
  maxDedicatedSessionsBeforeReboot;
19631
+ /**
19632
+ * Opt-in: when `false` (default), the lib never starts the 60s periodic
19633
+ * `getOnlineUserList` poll and never schedules an automatic reboot based
19634
+ * on the session count. The post-socket-create probe at line ~1859 is
19635
+ * also skipped. Consumers that want the legacy behaviour can pass
19636
+ * `enableSessionGuard: true` to the constructor.
19637
+ *
19638
+ * Rationale: on BCUDP (battery cameras) the periodic poll wakes the
19639
+ * camera every minute and triggers a perpetual sleeping↔awake cycle —
19640
+ * see issue #18. Even on AC cameras the auto-reboot side effect is
19641
+ * surprising; making it explicit avoids astonishment.
19642
+ */
19643
+ sessionGuardEnabled = false;
19624
19644
  sessionGuardRebootInFlight;
19625
19645
  sessionGuardLastRebootAtMs;
19626
19646
  /** Track last known session count and IDs for change detection. */
@@ -20312,7 +20332,9 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
20312
20332
  } catch {
20313
20333
  }
20314
20334
  }
20315
- void this.maybeRebootOnTooManySessions();
20335
+ if (this.sessionGuardEnabled) {
20336
+ void this.maybeRebootOnTooManySessions();
20337
+ }
20316
20338
  return newClient;
20317
20339
  } catch (loginError) {
20318
20340
  const prevCooldown = this.socketPoolCooldowns.get(this.host);
@@ -20622,6 +20644,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
20622
20644
  logger: this.logger,
20623
20645
  debugConfig: generalClient.getDebugConfig?.()
20624
20646
  });
20647
+ this.sessionGuardEnabled = opts.enableSessionGuard === true;
20625
20648
  const maxSessions = opts.maxDedicatedSessionsBeforeReboot;
20626
20649
  if (typeof maxSessions === "number" && Number.isFinite(maxSessions) && maxSessions > 0) {
20627
20650
  this.maxDedicatedSessionsBeforeReboot = Math.floor(maxSessions);
@@ -20795,6 +20818,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
20795
20818
  */
20796
20819
  async maybeRebootOnTooManySessions() {
20797
20820
  if (!this.client.isSocketConnected?.()) return;
20821
+ if (this.client.getTransport?.() === "udp") return;
20798
20822
  const threshold = this.maxDedicatedSessionsBeforeReboot ?? 10;
20799
20823
  if (this.sessionGuardRebootInFlight) return;
20800
20824
  const cooldownMs = 10 * 6e4;
@@ -26946,7 +26970,7 @@ ${xml}`
26946
26970
  const probed = await this.probeFloodlightSupportByCmd289(ch, {
26947
26971
  timeoutMs: 2500
26948
26972
  });
26949
- capabilities.hasFloodlight = probed;
26973
+ capabilities.hasFloodlight = capabilities.hasFloodlight || probed;
26950
26974
  }
26951
26975
  let dingDongListIds;
26952
26976
  let dingDongCfgIds;
@@ -27139,7 +27163,17 @@ ${xml}`
27139
27163
  const isSingleMotionModel = normalizedModel ? checkModelMatch(DUAL_LENS_SINGLE_MOTION_MODELS, normalizedModel) : false;
27140
27164
  const channelNumValue = typeof channelNum === "string" ? Number.parseInt(channelNum, 10) : channelNum;
27141
27165
  const hasDualLensChannelCount = channelNumValue === 2 && Number.isFinite(channelNumValue);
27142
- const isDualLens = isDualMotionModel || isSingleMotionModel || hasDualLensChannelCount;
27166
+ const supportItemForChannel = (() => {
27167
+ if (!supportInfo) return void 0;
27168
+ const items = supportInfo.items;
27169
+ if (!Array.isArray(items)) return void 0;
27170
+ return items.find(
27171
+ (it) => typeof it === "object" && it !== null && "ledCtrl" in it
27172
+ );
27173
+ })();
27174
+ const binoCfgRaw = supportItemForChannel ? supportItemForChannel.binoCfg : void 0;
27175
+ const hasBinoCfgFlag = typeof binoCfgRaw === "number" ? binoCfgRaw > 0 : typeof binoCfgRaw === "string" ? Number(binoCfgRaw) > 0 : false;
27176
+ const isDualLens = hasBinoCfgFlag || isDualMotionModel || isSingleMotionModel || hasDualLensChannelCount;
27143
27177
  if (!isDualLens) {
27144
27178
  return {
27145
27179
  isDualLens: false,