@apocaliss92/scrypted-reolink-native 0.3.7 → 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/dist/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/baichuan-base.ts +19 -18
- package/src/camera.ts +8 -4
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/baichuan-base.ts
CHANGED
|
@@ -485,7 +485,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
485
485
|
*/
|
|
486
486
|
private getAllActiveConnections(): ReolinkBaichuanApi[] {
|
|
487
487
|
const connections: ReolinkBaichuanApi[] = [];
|
|
488
|
-
|
|
488
|
+
|
|
489
489
|
// Add main connection if exists and is valid
|
|
490
490
|
if (this.baichuanApi) {
|
|
491
491
|
const isConnected = this.baichuanApi.client.isSocketConnected();
|
|
@@ -494,7 +494,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
494
494
|
connections.push(this.baichuanApi);
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
|
-
|
|
497
|
+
|
|
498
498
|
// Add all stream clients that are valid
|
|
499
499
|
for (const streamClient of this.streamClients.values()) {
|
|
500
500
|
const isConnected = streamClient.client.isSocketConnected();
|
|
@@ -503,7 +503,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
503
503
|
connections.push(streamClient);
|
|
504
504
|
}
|
|
505
505
|
}
|
|
506
|
-
|
|
506
|
+
|
|
507
507
|
return connections;
|
|
508
508
|
}
|
|
509
509
|
|
|
@@ -512,7 +512,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
512
512
|
*/
|
|
513
513
|
private startConnectionMaintenance(api: ReolinkBaichuanApi): void {
|
|
514
514
|
const logger = this.getBaichuanLogger();
|
|
515
|
-
|
|
515
|
+
|
|
516
516
|
// Stop any existing intervals
|
|
517
517
|
this.stopConnectionMaintenance();
|
|
518
518
|
|
|
@@ -526,11 +526,11 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
526
526
|
// Get all active connections (main + stream clients)
|
|
527
527
|
const allConnections = this.getAllActiveConnections();
|
|
528
528
|
logger.debug(`Pinging ${allConnections.length} connections`);
|
|
529
|
-
|
|
529
|
+
|
|
530
530
|
if (allConnections.length === 0) {
|
|
531
531
|
this.consecutivePingFailures++;
|
|
532
532
|
logger.debug(`No active connections found, failures=${this.consecutivePingFailures}`);
|
|
533
|
-
|
|
533
|
+
|
|
534
534
|
if (this.consecutivePingFailures >= 3) {
|
|
535
535
|
logger.log('No active connections detected, renewing connection');
|
|
536
536
|
await this.cleanupBaichuanApi();
|
|
@@ -557,7 +557,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
557
557
|
if (failedPings.length > 0) {
|
|
558
558
|
this.consecutivePingFailures++;
|
|
559
559
|
logger.debug(`Ping failed for ${failedPings.length}/${allConnections.length} connections, failures=${this.consecutivePingFailures}`);
|
|
560
|
-
|
|
560
|
+
|
|
561
561
|
if (this.consecutivePingFailures >= 3) {
|
|
562
562
|
logger.log(`Multiple ping failures detected (${failedPings.length} connections), renewing connection`);
|
|
563
563
|
await this.cleanupBaichuanApi();
|
|
@@ -584,7 +584,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
584
584
|
try {
|
|
585
585
|
// Check if there are active streams
|
|
586
586
|
const hasActiveStreams = this.getStreamManager?.()?.hasActiveStreams() ?? false;
|
|
587
|
-
|
|
587
|
+
|
|
588
588
|
if (!hasActiveStreams) {
|
|
589
589
|
logger.log('No active streams detected, renewing connection (auto-renewal)');
|
|
590
590
|
await this.cleanupBaichuanApi();
|
|
@@ -617,7 +617,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
617
617
|
*/
|
|
618
618
|
private startEventCheck(api: ReolinkBaichuanApi): void {
|
|
619
619
|
const logger = this.getBaichuanLogger();
|
|
620
|
-
|
|
620
|
+
|
|
621
621
|
// Stop any existing interval
|
|
622
622
|
this.stopEventCheck();
|
|
623
623
|
|
|
@@ -640,16 +640,16 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
640
640
|
if (this.lastEventTime > 0 && timeSinceLastEvent > fiveMinutesMs) {
|
|
641
641
|
logger.log(`No events received in the last ${Math.round(timeSinceLastEvent / 60_000)} minutes, restarting event listener`);
|
|
642
642
|
// Restart event subscription
|
|
643
|
-
await this.unsubscribeFromEvents();
|
|
644
|
-
await this.subscribeToEvents();
|
|
643
|
+
await this.unsubscribeFromEvents(true);
|
|
644
|
+
await this.subscribeToEvents(true);
|
|
645
645
|
} else if (this.lastEventTime === 0) {
|
|
646
646
|
// If lastEventTime is 0, it means we just subscribed but haven't received any events yet
|
|
647
647
|
// Wait a bit longer before considering it a problem
|
|
648
648
|
const timeSinceSubscription = now - (this.connectionTime || now);
|
|
649
649
|
if (timeSinceSubscription > fiveMinutesMs) {
|
|
650
650
|
logger.log(`No events received since subscription (${Math.round(timeSinceSubscription / 60_000)} minutes ago), restarting event listener`);
|
|
651
|
-
await this.unsubscribeFromEvents();
|
|
652
|
-
await this.subscribeToEvents();
|
|
651
|
+
await this.unsubscribeFromEvents(true);
|
|
652
|
+
await this.subscribeToEvents(true);
|
|
653
653
|
}
|
|
654
654
|
}
|
|
655
655
|
} catch (e) {
|
|
@@ -672,7 +672,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
672
672
|
/**
|
|
673
673
|
* Subscribe to Baichuan simple events
|
|
674
674
|
*/
|
|
675
|
-
async subscribeToEvents(): Promise<void> {
|
|
675
|
+
async subscribeToEvents(silent: boolean = false): Promise<void> {
|
|
676
676
|
const logger = this.getBaichuanLogger();
|
|
677
677
|
const callbacks = this.getConnectionCallbacks();
|
|
678
678
|
|
|
@@ -691,7 +691,7 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
691
691
|
}
|
|
692
692
|
|
|
693
693
|
// Unsubscribe first if handler exists (idempotent)
|
|
694
|
-
await this.unsubscribeFromEvents();
|
|
694
|
+
await this.unsubscribeFromEvents(silent);
|
|
695
695
|
|
|
696
696
|
// Get Baichuan client connection
|
|
697
697
|
const api = await this.ensureBaichuanClient();
|
|
@@ -717,11 +717,11 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
717
717
|
// Call original handler
|
|
718
718
|
originalHandler(ev);
|
|
719
719
|
};
|
|
720
|
-
|
|
720
|
+
|
|
721
721
|
await api.onSimpleEvent(wrappedHandler);
|
|
722
722
|
this.eventSubscriptionActive = true;
|
|
723
723
|
this.lastEventTime = Date.now(); // Initialize on subscription
|
|
724
|
-
logger.
|
|
724
|
+
logger.debug('Subscribed to Baichuan events');
|
|
725
725
|
}
|
|
726
726
|
catch (e) {
|
|
727
727
|
logger.warn('Failed to subscribe to events', e?.message || String(e));
|
|
@@ -731,8 +731,9 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
|
|
|
731
731
|
|
|
732
732
|
/**
|
|
733
733
|
* Unsubscribe from Baichuan simple events
|
|
734
|
+
* @param silent If true, don't log unsubscription messages
|
|
734
735
|
*/
|
|
735
|
-
async unsubscribeFromEvents(): Promise<void> {
|
|
736
|
+
async unsubscribeFromEvents(silent: boolean = false): Promise<void> {
|
|
736
737
|
const logger = this.getBaichuanLogger();
|
|
737
738
|
const callbacks = this.getConnectionCallbacks();
|
|
738
739
|
|
package/src/camera.ts
CHANGED
|
@@ -1731,7 +1731,7 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
|
|
|
1731
1731
|
* If this device has a parent (nvrDevice or multiFocalDevice), events will be forwarded from the parent.
|
|
1732
1732
|
* This ensures that only the root device in the hierarchy subscribes to events, avoiding duplicate subscriptions.
|
|
1733
1733
|
*/
|
|
1734
|
-
async subscribeToEvents(): Promise<void> {
|
|
1734
|
+
async subscribeToEvents(silent: boolean = false): Promise<void> {
|
|
1735
1735
|
// If this device has a parent (NVR or MultiFocal), don't subscribe - events will be forwarded from parent
|
|
1736
1736
|
if (this.nvrDevice || this.multiFocalDevice) {
|
|
1737
1737
|
const logger = this.getBaichuanLogger();
|
|
@@ -1754,7 +1754,9 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
|
|
|
1754
1754
|
}
|
|
1755
1755
|
|
|
1756
1756
|
if (!enabled) {
|
|
1757
|
-
|
|
1757
|
+
if (!silent) {
|
|
1758
|
+
logger.log('Event subscription disabled, unsubscribing');
|
|
1759
|
+
}
|
|
1758
1760
|
if (this.doorbellBinaryTimeout) {
|
|
1759
1761
|
clearTimeout(this.doorbellBinaryTimeout);
|
|
1760
1762
|
this.doorbellBinaryTimeout = undefined;
|
|
@@ -1766,8 +1768,10 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
|
|
|
1766
1768
|
// IMPORTANT: use base subscription logic so the callback is properly bound.
|
|
1767
1769
|
// Passing `this.onSimpleEvent` directly would lose `this` and can result in silent failures.
|
|
1768
1770
|
try {
|
|
1769
|
-
await super.subscribeToEvents();
|
|
1770
|
-
|
|
1771
|
+
await super.subscribeToEvents(silent);
|
|
1772
|
+
if (!silent) {
|
|
1773
|
+
logger.log(`Subscribed to events (${selection.join(', ')}) on ${this.protocol} connection`);
|
|
1774
|
+
}
|
|
1771
1775
|
}
|
|
1772
1776
|
catch (e) {
|
|
1773
1777
|
logger.warn('Failed to subscribe to Baichuan events', e?.message || String(e));
|