@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
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
+
captureModelFixtures,
|
|
2
3
|
collectCgiDiagnostics,
|
|
3
4
|
collectMultifocalDiagnostics,
|
|
4
5
|
collectNativeDiagnostics,
|
|
5
6
|
collectNvrDiagnostics,
|
|
7
|
+
computeExpectedStreamCompatibility,
|
|
6
8
|
createDiagnosticsBundle,
|
|
7
9
|
printNvrDiagnostics,
|
|
8
10
|
runAllDiagnosticsConsecutively,
|
|
9
11
|
runMultifocalDiagnosticsConsecutively,
|
|
10
12
|
sampleStreams,
|
|
13
|
+
sanitizeFixtureData,
|
|
11
14
|
testChannelStreams
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-DUHWTZ7U.js";
|
|
13
16
|
export {
|
|
17
|
+
captureModelFixtures,
|
|
14
18
|
collectCgiDiagnostics,
|
|
15
19
|
collectMultifocalDiagnostics,
|
|
16
20
|
collectNativeDiagnostics,
|
|
17
21
|
collectNvrDiagnostics,
|
|
22
|
+
computeExpectedStreamCompatibility,
|
|
18
23
|
createDiagnosticsBundle,
|
|
19
24
|
printNvrDiagnostics,
|
|
20
25
|
runAllDiagnosticsConsecutively,
|
|
21
26
|
runMultifocalDiagnosticsConsecutively,
|
|
22
27
|
sampleStreams,
|
|
28
|
+
sanitizeFixtureData,
|
|
23
29
|
testChannelStreams
|
|
24
30
|
};
|
|
25
|
-
//# sourceMappingURL=DiagnosticsTools-
|
|
31
|
+
//# sourceMappingURL=DiagnosticsTools-XIIYZDXL.js.map
|
|
@@ -4903,6 +4903,10 @@ function writeJson(filePath, obj) {
|
|
|
4903
4903
|
mkdirp(path4.dirname(filePath));
|
|
4904
4904
|
fs4.writeFileSync(filePath, JSON.stringify(obj, null, 2));
|
|
4905
4905
|
}
|
|
4906
|
+
function writeText(filePath, text) {
|
|
4907
|
+
mkdirp(path4.dirname(filePath));
|
|
4908
|
+
fs4.writeFileSync(filePath, text);
|
|
4909
|
+
}
|
|
4906
4910
|
function appendNdjson(filePath, obj) {
|
|
4907
4911
|
mkdirp(path4.dirname(filePath));
|
|
4908
4912
|
fs4.appendFileSync(filePath, JSON.stringify(obj) + "\n");
|
|
@@ -7166,6 +7170,431 @@ async function runAllDiagnosticsConsecutively(params) {
|
|
|
7166
7170
|
streamsDir
|
|
7167
7171
|
};
|
|
7168
7172
|
}
|
|
7173
|
+
var REDACT_KEYS = /* @__PURE__ */ new Set([
|
|
7174
|
+
"password",
|
|
7175
|
+
"pass",
|
|
7176
|
+
"token",
|
|
7177
|
+
"secret",
|
|
7178
|
+
"apiKey",
|
|
7179
|
+
"api_key"
|
|
7180
|
+
]);
|
|
7181
|
+
var MASK_KEYS = /* @__PURE__ */ new Set([
|
|
7182
|
+
"serialNumber",
|
|
7183
|
+
"serial",
|
|
7184
|
+
"uid",
|
|
7185
|
+
"mac",
|
|
7186
|
+
"ssid",
|
|
7187
|
+
"wifiPassword",
|
|
7188
|
+
"userName",
|
|
7189
|
+
"username",
|
|
7190
|
+
"user"
|
|
7191
|
+
]);
|
|
7192
|
+
var IPV4_RE = /\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/g;
|
|
7193
|
+
var MAC_RE = /\b([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}\b/g;
|
|
7194
|
+
function maskIp(ip) {
|
|
7195
|
+
const parts = ip.split(".");
|
|
7196
|
+
return `${parts[0]}.***.***.***`;
|
|
7197
|
+
}
|
|
7198
|
+
function maskMac(mac) {
|
|
7199
|
+
const sep = mac.includes("-") ? "-" : ":";
|
|
7200
|
+
const parts = mac.split(/[:-]/);
|
|
7201
|
+
return `${parts[0]}${sep}${parts[1]}${sep}**${sep}**${sep}**${sep}**`;
|
|
7202
|
+
}
|
|
7203
|
+
function maskSerial(val) {
|
|
7204
|
+
if (val.length <= 4) return "****";
|
|
7205
|
+
return val.slice(0, 2) + "*".repeat(val.length - 4) + val.slice(-2);
|
|
7206
|
+
}
|
|
7207
|
+
function sanitizeString(s) {
|
|
7208
|
+
let out = s;
|
|
7209
|
+
out = out.replace(/:\/\/([^:@]+):([^@]+)@/g, "://***:***@");
|
|
7210
|
+
out = out.replace(/(password=)[^&\s]*/gi, "$1***");
|
|
7211
|
+
out = out.replace(/(user=)[^&\s]*/gi, "$1***");
|
|
7212
|
+
out = out.replace(IPV4_RE, (match) => maskIp(match));
|
|
7213
|
+
out = out.replace(MAC_RE, (match) => maskMac(match));
|
|
7214
|
+
return out;
|
|
7215
|
+
}
|
|
7216
|
+
function sanitizeFixtureData(value) {
|
|
7217
|
+
if (value === null || value === void 0) return value;
|
|
7218
|
+
if (typeof value === "string") {
|
|
7219
|
+
return sanitizeString(value);
|
|
7220
|
+
}
|
|
7221
|
+
if (Array.isArray(value)) {
|
|
7222
|
+
return value.map(sanitizeFixtureData);
|
|
7223
|
+
}
|
|
7224
|
+
if (typeof value === "object") {
|
|
7225
|
+
const out = {};
|
|
7226
|
+
for (const [k, v] of Object.entries(value)) {
|
|
7227
|
+
const kLower = k.toLowerCase();
|
|
7228
|
+
if (REDACT_KEYS.has(kLower)) {
|
|
7229
|
+
out[k] = "***";
|
|
7230
|
+
} else if (MASK_KEYS.has(kLower) || kLower === "serialnumber") {
|
|
7231
|
+
out[k] = typeof v === "string" ? maskSerial(v) : "***";
|
|
7232
|
+
} else if (kLower === "mac") {
|
|
7233
|
+
out[k] = typeof v === "string" ? maskMac(v) : "***";
|
|
7234
|
+
} else if (kLower === "ip" || kLower === "ipaddress" || kLower === "host") {
|
|
7235
|
+
out[k] = typeof v === "string" ? maskIp(v) : v;
|
|
7236
|
+
} else if (kLower === "name" && typeof v === "string" && k !== "name") {
|
|
7237
|
+
out[k] = v;
|
|
7238
|
+
} else {
|
|
7239
|
+
out[k] = sanitizeFixtureData(v);
|
|
7240
|
+
}
|
|
7241
|
+
}
|
|
7242
|
+
return out;
|
|
7243
|
+
}
|
|
7244
|
+
return value;
|
|
7245
|
+
}
|
|
7246
|
+
function computeExpectedStreamCompatibility(params) {
|
|
7247
|
+
const { channelCount } = params;
|
|
7248
|
+
const profiles = params.profiles ?? ["main", "sub", "ext"];
|
|
7249
|
+
const expectedStreamType = { main: 0, sub: 1, ext: 0 };
|
|
7250
|
+
const allStreams = [];
|
|
7251
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
7252
|
+
for (const p of profiles) {
|
|
7253
|
+
allStreams.push({ ch, profile: p, label: channelCount > 1 ? `ch${ch}_${p}` : p });
|
|
7254
|
+
}
|
|
7255
|
+
}
|
|
7256
|
+
const results = [];
|
|
7257
|
+
for (let i = 0; i < allStreams.length; i++) {
|
|
7258
|
+
for (let j = i + 1; j < allStreams.length; j++) {
|
|
7259
|
+
const a = allStreams[i];
|
|
7260
|
+
const b = allStreams[j];
|
|
7261
|
+
const stA = expectedStreamType[a.profile] ?? 0;
|
|
7262
|
+
const stB = expectedStreamType[b.profile] ?? 0;
|
|
7263
|
+
const sameChannel = a.ch === b.ch;
|
|
7264
|
+
let expectedOk;
|
|
7265
|
+
let reason;
|
|
7266
|
+
if (sameChannel && stA === stB) {
|
|
7267
|
+
expectedOk = false;
|
|
7268
|
+
reason = `same streamType (${stA}) on same channel`;
|
|
7269
|
+
} else if (!sameChannel && a.profile === b.profile) {
|
|
7270
|
+
expectedOk = false;
|
|
7271
|
+
reason = `multifocal rejects same profile (${a.profile}) across channels`;
|
|
7272
|
+
} else if (!sameChannel && stA === stB) {
|
|
7273
|
+
expectedOk = false;
|
|
7274
|
+
reason = `same streamType (${stA}) across channels`;
|
|
7275
|
+
} else {
|
|
7276
|
+
expectedOk = true;
|
|
7277
|
+
reason = `different streamTypes (${stA} vs ${stB})`;
|
|
7278
|
+
}
|
|
7279
|
+
results.push({ pair: [a.label, b.label], expectedOk, reason });
|
|
7280
|
+
}
|
|
7281
|
+
}
|
|
7282
|
+
return results;
|
|
7283
|
+
}
|
|
7284
|
+
async function captureModelFixtures(params) {
|
|
7285
|
+
const { api, channel, outDir } = params;
|
|
7286
|
+
const log = params.log ?? console.log;
|
|
7287
|
+
mkdirp(outDir);
|
|
7288
|
+
const writeJsonSafe = (filePath, data) => writeJson(filePath, sanitizeFixtureData(data));
|
|
7289
|
+
const writeTextSafe = (filePath, text) => writeText(filePath, sanitizeString(text));
|
|
7290
|
+
const calls = {};
|
|
7291
|
+
const errors = [];
|
|
7292
|
+
async function capture(name, fn, writer) {
|
|
7293
|
+
try {
|
|
7294
|
+
const value = await fn();
|
|
7295
|
+
calls[name] = { ok: true, value };
|
|
7296
|
+
if (writer && value !== void 0 && value !== null) {
|
|
7297
|
+
writer(value);
|
|
7298
|
+
}
|
|
7299
|
+
log(` \u2713 ${name}`);
|
|
7300
|
+
return value;
|
|
7301
|
+
} catch (e) {
|
|
7302
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
7303
|
+
calls[name] = { ok: false, error: msg };
|
|
7304
|
+
errors.push(`${name}: ${msg}`);
|
|
7305
|
+
log(` \u2717 ${name}: ${msg}`);
|
|
7306
|
+
return void 0;
|
|
7307
|
+
}
|
|
7308
|
+
}
|
|
7309
|
+
const info = await capture(
|
|
7310
|
+
"getInfo",
|
|
7311
|
+
() => api.getInfo(channel),
|
|
7312
|
+
(v) => writeJsonSafe(path4.join(outDir, "device-info.json"), v)
|
|
7313
|
+
);
|
|
7314
|
+
const support = await capture(
|
|
7315
|
+
"getSupportInfo",
|
|
7316
|
+
() => api.getSupportInfo(),
|
|
7317
|
+
(v) => writeJsonSafe(path4.join(outDir, "support-info.json"), v)
|
|
7318
|
+
);
|
|
7319
|
+
const abilities = await capture(
|
|
7320
|
+
"getAbilityInfo",
|
|
7321
|
+
() => api.getAbilityInfo(),
|
|
7322
|
+
(v) => writeJsonSafe(path4.join(outDir, "ability-info.json"), v)
|
|
7323
|
+
);
|
|
7324
|
+
await capture(
|
|
7325
|
+
"getDeviceCapabilities",
|
|
7326
|
+
() => api.getDeviceCapabilities(channel),
|
|
7327
|
+
(v) => writeJsonSafe(path4.join(outDir, "capabilities.json"), v)
|
|
7328
|
+
);
|
|
7329
|
+
await capture("cmd289-WhiteLed", () => api.sendXml({
|
|
7330
|
+
cmdId: BC_CMD_ID_GET_WHITE_LED,
|
|
7331
|
+
channel,
|
|
7332
|
+
timeoutMs: 3e3
|
|
7333
|
+
}), (v) => writeTextSafe(path4.join(outDir, "cmd289-white-led.xml"), v));
|
|
7334
|
+
await capture(
|
|
7335
|
+
"getStreamMetadata",
|
|
7336
|
+
() => api.getStreamMetadata(channel),
|
|
7337
|
+
(v) => writeJsonSafe(path4.join(outDir, "stream-metadata.json"), v)
|
|
7338
|
+
);
|
|
7339
|
+
await capture(
|
|
7340
|
+
"getEncXml",
|
|
7341
|
+
() => api.getEncXml(channel),
|
|
7342
|
+
(v) => writeTextSafe(path4.join(outDir, "enc-config.xml"), v)
|
|
7343
|
+
);
|
|
7344
|
+
await capture(
|
|
7345
|
+
"getPorts",
|
|
7346
|
+
() => api.getPorts(),
|
|
7347
|
+
(v) => writeJsonSafe(path4.join(outDir, "ports.json"), v)
|
|
7348
|
+
);
|
|
7349
|
+
await capture(
|
|
7350
|
+
"getTalkAbility",
|
|
7351
|
+
() => api.getTalkAbility(channel),
|
|
7352
|
+
(v) => writeJsonSafe(path4.join(outDir, "talk-ability.json"), v)
|
|
7353
|
+
);
|
|
7354
|
+
await capture(
|
|
7355
|
+
"getTwoWayAudioConfig",
|
|
7356
|
+
() => api.getTwoWayAudioConfig(channel),
|
|
7357
|
+
(v) => writeJsonSafe(path4.join(outDir, "two-way-audio-config.json"), v)
|
|
7358
|
+
);
|
|
7359
|
+
await capture(
|
|
7360
|
+
"getAiState",
|
|
7361
|
+
() => api.getAiState(channel),
|
|
7362
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-state.json"), v)
|
|
7363
|
+
);
|
|
7364
|
+
await capture(
|
|
7365
|
+
"getAiCfg",
|
|
7366
|
+
() => api.getAiCfg(channel),
|
|
7367
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-cfg.json"), v)
|
|
7368
|
+
);
|
|
7369
|
+
await capture(
|
|
7370
|
+
"getOsd",
|
|
7371
|
+
() => api.getOsd(channel),
|
|
7372
|
+
(v) => writeJsonSafe(path4.join(outDir, "osd.json"), v)
|
|
7373
|
+
);
|
|
7374
|
+
await capture(
|
|
7375
|
+
"getMotionAlarm",
|
|
7376
|
+
() => api.getMotionAlarm(channel),
|
|
7377
|
+
(v) => writeJsonSafe(path4.join(outDir, "motion-alarm.json"), v)
|
|
7378
|
+
);
|
|
7379
|
+
await capture(
|
|
7380
|
+
"getRecordCfg",
|
|
7381
|
+
() => api.getRecordCfg(channel),
|
|
7382
|
+
(v) => writeJsonSafe(path4.join(outDir, "record-cfg.json"), v)
|
|
7383
|
+
);
|
|
7384
|
+
await capture(
|
|
7385
|
+
"getVideoInput",
|
|
7386
|
+
() => api.getVideoInput(channel),
|
|
7387
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-input.json"), v)
|
|
7388
|
+
);
|
|
7389
|
+
await capture(
|
|
7390
|
+
"getPtzPresets",
|
|
7391
|
+
() => api.getPtzPresets(channel),
|
|
7392
|
+
(v) => writeJsonSafe(path4.join(outDir, "ptz-presets.json"), v)
|
|
7393
|
+
);
|
|
7394
|
+
await capture(
|
|
7395
|
+
"getNetworkInfo",
|
|
7396
|
+
() => api.getNetworkInfo(),
|
|
7397
|
+
(v) => writeJsonSafe(path4.join(outDir, "network-info.json"), v)
|
|
7398
|
+
);
|
|
7399
|
+
await capture(
|
|
7400
|
+
"getSystemGeneral",
|
|
7401
|
+
() => api.getSystemGeneral(),
|
|
7402
|
+
(v) => writeJsonSafe(path4.join(outDir, "system-general.json"), v)
|
|
7403
|
+
);
|
|
7404
|
+
await capture(
|
|
7405
|
+
"getWifiSignal",
|
|
7406
|
+
() => api.getWifiSignal(channel),
|
|
7407
|
+
(v) => writeJsonSafe(path4.join(outDir, "wifi-signal.json"), v)
|
|
7408
|
+
);
|
|
7409
|
+
await capture(
|
|
7410
|
+
"getWhiteLedState",
|
|
7411
|
+
() => api.getWhiteLedState(channel),
|
|
7412
|
+
(v) => writeJsonSafe(path4.join(outDir, "white-led-state.json"), v)
|
|
7413
|
+
);
|
|
7414
|
+
await capture(
|
|
7415
|
+
"getFloodlightOnMotion",
|
|
7416
|
+
() => api.getFloodlightOnMotion(channel),
|
|
7417
|
+
(v) => writeJsonSafe(path4.join(outDir, "floodlight-on-motion.json"), v)
|
|
7418
|
+
);
|
|
7419
|
+
await capture(
|
|
7420
|
+
"buildVideoStreamOptions",
|
|
7421
|
+
() => api.buildVideoStreamOptions({ channel }),
|
|
7422
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-stream-options.json"), v)
|
|
7423
|
+
);
|
|
7424
|
+
await capture(
|
|
7425
|
+
"getDualLensChannelInfo",
|
|
7426
|
+
() => api.getDualLensChannelInfo(channel),
|
|
7427
|
+
(v) => writeJsonSafe(path4.join(outDir, "dual-lens-info.json"), v)
|
|
7428
|
+
);
|
|
7429
|
+
await capture("streamCombinationTest", async () => {
|
|
7430
|
+
let dualLensInfo;
|
|
7431
|
+
try {
|
|
7432
|
+
dualLensInfo = await api.getDualLensChannelInfo(channel);
|
|
7433
|
+
} catch {
|
|
7434
|
+
}
|
|
7435
|
+
const isMultifocal = dualLensInfo?.isDualLens === true;
|
|
7436
|
+
const channelCount = dualLensInfo?.streamChannelCount ?? 1;
|
|
7437
|
+
const allStreams = [];
|
|
7438
|
+
const profiles = ["main", "sub", "ext"];
|
|
7439
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
7440
|
+
for (const p of profiles) {
|
|
7441
|
+
const label = channelCount > 1 ? `ch${ch}_${p}` : p;
|
|
7442
|
+
allStreams.push({ ch, profile: p, label });
|
|
7443
|
+
}
|
|
7444
|
+
}
|
|
7445
|
+
const pairs = [];
|
|
7446
|
+
for (let i = 0; i < allStreams.length; i++) {
|
|
7447
|
+
for (let j = i + 1; j < allStreams.length; j++) {
|
|
7448
|
+
pairs.push([allStreams[i], allStreams[j]]);
|
|
7449
|
+
}
|
|
7450
|
+
}
|
|
7451
|
+
const expectedStreamType = { main: 0, sub: 1, ext: 0 };
|
|
7452
|
+
const expectedCompat = [];
|
|
7453
|
+
for (const [a, b] of pairs) {
|
|
7454
|
+
const stA = expectedStreamType[a.profile];
|
|
7455
|
+
const stB = expectedStreamType[b.profile];
|
|
7456
|
+
const sameChannel = a.ch === b.ch;
|
|
7457
|
+
let expectedOk;
|
|
7458
|
+
let reason;
|
|
7459
|
+
if (sameChannel && stA === stB) {
|
|
7460
|
+
expectedOk = false;
|
|
7461
|
+
reason = `same streamType (${stA}) on same channel`;
|
|
7462
|
+
} else if (!sameChannel && a.profile === b.profile) {
|
|
7463
|
+
expectedOk = false;
|
|
7464
|
+
reason = `multifocal rejects same profile (${a.profile}) across channels`;
|
|
7465
|
+
} else if (!sameChannel && stA === stB) {
|
|
7466
|
+
expectedOk = false;
|
|
7467
|
+
reason = `same streamType (${stA}) across channels`;
|
|
7468
|
+
} else {
|
|
7469
|
+
expectedOk = true;
|
|
7470
|
+
reason = `different streamTypes (${stA} vs ${stB})`;
|
|
7471
|
+
}
|
|
7472
|
+
expectedCompat.push({ pair: [a.label, b.label], expectedOk, reason });
|
|
7473
|
+
}
|
|
7474
|
+
const results = [];
|
|
7475
|
+
const TEST_DURATION_MS = 4e3;
|
|
7476
|
+
for (let pairIdx = 0; pairIdx < pairs.length; pairIdx++) {
|
|
7477
|
+
const [a, b] = pairs[pairIdx];
|
|
7478
|
+
const expected = expectedCompat[pairIdx];
|
|
7479
|
+
log(` testing ${a.label}+${b.label} on shared socket...`);
|
|
7480
|
+
let session;
|
|
7481
|
+
try {
|
|
7482
|
+
session = await api.createDedicatedSession(
|
|
7483
|
+
`test:combo:${a.label}_${b.label}`
|
|
7484
|
+
);
|
|
7485
|
+
} catch (e) {
|
|
7486
|
+
const result2 = {
|
|
7487
|
+
pair: [a.label, b.label],
|
|
7488
|
+
ok: false,
|
|
7489
|
+
framesA: 0,
|
|
7490
|
+
framesB: 0,
|
|
7491
|
+
mismatches: 0,
|
|
7492
|
+
error: `session: ${e instanceof Error ? e.message : String(e)}`,
|
|
7493
|
+
durationMs: 0,
|
|
7494
|
+
expectedOk: expected.expectedOk,
|
|
7495
|
+
expectedReason: expected.reason,
|
|
7496
|
+
matchesExpected: !expected.expectedOk
|
|
7497
|
+
// failed as expected if we expected failure
|
|
7498
|
+
};
|
|
7499
|
+
results.push(result2);
|
|
7500
|
+
continue;
|
|
7501
|
+
}
|
|
7502
|
+
const testClient = session.client;
|
|
7503
|
+
let framesA = 0;
|
|
7504
|
+
let framesB = 0;
|
|
7505
|
+
let mismatches = 0;
|
|
7506
|
+
const start = Date.now();
|
|
7507
|
+
const stTypes = {
|
|
7508
|
+
main: /* @__PURE__ */ new Set([0, 2]),
|
|
7509
|
+
sub: /* @__PURE__ */ new Set([1, 3]),
|
|
7510
|
+
ext: /* @__PURE__ */ new Set([0, 2])
|
|
7511
|
+
};
|
|
7512
|
+
const setA = stTypes[a.profile];
|
|
7513
|
+
const setB = stTypes[b.profile];
|
|
7514
|
+
const onFrame = (frame) => {
|
|
7515
|
+
if (frame.header?.cmdId !== BC_CMD_ID_VIDEO) return;
|
|
7516
|
+
const st = frame.header.streamType;
|
|
7517
|
+
if (setA.has(st)) framesA++;
|
|
7518
|
+
else if (setB.has(st)) framesB++;
|
|
7519
|
+
else mismatches++;
|
|
7520
|
+
};
|
|
7521
|
+
testClient.on("frame", onFrame);
|
|
7522
|
+
let error;
|
|
7523
|
+
try {
|
|
7524
|
+
await api.startVideoStream(a.ch, a.profile, { client: testClient });
|
|
7525
|
+
await api.startVideoStream(b.ch, b.profile, { client: testClient });
|
|
7526
|
+
await new Promise((r) => setTimeout(r, TEST_DURATION_MS));
|
|
7527
|
+
await api.stopVideoStream(a.ch, a.profile, { client: testClient }).catch(() => {
|
|
7528
|
+
});
|
|
7529
|
+
await api.stopVideoStream(b.ch, b.profile, { client: testClient }).catch(() => {
|
|
7530
|
+
});
|
|
7531
|
+
} catch (e) {
|
|
7532
|
+
error = e instanceof Error ? e.message : String(e);
|
|
7533
|
+
} finally {
|
|
7534
|
+
testClient.removeListener("frame", onFrame);
|
|
7535
|
+
await session.release().catch(() => {
|
|
7536
|
+
});
|
|
7537
|
+
}
|
|
7538
|
+
const elapsed = Date.now() - start;
|
|
7539
|
+
const ok2 = !error && framesA > 0 && framesB > 0 && mismatches === 0;
|
|
7540
|
+
const result = {
|
|
7541
|
+
pair: [a.label, b.label],
|
|
7542
|
+
ok: ok2,
|
|
7543
|
+
framesA,
|
|
7544
|
+
framesB,
|
|
7545
|
+
mismatches,
|
|
7546
|
+
...error ? { error } : {},
|
|
7547
|
+
durationMs: elapsed,
|
|
7548
|
+
expectedOk: expected.expectedOk,
|
|
7549
|
+
expectedReason: expected.reason,
|
|
7550
|
+
matchesExpected: ok2 === expected.expectedOk
|
|
7551
|
+
};
|
|
7552
|
+
results.push(result);
|
|
7553
|
+
const matchStr = result.matchesExpected ? "" : " *** UNEXPECTED ***";
|
|
7554
|
+
log(` ${a.label}+${b.label}: ${ok2 ? "OK" : "FAIL"} (expected=${expected.expectedOk ? "OK" : "FAIL"}) A=${framesA} B=${framesB} mismatch=${mismatches}${matchStr}`);
|
|
7555
|
+
}
|
|
7556
|
+
const unexpected = results.filter((r) => !r.matchesExpected);
|
|
7557
|
+
return {
|
|
7558
|
+
isMultifocal,
|
|
7559
|
+
channelCount,
|
|
7560
|
+
results,
|
|
7561
|
+
summary: {
|
|
7562
|
+
total: results.length,
|
|
7563
|
+
ok: results.filter((r) => r.ok).length,
|
|
7564
|
+
failed: results.filter((r) => !r.ok).length,
|
|
7565
|
+
matchesExpected: results.filter((r) => r.matchesExpected).length,
|
|
7566
|
+
unexpected: unexpected.map((r) => `${r.pair[0]}+${r.pair[1]}: got ${r.ok ? "OK" : "FAIL"}, expected ${r.expectedOk ? "OK" : "FAIL"}`)
|
|
7567
|
+
}
|
|
7568
|
+
};
|
|
7569
|
+
}, (v) => writeJsonSafe(path4.join(outDir, "stream-combination-test.json"), v));
|
|
7570
|
+
const total = Object.keys(calls).length;
|
|
7571
|
+
const ok = Object.values(calls).filter((c) => c.ok).length;
|
|
7572
|
+
const failed = total - ok;
|
|
7573
|
+
const summary = { total, ok, failed, errors };
|
|
7574
|
+
writeJsonSafe(path4.join(outDir, "_summary.json"), {
|
|
7575
|
+
collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7576
|
+
model: info?.type ?? "unknown",
|
|
7577
|
+
itemNo: info?.itemNo ?? "unknown",
|
|
7578
|
+
firmwareVersion: info?.firmwareVersion ?? "unknown",
|
|
7579
|
+
channel,
|
|
7580
|
+
...summary,
|
|
7581
|
+
calls: Object.fromEntries(
|
|
7582
|
+
Object.entries(calls).map(([k, v]) => [
|
|
7583
|
+
k,
|
|
7584
|
+
v.ok ? "ok" : `FAILED: ${v.error}`
|
|
7585
|
+
])
|
|
7586
|
+
)
|
|
7587
|
+
});
|
|
7588
|
+
log(`
|
|
7589
|
+
Summary: ${ok}/${total} ok, ${failed} failed`);
|
|
7590
|
+
if (errors.length) {
|
|
7591
|
+
log(` Errors:`);
|
|
7592
|
+
for (const err of errors) {
|
|
7593
|
+
log(` - ${err}`);
|
|
7594
|
+
}
|
|
7595
|
+
}
|
|
7596
|
+
return { calls, outDir, summary };
|
|
7597
|
+
}
|
|
7169
7598
|
|
|
7170
7599
|
export {
|
|
7171
7600
|
__require,
|
|
@@ -7348,7 +7777,10 @@ export {
|
|
|
7348
7777
|
collectMultifocalDiagnostics,
|
|
7349
7778
|
runMultifocalDiagnosticsConsecutively,
|
|
7350
7779
|
runAllDiagnosticsConsecutively,
|
|
7780
|
+
sanitizeFixtureData,
|
|
7781
|
+
computeExpectedStreamCompatibility,
|
|
7782
|
+
captureModelFixtures,
|
|
7351
7783
|
parseRecordingFileName,
|
|
7352
7784
|
ReolinkCgiApi
|
|
7353
7785
|
};
|
|
7354
|
-
//# sourceMappingURL=chunk-
|
|
7786
|
+
//# sourceMappingURL=chunk-DUHWTZ7U.js.map
|