@apocaliss92/nodelink-js 0.3.4 → 0.3.9

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.
@@ -144,7 +144,7 @@ import {
144
144
  talkTraceLog,
145
145
  traceLog,
146
146
  xmlEscape
147
- } from "./chunk-APEEZ4UN.js";
147
+ } from "./chunk-6Q6MK4WG.js";
148
148
 
149
149
  // src/protocol/framing.ts
150
150
  function encodeHeader(h) {
@@ -1822,6 +1822,22 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
1822
1822
  static coverPreviewBackoffMs = /* @__PURE__ */ new Map();
1823
1823
  static COVER_PREVIEW_INITIAL_BACKOFF_MS = 1e3;
1824
1824
  static COVER_PREVIEW_MAX_BACKOFF_MS = 3e4;
1825
+ /**
1826
+ * Per-client snapshot (cmd_id=109) serialization queue.
1827
+ *
1828
+ * WHY: On NVR/multi-camera devices sharing one socket, concurrent snapshot requests
1829
+ * can cause JPEG data to mix (even with per-request msgNum filtering):
1830
+ * - Camera A and B both send frames on same socket
1831
+ * - Frame listener is global per socket
1832
+ * - Timing quirks can cause chunk reordering or listener confusion
1833
+ *
1834
+ * FIX: Serialize all cmd_id=109 requests on THIS client instance.
1835
+ * Each snapshot waits for previous one to complete before starting.
1836
+ * This ensures clean frame sequences per request, zero data corruption.
1837
+ *
1838
+ * Impact: Snapshots are ~0–50ms slower per camera (negligible for users).
1839
+ */
1840
+ snapshotQueueTail = Promise.resolve();
1825
1841
  opts;
1826
1842
  debugCfg;
1827
1843
  logger;
@@ -4303,6 +4319,20 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
4303
4319
  });
4304
4320
  }
4305
4321
  async sendBinarySnapshot109(params) {
4322
+ const prevTail = this.snapshotQueueTail;
4323
+ let resolve;
4324
+ const newTail = new Promise((r) => {
4325
+ resolve = r;
4326
+ });
4327
+ this.snapshotQueueTail = newTail;
4328
+ try {
4329
+ await prevTail;
4330
+ return await this.sendBinarySnapshot109Impl(params);
4331
+ } finally {
4332
+ resolve();
4333
+ }
4334
+ }
4335
+ async sendBinarySnapshot109Impl(params) {
4306
4336
  await this.connect();
4307
4337
  const channel = params.channel ?? this.opts.channel ?? 0;
4308
4338
  const channelId = params.channelIdOverride ?? (params.channel == null ? this.hostChannelId : channel + 1);
@@ -4362,7 +4392,8 @@ var BaichuanClient = class _BaichuanClient extends EventEmitter2 {
4362
4392
  };
4363
4393
  const onFrame = (frame) => {
4364
4394
  if (frame.header.cmdId !== cmdId) return;
4365
- if (frame.header.msgNum === msgNum && frame.header.responseCode >= 400) {
4395
+ if (frame.header.msgNum !== msgNum) return;
4396
+ if (frame.header.responseCode >= 400) {
4366
4397
  fail(
4367
4398
  new Error(
4368
4399
  `Baichuan snapshot request rejected (cmdId=${cmdId} msgNum=${msgNum} responseCode=${frame.header.responseCode})`
@@ -7588,6 +7619,17 @@ function computeDeviceCapabilities(params) {
7588
7619
  if (ptzMode !== void 0) result.ptzMode = ptzMode;
7589
7620
  return result;
7590
7621
  }
7622
+ function xmlIndicatesFloodlight(xml) {
7623
+ if (/(<FloodlightTask\b|<FloodlightManual\b|<FloodlightStatusList\b)/i.test(
7624
+ xml
7625
+ )) {
7626
+ return true;
7627
+ }
7628
+ if (/<WhiteLed\b/i.test(xml)) {
7629
+ return /(<brightness_cur>|<bright>|<LightingSchedule\b)/i.test(xml);
7630
+ }
7631
+ return false;
7632
+ }
7591
7633
 
7592
7634
  // src/reolink/baichuan/ReolinkBaichuanApi.ts
7593
7635
  import { spawn as spawn2 } from "child_process";
@@ -16830,9 +16872,7 @@ ${stderr}`)
16830
16872
  `probeFloodlightSupportByCmd289: received XML for channel ${ch}:
16831
16873
  ${xml}`
16832
16874
  );
16833
- return /(<FloodlightTask\b|<FloodlightManual\b|<FloodlightStatusList\b|<WhiteLed\b)/i.test(
16834
- xml
16835
- );
16875
+ return xmlIndicatesFloodlight(xml);
16836
16876
  } catch {
16837
16877
  return false;
16838
16878
  }
@@ -17778,7 +17818,7 @@ ${xml}`
17778
17818
  * @returns Test results for all stream types and profiles
17779
17819
  */
17780
17820
  async testChannelStreams(channel, logger) {
17781
- const { testChannelStreams } = await import("./DiagnosticsTools-2JQRV5FE.js");
17821
+ const { testChannelStreams } = await import("./DiagnosticsTools-DQDDBRM6.js");
17782
17822
  return await testChannelStreams({
17783
17823
  api: this,
17784
17824
  channel: this.normalizeChannel(channel),
@@ -17794,7 +17834,7 @@ ${xml}`
17794
17834
  * @returns Complete diagnostics for all channels and streams
17795
17835
  */
17796
17836
  async collectMultifocalDiagnostics(logger) {
17797
- const { collectMultifocalDiagnostics } = await import("./DiagnosticsTools-2JQRV5FE.js");
17837
+ const { collectMultifocalDiagnostics } = await import("./DiagnosticsTools-DQDDBRM6.js");
17798
17838
  return await collectMultifocalDiagnostics({
17799
17839
  api: this,
17800
17840
  logger
@@ -21454,6 +21494,7 @@ export {
21454
21494
  parseSupportXml,
21455
21495
  getSupportItemForChannel,
21456
21496
  computeDeviceCapabilities,
21497
+ xmlIndicatesFloodlight,
21457
21498
  DUAL_LENS_DUAL_MOTION_MODELS,
21458
21499
  DUAL_LENS_SINGLE_MOTION_MODELS,
21459
21500
  DUAL_LENS_MODELS,
@@ -21475,4 +21516,4 @@ export {
21475
21516
  isTcpFailureThatShouldFallbackToUdp,
21476
21517
  autoDetectDeviceType
21477
21518
  };
21478
- //# sourceMappingURL=chunk-YSEFEQYV.js.map
21519
+ //# sourceMappingURL=chunk-OGIKBDON.js.map