@apocaliss92/nodelink-js 0.3.5 → 0.4.1

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,10 +3,10 @@ import {
3
3
  BaichuanRtspServer,
4
4
  ReolinkBaichuanApi,
5
5
  autoDetectDeviceType
6
- } from "../chunk-UDS2UR4S.js";
6
+ } from "../chunk-SDRNJQ5U.js";
7
7
  import {
8
8
  __require
9
- } from "../chunk-APEEZ4UN.js";
9
+ } from "../chunk-DUHWTZ7U.js";
10
10
 
11
11
  // src/cli/rtsp-server.ts
12
12
  function parseArgs() {
package/dist/index.cjs CHANGED
@@ -3103,15 +3103,18 @@ var init_urls = __esm({
3103
3103
  // src/debug/DiagnosticsTools.ts
3104
3104
  var DiagnosticsTools_exports = {};
3105
3105
  __export(DiagnosticsTools_exports, {
3106
+ captureModelFixtures: () => captureModelFixtures,
3106
3107
  collectCgiDiagnostics: () => collectCgiDiagnostics,
3107
3108
  collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
3108
3109
  collectNativeDiagnostics: () => collectNativeDiagnostics,
3109
3110
  collectNvrDiagnostics: () => collectNvrDiagnostics,
3111
+ computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
3110
3112
  createDiagnosticsBundle: () => createDiagnosticsBundle,
3111
3113
  printNvrDiagnostics: () => printNvrDiagnostics,
3112
3114
  runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
3113
3115
  runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
3114
3116
  sampleStreams: () => sampleStreams,
3117
+ sanitizeFixtureData: () => sanitizeFixtureData,
3115
3118
  testChannelStreams: () => testChannelStreams
3116
3119
  });
3117
3120
  function safeStringifyError(error) {
@@ -3136,6 +3139,10 @@ function writeJson(filePath, obj) {
3136
3139
  mkdirp(path4.dirname(filePath));
3137
3140
  fs4.writeFileSync(filePath, JSON.stringify(obj, null, 2));
3138
3141
  }
3142
+ function writeText(filePath, text) {
3143
+ mkdirp(path4.dirname(filePath));
3144
+ fs4.writeFileSync(filePath, text);
3145
+ }
3139
3146
  function appendNdjson(filePath, obj) {
3140
3147
  mkdirp(path4.dirname(filePath));
3141
3148
  fs4.appendFileSync(filePath, JSON.stringify(obj) + "\n");
@@ -5399,7 +5406,411 @@ async function runAllDiagnosticsConsecutively(params) {
5399
5406
  streamsDir
5400
5407
  };
5401
5408
  }
5402
- var fs4, path4, import_node_child_process, import_node_path;
5409
+ function maskIp(ip) {
5410
+ const parts = ip.split(".");
5411
+ return `${parts[0]}.***.***.***`;
5412
+ }
5413
+ function maskMac(mac) {
5414
+ const sep = mac.includes("-") ? "-" : ":";
5415
+ const parts = mac.split(/[:-]/);
5416
+ return `${parts[0]}${sep}${parts[1]}${sep}**${sep}**${sep}**${sep}**`;
5417
+ }
5418
+ function maskSerial(val) {
5419
+ if (val.length <= 4) return "****";
5420
+ return val.slice(0, 2) + "*".repeat(val.length - 4) + val.slice(-2);
5421
+ }
5422
+ function sanitizeString(s) {
5423
+ let out = s;
5424
+ out = out.replace(/:\/\/([^:@]+):([^@]+)@/g, "://***:***@");
5425
+ out = out.replace(/(password=)[^&\s]*/gi, "$1***");
5426
+ out = out.replace(/(user=)[^&\s]*/gi, "$1***");
5427
+ out = out.replace(IPV4_RE, (match) => maskIp(match));
5428
+ out = out.replace(MAC_RE, (match) => maskMac(match));
5429
+ return out;
5430
+ }
5431
+ function sanitizeFixtureData(value) {
5432
+ if (value === null || value === void 0) return value;
5433
+ if (typeof value === "string") {
5434
+ return sanitizeString(value);
5435
+ }
5436
+ if (Array.isArray(value)) {
5437
+ return value.map(sanitizeFixtureData);
5438
+ }
5439
+ if (typeof value === "object") {
5440
+ const out = {};
5441
+ for (const [k, v] of Object.entries(value)) {
5442
+ const kLower = k.toLowerCase();
5443
+ if (REDACT_KEYS.has(kLower)) {
5444
+ out[k] = "***";
5445
+ } else if (MASK_KEYS.has(kLower) || kLower === "serialnumber") {
5446
+ out[k] = typeof v === "string" ? maskSerial(v) : "***";
5447
+ } else if (kLower === "mac") {
5448
+ out[k] = typeof v === "string" ? maskMac(v) : "***";
5449
+ } else if (kLower === "ip" || kLower === "ipaddress" || kLower === "host") {
5450
+ out[k] = typeof v === "string" ? maskIp(v) : v;
5451
+ } else if (kLower === "name" && typeof v === "string" && k !== "name") {
5452
+ out[k] = v;
5453
+ } else {
5454
+ out[k] = sanitizeFixtureData(v);
5455
+ }
5456
+ }
5457
+ return out;
5458
+ }
5459
+ return value;
5460
+ }
5461
+ function computeExpectedStreamCompatibility(params) {
5462
+ const { channelCount } = params;
5463
+ const profiles = params.profiles ?? ["main", "sub", "ext"];
5464
+ const expectedStreamType = { main: 0, sub: 1, ext: 0 };
5465
+ const allStreams = [];
5466
+ for (let ch = 0; ch < channelCount; ch++) {
5467
+ for (const p of profiles) {
5468
+ allStreams.push({ ch, profile: p, label: channelCount > 1 ? `ch${ch}_${p}` : p });
5469
+ }
5470
+ }
5471
+ const results = [];
5472
+ for (let i = 0; i < allStreams.length; i++) {
5473
+ for (let j = i + 1; j < allStreams.length; j++) {
5474
+ const a = allStreams[i];
5475
+ const b = allStreams[j];
5476
+ const stA = expectedStreamType[a.profile] ?? 0;
5477
+ const stB = expectedStreamType[b.profile] ?? 0;
5478
+ const sameChannel = a.ch === b.ch;
5479
+ let expectedOk;
5480
+ let reason;
5481
+ if (sameChannel && stA === stB) {
5482
+ expectedOk = false;
5483
+ reason = `same streamType (${stA}) on same channel`;
5484
+ } else if (!sameChannel && a.profile === b.profile) {
5485
+ expectedOk = false;
5486
+ reason = `multifocal rejects same profile (${a.profile}) across channels`;
5487
+ } else if (!sameChannel && stA === stB) {
5488
+ expectedOk = false;
5489
+ reason = `same streamType (${stA}) across channels`;
5490
+ } else {
5491
+ expectedOk = true;
5492
+ reason = `different streamTypes (${stA} vs ${stB})`;
5493
+ }
5494
+ results.push({ pair: [a.label, b.label], expectedOk, reason });
5495
+ }
5496
+ }
5497
+ return results;
5498
+ }
5499
+ async function captureModelFixtures(params) {
5500
+ const { api, channel, outDir } = params;
5501
+ const log = params.log ?? console.log;
5502
+ mkdirp(outDir);
5503
+ const writeJsonSafe = (filePath, data) => writeJson(filePath, sanitizeFixtureData(data));
5504
+ const writeTextSafe = (filePath, text) => writeText(filePath, sanitizeString(text));
5505
+ const calls = {};
5506
+ const errors = [];
5507
+ async function capture(name, fn, writer) {
5508
+ try {
5509
+ const value = await fn();
5510
+ calls[name] = { ok: true, value };
5511
+ if (writer && value !== void 0 && value !== null) {
5512
+ writer(value);
5513
+ }
5514
+ log(` \u2713 ${name}`);
5515
+ return value;
5516
+ } catch (e) {
5517
+ const msg = e instanceof Error ? e.message : String(e);
5518
+ calls[name] = { ok: false, error: msg };
5519
+ errors.push(`${name}: ${msg}`);
5520
+ log(` \u2717 ${name}: ${msg}`);
5521
+ return void 0;
5522
+ }
5523
+ }
5524
+ const info = await capture(
5525
+ "getInfo",
5526
+ () => api.getInfo(channel),
5527
+ (v) => writeJsonSafe(path4.join(outDir, "device-info.json"), v)
5528
+ );
5529
+ const support = await capture(
5530
+ "getSupportInfo",
5531
+ () => api.getSupportInfo(),
5532
+ (v) => writeJsonSafe(path4.join(outDir, "support-info.json"), v)
5533
+ );
5534
+ const abilities = await capture(
5535
+ "getAbilityInfo",
5536
+ () => api.getAbilityInfo(),
5537
+ (v) => writeJsonSafe(path4.join(outDir, "ability-info.json"), v)
5538
+ );
5539
+ await capture(
5540
+ "getDeviceCapabilities",
5541
+ () => api.getDeviceCapabilities(channel),
5542
+ (v) => writeJsonSafe(path4.join(outDir, "capabilities.json"), v)
5543
+ );
5544
+ await capture("cmd289-WhiteLed", () => api.sendXml({
5545
+ cmdId: BC_CMD_ID_GET_WHITE_LED,
5546
+ channel,
5547
+ timeoutMs: 3e3
5548
+ }), (v) => writeTextSafe(path4.join(outDir, "cmd289-white-led.xml"), v));
5549
+ await capture(
5550
+ "getStreamMetadata",
5551
+ () => api.getStreamMetadata(channel),
5552
+ (v) => writeJsonSafe(path4.join(outDir, "stream-metadata.json"), v)
5553
+ );
5554
+ await capture(
5555
+ "getEncXml",
5556
+ () => api.getEncXml(channel),
5557
+ (v) => writeTextSafe(path4.join(outDir, "enc-config.xml"), v)
5558
+ );
5559
+ await capture(
5560
+ "getPorts",
5561
+ () => api.getPorts(),
5562
+ (v) => writeJsonSafe(path4.join(outDir, "ports.json"), v)
5563
+ );
5564
+ await capture(
5565
+ "getTalkAbility",
5566
+ () => api.getTalkAbility(channel),
5567
+ (v) => writeJsonSafe(path4.join(outDir, "talk-ability.json"), v)
5568
+ );
5569
+ await capture(
5570
+ "getTwoWayAudioConfig",
5571
+ () => api.getTwoWayAudioConfig(channel),
5572
+ (v) => writeJsonSafe(path4.join(outDir, "two-way-audio-config.json"), v)
5573
+ );
5574
+ await capture(
5575
+ "getAiState",
5576
+ () => api.getAiState(channel),
5577
+ (v) => writeJsonSafe(path4.join(outDir, "ai-state.json"), v)
5578
+ );
5579
+ await capture(
5580
+ "getAiCfg",
5581
+ () => api.getAiCfg(channel),
5582
+ (v) => writeJsonSafe(path4.join(outDir, "ai-cfg.json"), v)
5583
+ );
5584
+ await capture(
5585
+ "getOsd",
5586
+ () => api.getOsd(channel),
5587
+ (v) => writeJsonSafe(path4.join(outDir, "osd.json"), v)
5588
+ );
5589
+ await capture(
5590
+ "getMotionAlarm",
5591
+ () => api.getMotionAlarm(channel),
5592
+ (v) => writeJsonSafe(path4.join(outDir, "motion-alarm.json"), v)
5593
+ );
5594
+ await capture(
5595
+ "getRecordCfg",
5596
+ () => api.getRecordCfg(channel),
5597
+ (v) => writeJsonSafe(path4.join(outDir, "record-cfg.json"), v)
5598
+ );
5599
+ await capture(
5600
+ "getVideoInput",
5601
+ () => api.getVideoInput(channel),
5602
+ (v) => writeJsonSafe(path4.join(outDir, "video-input.json"), v)
5603
+ );
5604
+ await capture(
5605
+ "getPtzPresets",
5606
+ () => api.getPtzPresets(channel),
5607
+ (v) => writeJsonSafe(path4.join(outDir, "ptz-presets.json"), v)
5608
+ );
5609
+ await capture(
5610
+ "getNetworkInfo",
5611
+ () => api.getNetworkInfo(),
5612
+ (v) => writeJsonSafe(path4.join(outDir, "network-info.json"), v)
5613
+ );
5614
+ await capture(
5615
+ "getSystemGeneral",
5616
+ () => api.getSystemGeneral(),
5617
+ (v) => writeJsonSafe(path4.join(outDir, "system-general.json"), v)
5618
+ );
5619
+ await capture(
5620
+ "getWifiSignal",
5621
+ () => api.getWifiSignal(channel),
5622
+ (v) => writeJsonSafe(path4.join(outDir, "wifi-signal.json"), v)
5623
+ );
5624
+ await capture(
5625
+ "getWhiteLedState",
5626
+ () => api.getWhiteLedState(channel),
5627
+ (v) => writeJsonSafe(path4.join(outDir, "white-led-state.json"), v)
5628
+ );
5629
+ await capture(
5630
+ "getFloodlightOnMotion",
5631
+ () => api.getFloodlightOnMotion(channel),
5632
+ (v) => writeJsonSafe(path4.join(outDir, "floodlight-on-motion.json"), v)
5633
+ );
5634
+ await capture(
5635
+ "buildVideoStreamOptions",
5636
+ () => api.buildVideoStreamOptions({ channel }),
5637
+ (v) => writeJsonSafe(path4.join(outDir, "video-stream-options.json"), v)
5638
+ );
5639
+ await capture(
5640
+ "getDualLensChannelInfo",
5641
+ () => api.getDualLensChannelInfo(channel),
5642
+ (v) => writeJsonSafe(path4.join(outDir, "dual-lens-info.json"), v)
5643
+ );
5644
+ await capture("streamCombinationTest", async () => {
5645
+ let dualLensInfo;
5646
+ try {
5647
+ dualLensInfo = await api.getDualLensChannelInfo(channel);
5648
+ } catch {
5649
+ }
5650
+ const isMultifocal = dualLensInfo?.isDualLens === true;
5651
+ const channelCount = dualLensInfo?.streamChannelCount ?? 1;
5652
+ const allStreams = [];
5653
+ const profiles = ["main", "sub", "ext"];
5654
+ for (let ch = 0; ch < channelCount; ch++) {
5655
+ for (const p of profiles) {
5656
+ const label = channelCount > 1 ? `ch${ch}_${p}` : p;
5657
+ allStreams.push({ ch, profile: p, label });
5658
+ }
5659
+ }
5660
+ const pairs = [];
5661
+ for (let i = 0; i < allStreams.length; i++) {
5662
+ for (let j = i + 1; j < allStreams.length; j++) {
5663
+ pairs.push([allStreams[i], allStreams[j]]);
5664
+ }
5665
+ }
5666
+ const expectedStreamType = { main: 0, sub: 1, ext: 0 };
5667
+ const expectedCompat = [];
5668
+ for (const [a, b] of pairs) {
5669
+ const stA = expectedStreamType[a.profile];
5670
+ const stB = expectedStreamType[b.profile];
5671
+ const sameChannel = a.ch === b.ch;
5672
+ let expectedOk;
5673
+ let reason;
5674
+ if (sameChannel && stA === stB) {
5675
+ expectedOk = false;
5676
+ reason = `same streamType (${stA}) on same channel`;
5677
+ } else if (!sameChannel && a.profile === b.profile) {
5678
+ expectedOk = false;
5679
+ reason = `multifocal rejects same profile (${a.profile}) across channels`;
5680
+ } else if (!sameChannel && stA === stB) {
5681
+ expectedOk = false;
5682
+ reason = `same streamType (${stA}) across channels`;
5683
+ } else {
5684
+ expectedOk = true;
5685
+ reason = `different streamTypes (${stA} vs ${stB})`;
5686
+ }
5687
+ expectedCompat.push({ pair: [a.label, b.label], expectedOk, reason });
5688
+ }
5689
+ const results = [];
5690
+ const TEST_DURATION_MS = 4e3;
5691
+ for (let pairIdx = 0; pairIdx < pairs.length; pairIdx++) {
5692
+ const [a, b] = pairs[pairIdx];
5693
+ const expected = expectedCompat[pairIdx];
5694
+ log(` testing ${a.label}+${b.label} on shared socket...`);
5695
+ let session;
5696
+ try {
5697
+ session = await api.createDedicatedSession(
5698
+ `test:combo:${a.label}_${b.label}`
5699
+ );
5700
+ } catch (e) {
5701
+ const result2 = {
5702
+ pair: [a.label, b.label],
5703
+ ok: false,
5704
+ framesA: 0,
5705
+ framesB: 0,
5706
+ mismatches: 0,
5707
+ error: `session: ${e instanceof Error ? e.message : String(e)}`,
5708
+ durationMs: 0,
5709
+ expectedOk: expected.expectedOk,
5710
+ expectedReason: expected.reason,
5711
+ matchesExpected: !expected.expectedOk
5712
+ // failed as expected if we expected failure
5713
+ };
5714
+ results.push(result2);
5715
+ continue;
5716
+ }
5717
+ const testClient = session.client;
5718
+ let framesA = 0;
5719
+ let framesB = 0;
5720
+ let mismatches = 0;
5721
+ const start = Date.now();
5722
+ const stTypes = {
5723
+ main: /* @__PURE__ */ new Set([0, 2]),
5724
+ sub: /* @__PURE__ */ new Set([1, 3]),
5725
+ ext: /* @__PURE__ */ new Set([0, 2])
5726
+ };
5727
+ const setA = stTypes[a.profile];
5728
+ const setB = stTypes[b.profile];
5729
+ const onFrame = (frame) => {
5730
+ if (frame.header?.cmdId !== BC_CMD_ID_VIDEO) return;
5731
+ const st = frame.header.streamType;
5732
+ if (setA.has(st)) framesA++;
5733
+ else if (setB.has(st)) framesB++;
5734
+ else mismatches++;
5735
+ };
5736
+ testClient.on("frame", onFrame);
5737
+ let error;
5738
+ try {
5739
+ await api.startVideoStream(a.ch, a.profile, { client: testClient });
5740
+ await api.startVideoStream(b.ch, b.profile, { client: testClient });
5741
+ await new Promise((r) => setTimeout(r, TEST_DURATION_MS));
5742
+ await api.stopVideoStream(a.ch, a.profile, { client: testClient }).catch(() => {
5743
+ });
5744
+ await api.stopVideoStream(b.ch, b.profile, { client: testClient }).catch(() => {
5745
+ });
5746
+ } catch (e) {
5747
+ error = e instanceof Error ? e.message : String(e);
5748
+ } finally {
5749
+ testClient.removeListener("frame", onFrame);
5750
+ await session.release().catch(() => {
5751
+ });
5752
+ }
5753
+ const elapsed = Date.now() - start;
5754
+ const ok2 = !error && framesA > 0 && framesB > 0 && mismatches === 0;
5755
+ const result = {
5756
+ pair: [a.label, b.label],
5757
+ ok: ok2,
5758
+ framesA,
5759
+ framesB,
5760
+ mismatches,
5761
+ ...error ? { error } : {},
5762
+ durationMs: elapsed,
5763
+ expectedOk: expected.expectedOk,
5764
+ expectedReason: expected.reason,
5765
+ matchesExpected: ok2 === expected.expectedOk
5766
+ };
5767
+ results.push(result);
5768
+ const matchStr = result.matchesExpected ? "" : " *** UNEXPECTED ***";
5769
+ log(` ${a.label}+${b.label}: ${ok2 ? "OK" : "FAIL"} (expected=${expected.expectedOk ? "OK" : "FAIL"}) A=${framesA} B=${framesB} mismatch=${mismatches}${matchStr}`);
5770
+ }
5771
+ const unexpected = results.filter((r) => !r.matchesExpected);
5772
+ return {
5773
+ isMultifocal,
5774
+ channelCount,
5775
+ results,
5776
+ summary: {
5777
+ total: results.length,
5778
+ ok: results.filter((r) => r.ok).length,
5779
+ failed: results.filter((r) => !r.ok).length,
5780
+ matchesExpected: results.filter((r) => r.matchesExpected).length,
5781
+ unexpected: unexpected.map((r) => `${r.pair[0]}+${r.pair[1]}: got ${r.ok ? "OK" : "FAIL"}, expected ${r.expectedOk ? "OK" : "FAIL"}`)
5782
+ }
5783
+ };
5784
+ }, (v) => writeJsonSafe(path4.join(outDir, "stream-combination-test.json"), v));
5785
+ const total = Object.keys(calls).length;
5786
+ const ok = Object.values(calls).filter((c) => c.ok).length;
5787
+ const failed = total - ok;
5788
+ const summary = { total, ok, failed, errors };
5789
+ writeJsonSafe(path4.join(outDir, "_summary.json"), {
5790
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
5791
+ model: info?.type ?? "unknown",
5792
+ itemNo: info?.itemNo ?? "unknown",
5793
+ firmwareVersion: info?.firmwareVersion ?? "unknown",
5794
+ channel,
5795
+ ...summary,
5796
+ calls: Object.fromEntries(
5797
+ Object.entries(calls).map(([k, v]) => [
5798
+ k,
5799
+ v.ok ? "ok" : `FAILED: ${v.error}`
5800
+ ])
5801
+ )
5802
+ });
5803
+ log(`
5804
+ Summary: ${ok}/${total} ok, ${failed} failed`);
5805
+ if (errors.length) {
5806
+ log(` Errors:`);
5807
+ for (const err of errors) {
5808
+ log(` - ${err}`);
5809
+ }
5810
+ }
5811
+ return { calls, outDir, summary };
5812
+ }
5813
+ var fs4, path4, import_node_child_process, import_node_path, REDACT_KEYS, MASK_KEYS, IPV4_RE, MAC_RE;
5403
5814
  var init_DiagnosticsTools = __esm({
5404
5815
  "src/debug/DiagnosticsTools.ts"() {
5405
5816
  "use strict";
@@ -5415,6 +5826,27 @@ var init_DiagnosticsTools = __esm({
5415
5826
  init_H265Converter();
5416
5827
  init_constants();
5417
5828
  init_xml();
5829
+ REDACT_KEYS = /* @__PURE__ */ new Set([
5830
+ "password",
5831
+ "pass",
5832
+ "token",
5833
+ "secret",
5834
+ "apiKey",
5835
+ "api_key"
5836
+ ]);
5837
+ MASK_KEYS = /* @__PURE__ */ new Set([
5838
+ "serialNumber",
5839
+ "serial",
5840
+ "uid",
5841
+ "mac",
5842
+ "ssid",
5843
+ "wifiPassword",
5844
+ "userName",
5845
+ "username",
5846
+ "user"
5847
+ ]);
5848
+ IPV4_RE = /\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/g;
5849
+ MAC_RE = /\b([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}\b/g;
5418
5850
  }
5419
5851
  });
5420
5852
 
@@ -7486,11 +7918,13 @@ __export(index_exports, {
7486
7918
  buildSirenTimesXml: () => buildSirenTimesXml,
7487
7919
  buildStartZoomFocusXml: () => buildStartZoomFocusXml,
7488
7920
  buildWhiteLedStateXml: () => buildWhiteLedStateXml,
7921
+ captureModelFixtures: () => captureModelFixtures,
7489
7922
  collectCgiDiagnostics: () => collectCgiDiagnostics,
7490
7923
  collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
7491
7924
  collectNativeDiagnostics: () => collectNativeDiagnostics,
7492
7925
  collectNvrDiagnostics: () => collectNvrDiagnostics,
7493
7926
  computeDeviceCapabilities: () => computeDeviceCapabilities,
7927
+ computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
7494
7928
  convertH265ToAnnexB: () => convertToAnnexB2,
7495
7929
  convertToAnnexB: () => convertToAnnexB,
7496
7930
  convertToLengthPrefixed: () => convertToLengthPrefixed,
@@ -7561,12 +7995,14 @@ __export(index_exports, {
7561
7995
  runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
7562
7996
  runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
7563
7997
  sampleStreams: () => sampleStreams,
7998
+ sanitizeFixtureData: () => sanitizeFixtureData,
7564
7999
  setGlobalLogger: () => setGlobalLogger,
7565
8000
  splitAnnexBToNalPayloads: () => splitAnnexBToNalPayloads,
7566
8001
  splitAnnexBToNals: () => splitAnnexBToNals,
7567
8002
  splitH265AnnexBToNalPayloads: () => splitAnnexBToNalPayloads2,
7568
8003
  testChannelStreams: () => testChannelStreams,
7569
8004
  xmlEscape: () => xmlEscape,
8005
+ xmlIndicatesFloodlight: () => xmlIndicatesFloodlight,
7570
8006
  zipDirectory: () => zipDirectory
7571
8007
  });
7572
8008
  module.exports = __toCommonJS(index_exports);
@@ -15253,7 +15689,7 @@ function computeDeviceCapabilities(params) {
15253
15689
  const ptzControlRaw = supportItem ? supportItem.ptzControl : void 0;
15254
15690
  const supportExplicitlyDefinesPtz = ptzTypeRaw !== void 0 || ptzControlRaw !== void 0;
15255
15691
  const ptzExplicitlyDisabledBySupportItem = supportExplicitlyDefinesPtz && !isTruthyNumberLike(ptzTypeRaw) && !isTruthyNumberLike(ptzControlRaw);
15256
- const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw) || isTruthyNumberLike(ptzControlRaw) || isTruthyNumberLike(supportItem?.ptzPreset);
15692
+ const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw);
15257
15693
  const ptzDisabledBySupport = (ptzMode === "none" || ptzMode === "0") && !hasPtzFromSupportItem;
15258
15694
  const hasBatteryFromSupport = supportItem ? isTruthyNumberLike(supportItem.battery) : false;
15259
15695
  const ptzPresetRaw = supportItem ? supportItem.ptzPreset : void 0;
@@ -15317,6 +15753,17 @@ function computeDeviceCapabilities(params) {
15317
15753
  if (ptzMode !== void 0) result.ptzMode = ptzMode;
15318
15754
  return result;
15319
15755
  }
15756
+ function xmlIndicatesFloodlight(xml) {
15757
+ if (/(<FloodlightTask\b|<FloodlightManual\b|<FloodlightStatusList\b)/i.test(
15758
+ xml
15759
+ )) {
15760
+ return true;
15761
+ }
15762
+ if (/<WhiteLed\b/i.test(xml)) {
15763
+ return /(<brightness_cur>|<bright>|<LightingSchedule\b)/i.test(xml);
15764
+ }
15765
+ return false;
15766
+ }
15320
15767
 
15321
15768
  // src/reolink/baichuan/utils/abilityInfo.ts
15322
15769
  init_xml();
@@ -24353,9 +24800,7 @@ ${stderr}`)
24353
24800
  `probeFloodlightSupportByCmd289: received XML for channel ${ch}:
24354
24801
  ${xml}`
24355
24802
  );
24356
- return /(<FloodlightTask\b|<FloodlightManual\b|<FloodlightStatusList\b|<WhiteLed\b)/i.test(
24357
- xml
24358
- );
24803
+ return xmlIndicatesFloodlight(xml);
24359
24804
  } catch {
24360
24805
  return false;
24361
24806
  }
@@ -36487,11 +36932,13 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
36487
36932
  buildSirenTimesXml,
36488
36933
  buildStartZoomFocusXml,
36489
36934
  buildWhiteLedStateXml,
36935
+ captureModelFixtures,
36490
36936
  collectCgiDiagnostics,
36491
36937
  collectMultifocalDiagnostics,
36492
36938
  collectNativeDiagnostics,
36493
36939
  collectNvrDiagnostics,
36494
36940
  computeDeviceCapabilities,
36941
+ computeExpectedStreamCompatibility,
36495
36942
  convertH265ToAnnexB,
36496
36943
  convertToAnnexB,
36497
36944
  convertToLengthPrefixed,
@@ -36562,12 +37009,14 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
36562
37009
  runAllDiagnosticsConsecutively,
36563
37010
  runMultifocalDiagnosticsConsecutively,
36564
37011
  sampleStreams,
37012
+ sanitizeFixtureData,
36565
37013
  setGlobalLogger,
36566
37014
  splitAnnexBToNalPayloads,
36567
37015
  splitAnnexBToNals,
36568
37016
  splitH265AnnexBToNalPayloads,
36569
37017
  testChannelStreams,
36570
37018
  xmlEscape,
37019
+ xmlIndicatesFloodlight,
36571
37020
  zipDirectory
36572
37021
  });
36573
37022
  //# sourceMappingURL=index.cjs.map