@apocaliss92/nodelink-js 0.4.4 → 0.4.6
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 +2 -0
- package/dist/{DiagnosticsTools-55PR4WFD.js → DiagnosticsTools-UMN4C7SY.js} +2 -2
- package/dist/{chunk-UHFJPQA4.js → chunk-F2Y5U3YP.js} +251 -28
- package/dist/chunk-F2Y5U3YP.js.map +1 -0
- package/dist/{chunk-DEOMUWBN.js → chunk-TR3V5FTO.js} +15 -1
- package/dist/chunk-TR3V5FTO.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +261 -24
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +2 -2
- package/dist/index.cjs +290 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -1
- package/dist/index.d.ts +66 -1
- package/dist/index.js +31 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-DEOMUWBN.js.map +0 -1
- package/dist/chunk-UHFJPQA4.js.map +0 -1
- /package/dist/{DiagnosticsTools-55PR4WFD.js.map → DiagnosticsTools-UMN4C7SY.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1009,11 +1009,13 @@ interface ReolinkDayNightNotification {
|
|
|
1009
1009
|
timestamp?: number;
|
|
1010
1010
|
}
|
|
1011
1011
|
type ReolinkEvent = ReolinkMotionNotification | ReolinkAiNotification | ReolinkVisitorNotification | ReolinkDayNightNotification;
|
|
1012
|
-
type ReolinkSimpleEventType = "motion" | "doorbell" | "people" | "vehicle" | "animal" | "face" | "package" | "daynight" | "sleeping" | "awake" | "online" | "offline" | "other";
|
|
1012
|
+
type ReolinkSimpleEventType = "motion" | "doorbell" | "people" | "vehicle" | "animal" | "face" | "package" | "daynight" | "sleeping" | "awake" | "online" | "offline" | "battery" | "other";
|
|
1013
1013
|
interface ReolinkSimpleEvent {
|
|
1014
1014
|
type: ReolinkSimpleEventType;
|
|
1015
1015
|
channel: number;
|
|
1016
1016
|
timestamp: number;
|
|
1017
|
+
/** Present when type === "battery" — pushed by the camera via cmdId 252. */
|
|
1018
|
+
battery?: Partial<BatteryInfo>;
|
|
1017
1019
|
}
|
|
1018
1020
|
interface TwoWayAudioConfig {
|
|
1019
1021
|
channel: number;
|
|
@@ -1935,6 +1937,11 @@ declare class BaichuanClient extends EventEmitter<{
|
|
|
1935
1937
|
debug: [string, unknown?];
|
|
1936
1938
|
event: [ReolinkEvent];
|
|
1937
1939
|
channelInfo: [string];
|
|
1940
|
+
batteryPush: [BaichuanFrame];
|
|
1941
|
+
d2c_disc: [{
|
|
1942
|
+
host: string;
|
|
1943
|
+
atMs: number;
|
|
1944
|
+
}];
|
|
1938
1945
|
}> {
|
|
1939
1946
|
/**
|
|
1940
1947
|
* Process-wide streaming activity registry.
|
|
@@ -1946,6 +1953,14 @@ declare class BaichuanClient extends EventEmitter<{
|
|
|
1946
1953
|
* even if the current client instance is idle/disconnected.
|
|
1947
1954
|
*/
|
|
1948
1955
|
private static readonly streamingRegistry;
|
|
1956
|
+
/**
|
|
1957
|
+
* Per-host D2C_DISC backoff state that persists across client instance recreation.
|
|
1958
|
+
*
|
|
1959
|
+
* Why: when a D2C_DISC kills a client, the socket pool destroys the old instance
|
|
1960
|
+
* and creates a new one. Instance-level backoff variables would reset to zero,
|
|
1961
|
+
* allowing immediate reconnection and perpetuating the storm.
|
|
1962
|
+
*/
|
|
1963
|
+
private static readonly d2cDiscBackoff;
|
|
1949
1964
|
/**
|
|
1950
1965
|
* Global (process-wide) CoverPreview serialization.
|
|
1951
1966
|
*
|
|
@@ -2419,6 +2434,7 @@ declare class BcUdpStream extends EventEmitter<{
|
|
|
2419
2434
|
private resendTimer;
|
|
2420
2435
|
private hbTimer;
|
|
2421
2436
|
private discoveryTid;
|
|
2437
|
+
private discoveryTimers;
|
|
2422
2438
|
private acceptSent;
|
|
2423
2439
|
private lastAcceptAtMs;
|
|
2424
2440
|
private ackScheduled;
|
|
@@ -3640,6 +3656,15 @@ declare class BaichuanVideoStream extends EventEmitter<{
|
|
|
3640
3656
|
private lastPpsH265;
|
|
3641
3657
|
private lastPrependedParamSetsH265;
|
|
3642
3658
|
private aesStreamDecryptor;
|
|
3659
|
+
/**
|
|
3660
|
+
* Pending startup error stashed when emitSafeError is called before any
|
|
3661
|
+
* "error" listener is registered (e.g. camera returns 400 during start()).
|
|
3662
|
+
* The rfc4571-server's waitForKeyframe can consume this immediately instead
|
|
3663
|
+
* of waiting for the full keyframe timeout.
|
|
3664
|
+
*/
|
|
3665
|
+
private _pendingStartupError;
|
|
3666
|
+
/** Consume and clear any pending startup error. */
|
|
3667
|
+
consumePendingStartupError(): Error | undefined;
|
|
3643
3668
|
private emitSafeError;
|
|
3644
3669
|
private lastMediaAtMs;
|
|
3645
3670
|
private watchdogTimer;
|
|
@@ -4338,6 +4363,19 @@ declare class ReolinkBaichuanApi {
|
|
|
4338
4363
|
private readonly aiAlarmCandidateTypesCache;
|
|
4339
4364
|
private rtspServers;
|
|
4340
4365
|
private readonly activeVideoMsgNums;
|
|
4366
|
+
/** Timestamp of the most recent D2C_DISC from any client for this device. */
|
|
4367
|
+
private lastD2cDiscAtMs;
|
|
4368
|
+
/** Sliding window of recent D2C_DISC timestamps for storm detection. */
|
|
4369
|
+
private readonly d2cDiscTimestamps;
|
|
4370
|
+
/** Immediate cooldown (ms) applied to socket pool on every D2C_DISC.
|
|
4371
|
+
* Prevents reconnect attempts while the camera is transitioning to sleep. */
|
|
4372
|
+
private static readonly D2C_DISC_IMMEDIATE_COOLDOWN_MS;
|
|
4373
|
+
/** Number of D2C_DISCs within the storm window to trigger extended cooldown. */
|
|
4374
|
+
private static readonly D2C_DISC_STORM_THRESHOLD;
|
|
4375
|
+
/** Sliding window size (ms) for storm detection. */
|
|
4376
|
+
private static readonly D2C_DISC_STORM_WINDOW_MS;
|
|
4377
|
+
/** Extended cooldown (ms) applied to socket pool when a D2C_DISC storm is detected. */
|
|
4378
|
+
private static readonly D2C_DISC_STORM_COOLDOWN_MS;
|
|
4341
4379
|
private readonly nvrChannelsSummaryCache;
|
|
4342
4380
|
/**
|
|
4343
4381
|
* Cached device capabilities per channel.
|
|
@@ -4477,6 +4515,18 @@ declare class ReolinkBaichuanApi {
|
|
|
4477
4515
|
* which indicates subStream (e.g., RecS03_, RecS_).
|
|
4478
4516
|
*/
|
|
4479
4517
|
private determineStreamTypeFromFileName;
|
|
4518
|
+
/**
|
|
4519
|
+
* Stream profiles that the device explicitly rejected (response_code 400).
|
|
4520
|
+
* Keyed by `"ch:profile"` (e.g. `"0:ext"`). Once a profile is in this set
|
|
4521
|
+
* it is excluded from `buildVideoStreamOptions()` results and no further
|
|
4522
|
+
* start attempts are made until the API instance is recreated.
|
|
4523
|
+
*/
|
|
4524
|
+
private readonly _rejectedStreamProfiles;
|
|
4525
|
+
/**
|
|
4526
|
+
* Check whether a stream profile was rejected by the device at runtime
|
|
4527
|
+
* (e.g. ext returned response_code 400).
|
|
4528
|
+
*/
|
|
4529
|
+
isStreamProfileRejected(channel: number, profile: StreamProfile): boolean;
|
|
4480
4530
|
/**
|
|
4481
4531
|
* Cache for buildVideoStreamOptions.
|
|
4482
4532
|
*
|
|
@@ -4512,6 +4562,12 @@ declare class ReolinkBaichuanApi {
|
|
|
4512
4562
|
* @returns The socket pool tag to use
|
|
4513
4563
|
*/
|
|
4514
4564
|
private resolveSocketTag;
|
|
4565
|
+
/**
|
|
4566
|
+
* Attach a D2C_DISC listener to a BaichuanClient so that the API-level
|
|
4567
|
+
* grace period and storm detection are updated regardless of which
|
|
4568
|
+
* pool socket receives the disconnect.
|
|
4569
|
+
*/
|
|
4570
|
+
private attachD2cDiscListener;
|
|
4515
4571
|
/**
|
|
4516
4572
|
* Acquire a socket from the pool by tag.
|
|
4517
4573
|
* Creates a new socket if needed, or reuses an existing one.
|
|
@@ -5657,6 +5713,15 @@ declare class ReolinkBaichuanApi {
|
|
|
5657
5713
|
zoomToFactor(zoomFactor: number, channel?: number): Promise<void>;
|
|
5658
5714
|
zoomToFactor(channel: number, zoomFactor: number): Promise<void>;
|
|
5659
5715
|
private parseBatteryInfoXml;
|
|
5716
|
+
/**
|
|
5717
|
+
* Called when any BaichuanClient for this device receives a D2C_DISC.
|
|
5718
|
+
*
|
|
5719
|
+
* Two-tier response:
|
|
5720
|
+
* 1. **Immediate**: every D2C_DISC applies a short socket pool cooldown
|
|
5721
|
+
* (10 s) to prevent reconnect attempts while the camera transitions to sleep.
|
|
5722
|
+
* 2. **Storm**: ≥3 D2C_DISCs within 60 s triggers extended cooldown (120 s).
|
|
5723
|
+
*/
|
|
5724
|
+
private notifyD2cDisc;
|
|
5660
5725
|
/**
|
|
5661
5726
|
* Best-effort sleeping inference for battery/BCUDP cameras.
|
|
5662
5727
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -396,6 +396,11 @@ export declare class BaichuanClient extends EventEmitter<{
|
|
|
396
396
|
debug: [string, unknown?];
|
|
397
397
|
event: [ReolinkEvent];
|
|
398
398
|
channelInfo: [string];
|
|
399
|
+
batteryPush: [BaichuanFrame];
|
|
400
|
+
d2c_disc: [{
|
|
401
|
+
host: string;
|
|
402
|
+
atMs: number;
|
|
403
|
+
}];
|
|
399
404
|
}> {
|
|
400
405
|
/**
|
|
401
406
|
* Process-wide streaming activity registry.
|
|
@@ -407,6 +412,14 @@ export declare class BaichuanClient extends EventEmitter<{
|
|
|
407
412
|
* even if the current client instance is idle/disconnected.
|
|
408
413
|
*/
|
|
409
414
|
private static readonly streamingRegistry;
|
|
415
|
+
/**
|
|
416
|
+
* Per-host D2C_DISC backoff state that persists across client instance recreation.
|
|
417
|
+
*
|
|
418
|
+
* Why: when a D2C_DISC kills a client, the socket pool destroys the old instance
|
|
419
|
+
* and creates a new one. Instance-level backoff variables would reset to zero,
|
|
420
|
+
* allowing immediate reconnection and perpetuating the storm.
|
|
421
|
+
*/
|
|
422
|
+
private static readonly d2cDiscBackoff;
|
|
410
423
|
/**
|
|
411
424
|
* Global (process-wide) CoverPreview serialization.
|
|
412
425
|
*
|
|
@@ -1634,6 +1647,15 @@ export declare class BaichuanVideoStream extends EventEmitter<{
|
|
|
1634
1647
|
private lastPpsH265;
|
|
1635
1648
|
private lastPrependedParamSetsH265;
|
|
1636
1649
|
private aesStreamDecryptor;
|
|
1650
|
+
/**
|
|
1651
|
+
* Pending startup error stashed when emitSafeError is called before any
|
|
1652
|
+
* "error" listener is registered (e.g. camera returns 400 during start()).
|
|
1653
|
+
* The rfc4571-server's waitForKeyframe can consume this immediately instead
|
|
1654
|
+
* of waiting for the full keyframe timeout.
|
|
1655
|
+
*/
|
|
1656
|
+
private _pendingStartupError;
|
|
1657
|
+
/** Consume and clear any pending startup error. */
|
|
1658
|
+
consumePendingStartupError(): Error | undefined;
|
|
1637
1659
|
private emitSafeError;
|
|
1638
1660
|
private lastMediaAtMs;
|
|
1639
1661
|
private watchdogTimer;
|
|
@@ -2324,6 +2346,7 @@ export declare class BcUdpStream extends EventEmitter<{
|
|
|
2324
2346
|
private resendTimer;
|
|
2325
2347
|
private hbTimer;
|
|
2326
2348
|
private discoveryTid;
|
|
2349
|
+
private discoveryTimers;
|
|
2327
2350
|
private acceptSent;
|
|
2328
2351
|
private lastAcceptAtMs;
|
|
2329
2352
|
private ackScheduled;
|
|
@@ -5183,6 +5206,19 @@ export declare class ReolinkBaichuanApi {
|
|
|
5183
5206
|
private readonly aiAlarmCandidateTypesCache;
|
|
5184
5207
|
private rtspServers;
|
|
5185
5208
|
private readonly activeVideoMsgNums;
|
|
5209
|
+
/** Timestamp of the most recent D2C_DISC from any client for this device. */
|
|
5210
|
+
private lastD2cDiscAtMs;
|
|
5211
|
+
/** Sliding window of recent D2C_DISC timestamps for storm detection. */
|
|
5212
|
+
private readonly d2cDiscTimestamps;
|
|
5213
|
+
/** Immediate cooldown (ms) applied to socket pool on every D2C_DISC.
|
|
5214
|
+
* Prevents reconnect attempts while the camera is transitioning to sleep. */
|
|
5215
|
+
private static readonly D2C_DISC_IMMEDIATE_COOLDOWN_MS;
|
|
5216
|
+
/** Number of D2C_DISCs within the storm window to trigger extended cooldown. */
|
|
5217
|
+
private static readonly D2C_DISC_STORM_THRESHOLD;
|
|
5218
|
+
/** Sliding window size (ms) for storm detection. */
|
|
5219
|
+
private static readonly D2C_DISC_STORM_WINDOW_MS;
|
|
5220
|
+
/** Extended cooldown (ms) applied to socket pool when a D2C_DISC storm is detected. */
|
|
5221
|
+
private static readonly D2C_DISC_STORM_COOLDOWN_MS;
|
|
5186
5222
|
private readonly nvrChannelsSummaryCache;
|
|
5187
5223
|
/**
|
|
5188
5224
|
* Cached device capabilities per channel.
|
|
@@ -5322,6 +5358,18 @@ export declare class ReolinkBaichuanApi {
|
|
|
5322
5358
|
* which indicates subStream (e.g., RecS03_, RecS_).
|
|
5323
5359
|
*/
|
|
5324
5360
|
private determineStreamTypeFromFileName;
|
|
5361
|
+
/**
|
|
5362
|
+
* Stream profiles that the device explicitly rejected (response_code 400).
|
|
5363
|
+
* Keyed by `"ch:profile"` (e.g. `"0:ext"`). Once a profile is in this set
|
|
5364
|
+
* it is excluded from `buildVideoStreamOptions()` results and no further
|
|
5365
|
+
* start attempts are made until the API instance is recreated.
|
|
5366
|
+
*/
|
|
5367
|
+
private readonly _rejectedStreamProfiles;
|
|
5368
|
+
/**
|
|
5369
|
+
* Check whether a stream profile was rejected by the device at runtime
|
|
5370
|
+
* (e.g. ext returned response_code 400).
|
|
5371
|
+
*/
|
|
5372
|
+
isStreamProfileRejected(channel: number, profile: StreamProfile): boolean;
|
|
5325
5373
|
/**
|
|
5326
5374
|
* Cache for buildVideoStreamOptions.
|
|
5327
5375
|
*
|
|
@@ -5357,6 +5405,12 @@ export declare class ReolinkBaichuanApi {
|
|
|
5357
5405
|
* @returns The socket pool tag to use
|
|
5358
5406
|
*/
|
|
5359
5407
|
private resolveSocketTag;
|
|
5408
|
+
/**
|
|
5409
|
+
* Attach a D2C_DISC listener to a BaichuanClient so that the API-level
|
|
5410
|
+
* grace period and storm detection are updated regardless of which
|
|
5411
|
+
* pool socket receives the disconnect.
|
|
5412
|
+
*/
|
|
5413
|
+
private attachD2cDiscListener;
|
|
5360
5414
|
/**
|
|
5361
5415
|
* Acquire a socket from the pool by tag.
|
|
5362
5416
|
* Creates a new socket if needed, or reuses an existing one.
|
|
@@ -6502,6 +6556,15 @@ export declare class ReolinkBaichuanApi {
|
|
|
6502
6556
|
zoomToFactor(zoomFactor: number, channel?: number): Promise<void>;
|
|
6503
6557
|
zoomToFactor(channel: number, zoomFactor: number): Promise<void>;
|
|
6504
6558
|
private parseBatteryInfoXml;
|
|
6559
|
+
/**
|
|
6560
|
+
* Called when any BaichuanClient for this device receives a D2C_DISC.
|
|
6561
|
+
*
|
|
6562
|
+
* Two-tier response:
|
|
6563
|
+
* 1. **Immediate**: every D2C_DISC applies a short socket pool cooldown
|
|
6564
|
+
* (10 s) to prevent reconnect attempts while the camera transitions to sleep.
|
|
6565
|
+
* 2. **Storm**: ≥3 D2C_DISCs within 60 s triggers extended cooldown (120 s).
|
|
6566
|
+
*/
|
|
6567
|
+
private notifyD2cDisc;
|
|
6505
6568
|
/**
|
|
6506
6569
|
* Best-effort sleeping inference for battery/BCUDP cameras.
|
|
6507
6570
|
*
|
|
@@ -8361,9 +8424,11 @@ export declare interface ReolinkSimpleEvent {
|
|
|
8361
8424
|
type: ReolinkSimpleEventType;
|
|
8362
8425
|
channel: number;
|
|
8363
8426
|
timestamp: number;
|
|
8427
|
+
/** Present when type === "battery" — pushed by the camera via cmdId 252. */
|
|
8428
|
+
battery?: Partial<BatteryInfo>;
|
|
8364
8429
|
}
|
|
8365
8430
|
|
|
8366
|
-
export declare type ReolinkSimpleEventType = "motion" | "doorbell" | "people" | "vehicle" | "animal" | "face" | "package" | "daynight" | "sleeping" | "awake" | "online" | "offline" | "other";
|
|
8431
|
+
export declare type ReolinkSimpleEventType = "motion" | "doorbell" | "people" | "vehicle" | "animal" | "face" | "package" | "daynight" | "sleeping" | "awake" | "online" | "offline" | "battery" | "other";
|
|
8367
8432
|
|
|
8368
8433
|
/**
|
|
8369
8434
|
* Complete media stream options with all available metadata.
|
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
parseSupportXml,
|
|
44
44
|
setGlobalLogger,
|
|
45
45
|
xmlIndicatesFloodlight
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-F2Y5U3YP.js";
|
|
47
47
|
import {
|
|
48
48
|
AesStreamDecryptor,
|
|
49
49
|
BC_AES_IV,
|
|
@@ -223,7 +223,7 @@ import {
|
|
|
223
223
|
testChannelStreams,
|
|
224
224
|
xmlEscape,
|
|
225
225
|
zipDirectory
|
|
226
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-TR3V5FTO.js";
|
|
227
227
|
|
|
228
228
|
// src/reolink/baichuan/HlsSessionManager.ts
|
|
229
229
|
var withTimeout = async (p, ms, label) => {
|
|
@@ -3466,6 +3466,11 @@ async function createRfc4571TcpServerInternal(options) {
|
|
|
3466
3466
|
"videoAccessUnit",
|
|
3467
3467
|
onAu
|
|
3468
3468
|
);
|
|
3469
|
+
const pendingErr = videoStream.consumePendingStartupError?.();
|
|
3470
|
+
if (pendingErr) {
|
|
3471
|
+
cleanup();
|
|
3472
|
+
reject(pendingErr);
|
|
3473
|
+
}
|
|
3469
3474
|
});
|
|
3470
3475
|
}
|
|
3471
3476
|
};
|
|
@@ -3477,24 +3482,32 @@ async function createRfc4571TcpServerInternal(options) {
|
|
|
3477
3482
|
await videoStream.stop();
|
|
3478
3483
|
} catch {
|
|
3479
3484
|
}
|
|
3480
|
-
if (
|
|
3481
|
-
|
|
3482
|
-
|
|
3485
|
+
if (dedicatedSession) {
|
|
3486
|
+
try {
|
|
3487
|
+
await dedicatedSession.release();
|
|
3488
|
+
} catch {
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
if (!dedicatedSession) {
|
|
3492
|
+
if (closeApiOnTeardown) {
|
|
3493
|
+
await Promise.allSettled(
|
|
3494
|
+
Array.from(apisToClose).map(async (a) => {
|
|
3495
|
+
try {
|
|
3496
|
+
await a.close();
|
|
3497
|
+
} catch {
|
|
3498
|
+
}
|
|
3499
|
+
})
|
|
3500
|
+
);
|
|
3501
|
+
} else {
|
|
3502
|
+
const graceMs = isComposite ? 5e3 : 0;
|
|
3503
|
+
for (const a of Array.from(apisToClose)) {
|
|
3483
3504
|
try {
|
|
3484
|
-
|
|
3505
|
+
a?.client?.requestIdleDisconnectSoon?.(
|
|
3506
|
+
"rfc4571_teardown",
|
|
3507
|
+
graceMs
|
|
3508
|
+
);
|
|
3485
3509
|
} catch {
|
|
3486
3510
|
}
|
|
3487
|
-
})
|
|
3488
|
-
);
|
|
3489
|
-
} else {
|
|
3490
|
-
const graceMs = isComposite ? 5e3 : 0;
|
|
3491
|
-
for (const a of Array.from(apisToClose)) {
|
|
3492
|
-
try {
|
|
3493
|
-
a?.client?.requestIdleDisconnectSoon?.(
|
|
3494
|
-
"rfc4571_teardown",
|
|
3495
|
-
graceMs
|
|
3496
|
-
);
|
|
3497
|
-
} catch {
|
|
3498
3511
|
}
|
|
3499
3512
|
}
|
|
3500
3513
|
}
|
|
@@ -3750,7 +3763,7 @@ async function createRfc4571TcpServerInternal(options) {
|
|
|
3750
3763
|
} catch {
|
|
3751
3764
|
}
|
|
3752
3765
|
}
|
|
3753
|
-
if (closeApiOnTeardown) {
|
|
3766
|
+
if (closeApiOnTeardown && !dedicatedSession) {
|
|
3754
3767
|
await Promise.allSettled(
|
|
3755
3768
|
Array.from(apisToClose).map(async (a) => {
|
|
3756
3769
|
try {
|