From 925ccba647e20a0cb4411606dcdbd9f89b7dc89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Hagelb=C3=A4ck?= Date: Sat, 27 Feb 2021 09:57:29 +0100 Subject: [PATCH] Stop recreating the dbus.systemBus on retries (old instances are not disposed correctly by underlying code) --- plejd/PlejdAddon.js | 17 +++++++---------- plejd/PlejdBLEHandler.js | 31 +++++++++++++++++++++++++++++-- plejd/PlejdDeviceCommunication.js | 4 +++- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/plejd/PlejdAddon.js b/plejd/PlejdAddon.js index 196d986..eb39c50 100644 --- a/plejd/PlejdAddon.js +++ b/plejd/PlejdAddon.js @@ -122,16 +122,13 @@ class PlejdAddon extends EventEmitter { }, ); - this.plejdDeviceCommunication.on( - PlejdDeviceCommunication.EVENTS.sceneTriggered, - (sceneId) => { - try { - this.mqttClient.sceneTriggered(sceneId); - } catch (err) { - logger.error('Error in PlejdService.sceneTriggered callback', err); - } - }, - ); + this.plejdDeviceCommunication.on(PlejdDeviceCommunication.EVENTS.sceneTriggered, (sceneId) => { + try { + this.mqttClient.sceneTriggered(sceneId); + } catch (err) { + logger.error('Error in PlejdService.sceneTriggered callback', err); + } + }); await this.plejdDeviceCommunication.init(); logger.info('Main init done'); diff --git a/plejd/PlejdBLEHandler.js b/plejd/PlejdBLEHandler.js index 05375d8..6f68a76 100644 --- a/plejd/PlejdBLEHandler.js +++ b/plejd/PlejdBLEHandler.js @@ -53,6 +53,7 @@ class PlejBLEHandler extends EventEmitter { pingRef = null; requestCurrentPlejdTimeRef = null; reconnectInProgress = false; + emergencyReconnectTimeout = null; // Refer to BLE-states.md regarding the internal BLE/bluez state machine of Bluetooth states // These states refer to the state machine of this file @@ -82,6 +83,8 @@ class PlejBLEHandler extends EventEmitter { auth: null, ping: null, }; + + this.bus = dbus.systemBus(); } cleanup() { @@ -112,7 +115,6 @@ class PlejBLEHandler extends EventEmitter { this.on(PlejBLEHandler.EVENTS.writeFailed, (error) => this._onWriteFailed(error)); this.on(PlejBLEHandler.EVENTS.writeSuccess, () => this._onWriteSuccess()); - this.bus = dbus.systemBus(); this.bus.on('error', (err) => { // Uncaught error events will show UnhandledPromiseRejection logs logger.verbose(`dbus-next error event: ${err.message}`); @@ -290,6 +292,9 @@ class PlejBLEHandler extends EventEmitter { ) => this._onLastDataUpdated(iface, properties)); this.characteristics.lastData.StartNotify(); this.emit(PlejBLEHandler.EVENTS.connected); + + clearTimeout(this.emergencyReconnectTimeout); + this.emergencyReconnectTimeout = null; } catch (err) { // This method is run on a timer, so errors can't e re-thrown. // Start reconnect loop if errors occur here @@ -463,10 +468,24 @@ class PlejBLEHandler extends EventEmitter { async startReconnectPeriodicallyLoop() { logger.info('Starting reconnect loop...'); - if (this.reconnectInProgress) { + clearTimeout(this.emergencyReconnectTimeout); + this.emergencyReconnectTimeout = null; + await this._startReconnectPeriodicallyLoopInternal(); + } + + async _startReconnectPeriodicallyLoopInternal() { + logger.verbose('Starting internal reconnect loop...'); + + if (this.reconnectInProgress && !this.emergencyReconnectTimeout) { logger.debug('Reconnect already in progress. Skipping this call.'); return; } + if (this.emergencyReconnectTimeout) { + logger.warn( + 'Restarting reconnect loop due to emergency reconnect timer elapsed. This should very rarely happen!', + ); + } + this.reconnectInProgress = true; /* eslint-disable no-await-in-loop */ @@ -476,6 +495,14 @@ class PlejBLEHandler extends EventEmitter { logger.verbose('Reconnect: Clean up, emit reconnect event, wait 5s and the re-init...'); this.cleanup(); this.emit(PlejBLEHandler.EVENTS.reconnecting); + + // Emergency 2 minute timer if reconnect silently fails somewhere + clearTimeout(this.emergencyReconnectTimeout); + this.emergencyReconnectTimeout = setTimeout( + () => this._startReconnectPeriodicallyLoopInternal(), + 120 * 1000, + ); + await delay(5000); logger.info('Reconnecting BLE...'); await this.init(); diff --git a/plejd/PlejdDeviceCommunication.js b/plejd/PlejdDeviceCommunication.js index 4fafb6c..e64c8cd 100644 --- a/plejd/PlejdDeviceCommunication.js +++ b/plejd/PlejdDeviceCommunication.js @@ -56,7 +56,9 @@ class PlejdDeviceCommunication extends EventEmitter { }); this.plejdBleHandler.on(PlejBLEHandler.EVENTS.reconnecting, () => { logger.info('Bluetooth reconnecting...'); - logger.verbose(`Stopping writeQueue loop until connection is established. Write queue length: ${this.writeQueue.length}`); + logger.verbose( + `Stopping writeQueue loop until connection is established. Write queue length: ${this.writeQueue.length}`, + ); this.bleConnected = false; clearTimeout(this.writeQueueRef); });