@apocaliss92/nodelink-js 0.3.4 → 0.3.9
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/README.md +48 -82
- package/dist/{DiagnosticsTools-2JQRV5FE.js → DiagnosticsTools-DQDDBRM6.js} +4 -2
- package/dist/{chunk-APEEZ4UN.js → chunk-6Q6MK4WG.js} +172 -1
- package/dist/chunk-6Q6MK4WG.js.map +1 -0
- package/dist/{chunk-YSEFEQYV.js → chunk-OGIKBDON.js} +49 -8
- package/dist/chunk-OGIKBDON.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +215 -4
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +756 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +184 -1
- package/dist/index.d.ts +165 -0
- package/dist/index.js +541 -17
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/dist/chunk-APEEZ4UN.js.map +0 -1
- package/dist/chunk-YSEFEQYV.js.map +0 -1
- /package/dist/{DiagnosticsTools-2JQRV5FE.js.map → DiagnosticsTools-DQDDBRM6.js.map} +0 -0
package/dist/cli/rtsp-server.cjs
CHANGED
|
@@ -4912,6 +4912,7 @@ var init_zip = __esm({
|
|
|
4912
4912
|
// src/debug/DiagnosticsTools.ts
|
|
4913
4913
|
var DiagnosticsTools_exports = {};
|
|
4914
4914
|
__export(DiagnosticsTools_exports, {
|
|
4915
|
+
captureModelFixtures: () => captureModelFixtures,
|
|
4915
4916
|
collectCgiDiagnostics: () => collectCgiDiagnostics,
|
|
4916
4917
|
collectMultifocalDiagnostics: () => collectMultifocalDiagnostics,
|
|
4917
4918
|
collectNativeDiagnostics: () => collectNativeDiagnostics,
|
|
@@ -4945,6 +4946,10 @@ function writeJson(filePath, obj) {
|
|
|
4945
4946
|
mkdirp(path4.dirname(filePath));
|
|
4946
4947
|
fs4.writeFileSync(filePath, JSON.stringify(obj, null, 2));
|
|
4947
4948
|
}
|
|
4949
|
+
function writeText(filePath, text) {
|
|
4950
|
+
mkdirp(path4.dirname(filePath));
|
|
4951
|
+
fs4.writeFileSync(filePath, text);
|
|
4952
|
+
}
|
|
4948
4953
|
function appendNdjson(filePath, obj) {
|
|
4949
4954
|
mkdirp(path4.dirname(filePath));
|
|
4950
4955
|
fs4.appendFileSync(filePath, JSON.stringify(obj) + "\n");
|
|
@@ -7208,6 +7213,172 @@ async function runAllDiagnosticsConsecutively(params) {
|
|
|
7208
7213
|
streamsDir
|
|
7209
7214
|
};
|
|
7210
7215
|
}
|
|
7216
|
+
async function captureModelFixtures(params) {
|
|
7217
|
+
const { api, channel, outDir } = params;
|
|
7218
|
+
const log = params.log ?? console.log;
|
|
7219
|
+
mkdirp(outDir);
|
|
7220
|
+
const calls = {};
|
|
7221
|
+
const errors = [];
|
|
7222
|
+
async function capture(name, fn, writer) {
|
|
7223
|
+
try {
|
|
7224
|
+
const value = await fn();
|
|
7225
|
+
calls[name] = { ok: true, value };
|
|
7226
|
+
if (writer && value !== void 0 && value !== null) {
|
|
7227
|
+
writer(value);
|
|
7228
|
+
}
|
|
7229
|
+
log(` \u2713 ${name}`);
|
|
7230
|
+
return value;
|
|
7231
|
+
} catch (e) {
|
|
7232
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
7233
|
+
calls[name] = { ok: false, error: msg };
|
|
7234
|
+
errors.push(`${name}: ${msg}`);
|
|
7235
|
+
log(` \u2717 ${name}: ${msg}`);
|
|
7236
|
+
return void 0;
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
const info = await capture(
|
|
7240
|
+
"getInfo",
|
|
7241
|
+
() => api.getInfo(channel),
|
|
7242
|
+
(v) => writeJson(path4.join(outDir, "device-info.json"), v)
|
|
7243
|
+
);
|
|
7244
|
+
const support = await capture(
|
|
7245
|
+
"getSupportInfo",
|
|
7246
|
+
() => api.getSupportInfo(),
|
|
7247
|
+
(v) => writeJson(path4.join(outDir, "support-info.json"), v)
|
|
7248
|
+
);
|
|
7249
|
+
const abilities = await capture(
|
|
7250
|
+
"getAbilityInfo",
|
|
7251
|
+
() => api.getAbilityInfo(),
|
|
7252
|
+
(v) => writeJson(path4.join(outDir, "ability-info.json"), v)
|
|
7253
|
+
);
|
|
7254
|
+
await capture(
|
|
7255
|
+
"getDeviceCapabilities",
|
|
7256
|
+
() => api.getDeviceCapabilities(channel),
|
|
7257
|
+
(v) => writeJson(path4.join(outDir, "capabilities.json"), v)
|
|
7258
|
+
);
|
|
7259
|
+
await capture("cmd289-WhiteLed", () => api.sendXml({
|
|
7260
|
+
cmdId: BC_CMD_ID_GET_WHITE_LED,
|
|
7261
|
+
channel,
|
|
7262
|
+
timeoutMs: 3e3
|
|
7263
|
+
}), (v) => writeText(path4.join(outDir, "cmd289-white-led.xml"), v));
|
|
7264
|
+
await capture(
|
|
7265
|
+
"getStreamMetadata",
|
|
7266
|
+
() => api.getStreamMetadata(channel),
|
|
7267
|
+
(v) => writeJson(path4.join(outDir, "stream-metadata.json"), v)
|
|
7268
|
+
);
|
|
7269
|
+
await capture(
|
|
7270
|
+
"getEncXml",
|
|
7271
|
+
() => api.getEncXml(channel),
|
|
7272
|
+
(v) => writeText(path4.join(outDir, "enc-config.xml"), v)
|
|
7273
|
+
);
|
|
7274
|
+
await capture(
|
|
7275
|
+
"getPorts",
|
|
7276
|
+
() => api.getPorts(),
|
|
7277
|
+
(v) => writeJson(path4.join(outDir, "ports.json"), v)
|
|
7278
|
+
);
|
|
7279
|
+
await capture(
|
|
7280
|
+
"getTalkAbility",
|
|
7281
|
+
() => api.getTalkAbility(channel),
|
|
7282
|
+
(v) => writeJson(path4.join(outDir, "talk-ability.json"), v)
|
|
7283
|
+
);
|
|
7284
|
+
await capture(
|
|
7285
|
+
"getTwoWayAudioConfig",
|
|
7286
|
+
() => api.getTwoWayAudioConfig(channel),
|
|
7287
|
+
(v) => writeJson(path4.join(outDir, "two-way-audio-config.json"), v)
|
|
7288
|
+
);
|
|
7289
|
+
await capture(
|
|
7290
|
+
"getAiState",
|
|
7291
|
+
() => api.getAiState(channel),
|
|
7292
|
+
(v) => writeJson(path4.join(outDir, "ai-state.json"), v)
|
|
7293
|
+
);
|
|
7294
|
+
await capture(
|
|
7295
|
+
"getAiCfg",
|
|
7296
|
+
() => api.getAiCfg(channel),
|
|
7297
|
+
(v) => writeJson(path4.join(outDir, "ai-cfg.json"), v)
|
|
7298
|
+
);
|
|
7299
|
+
await capture(
|
|
7300
|
+
"getOsd",
|
|
7301
|
+
() => api.getOsd(channel),
|
|
7302
|
+
(v) => writeJson(path4.join(outDir, "osd.json"), v)
|
|
7303
|
+
);
|
|
7304
|
+
await capture(
|
|
7305
|
+
"getMotionAlarm",
|
|
7306
|
+
() => api.getMotionAlarm(channel),
|
|
7307
|
+
(v) => writeJson(path4.join(outDir, "motion-alarm.json"), v)
|
|
7308
|
+
);
|
|
7309
|
+
await capture(
|
|
7310
|
+
"getRecordCfg",
|
|
7311
|
+
() => api.getRecordCfg(channel),
|
|
7312
|
+
(v) => writeJson(path4.join(outDir, "record-cfg.json"), v)
|
|
7313
|
+
);
|
|
7314
|
+
await capture(
|
|
7315
|
+
"getVideoInput",
|
|
7316
|
+
() => api.getVideoInput(channel),
|
|
7317
|
+
(v) => writeJson(path4.join(outDir, "video-input.json"), v)
|
|
7318
|
+
);
|
|
7319
|
+
await capture(
|
|
7320
|
+
"getPtzPresets",
|
|
7321
|
+
() => api.getPtzPresets(channel),
|
|
7322
|
+
(v) => writeJson(path4.join(outDir, "ptz-presets.json"), v)
|
|
7323
|
+
);
|
|
7324
|
+
await capture(
|
|
7325
|
+
"getNetworkInfo",
|
|
7326
|
+
() => api.getNetworkInfo(),
|
|
7327
|
+
(v) => writeJson(path4.join(outDir, "network-info.json"), v)
|
|
7328
|
+
);
|
|
7329
|
+
await capture(
|
|
7330
|
+
"getSystemGeneral",
|
|
7331
|
+
() => api.getSystemGeneral(),
|
|
7332
|
+
(v) => writeJson(path4.join(outDir, "system-general.json"), v)
|
|
7333
|
+
);
|
|
7334
|
+
await capture(
|
|
7335
|
+
"getWifiSignal",
|
|
7336
|
+
() => api.getWifiSignal(channel),
|
|
7337
|
+
(v) => writeJson(path4.join(outDir, "wifi-signal.json"), v)
|
|
7338
|
+
);
|
|
7339
|
+
await capture(
|
|
7340
|
+
"getWhiteLedState",
|
|
7341
|
+
() => api.getWhiteLedState(channel),
|
|
7342
|
+
(v) => writeJson(path4.join(outDir, "white-led-state.json"), v)
|
|
7343
|
+
);
|
|
7344
|
+
await capture(
|
|
7345
|
+
"getFloodlightOnMotion",
|
|
7346
|
+
() => api.getFloodlightOnMotion(channel),
|
|
7347
|
+
(v) => writeJson(path4.join(outDir, "floodlight-on-motion.json"), v)
|
|
7348
|
+
);
|
|
7349
|
+
await capture(
|
|
7350
|
+
"buildVideoStreamOptions",
|
|
7351
|
+
() => api.buildVideoStreamOptions({ channel }),
|
|
7352
|
+
(v) => writeJson(path4.join(outDir, "video-stream-options.json"), v)
|
|
7353
|
+
);
|
|
7354
|
+
const total = Object.keys(calls).length;
|
|
7355
|
+
const ok = Object.values(calls).filter((c) => c.ok).length;
|
|
7356
|
+
const failed = total - ok;
|
|
7357
|
+
const summary = { total, ok, failed, errors };
|
|
7358
|
+
writeJson(path4.join(outDir, "_summary.json"), {
|
|
7359
|
+
collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7360
|
+
model: info?.type ?? "unknown",
|
|
7361
|
+
itemNo: info?.itemNo ?? "unknown",
|
|
7362
|
+
firmwareVersion: info?.firmwareVersion ?? "unknown",
|
|
7363
|
+
channel,
|
|
7364
|
+
...summary,
|
|
7365
|
+
calls: Object.fromEntries(
|
|
7366
|
+
Object.entries(calls).map(([k, v]) => [
|
|
7367
|
+
k,
|
|
7368
|
+
v.ok ? "ok" : `FAILED: ${v.error}`
|
|
7369
|
+
])
|
|
7370
|
+
)
|
|
7371
|
+
});
|
|
7372
|
+
log(`
|
|
7373
|
+
Summary: ${ok}/${total} ok, ${failed} failed`);
|
|
7374
|
+
if (errors.length) {
|
|
7375
|
+
log(` Errors:`);
|
|
7376
|
+
for (const err of errors) {
|
|
7377
|
+
log(` - ${err}`);
|
|
7378
|
+
}
|
|
7379
|
+
}
|
|
7380
|
+
return { calls, outDir, summary };
|
|
7381
|
+
}
|
|
7211
7382
|
var fs4, path4, import_node_child_process2, import_node_path;
|
|
7212
7383
|
var init_DiagnosticsTools = __esm({
|
|
7213
7384
|
"src/debug/DiagnosticsTools.ts"() {
|
|
@@ -11371,6 +11542,22 @@ var BaichuanClient = class _BaichuanClient extends import_node_events4.EventEmit
|
|
|
11371
11542
|
static coverPreviewBackoffMs = /* @__PURE__ */ new Map();
|
|
11372
11543
|
static COVER_PREVIEW_INITIAL_BACKOFF_MS = 1e3;
|
|
11373
11544
|
static COVER_PREVIEW_MAX_BACKOFF_MS = 3e4;
|
|
11545
|
+
/**
|
|
11546
|
+
* Per-client snapshot (cmd_id=109) serialization queue.
|
|
11547
|
+
*
|
|
11548
|
+
* WHY: On NVR/multi-camera devices sharing one socket, concurrent snapshot requests
|
|
11549
|
+
* can cause JPEG data to mix (even with per-request msgNum filtering):
|
|
11550
|
+
* - Camera A and B both send frames on same socket
|
|
11551
|
+
* - Frame listener is global per socket
|
|
11552
|
+
* - Timing quirks can cause chunk reordering or listener confusion
|
|
11553
|
+
*
|
|
11554
|
+
* FIX: Serialize all cmd_id=109 requests on THIS client instance.
|
|
11555
|
+
* Each snapshot waits for previous one to complete before starting.
|
|
11556
|
+
* This ensures clean frame sequences per request, zero data corruption.
|
|
11557
|
+
*
|
|
11558
|
+
* Impact: Snapshots are ~0–50ms slower per camera (negligible for users).
|
|
11559
|
+
*/
|
|
11560
|
+
snapshotQueueTail = Promise.resolve();
|
|
11374
11561
|
opts;
|
|
11375
11562
|
debugCfg;
|
|
11376
11563
|
logger;
|
|
@@ -13852,6 +14039,20 @@ var BaichuanClient = class _BaichuanClient extends import_node_events4.EventEmit
|
|
|
13852
14039
|
});
|
|
13853
14040
|
}
|
|
13854
14041
|
async sendBinarySnapshot109(params) {
|
|
14042
|
+
const prevTail = this.snapshotQueueTail;
|
|
14043
|
+
let resolve;
|
|
14044
|
+
const newTail = new Promise((r) => {
|
|
14045
|
+
resolve = r;
|
|
14046
|
+
});
|
|
14047
|
+
this.snapshotQueueTail = newTail;
|
|
14048
|
+
try {
|
|
14049
|
+
await prevTail;
|
|
14050
|
+
return await this.sendBinarySnapshot109Impl(params);
|
|
14051
|
+
} finally {
|
|
14052
|
+
resolve();
|
|
14053
|
+
}
|
|
14054
|
+
}
|
|
14055
|
+
async sendBinarySnapshot109Impl(params) {
|
|
13855
14056
|
await this.connect();
|
|
13856
14057
|
const channel = params.channel ?? this.opts.channel ?? 0;
|
|
13857
14058
|
const channelId = params.channelIdOverride ?? (params.channel == null ? this.hostChannelId : channel + 1);
|
|
@@ -13911,7 +14112,8 @@ var BaichuanClient = class _BaichuanClient extends import_node_events4.EventEmit
|
|
|
13911
14112
|
};
|
|
13912
14113
|
const onFrame = (frame) => {
|
|
13913
14114
|
if (frame.header.cmdId !== cmdId) return;
|
|
13914
|
-
if (frame.header.msgNum
|
|
14115
|
+
if (frame.header.msgNum !== msgNum) return;
|
|
14116
|
+
if (frame.header.responseCode >= 400) {
|
|
13915
14117
|
fail(
|
|
13916
14118
|
new Error(
|
|
13917
14119
|
`Baichuan snapshot request rejected (cmdId=${cmdId} msgNum=${msgNum} responseCode=${frame.header.responseCode})`
|
|
@@ -14713,6 +14915,17 @@ function computeDeviceCapabilities(params) {
|
|
|
14713
14915
|
if (ptzMode !== void 0) result.ptzMode = ptzMode;
|
|
14714
14916
|
return result;
|
|
14715
14917
|
}
|
|
14918
|
+
function xmlIndicatesFloodlight(xml) {
|
|
14919
|
+
if (/(<FloodlightTask\b|<FloodlightManual\b|<FloodlightStatusList\b)/i.test(
|
|
14920
|
+
xml
|
|
14921
|
+
)) {
|
|
14922
|
+
return true;
|
|
14923
|
+
}
|
|
14924
|
+
if (/<WhiteLed\b/i.test(xml)) {
|
|
14925
|
+
return /(<brightness_cur>|<bright>|<LightingSchedule\b)/i.test(xml);
|
|
14926
|
+
}
|
|
14927
|
+
return false;
|
|
14928
|
+
}
|
|
14716
14929
|
|
|
14717
14930
|
// src/reolink/baichuan/utils/abilityInfo.ts
|
|
14718
14931
|
init_xml();
|
|
@@ -23749,9 +23962,7 @@ ${stderr}`)
|
|
|
23749
23962
|
`probeFloodlightSupportByCmd289: received XML for channel ${ch}:
|
|
23750
23963
|
${xml}`
|
|
23751
23964
|
);
|
|
23752
|
-
return
|
|
23753
|
-
xml
|
|
23754
|
-
);
|
|
23965
|
+
return xmlIndicatesFloodlight(xml);
|
|
23755
23966
|
} catch {
|
|
23756
23967
|
return false;
|
|
23757
23968
|
}
|