@apocaliss92/nodelink-js 0.2.5 → 0.3.5
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/{chunk-EG5IY3CM.js → chunk-UDS2UR4S.js} +444 -20
- package/dist/chunk-UDS2UR4S.js.map +1 -0
- package/dist/cli/rtsp-server.cjs +78 -16
- package/dist/cli/rtsp-server.cjs.map +1 -1
- package/dist/cli/rtsp-server.js +1 -1
- package/dist/index.cjs +1071 -210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +211 -70
- package/dist/index.d.ts +193 -69
- package/dist/index.js +580 -142
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/dist/chunk-EG5IY3CM.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -300,27 +300,30 @@ export declare type AutoDetectResult = {
|
|
|
300
300
|
};
|
|
301
301
|
|
|
302
302
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
303
|
+
* Continuous discovery client for Reolink cameras on the network.
|
|
304
|
+
* Runs periodic scans using all configured discovery methods and maintains
|
|
305
|
+
* an always-up-to-date list of discovered devices.
|
|
305
306
|
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
307
|
+
* Supports callbacks for new/updated devices, making it ideal for plugins
|
|
308
|
+
* that want to be notified as cameras appear (e.g. battery cameras waking up).
|
|
308
309
|
*
|
|
309
310
|
* @example
|
|
310
311
|
* ```typescript
|
|
311
312
|
* const client = new AutodiscoveryClient({
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* scanIntervalMs:
|
|
313
|
+
* enableArpLookup: true,
|
|
314
|
+
* enableOnvifDiscovery: true,
|
|
315
|
+
* scanIntervalMs: 60_000,
|
|
315
316
|
* autoStart: true,
|
|
317
|
+
* onDeviceDiscovered: (device) => {
|
|
318
|
+
* console.log(`New device: ${device.host} (${device.model})`);
|
|
319
|
+
* },
|
|
316
320
|
* });
|
|
317
321
|
*
|
|
318
|
-
* //
|
|
322
|
+
* // Get the current list
|
|
319
323
|
* const devices = client.getDiscoveredDevices();
|
|
320
|
-
* console.log(`Trovate ${devices.length} telecamere`);
|
|
321
324
|
*
|
|
322
|
-
* //
|
|
323
|
-
*
|
|
325
|
+
* // Stop
|
|
326
|
+
* client.stop();
|
|
324
327
|
* ```
|
|
325
328
|
*/
|
|
326
329
|
export declare class AutodiscoveryClient {
|
|
@@ -329,96 +332,54 @@ export declare class AutodiscoveryClient {
|
|
|
329
332
|
private scanTimer;
|
|
330
333
|
private isRunning;
|
|
331
334
|
private currentScanPromise;
|
|
332
|
-
/**
|
|
333
|
-
* Costruttore del client di autodiscovery.
|
|
334
|
-
*
|
|
335
|
-
* @param options - Opzioni di configurazione per il discovery
|
|
336
|
-
*/
|
|
337
335
|
constructor(options?: AutodiscoveryClientOptions);
|
|
338
336
|
/**
|
|
339
|
-
*
|
|
340
|
-
* Se già in esecuzione, non fa nulla.
|
|
337
|
+
* Start continuous discovery. If already running, does nothing.
|
|
341
338
|
*/
|
|
342
339
|
start(): void;
|
|
343
340
|
/**
|
|
344
|
-
*
|
|
345
|
-
* Se non è in esecuzione, non fa nulla.
|
|
341
|
+
* Stop continuous discovery. If not running, does nothing.
|
|
346
342
|
*/
|
|
347
343
|
stop(): void;
|
|
348
344
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
* @returns Array di dispositivi discoverati, ordinati per host
|
|
345
|
+
* Returns the current list of discovered devices, sorted by host IP.
|
|
352
346
|
*/
|
|
353
347
|
getDiscoveredDevices(): DiscoveredDevice[];
|
|
354
348
|
/**
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
* @returns Numero di dispositivi discoverati
|
|
349
|
+
* Returns the number of currently discovered devices.
|
|
358
350
|
*/
|
|
359
351
|
getDeviceCount(): number;
|
|
360
352
|
/**
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
* @returns `true` se il discovery è in esecuzione, `false` altrimenti
|
|
353
|
+
* Returns whether continuous discovery is currently running.
|
|
364
354
|
*/
|
|
365
355
|
isActive(): boolean;
|
|
366
356
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
* @returns Promise che si risolve quando lo scan è completato
|
|
357
|
+
* Force an immediate scan (doesn't wait for the scheduled interval).
|
|
358
|
+
* If a scan is already in progress, waits for it to complete.
|
|
371
359
|
*/
|
|
372
360
|
scanNow(): Promise<void>;
|
|
373
361
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* @param host - Indirizzo IP del dispositivo da rimuovere
|
|
377
|
-
* @returns `true` se il dispositivo è stato rimosso, `false` se non era presente
|
|
362
|
+
* Remove a device from the discovered list.
|
|
378
363
|
*/
|
|
379
364
|
removeDevice(host: string): boolean;
|
|
380
365
|
/**
|
|
381
|
-
*
|
|
366
|
+
* Clear all discovered devices.
|
|
382
367
|
*/
|
|
383
368
|
clearDevices(): void;
|
|
384
|
-
/**
|
|
385
|
-
* Esegue un singolo scan della rete.
|
|
386
|
-
*/
|
|
387
369
|
private performScan;
|
|
388
|
-
/**
|
|
389
|
-
* Unisce le informazioni di un dispositivo esistente con quelle di un nuovo scan.
|
|
390
|
-
* Restituisce il dispositivo aggiornato se ci sono state modifiche, altrimenti `null`.
|
|
391
|
-
*/
|
|
392
370
|
private mergeDeviceInfo;
|
|
393
|
-
/**
|
|
394
|
-
* Programma il prossimo scan.
|
|
395
|
-
*/
|
|
396
371
|
private scheduleNextScan;
|
|
397
372
|
}
|
|
398
373
|
|
|
399
|
-
export declare interface AutodiscoveryClientOptions {
|
|
400
|
-
/**
|
|
401
|
-
networkCidr?: string;
|
|
402
|
-
/** Username to use for authentication attempts (default: "admin") */
|
|
403
|
-
username?: string;
|
|
404
|
-
/** Password to use for authentication attempts (default: empty, will try unauthenticated) */
|
|
405
|
-
password?: string;
|
|
406
|
-
/** Timeout per HTTP probe in milliseconds (default: 2000) */
|
|
407
|
-
httpProbeTimeoutMs?: number;
|
|
408
|
-
/** Maximum number of concurrent HTTP probes (default: 50) */
|
|
409
|
-
maxConcurrentProbes?: number;
|
|
410
|
-
/** Logger instance for debug output */
|
|
411
|
-
logger?: Logger;
|
|
412
|
-
/** Ports to scan for HTTP (default: [80, 443]) */
|
|
413
|
-
httpPorts?: number[];
|
|
414
|
-
/** Interval between discovery scans in milliseconds (default: 60000 = 60 seconds) */
|
|
374
|
+
export declare interface AutodiscoveryClientOptions extends DiscoveryOptions {
|
|
375
|
+
/** Interval between discovery scans in milliseconds (default: 120000 = 2 minutes) */
|
|
415
376
|
scanIntervalMs?: number;
|
|
416
377
|
/** Whether to start discovery automatically on construction (default: false) */
|
|
417
378
|
autoStart?: boolean;
|
|
418
|
-
/**
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
|
|
379
|
+
/** Called when new (previously unseen) devices are discovered */
|
|
380
|
+
onDeviceDiscovered?: (device: DiscoveredDevice) => void;
|
|
381
|
+
/** Called when an existing device's info is updated (e.g. model filled in) */
|
|
382
|
+
onDeviceUpdated?: (device: DiscoveredDevice) => void;
|
|
422
383
|
}
|
|
423
384
|
|
|
424
385
|
export declare type BaichuanCachedPush<T> = {
|
|
@@ -461,6 +422,22 @@ export declare class BaichuanClient extends EventEmitter<{
|
|
|
461
422
|
private static readonly coverPreviewBackoffMs;
|
|
462
423
|
private static readonly COVER_PREVIEW_INITIAL_BACKOFF_MS;
|
|
463
424
|
private static readonly COVER_PREVIEW_MAX_BACKOFF_MS;
|
|
425
|
+
/**
|
|
426
|
+
* Per-client snapshot (cmd_id=109) serialization queue.
|
|
427
|
+
*
|
|
428
|
+
* WHY: On NVR/multi-camera devices sharing one socket, concurrent snapshot requests
|
|
429
|
+
* can cause JPEG data to mix (even with per-request msgNum filtering):
|
|
430
|
+
* - Camera A and B both send frames on same socket
|
|
431
|
+
* - Frame listener is global per socket
|
|
432
|
+
* - Timing quirks can cause chunk reordering or listener confusion
|
|
433
|
+
*
|
|
434
|
+
* FIX: Serialize all cmd_id=109 requests on THIS client instance.
|
|
435
|
+
* Each snapshot waits for previous one to complete before starting.
|
|
436
|
+
* This ensures clean frame sequences per request, zero data corruption.
|
|
437
|
+
*
|
|
438
|
+
* Impact: Snapshots are ~0–50ms slower per camera (negligible for users).
|
|
439
|
+
*/
|
|
440
|
+
private snapshotQueueTail;
|
|
464
441
|
private readonly opts;
|
|
465
442
|
private readonly debugCfg;
|
|
466
443
|
private readonly logger;
|
|
@@ -807,6 +784,7 @@ export declare class BaichuanClient extends EventEmitter<{
|
|
|
807
784
|
private sendBinaryFileDownload6482;
|
|
808
785
|
private sendBinaryFileInfoListReplay5;
|
|
809
786
|
private sendBinarySnapshot109;
|
|
787
|
+
private sendBinarySnapshot109Impl;
|
|
810
788
|
/**
|
|
811
789
|
* Send CoverPreview command (cmd_id=298) to get an I-frame from a past recording.
|
|
812
790
|
* Similar to sendBinarySnapshot109 but handles the stream header + frame format
|
|
@@ -3628,7 +3606,7 @@ export declare interface DiscoveredDevice {
|
|
|
3628
3606
|
/** Firmware version (if available) */
|
|
3629
3607
|
firmwareVersion?: string;
|
|
3630
3608
|
/** Discovery method used to find this device */
|
|
3631
|
-
discoveryMethod: "http_probe" | "udp_broadcast" | "udp_direct";
|
|
3609
|
+
discoveryMethod: "http_probe" | "udp_broadcast" | "udp_direct" | "tcp_port_scan" | "arp" | "dhcp" | "onvif";
|
|
3632
3610
|
/** Whether HTTPS is supported */
|
|
3633
3611
|
supportsHttps?: boolean;
|
|
3634
3612
|
/** Whether the device is accessible via HTTP */
|
|
@@ -3657,11 +3635,45 @@ export declare interface DiscoveredDevice {
|
|
|
3657
3635
|
*/
|
|
3658
3636
|
export declare function discoverReolinkDevices(options?: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3659
3637
|
|
|
3638
|
+
/**
|
|
3639
|
+
* Discover Reolink devices by reading the system ARP table and filtering
|
|
3640
|
+
* for Reolink MAC address prefixes (EC:71:DB). This mirrors the DHCP-based
|
|
3641
|
+
* discovery used by Home Assistant but reads the already-populated ARP cache
|
|
3642
|
+
* instead of sniffing live DHCP packets.
|
|
3643
|
+
*
|
|
3644
|
+
* Works on Linux, macOS, and Docker containers (reads /proc/net/arp or `arp -a`).
|
|
3645
|
+
*/
|
|
3646
|
+
export declare function discoverViaArpTable(options: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3647
|
+
|
|
3648
|
+
/**
|
|
3649
|
+
* Discover Reolink devices by passively listening for DHCP traffic (port 67/68).
|
|
3650
|
+
* Parses DHCP ACK/REQUEST packets and filters for Reolink MAC prefix or hostname.
|
|
3651
|
+
* Requires root or CAP_NET_RAW (typical in Docker with --net=host).
|
|
3652
|
+
*
|
|
3653
|
+
* This mirrors Home Assistant's DHCP discovery: matches hostname "reolink*" or MAC "EC:71:DB".
|
|
3654
|
+
*/
|
|
3655
|
+
export declare function discoverViaDhcpListener(options: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3656
|
+
|
|
3660
3657
|
/**
|
|
3661
3658
|
* Discover devices via HTTP port scanning.
|
|
3662
3659
|
*/
|
|
3663
3660
|
export declare function discoverViaHttpScan(options: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3664
3661
|
|
|
3662
|
+
/**
|
|
3663
|
+
* Discover devices via ONVIF WS-Discovery (multicast probe on 239.255.255.250:3702).
|
|
3664
|
+
* Most Reolink cameras and NVRs support ONVIF and will respond with their service
|
|
3665
|
+
* endpoint (XAddrs), model, and scopes. This is the standard IP camera discovery
|
|
3666
|
+
* mechanism used by NVRs, VMS, and similar software.
|
|
3667
|
+
*/
|
|
3668
|
+
export declare function discoverViaOnvif(options: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3669
|
+
|
|
3670
|
+
/**
|
|
3671
|
+
* Discover Reolink devices by scanning TCP port 9000 (Baichuan protocol).
|
|
3672
|
+
* This is the most reliable method — every Reolink camera/NVR listens on port 9000.
|
|
3673
|
+
* It only checks if the port is open; it does not authenticate or extract device info.
|
|
3674
|
+
*/
|
|
3675
|
+
export declare function discoverViaTcpPortScan(options: DiscoveryOptions): Promise<DiscoveredDevice[]>;
|
|
3676
|
+
|
|
3665
3677
|
/**
|
|
3666
3678
|
* Discover devices via UDP broadcast (for battery cameras).
|
|
3667
3679
|
*/
|
|
@@ -3692,6 +3704,20 @@ export declare type DiscoveryOptions = {
|
|
|
3692
3704
|
enableUdpDiscovery?: boolean;
|
|
3693
3705
|
/** Whether to enable HTTP port scanning (default: true) */
|
|
3694
3706
|
enableHttpScanning?: boolean;
|
|
3707
|
+
/** Whether to enable TCP port 9000 scanning (Baichuan protocol). Works with all Reolink devices. (default: false) */
|
|
3708
|
+
enableTcpPortScan?: boolean;
|
|
3709
|
+
/** Timeout per TCP port probe in milliseconds (default: 1500) */
|
|
3710
|
+
tcpProbeTimeoutMs?: number;
|
|
3711
|
+
/** Whether to enable ARP table lookup for Reolink MAC prefix (ec:71:db). Similar to Home Assistant DHCP discovery. (default: false) */
|
|
3712
|
+
enableArpLookup?: boolean;
|
|
3713
|
+
/** Whether to enable passive DHCP listening for Reolink devices (requires root/NET_RAW). (default: false) */
|
|
3714
|
+
enableDhcpListener?: boolean;
|
|
3715
|
+
/** Timeout for DHCP listener in milliseconds (default: 10000) */
|
|
3716
|
+
dhcpListenerTimeoutMs?: number;
|
|
3717
|
+
/** Whether to enable ONVIF WS-Discovery (multicast probe on 239.255.255.250:3702). Most Reolink cameras support ONVIF. (default: false) */
|
|
3718
|
+
enableOnvifDiscovery?: boolean;
|
|
3719
|
+
/** Timeout for ONVIF WS-Discovery in milliseconds (default: 5000) */
|
|
3720
|
+
onvifDiscoveryTimeoutMs?: number;
|
|
3695
3721
|
/** Ports to scan for HTTP (default: [80, 443]) */
|
|
3696
3722
|
httpPorts?: number[];
|
|
3697
3723
|
};
|
|
@@ -4031,6 +4057,104 @@ export declare interface GetVodUrlParams {
|
|
|
4031
4057
|
*/
|
|
4032
4058
|
export declare function getXmlText(xml: string, tagName: string): string | undefined;
|
|
4033
4059
|
|
|
4060
|
+
export declare class Go2rtcTcpServer extends EventEmitter<{
|
|
4061
|
+
client: [string];
|
|
4062
|
+
clientDisconnected: [string];
|
|
4063
|
+
error: [Error];
|
|
4064
|
+
close: [];
|
|
4065
|
+
listening: [{
|
|
4066
|
+
host: string;
|
|
4067
|
+
port: number;
|
|
4068
|
+
}];
|
|
4069
|
+
}> {
|
|
4070
|
+
private readonly api;
|
|
4071
|
+
private readonly channel;
|
|
4072
|
+
private readonly profile;
|
|
4073
|
+
private readonly variant;
|
|
4074
|
+
private readonly listenHost;
|
|
4075
|
+
private readonly listenPort;
|
|
4076
|
+
private readonly logger;
|
|
4077
|
+
private readonly deviceId;
|
|
4078
|
+
private readonly gracePeriodMs;
|
|
4079
|
+
private readonly prebufferMaxMs;
|
|
4080
|
+
private readonly maxBufferBytes;
|
|
4081
|
+
private readonly prestartStream;
|
|
4082
|
+
private active;
|
|
4083
|
+
private server;
|
|
4084
|
+
private resolvedPort;
|
|
4085
|
+
private nativeFanout;
|
|
4086
|
+
private nativeStreamActive;
|
|
4087
|
+
private dedicatedSessionRelease;
|
|
4088
|
+
private detectedVideoType;
|
|
4089
|
+
private connectedClients;
|
|
4090
|
+
private clientSockets;
|
|
4091
|
+
private stopGraceTimer;
|
|
4092
|
+
private prebuffer;
|
|
4093
|
+
constructor(options: Go2rtcTcpServerOptions);
|
|
4094
|
+
/** Start listening. Resolves once the TCP server is bound. */
|
|
4095
|
+
start(): Promise<void>;
|
|
4096
|
+
/** Stop the server and all active streams. */
|
|
4097
|
+
stop(): Promise<void>;
|
|
4098
|
+
/** The actual port the server is listening on (available after start()). */
|
|
4099
|
+
get port(): number | undefined;
|
|
4100
|
+
/** The go2rtc-compatible source URL. */
|
|
4101
|
+
get go2rtcSourceUrl(): string | undefined;
|
|
4102
|
+
/** Number of currently connected clients. */
|
|
4103
|
+
get clientCount(): number;
|
|
4104
|
+
private handleClient;
|
|
4105
|
+
private feedClient;
|
|
4106
|
+
/**
|
|
4107
|
+
* Convert a native frame to wire-ready Annex-B.
|
|
4108
|
+
* Audio frames are skipped — raw TCP carries only video (Annex-B).
|
|
4109
|
+
* go2rtc auto-detects the codec from SPS/PPS/VPS NALUs.
|
|
4110
|
+
*/
|
|
4111
|
+
private convertFrame;
|
|
4112
|
+
/** Check if an Annex-B buffer contains a keyframe (IDR for H.264, IRAP for H.265). */
|
|
4113
|
+
private isAnnexBKeyframe;
|
|
4114
|
+
/** Split Annex-B byte stream into individual NAL units. */
|
|
4115
|
+
private static splitAnnexBNals;
|
|
4116
|
+
private startNativeStream;
|
|
4117
|
+
private stopNativeStream;
|
|
4118
|
+
private removeClient;
|
|
4119
|
+
private scheduleStop;
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
export declare interface Go2rtcTcpServerOptions {
|
|
4123
|
+
/** API instance (required). */
|
|
4124
|
+
api: ReolinkBaichuanApi;
|
|
4125
|
+
/** Channel number (required). */
|
|
4126
|
+
channel: number;
|
|
4127
|
+
/** Stream profile (required). */
|
|
4128
|
+
profile: StreamProfile;
|
|
4129
|
+
/** TrackMix tele/autotrack variant. */
|
|
4130
|
+
variant?: NativeVideoStreamVariant;
|
|
4131
|
+
/** Host to listen on (default: "127.0.0.1"). */
|
|
4132
|
+
listenHost?: string;
|
|
4133
|
+
/** Port to listen on (default: 0 = OS picks). */
|
|
4134
|
+
listenPort?: number;
|
|
4135
|
+
/** Logger. */
|
|
4136
|
+
logger?: Logger;
|
|
4137
|
+
/**
|
|
4138
|
+
* External identifier for dedicated socket session.
|
|
4139
|
+
* When provided, a dedicated BaichuanClient is created for the stream,
|
|
4140
|
+
* isolating it from other streams on the shared socket.
|
|
4141
|
+
*/
|
|
4142
|
+
deviceId?: string;
|
|
4143
|
+
/** Grace period in ms before stopping native stream after last client disconnects (default: 30 000). */
|
|
4144
|
+
gracePeriodMs?: number;
|
|
4145
|
+
/** Maximum prebuffer window in ms (default: 3 000). */
|
|
4146
|
+
prebufferMs?: number;
|
|
4147
|
+
/** Maximum write buffer per client before dropping the connection (default: 100 MB). */
|
|
4148
|
+
maxBufferBytes?: number;
|
|
4149
|
+
/**
|
|
4150
|
+
* When true, the native camera stream is started immediately on start()
|
|
4151
|
+
* rather than waiting for the first TCP client. This ensures frames are
|
|
4152
|
+
* already flowing (and the prebuffer is warm) when go2rtc connects.
|
|
4153
|
+
* Default: true.
|
|
4154
|
+
*/
|
|
4155
|
+
prestartStream?: boolean;
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4034
4158
|
/**
|
|
4035
4159
|
* Depacketizer for H.264 "RTP-like" payloads (RFC 6184) when the camera sends single NAL units,
|
|
4036
4160
|
* STAP/MTAP aggregation or FU-A/FU-B fragmentation inside a BcMedia frame payload.
|