@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.cjs
CHANGED
|
@@ -4917,11 +4917,13 @@ __export(DiagnosticsTools_exports, {
|
|
|
4917
4917
|
collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
|
|
4918
4918
|
collectNativeDiagnostics: () => collectNativeDiagnostics,
|
|
4919
4919
|
collectNvrDiagnostics: () => collectNvrDiagnostics,
|
|
4920
|
+
computeExpectedStreamCompatibility: () => computeExpectedStreamCompatibility,
|
|
4920
4921
|
createDiagnosticsBundle: () => createDiagnosticsBundle,
|
|
4921
4922
|
printNvrDiagnostics: () => printNvrDiagnostics,
|
|
4922
4923
|
runAllDiagnosticsConsecutively: () => runAllDiagnosticsConsecutively,
|
|
4923
4924
|
runMultifocalDiagnosticsConsecutively: () => runMultifocalDiagnosticsConsecutively,
|
|
4924
4925
|
sampleStreams: () => sampleStreams,
|
|
4926
|
+
sanitizeFixtureData: () => sanitizeFixtureData,
|
|
4925
4927
|
testChannelStreams: () => testChannelStreams
|
|
4926
4928
|
});
|
|
4927
4929
|
function safeStringifyError(error) {
|
|
@@ -7213,10 +7215,102 @@ async function runAllDiagnosticsConsecutively(params) {
|
|
|
7213
7215
|
streamsDir
|
|
7214
7216
|
};
|
|
7215
7217
|
}
|
|
7218
|
+
function maskIp(ip) {
|
|
7219
|
+
const parts = ip.split(".");
|
|
7220
|
+
return `${parts[0]}.***.***.***`;
|
|
7221
|
+
}
|
|
7222
|
+
function maskMac(mac) {
|
|
7223
|
+
const sep = mac.includes("-") ? "-" : ":";
|
|
7224
|
+
const parts = mac.split(/[:-]/);
|
|
7225
|
+
return `${parts[0]}${sep}${parts[1]}${sep}**${sep}**${sep}**${sep}**`;
|
|
7226
|
+
}
|
|
7227
|
+
function maskSerial(val) {
|
|
7228
|
+
if (val.length <= 4) return "****";
|
|
7229
|
+
return val.slice(0, 2) + "*".repeat(val.length - 4) + val.slice(-2);
|
|
7230
|
+
}
|
|
7231
|
+
function sanitizeString(s) {
|
|
7232
|
+
let out = s;
|
|
7233
|
+
out = out.replace(/:\/\/([^:@]+):([^@]+)@/g, "://***:***@");
|
|
7234
|
+
out = out.replace(/(password=)[^&\s]*/gi, "$1***");
|
|
7235
|
+
out = out.replace(/(user=)[^&\s]*/gi, "$1***");
|
|
7236
|
+
out = out.replace(IPV4_RE, (match) => maskIp(match));
|
|
7237
|
+
out = out.replace(MAC_RE, (match) => maskMac(match));
|
|
7238
|
+
return out;
|
|
7239
|
+
}
|
|
7240
|
+
function sanitizeFixtureData(value) {
|
|
7241
|
+
if (value === null || value === void 0) return value;
|
|
7242
|
+
if (typeof value === "string") {
|
|
7243
|
+
return sanitizeString(value);
|
|
7244
|
+
}
|
|
7245
|
+
if (Array.isArray(value)) {
|
|
7246
|
+
return value.map(sanitizeFixtureData);
|
|
7247
|
+
}
|
|
7248
|
+
if (typeof value === "object") {
|
|
7249
|
+
const out = {};
|
|
7250
|
+
for (const [k, v] of Object.entries(value)) {
|
|
7251
|
+
const kLower = k.toLowerCase();
|
|
7252
|
+
if (REDACT_KEYS.has(kLower)) {
|
|
7253
|
+
out[k] = "***";
|
|
7254
|
+
} else if (MASK_KEYS.has(kLower) || kLower === "serialnumber") {
|
|
7255
|
+
out[k] = typeof v === "string" ? maskSerial(v) : "***";
|
|
7256
|
+
} else if (kLower === "mac") {
|
|
7257
|
+
out[k] = typeof v === "string" ? maskMac(v) : "***";
|
|
7258
|
+
} else if (kLower === "ip" || kLower === "ipaddress" || kLower === "host") {
|
|
7259
|
+
out[k] = typeof v === "string" ? maskIp(v) : v;
|
|
7260
|
+
} else if (kLower === "name" && typeof v === "string" && k !== "name") {
|
|
7261
|
+
out[k] = v;
|
|
7262
|
+
} else {
|
|
7263
|
+
out[k] = sanitizeFixtureData(v);
|
|
7264
|
+
}
|
|
7265
|
+
}
|
|
7266
|
+
return out;
|
|
7267
|
+
}
|
|
7268
|
+
return value;
|
|
7269
|
+
}
|
|
7270
|
+
function computeExpectedStreamCompatibility(params) {
|
|
7271
|
+
const { channelCount } = params;
|
|
7272
|
+
const profiles = params.profiles ?? ["main", "sub", "ext"];
|
|
7273
|
+
const expectedStreamType = { main: 0, sub: 1, ext: 0 };
|
|
7274
|
+
const allStreams = [];
|
|
7275
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
7276
|
+
for (const p of profiles) {
|
|
7277
|
+
allStreams.push({ ch, profile: p, label: channelCount > 1 ? `ch${ch}_${p}` : p });
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
const results = [];
|
|
7281
|
+
for (let i = 0; i < allStreams.length; i++) {
|
|
7282
|
+
for (let j = i + 1; j < allStreams.length; j++) {
|
|
7283
|
+
const a = allStreams[i];
|
|
7284
|
+
const b = allStreams[j];
|
|
7285
|
+
const stA = expectedStreamType[a.profile] ?? 0;
|
|
7286
|
+
const stB = expectedStreamType[b.profile] ?? 0;
|
|
7287
|
+
const sameChannel = a.ch === b.ch;
|
|
7288
|
+
let expectedOk;
|
|
7289
|
+
let reason;
|
|
7290
|
+
if (sameChannel && stA === stB) {
|
|
7291
|
+
expectedOk = false;
|
|
7292
|
+
reason = `same streamType (${stA}) on same channel`;
|
|
7293
|
+
} else if (!sameChannel && a.profile === b.profile) {
|
|
7294
|
+
expectedOk = false;
|
|
7295
|
+
reason = `multifocal rejects same profile (${a.profile}) across channels`;
|
|
7296
|
+
} else if (!sameChannel && stA === stB) {
|
|
7297
|
+
expectedOk = false;
|
|
7298
|
+
reason = `same streamType (${stA}) across channels`;
|
|
7299
|
+
} else {
|
|
7300
|
+
expectedOk = true;
|
|
7301
|
+
reason = `different streamTypes (${stA} vs ${stB})`;
|
|
7302
|
+
}
|
|
7303
|
+
results.push({ pair: [a.label, b.label], expectedOk, reason });
|
|
7304
|
+
}
|
|
7305
|
+
}
|
|
7306
|
+
return results;
|
|
7307
|
+
}
|
|
7216
7308
|
async function captureModelFixtures(params) {
|
|
7217
7309
|
const { api, channel, outDir } = params;
|
|
7218
7310
|
const log = params.log ?? console.log;
|
|
7219
7311
|
mkdirp(outDir);
|
|
7312
|
+
const writeJsonSafe = (filePath, data) => writeJson(filePath, sanitizeFixtureData(data));
|
|
7313
|
+
const writeTextSafe = (filePath, text) => writeText(filePath, sanitizeString(text));
|
|
7220
7314
|
const calls = {};
|
|
7221
7315
|
const errors = [];
|
|
7222
7316
|
async function capture(name, fn, writer) {
|
|
@@ -7239,123 +7333,269 @@ async function captureModelFixtures(params) {
|
|
|
7239
7333
|
const info = await capture(
|
|
7240
7334
|
"getInfo",
|
|
7241
7335
|
() => api.getInfo(channel),
|
|
7242
|
-
(v) =>
|
|
7336
|
+
(v) => writeJsonSafe(path4.join(outDir, "device-info.json"), v)
|
|
7243
7337
|
);
|
|
7244
7338
|
const support = await capture(
|
|
7245
7339
|
"getSupportInfo",
|
|
7246
7340
|
() => api.getSupportInfo(),
|
|
7247
|
-
(v) =>
|
|
7341
|
+
(v) => writeJsonSafe(path4.join(outDir, "support-info.json"), v)
|
|
7248
7342
|
);
|
|
7249
7343
|
const abilities = await capture(
|
|
7250
7344
|
"getAbilityInfo",
|
|
7251
7345
|
() => api.getAbilityInfo(),
|
|
7252
|
-
(v) =>
|
|
7346
|
+
(v) => writeJsonSafe(path4.join(outDir, "ability-info.json"), v)
|
|
7253
7347
|
);
|
|
7254
7348
|
await capture(
|
|
7255
7349
|
"getDeviceCapabilities",
|
|
7256
7350
|
() => api.getDeviceCapabilities(channel),
|
|
7257
|
-
(v) =>
|
|
7351
|
+
(v) => writeJsonSafe(path4.join(outDir, "capabilities.json"), v)
|
|
7258
7352
|
);
|
|
7259
7353
|
await capture("cmd289-WhiteLed", () => api.sendXml({
|
|
7260
7354
|
cmdId: BC_CMD_ID_GET_WHITE_LED,
|
|
7261
7355
|
channel,
|
|
7262
7356
|
timeoutMs: 3e3
|
|
7263
|
-
}), (v) =>
|
|
7357
|
+
}), (v) => writeTextSafe(path4.join(outDir, "cmd289-white-led.xml"), v));
|
|
7264
7358
|
await capture(
|
|
7265
7359
|
"getStreamMetadata",
|
|
7266
7360
|
() => api.getStreamMetadata(channel),
|
|
7267
|
-
(v) =>
|
|
7361
|
+
(v) => writeJsonSafe(path4.join(outDir, "stream-metadata.json"), v)
|
|
7268
7362
|
);
|
|
7269
7363
|
await capture(
|
|
7270
7364
|
"getEncXml",
|
|
7271
7365
|
() => api.getEncXml(channel),
|
|
7272
|
-
(v) =>
|
|
7366
|
+
(v) => writeTextSafe(path4.join(outDir, "enc-config.xml"), v)
|
|
7273
7367
|
);
|
|
7274
7368
|
await capture(
|
|
7275
7369
|
"getPorts",
|
|
7276
7370
|
() => api.getPorts(),
|
|
7277
|
-
(v) =>
|
|
7371
|
+
(v) => writeJsonSafe(path4.join(outDir, "ports.json"), v)
|
|
7278
7372
|
);
|
|
7279
7373
|
await capture(
|
|
7280
7374
|
"getTalkAbility",
|
|
7281
7375
|
() => api.getTalkAbility(channel),
|
|
7282
|
-
(v) =>
|
|
7376
|
+
(v) => writeJsonSafe(path4.join(outDir, "talk-ability.json"), v)
|
|
7283
7377
|
);
|
|
7284
7378
|
await capture(
|
|
7285
7379
|
"getTwoWayAudioConfig",
|
|
7286
7380
|
() => api.getTwoWayAudioConfig(channel),
|
|
7287
|
-
(v) =>
|
|
7381
|
+
(v) => writeJsonSafe(path4.join(outDir, "two-way-audio-config.json"), v)
|
|
7288
7382
|
);
|
|
7289
7383
|
await capture(
|
|
7290
7384
|
"getAiState",
|
|
7291
7385
|
() => api.getAiState(channel),
|
|
7292
|
-
(v) =>
|
|
7386
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-state.json"), v)
|
|
7293
7387
|
);
|
|
7294
7388
|
await capture(
|
|
7295
7389
|
"getAiCfg",
|
|
7296
7390
|
() => api.getAiCfg(channel),
|
|
7297
|
-
(v) =>
|
|
7391
|
+
(v) => writeJsonSafe(path4.join(outDir, "ai-cfg.json"), v)
|
|
7298
7392
|
);
|
|
7299
7393
|
await capture(
|
|
7300
7394
|
"getOsd",
|
|
7301
7395
|
() => api.getOsd(channel),
|
|
7302
|
-
(v) =>
|
|
7396
|
+
(v) => writeJsonSafe(path4.join(outDir, "osd.json"), v)
|
|
7303
7397
|
);
|
|
7304
7398
|
await capture(
|
|
7305
7399
|
"getMotionAlarm",
|
|
7306
7400
|
() => api.getMotionAlarm(channel),
|
|
7307
|
-
(v) =>
|
|
7401
|
+
(v) => writeJsonSafe(path4.join(outDir, "motion-alarm.json"), v)
|
|
7308
7402
|
);
|
|
7309
7403
|
await capture(
|
|
7310
7404
|
"getRecordCfg",
|
|
7311
7405
|
() => api.getRecordCfg(channel),
|
|
7312
|
-
(v) =>
|
|
7406
|
+
(v) => writeJsonSafe(path4.join(outDir, "record-cfg.json"), v)
|
|
7313
7407
|
);
|
|
7314
7408
|
await capture(
|
|
7315
7409
|
"getVideoInput",
|
|
7316
7410
|
() => api.getVideoInput(channel),
|
|
7317
|
-
(v) =>
|
|
7411
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-input.json"), v)
|
|
7318
7412
|
);
|
|
7319
7413
|
await capture(
|
|
7320
7414
|
"getPtzPresets",
|
|
7321
7415
|
() => api.getPtzPresets(channel),
|
|
7322
|
-
(v) =>
|
|
7416
|
+
(v) => writeJsonSafe(path4.join(outDir, "ptz-presets.json"), v)
|
|
7323
7417
|
);
|
|
7324
7418
|
await capture(
|
|
7325
7419
|
"getNetworkInfo",
|
|
7326
7420
|
() => api.getNetworkInfo(),
|
|
7327
|
-
(v) =>
|
|
7421
|
+
(v) => writeJsonSafe(path4.join(outDir, "network-info.json"), v)
|
|
7328
7422
|
);
|
|
7329
7423
|
await capture(
|
|
7330
7424
|
"getSystemGeneral",
|
|
7331
7425
|
() => api.getSystemGeneral(),
|
|
7332
|
-
(v) =>
|
|
7426
|
+
(v) => writeJsonSafe(path4.join(outDir, "system-general.json"), v)
|
|
7333
7427
|
);
|
|
7334
7428
|
await capture(
|
|
7335
7429
|
"getWifiSignal",
|
|
7336
7430
|
() => api.getWifiSignal(channel),
|
|
7337
|
-
(v) =>
|
|
7431
|
+
(v) => writeJsonSafe(path4.join(outDir, "wifi-signal.json"), v)
|
|
7338
7432
|
);
|
|
7339
7433
|
await capture(
|
|
7340
7434
|
"getWhiteLedState",
|
|
7341
7435
|
() => api.getWhiteLedState(channel),
|
|
7342
|
-
(v) =>
|
|
7436
|
+
(v) => writeJsonSafe(path4.join(outDir, "white-led-state.json"), v)
|
|
7343
7437
|
);
|
|
7344
7438
|
await capture(
|
|
7345
7439
|
"getFloodlightOnMotion",
|
|
7346
7440
|
() => api.getFloodlightOnMotion(channel),
|
|
7347
|
-
(v) =>
|
|
7441
|
+
(v) => writeJsonSafe(path4.join(outDir, "floodlight-on-motion.json"), v)
|
|
7348
7442
|
);
|
|
7349
7443
|
await capture(
|
|
7350
7444
|
"buildVideoStreamOptions",
|
|
7351
7445
|
() => api.buildVideoStreamOptions({ channel }),
|
|
7352
|
-
(v) =>
|
|
7446
|
+
(v) => writeJsonSafe(path4.join(outDir, "video-stream-options.json"), v)
|
|
7353
7447
|
);
|
|
7448
|
+
await capture(
|
|
7449
|
+
"getDualLensChannelInfo",
|
|
7450
|
+
() => api.getDualLensChannelInfo(channel),
|
|
7451
|
+
(v) => writeJsonSafe(path4.join(outDir, "dual-lens-info.json"), v)
|
|
7452
|
+
);
|
|
7453
|
+
await capture("streamCombinationTest", async () => {
|
|
7454
|
+
let dualLensInfo;
|
|
7455
|
+
try {
|
|
7456
|
+
dualLensInfo = await api.getDualLensChannelInfo(channel);
|
|
7457
|
+
} catch {
|
|
7458
|
+
}
|
|
7459
|
+
const isMultifocal = dualLensInfo?.isDualLens === true;
|
|
7460
|
+
const channelCount = dualLensInfo?.streamChannelCount ?? 1;
|
|
7461
|
+
const allStreams = [];
|
|
7462
|
+
const profiles = ["main", "sub", "ext"];
|
|
7463
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
7464
|
+
for (const p of profiles) {
|
|
7465
|
+
const label = channelCount > 1 ? `ch${ch}_${p}` : p;
|
|
7466
|
+
allStreams.push({ ch, profile: p, label });
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
7469
|
+
const pairs = [];
|
|
7470
|
+
for (let i = 0; i < allStreams.length; i++) {
|
|
7471
|
+
for (let j = i + 1; j < allStreams.length; j++) {
|
|
7472
|
+
pairs.push([allStreams[i], allStreams[j]]);
|
|
7473
|
+
}
|
|
7474
|
+
}
|
|
7475
|
+
const expectedStreamType = { main: 0, sub: 1, ext: 0 };
|
|
7476
|
+
const expectedCompat = [];
|
|
7477
|
+
for (const [a, b] of pairs) {
|
|
7478
|
+
const stA = expectedStreamType[a.profile];
|
|
7479
|
+
const stB = expectedStreamType[b.profile];
|
|
7480
|
+
const sameChannel = a.ch === b.ch;
|
|
7481
|
+
let expectedOk;
|
|
7482
|
+
let reason;
|
|
7483
|
+
if (sameChannel && stA === stB) {
|
|
7484
|
+
expectedOk = false;
|
|
7485
|
+
reason = `same streamType (${stA}) on same channel`;
|
|
7486
|
+
} else if (!sameChannel && a.profile === b.profile) {
|
|
7487
|
+
expectedOk = false;
|
|
7488
|
+
reason = `multifocal rejects same profile (${a.profile}) across channels`;
|
|
7489
|
+
} else if (!sameChannel && stA === stB) {
|
|
7490
|
+
expectedOk = false;
|
|
7491
|
+
reason = `same streamType (${stA}) across channels`;
|
|
7492
|
+
} else {
|
|
7493
|
+
expectedOk = true;
|
|
7494
|
+
reason = `different streamTypes (${stA} vs ${stB})`;
|
|
7495
|
+
}
|
|
7496
|
+
expectedCompat.push({ pair: [a.label, b.label], expectedOk, reason });
|
|
7497
|
+
}
|
|
7498
|
+
const results = [];
|
|
7499
|
+
const TEST_DURATION_MS = 4e3;
|
|
7500
|
+
for (let pairIdx = 0; pairIdx < pairs.length; pairIdx++) {
|
|
7501
|
+
const [a, b] = pairs[pairIdx];
|
|
7502
|
+
const expected = expectedCompat[pairIdx];
|
|
7503
|
+
log(` testing ${a.label}+${b.label} on shared socket...`);
|
|
7504
|
+
let session;
|
|
7505
|
+
try {
|
|
7506
|
+
session = await api.createDedicatedSession(
|
|
7507
|
+
`test:combo:${a.label}_${b.label}`
|
|
7508
|
+
);
|
|
7509
|
+
} catch (e) {
|
|
7510
|
+
const result2 = {
|
|
7511
|
+
pair: [a.label, b.label],
|
|
7512
|
+
ok: false,
|
|
7513
|
+
framesA: 0,
|
|
7514
|
+
framesB: 0,
|
|
7515
|
+
mismatches: 0,
|
|
7516
|
+
error: `session: ${e instanceof Error ? e.message : String(e)}`,
|
|
7517
|
+
durationMs: 0,
|
|
7518
|
+
expectedOk: expected.expectedOk,
|
|
7519
|
+
expectedReason: expected.reason,
|
|
7520
|
+
matchesExpected: !expected.expectedOk
|
|
7521
|
+
// failed as expected if we expected failure
|
|
7522
|
+
};
|
|
7523
|
+
results.push(result2);
|
|
7524
|
+
continue;
|
|
7525
|
+
}
|
|
7526
|
+
const testClient = session.client;
|
|
7527
|
+
let framesA = 0;
|
|
7528
|
+
let framesB = 0;
|
|
7529
|
+
let mismatches = 0;
|
|
7530
|
+
const start = Date.now();
|
|
7531
|
+
const stTypes = {
|
|
7532
|
+
main: /* @__PURE__ */ new Set([0, 2]),
|
|
7533
|
+
sub: /* @__PURE__ */ new Set([1, 3]),
|
|
7534
|
+
ext: /* @__PURE__ */ new Set([0, 2])
|
|
7535
|
+
};
|
|
7536
|
+
const setA = stTypes[a.profile];
|
|
7537
|
+
const setB = stTypes[b.profile];
|
|
7538
|
+
const onFrame = (frame) => {
|
|
7539
|
+
if (frame.header?.cmdId !== BC_CMD_ID_VIDEO) return;
|
|
7540
|
+
const st = frame.header.streamType;
|
|
7541
|
+
if (setA.has(st)) framesA++;
|
|
7542
|
+
else if (setB.has(st)) framesB++;
|
|
7543
|
+
else mismatches++;
|
|
7544
|
+
};
|
|
7545
|
+
testClient.on("frame", onFrame);
|
|
7546
|
+
let error;
|
|
7547
|
+
try {
|
|
7548
|
+
await api.startVideoStream(a.ch, a.profile, { client: testClient });
|
|
7549
|
+
await api.startVideoStream(b.ch, b.profile, { client: testClient });
|
|
7550
|
+
await new Promise((r) => setTimeout(r, TEST_DURATION_MS));
|
|
7551
|
+
await api.stopVideoStream(a.ch, a.profile, { client: testClient }).catch(() => {
|
|
7552
|
+
});
|
|
7553
|
+
await api.stopVideoStream(b.ch, b.profile, { client: testClient }).catch(() => {
|
|
7554
|
+
});
|
|
7555
|
+
} catch (e) {
|
|
7556
|
+
error = e instanceof Error ? e.message : String(e);
|
|
7557
|
+
} finally {
|
|
7558
|
+
testClient.removeListener("frame", onFrame);
|
|
7559
|
+
await session.release().catch(() => {
|
|
7560
|
+
});
|
|
7561
|
+
}
|
|
7562
|
+
const elapsed = Date.now() - start;
|
|
7563
|
+
const ok2 = !error && framesA > 0 && framesB > 0 && mismatches === 0;
|
|
7564
|
+
const result = {
|
|
7565
|
+
pair: [a.label, b.label],
|
|
7566
|
+
ok: ok2,
|
|
7567
|
+
framesA,
|
|
7568
|
+
framesB,
|
|
7569
|
+
mismatches,
|
|
7570
|
+
...error ? { error } : {},
|
|
7571
|
+
durationMs: elapsed,
|
|
7572
|
+
expectedOk: expected.expectedOk,
|
|
7573
|
+
expectedReason: expected.reason,
|
|
7574
|
+
matchesExpected: ok2 === expected.expectedOk
|
|
7575
|
+
};
|
|
7576
|
+
results.push(result);
|
|
7577
|
+
const matchStr = result.matchesExpected ? "" : " *** UNEXPECTED ***";
|
|
7578
|
+
log(` ${a.label}+${b.label}: ${ok2 ? "OK" : "FAIL"} (expected=${expected.expectedOk ? "OK" : "FAIL"}) A=${framesA} B=${framesB} mismatch=${mismatches}${matchStr}`);
|
|
7579
|
+
}
|
|
7580
|
+
const unexpected = results.filter((r) => !r.matchesExpected);
|
|
7581
|
+
return {
|
|
7582
|
+
isMultifocal,
|
|
7583
|
+
channelCount,
|
|
7584
|
+
results,
|
|
7585
|
+
summary: {
|
|
7586
|
+
total: results.length,
|
|
7587
|
+
ok: results.filter((r) => r.ok).length,
|
|
7588
|
+
failed: results.filter((r) => !r.ok).length,
|
|
7589
|
+
matchesExpected: results.filter((r) => r.matchesExpected).length,
|
|
7590
|
+
unexpected: unexpected.map((r) => `${r.pair[0]}+${r.pair[1]}: got ${r.ok ? "OK" : "FAIL"}, expected ${r.expectedOk ? "OK" : "FAIL"}`)
|
|
7591
|
+
}
|
|
7592
|
+
};
|
|
7593
|
+
}, (v) => writeJsonSafe(path4.join(outDir, "stream-combination-test.json"), v));
|
|
7354
7594
|
const total = Object.keys(calls).length;
|
|
7355
7595
|
const ok = Object.values(calls).filter((c) => c.ok).length;
|
|
7356
7596
|
const failed = total - ok;
|
|
7357
7597
|
const summary = { total, ok, failed, errors };
|
|
7358
|
-
|
|
7598
|
+
writeJsonSafe(path4.join(outDir, "_summary.json"), {
|
|
7359
7599
|
collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7360
7600
|
model: info?.type ?? "unknown",
|
|
7361
7601
|
itemNo: info?.itemNo ?? "unknown",
|
|
@@ -7379,7 +7619,7 @@ async function captureModelFixtures(params) {
|
|
|
7379
7619
|
}
|
|
7380
7620
|
return { calls, outDir, summary };
|
|
7381
7621
|
}
|
|
7382
|
-
var fs4, path4, import_node_child_process2, import_node_path;
|
|
7622
|
+
var fs4, path4, import_node_child_process2, import_node_path, REDACT_KEYS, MASK_KEYS, IPV4_RE, MAC_RE;
|
|
7383
7623
|
var init_DiagnosticsTools = __esm({
|
|
7384
7624
|
"src/debug/DiagnosticsTools.ts"() {
|
|
7385
7625
|
"use strict";
|
|
@@ -7395,6 +7635,27 @@ var init_DiagnosticsTools = __esm({
|
|
|
7395
7635
|
init_H265Converter();
|
|
7396
7636
|
init_constants();
|
|
7397
7637
|
init_xml();
|
|
7638
|
+
REDACT_KEYS = /* @__PURE__ */ new Set([
|
|
7639
|
+
"password",
|
|
7640
|
+
"pass",
|
|
7641
|
+
"token",
|
|
7642
|
+
"secret",
|
|
7643
|
+
"apiKey",
|
|
7644
|
+
"api_key"
|
|
7645
|
+
]);
|
|
7646
|
+
MASK_KEYS = /* @__PURE__ */ new Set([
|
|
7647
|
+
"serialNumber",
|
|
7648
|
+
"serial",
|
|
7649
|
+
"uid",
|
|
7650
|
+
"mac",
|
|
7651
|
+
"ssid",
|
|
7652
|
+
"wifiPassword",
|
|
7653
|
+
"userName",
|
|
7654
|
+
"username",
|
|
7655
|
+
"user"
|
|
7656
|
+
]);
|
|
7657
|
+
IPV4_RE = /\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/g;
|
|
7658
|
+
MAC_RE = /\b([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}\b/g;
|
|
7398
7659
|
}
|
|
7399
7660
|
});
|
|
7400
7661
|
|
|
@@ -14851,7 +15112,7 @@ function computeDeviceCapabilities(params) {
|
|
|
14851
15112
|
const ptzControlRaw = supportItem ? supportItem.ptzControl : void 0;
|
|
14852
15113
|
const supportExplicitlyDefinesPtz = ptzTypeRaw !== void 0 || ptzControlRaw !== void 0;
|
|
14853
15114
|
const ptzExplicitlyDisabledBySupportItem = supportExplicitlyDefinesPtz && !isTruthyNumberLike(ptzTypeRaw) && !isTruthyNumberLike(ptzControlRaw);
|
|
14854
|
-
const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw)
|
|
15115
|
+
const hasPtzFromSupportItem = isTruthyNumberLike(ptzTypeRaw);
|
|
14855
15116
|
const ptzDisabledBySupport = (ptzMode === "none" || ptzMode === "0") && !hasPtzFromSupportItem;
|
|
14856
15117
|
const hasBatteryFromSupport = supportItem ? isTruthyNumberLike(supportItem.battery) : false;
|
|
14857
15118
|
const ptzPresetRaw = supportItem ? supportItem.ptzPreset : void 0;
|