Stop recreating the dbus.systemBus on retries (old instances are not disposed correctly by underlying code)

This commit is contained in:
Victor Hagelbäck 2021-02-27 09:57:29 +01:00
parent e7b8a5a82a
commit 042447d1a8
3 changed files with 39 additions and 13 deletions

View file

@ -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');

View file

@ -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();

View file

@ -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);
});