@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.
- package/dist/{DiagnosticsTools-2JQRV5FE.js → DiagnosticsTools-XIIYZDXL.js} +8 -2
- package/dist/{chunk-APEEZ4UN.js → chunk-DUHWTZ7U.js} +433 -1
- package/dist/chunk-DUHWTZ7U.js.map +1 -0
- package/dist/{chunk-UDS2UR4S.js → chunk-SDRNJQ5U.js} +18 -8
- package/dist/chunk-SDRNJQ5U.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +446 -5
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +454 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -1
- package/dist/index.d.ts +77 -0
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-APEEZ4UN.js.map +0 -1
- package/dist/chunk-UDS2UR4S.js.map +0 -1
- /package/dist/{DiagnosticsTools-2JQRV5FE.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
|
@@ -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
|
-
|
|
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)
|
|
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
|
|
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
|