@apocaliss92/nodelink-js 0.3.9 → 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.
- package/dist/{DiagnosticsTools-DQDDBRM6.js → DiagnosticsTools-XIIYZDXL.js} +6 -2
- package/dist/{chunk-6Q6MK4WG.js → chunk-DUHWTZ7U.js} +286 -25
- package/dist/chunk-DUHWTZ7U.js.map +1 -0
- package/dist/{chunk-OGIKBDON.js → chunk-SDRNJQ5U.js} +5 -5
- package/dist/chunk-SDRNJQ5U.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +287 -26
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +291 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +27 -0
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6Q6MK4WG.js.map +0 -1
- package/dist/chunk-OGIKBDON.js.map +0 -1
- /package/dist/{DiagnosticsTools-DQDDBRM6.js.map → DiagnosticsTools-XIIYZDXL.js.map} +0 -0
package/dist/cli/rtsp-server.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
BaichuanRtspServer,
|
|
4
4
|
ReolinkBaichuanApi,
|
|
5
5
|
autoDetectDeviceType
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-SDRNJQ5U.js";
|
|
7
7
|
import {
|
|
8
8
|
__require
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-DUHWTZ7U.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/rtsp-server.ts
|
|
12
12
|
function parseArgs() {
|
package/dist/index.cjs
CHANGED
|
@@ -3108,11 +3108,13 @@ __export(DiagnosticsTools_exports, {
|
|
|
3108
3108
|
collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
|
|
3109
3109
|
collectNativeDiagnostics: () => collectNativeDiagnostics,
|
|
3110
3110
|
collectNvrDiagnostics: () => collectNvrDiagnostics,
|
|
3111
|
+
computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
|
|
3111
3112
|
createDiagnosticsBundle: () => createDiagnosticsBundle,
|
|
3112
3113
|
printNvrDiagnostics: () => printNvrDiagnostics,
|
|
3113
3114
|
runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
|
|
3114
3115
|
runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
|
|
3115
3116
|
sampleStreams: () => sampleStreams,
|
|
3117
|
+
sanitizeFixtureData: () => sanitizeFixtureData,
|
|
3116
3118
|
testChannelStreams: () => testChannelStreams
|
|
3117
3119
|
});
|
|
3118
3120
|
function safeStringifyError(error) {
|
|
@@ -5404,10 +5406,102 @@ async function runAllDiagnosticsConsecutively(params) {
|
|
|
5404
5406
|
streamsDir
|
|
5405
5407
|
};
|
|
5406
5408
|
}
|
|
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
|
+
}
|
|
5407
5499
|
async function captureModelFixtures(params) {
|
|
5408
5500
|
const { api, channel, outDir } = params;
|
|
5409
5501
|
const log = params.log ?? console.log;
|
|
5410
5502
|
mkdirp(outDir);
|
|
5503
|
+
const writeJsonSafe = (filePath, data) => writeJson(filePath, sanitizeFixtureData(data));
|
|
5504
|
+
const writeTextSafe = (filePath, text) => writeText(filePath, sanitizeString(text));
|
|
5411
5505
|
const calls = {};
|
|
5412
5506
|
const errors = [];
|
|
5413
5507
|
async function capture(name, fn, writer) {
|
|
@@ -5430,123 +5524,269 @@ async function captureModelFixtures(params) {
|
|
|
5430
5524
|
const info = await capture(
|
|
5431
5525
|
"getInfo",
|
|
5432
5526
|
() => api.getInfo(channel),
|
|
5433
|
-
(v) =>
|
|
5527
|
+
(v) => writeJsonSafe(path4.join(outDir, "device-info.json"), v)
|
|
5434
5528
|
);
|
|
5435
5529
|
const support = await capture(
|
|
5436
5530
|
"getSupportInfo",
|
|
5437
5531
|
() => api.getSupportInfo(),
|
|
5438
|
-
(v) =>
|
|
5532
|
+
(v) => writeJsonSafe(path4.join(outDir, "support-info.json"), v)
|
|
5439
5533
|
);
|
|
5440
5534
|
const abilities = await capture(
|
|
5441
5535
|
"getAbilityInfo",
|
|
5442
5536
|
() => api.getAbilityInfo(),
|
|
5443
|
-
(v) =>
|
|
5537
|
+
(v) => writeJsonSafe(path4.join(outDir, "ability-info.json"), v)
|
|
5444
5538
|
);
|
|
5445
5539
|
await capture(
|
|
5446
5540
|
"getDeviceCapabilities",
|
|
5447
5541
|
() => api.getDeviceCapabilities(channel),
|
|
5448
|
-
(v) =>
|
|
5542
|
+
(v) => writeJsonSafe(path4.join(outDir, "capabilities.json"), v)
|
|
5449
5543
|
);
|
|
5450
5544
|
await capture("cmd289-WhiteLed", () => api.sendXml({
|
|
5451
5545
|
cmdId: BC_CMD_ID_GET_WHITE_LED,
|
|
5452
5546
|
channel,
|
|
5453
5547
|
timeoutMs: 3e3
|
|
5454
|
-
}), (v) =>
|
|
5548
|
+
}), (v) => writeTextSafe(path4.join(outDir, "cmd289-white-led.xml"), v));
|
|
5455
5549
|
await capture(
|
|
5456
5550
|
"getStreamMetadata",
|
|
5457
5551
|
() => api.getStreamMetadata(channel),
|
|
5458
|
-
(v) =>
|
|
5552
|
+
(v) => writeJsonSafe(path4.join(outDir, "stream-metadata.json"), v)
|
|
5459
5553
|
);
|
|
5460
5554
|
await capture(
|
|
5461
5555
|
"getEncXml",
|
|
5462
5556
|
() => api.getEncXml(channel),
|
|
5463
|
-
(v) =>
|
|
5557
|
+
(v) => writeTextSafe(path4.join(outDir, "enc-config.xml"), v)
|
|
5464
5558
|
);
|
|
5465
5559
|
await capture(
|
|
5466
5560
|
"getPorts",
|
|
5467
5561
|
() => api.getPorts(),
|
|
5468
|
-
(v) =>
|
|
5562
|
+
(v) => writeJsonSafe(path4.join(outDir, "ports.json"), v)
|
|
5469
5563
|
);
|
|
5470
5564
|
await capture(
|
|
5471
5565
|
"getTalkAbility",
|
|
5472
5566
|
() => api.getTalkAbility(channel),
|
|
5473
|
-
(v) =>
|
|
5567
|
+
(v) => writeJsonSafe(path4.join(outDir, "talk-ability.json"), v)
|
|
5474
5568
|
);
|
|
5475
5569
|
await capture(
|
|
5476
5570
|
"getTwoWayAudioConfig",
|
|
5477
5571
|
() => api.getTwoWayAudioConfig(channel),
|
|
5478
|
-
(v) =>
|
|
5572
|
+
(v) => writeJsonSafe(path4.join(outDir, "two-way-audio-config.json"), v)
|
|
5479
5573
|
);
|
|
5480
5574
|
await capture(
|
|
5481
5575
|
"getAiState",
|
|
5482
5576
|
() => api.getAiState(channel),
|
|
5483
|
-
(v) =>
|
|
5577
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-state.json"), v)
|
|
5484
5578
|
);
|
|
5485
5579
|
await capture(
|
|
5486
5580
|
"getAiCfg",
|
|
5487
5581
|
() => api.getAiCfg(channel),
|
|
5488
|
-
(v) =>
|
|
5582
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-cfg.json"), v)
|
|
5489
5583
|
);
|
|
5490
5584
|
await capture(
|
|
5491
5585
|
"getOsd",
|
|
5492
5586
|
() => api.getOsd(channel),
|
|
5493
|
-
(v) =>
|
|
5587
|
+
(v) => writeJsonSafe(path4.join(outDir, "osd.json"), v)
|
|
5494
5588
|
);
|
|
5495
5589
|
await capture(
|
|
5496
5590
|
"getMotionAlarm",
|
|
5497
5591
|
() => api.getMotionAlarm(channel),
|
|
5498
|
-
(v) =>
|
|
5592
|
+
(v) => writeJsonSafe(path4.join(outDir, "motion-alarm.json"), v)
|
|
5499
5593
|
);
|
|
5500
5594
|
await capture(
|
|
5501
5595
|
"getRecordCfg",
|
|
5502
5596
|
() => api.getRecordCfg(channel),
|
|
5503
|
-
(v) =>
|
|
5597
|
+
(v) => writeJsonSafe(path4.join(outDir, "record-cfg.json"), v)
|
|
5504
5598
|
);
|
|
5505
5599
|
await capture(
|
|
5506
5600
|
"getVideoInput",
|
|
5507
5601
|
() => api.getVideoInput(channel),
|
|
5508
|
-
(v) =>
|
|
5602
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-input.json"), v)
|
|
5509
5603
|
);
|
|
5510
5604
|
await capture(
|
|
5511
5605
|
"getPtzPresets",
|
|
5512
5606
|
() => api.getPtzPresets(channel),
|
|
5513
|
-
(v) =>
|
|
5607
|
+
(v) => writeJsonSafe(path4.join(outDir, "ptz-presets.json"), v)
|
|
5514
5608
|
);
|
|
5515
5609
|
await capture(
|
|
5516
5610
|
"getNetworkInfo",
|
|
5517
5611
|
() => api.getNetworkInfo(),
|
|
5518
|
-
(v) =>
|
|
5612
|
+
(v) => writeJsonSafe(path4.join(outDir, "network-info.json"), v)
|
|
5519
5613
|
);
|
|
5520
5614
|
await capture(
|
|
5521
5615
|
"getSystemGeneral",
|
|
5522
5616
|
() => api.getSystemGeneral(),
|
|
5523
|
-
(v) =>
|
|
5617
|
+
(v) => writeJsonSafe(path4.join(outDir, "system-general.json"), v)
|
|
5524
5618
|
);
|
|
5525
5619
|
await capture(
|
|
5526
5620
|
"getWifiSignal",
|
|
5527
5621
|
() => api.getWifiSignal(channel),
|
|
5528
|
-
(v) =>
|
|
5622
|
+
(v) => writeJsonSafe(path4.join(outDir, "wifi-signal.json"), v)
|
|
5529
5623
|
);
|
|
5530
5624
|
await capture(
|
|
5531
5625
|
"getWhiteLedState",
|
|
5532
5626
|
() => api.getWhiteLedState(channel),
|
|
5533
|
-
(v) =>
|
|
5627
|
+
(v) => writeJsonSafe(path4.join(outDir, "white-led-state.json"), v)
|
|
5534
5628
|
);
|
|
5535
5629
|
await capture(
|
|
5536
5630
|
"getFloodlightOnMotion",
|
|
5537
5631
|
() => api.getFloodlightOnMotion(channel),
|
|
5538
|
-
(v) =>
|
|
5632
|
+
(v) => writeJsonSafe(path4.join(outDir, "floodlight-on-motion.json"), v)
|
|
5539
5633
|
);
|
|
5540
5634
|
await capture(
|
|
5541
5635
|
"buildVideoStreamOptions",
|
|
5542
5636
|
() => api.buildVideoStreamOptions({ channel }),
|
|
5543
|
-
(v) =>
|
|
5637
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-stream-options.json"), v)
|
|
5544
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));
|
|
5545
5785
|
const total = Object.keys(calls).length;
|
|
5546
5786
|
const ok = Object.values(calls).filter((c) => c.ok).length;
|
|
5547
5787
|
const failed = total - ok;
|
|
5548
5788
|
const summary = { total, ok, failed, errors };
|
|
5549
|
-
|
|
5789
|
+
writeJsonSafe(path4.join(outDir, "_summary.json"), {
|
|
5550
5790
|
collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5551
5791
|
model: info?.type ?? "unknown",
|
|
5552
5792
|
itemNo: info?.itemNo ?? "unknown",
|
|
@@ -5570,7 +5810,7 @@ async function captureModelFixtures(params) {
|
|
|
5570
5810
|
}
|
|
5571
5811
|
return { calls, outDir, summary };
|
|
5572
5812
|
}
|
|
5573
|
-
var fs4, path4, import_node_child_process, import_node_path;
|
|
5813
|
+
var fs4, path4, import_node_child_process, import_node_path, REDACT_KEYS, MASK_KEYS, IPV4_RE, MAC_RE;
|
|
5574
5814
|
var init_DiagnosticsTools = __esm({
|
|
5575
5815
|
"src/debug/DiagnosticsTools.ts"() {
|
|
5576
5816
|
"use strict";
|
|
@@ -5586,6 +5826,27 @@ var init_DiagnosticsTools = __esm({
|
|
|
5586
5826
|
init_H265Converter();
|
|
5587
5827
|
init_constants();
|
|
5588
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;
|
|
5589
5850
|
}
|
|
5590
5851
|
});
|
|
5591
5852
|
|
|
@@ -7663,6 +7924,7 @@ __export(index_exports, {
|
|
|
7663
7924
|
collectNativeDiagnostics: () => collectNativeDiagnostics,
|
|
7664
7925
|
collectNvrDiagnostics: () => collectNvrDiagnostics,
|
|
7665
7926
|
computeDeviceCapabilities: () => computeDeviceCapabilities,
|
|
7927
|
+
computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
|
|
7666
7928
|
convertH265ToAnnexB: () => convertToAnnexB2,
|
|
7667
7929
|
convertToAnnexB: () => convertToAnnexB,
|
|
7668
7930
|
convertToLengthPrefixed: () => convertToLengthPrefixed,
|
|
@@ -7733,6 +7995,7 @@ __export(index_exports, {
|
|
|
7733
7995
|
runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
|
|
7734
7996
|
runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
|
|
7735
7997
|
sampleStreams: () => sampleStreams,
|
|
7998
|
+
sanitizeFixtureData: () => sanitizeFixtureData,
|
|
7736
7999
|
setGlobalLogger: () => setGlobalLogger,
|
|
7737
8000
|
splitAnnexBToNalPayloads: () => splitAnnexBToNalPayloads,
|
|
7738
8001
|
splitAnnexBToNals: () => splitAnnexBToNals,
|
|
@@ -15426,7 +15689,7 @@ function computeDeviceCapabilities(params) {
|
|
|
15426
15689
|
const ptzControlRaw = supportItem ? supportItem.ptzControl : void 0;
|
|
15427
15690
|
const supportExplicitlyDefinesPtz = ptzTypeRaw !== void 0 || ptzControlRaw !== void 0;
|
|
15428
15691
|
const ptzExplicitlyDisabledBySupportItem = supportExplicitlyDefinesPtz && !isTruthyNumberLike(ptzTypeRaw) && !isTruthyNumberLike(ptzControlRaw);
|
|
15429
|
-
const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw)
|
|
15692
|
+
const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw);
|
|
15430
15693
|
const ptzDisabledBySupport = (ptzMode === "none" || ptzMode === "0") && !hasPtzFromSupportItem;
|
|
15431
15694
|
const hasBatteryFromSupport = supportItem ? isTruthyNumberLike(supportItem.battery) : false;
|
|
15432
15695
|
const ptzPresetRaw = supportItem ? supportItem.ptzPreset : void 0;
|
|
@@ -36675,6 +36938,7 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
|
|
|
36675
36938
|
collectNativeDiagnostics,
|
|
36676
36939
|
collectNvrDiagnostics,
|
|
36677
36940
|
computeDeviceCapabilities,
|
|
36941
|
+
computeExpectedStreamCompatibility,
|
|
36678
36942
|
convertH265ToAnnexB,
|
|
36679
36943
|
convertToAnnexB,
|
|
36680
36944
|
convertToLengthPrefixed,
|
|
@@ -36745,6 +37009,7 @@ var CompositeRtspServer = class extends import_node_events12.EventEmitter {
|
|
|
36745
37009
|
runAllDiagnosticsConsecutively,
|
|
36746
37010
|
runMultifocalDiagnosticsConsecutively,
|
|
36747
37011
|
sampleStreams,
|
|
37012
|
+
sanitizeFixtureData,
|
|
36748
37013
|
setGlobalLogger,
|
|
36749
37014
|
splitAnnexBToNalPayloads,
|
|
36750
37015
|
splitAnnexBToNals,
|