Lifecycle improvement including catching dbus-next error events
- Avoid UnhandledPromiseRejectionWarnings from dbus-next - Improve retry logic
This commit is contained in:
parent
be86f08bec
commit
dca491bf00
1 changed files with 43 additions and 35 deletions
|
|
@ -39,8 +39,19 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
adapter;
|
adapter;
|
||||||
adapterProperties;
|
adapterProperties;
|
||||||
config;
|
config;
|
||||||
deviceRegistry;
|
bleDevices = [];
|
||||||
|
bleDeviceTransitionTimers = {};
|
||||||
|
bus = null;
|
||||||
|
connectedDevice = null;
|
||||||
consecutiveWriteFails;
|
consecutiveWriteFails;
|
||||||
|
deviceRegistry;
|
||||||
|
discoveryTimeout = null;
|
||||||
|
plejdService = null;
|
||||||
|
plejdDevices = {};
|
||||||
|
pingRef = null;
|
||||||
|
writeQueue = {};
|
||||||
|
writeQueueRef = null;
|
||||||
|
reconnectInProgress = false;
|
||||||
|
|
||||||
// Refer to BLE-states.md regarding the internal BLE/bluez state machine of Bluetooth states
|
// 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
|
// These states refer to the state machine of this file
|
||||||
|
|
@ -54,18 +65,7 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
logger.info('Starting Plejd BLE Handler, resetting all device states.');
|
logger.info('Starting Plejd BLE Handler, resetting all device states.');
|
||||||
|
|
||||||
this.config = Configuration.getOptions();
|
this.config = Configuration.getOptions();
|
||||||
|
|
||||||
this.connectedDevice = null;
|
|
||||||
this.deviceRegistry = deviceRegistry;
|
this.deviceRegistry = deviceRegistry;
|
||||||
this.plejdService = null;
|
|
||||||
this.bleDevices = [];
|
|
||||||
this.bleDeviceTransitionTimers = {};
|
|
||||||
this.discoveryTimeout = null;
|
|
||||||
this.plejdDevices = {};
|
|
||||||
this.connectEventHooked = false;
|
|
||||||
this.writeQueue = [];
|
|
||||||
this.writeQueueRef = null;
|
|
||||||
this.reconnectInProgress = false;
|
|
||||||
|
|
||||||
// Holds a reference to all characteristics
|
// Holds a reference to all characteristics
|
||||||
this.characteristics = {
|
this.characteristics = {
|
||||||
|
|
@ -76,15 +76,23 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
ping: null,
|
ping: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.bus = null;
|
|
||||||
|
|
||||||
this.on('writeFailed', (error) => this.onWriteFailed(error));
|
this.on('writeFailed', (error) => this.onWriteFailed(error));
|
||||||
this.on('writeSuccess', () => this.onWriteSuccess());
|
this.on('writeSuccess', () => this.onWriteSuccess());
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
logger.info('init()');
|
logger.info('init()');
|
||||||
|
|
||||||
this.bus = dbus.systemBus();
|
this.bus = dbus.systemBus();
|
||||||
|
this.bus.on('connect', () => {
|
||||||
|
logger.verbose('dbus-next connected');
|
||||||
|
});
|
||||||
|
this.bus.on('error', (err) => {
|
||||||
|
// Uncaught error events will show UnhandledPromiseRejection logs
|
||||||
|
logger.verbose(`dbus-next error event: ${err.message}`);
|
||||||
|
});
|
||||||
|
// this.bus also has a 'message' event that gets emitted _very_ frequently
|
||||||
|
|
||||||
this.adapter = null;
|
this.adapter = null;
|
||||||
this.adapterProperties = null;
|
this.adapterProperties = null;
|
||||||
this.consecutiveWriteFails = 0;
|
this.consecutiveWriteFails = 0;
|
||||||
|
|
@ -171,7 +179,7 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.warn('Unable to connect.', err);
|
logger.warn('Unable to connect. ', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,7 +358,10 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
|
|
||||||
_scheduleInternalInit() {
|
_scheduleInternalInit() {
|
||||||
clearTimeout(this.discoveryTimeout);
|
clearTimeout(this.discoveryTimeout);
|
||||||
setTimeout(() => this._inspectDevicesDiscovered(), this.config.connectionTimeout * 1000);
|
this.discoveryTimeout = setTimeout(
|
||||||
|
() => this._inspectDevicesDiscovered(),
|
||||||
|
this.config.connectionTimeout * 1000,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onInterfacesAdded(path, interfaces) {
|
async onInterfacesAdded(path, interfaces) {
|
||||||
|
|
@ -535,10 +546,9 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async startReconnectPeriodicallyLoop() {
|
async startReconnectPeriodicallyLoop() {
|
||||||
|
logger.verbose('startReconnectPeriodicallyLoop');
|
||||||
if (this.reconnectInProgress) {
|
if (this.reconnectInProgress) {
|
||||||
logger.debug(
|
logger.debug('Reconnect already in progress. Skipping this call.');
|
||||||
'Reconnect already in progress. Skipping this call and returning existing promise.',
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearInterval(this.pingRef);
|
clearInterval(this.pingRef);
|
||||||
|
|
@ -549,13 +559,13 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
await delay(5000);
|
||||||
this.emit('reconnecting');
|
this.emit('reconnecting');
|
||||||
logger.info('Reconnecting BLE...');
|
logger.info('Reconnecting BLE...');
|
||||||
await this.init();
|
await this.init();
|
||||||
break;
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.warn('Failed reconnecting', err);
|
logger.warn('Failed reconnecting.', err);
|
||||||
await delay(1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* eslint-enable no-await-in-loop */
|
/* eslint-enable no-await-in-loop */
|
||||||
|
|
@ -604,28 +614,26 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
async onWriteFailed(error) {
|
async onWriteFailed(error) {
|
||||||
this.consecutiveWriteFails++;
|
this.consecutiveWriteFails++;
|
||||||
logger.debug(`onWriteFailed #${this.consecutiveWriteFails} in a row.`, error);
|
logger.debug(`onWriteFailed #${this.consecutiveWriteFails} in a row.`, error);
|
||||||
|
logger.verbose(`Error message: ${error.message}`);
|
||||||
|
|
||||||
let errorIndicatesDisconnected = false;
|
let errorIndicatesDisconnected = false;
|
||||||
if (error.message.contains('error: 0x0e')) {
|
if (error.message.contains('error: 0x0e')) {
|
||||||
logger.error("'Unlikely error' (0x0e) pinging Plejd. Will retry.", error);
|
logger.error("'Unlikely error' (0x0e) writing to Plejd. Will retry.", error);
|
||||||
} else if (error.message.contains('Not connected')) {
|
} else if (error.message.contains('Not connected')) {
|
||||||
logger.error("'Not connected' (0x0e) pinging Plejd. Plejd device is probably disconnected.");
|
logger.error(
|
||||||
|
"'Not connected' (0x0e) writing to Plejd. Plejd device is probably disconnected.",
|
||||||
|
);
|
||||||
errorIndicatesDisconnected = true;
|
errorIndicatesDisconnected = true;
|
||||||
} else if (
|
} else if (error.message.contains('Method "WriteValue" with signature')) {
|
||||||
error.message.contains(
|
|
||||||
'Method "WriteValue" with signature "aya{sv}" on interface "org.bluez.GattCharacteristic1" doesn\'t exist',
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
logger.error("'Method \"WriteValue\" doesn't exist'. Plejd device is probably disconnected.");
|
logger.error("'Method \"WriteValue\" doesn't exist'. Plejd device is probably disconnected.");
|
||||||
errorIndicatesDisconnected = true;
|
errorIndicatesDisconnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorIndicatesDisconnected) {
|
if (errorIndicatesDisconnected || this.consecutiveWriteFails >= 5) {
|
||||||
logger.warn('Write error indicates BLE is disconnected. Reconnecting...');
|
logger.warn(
|
||||||
await this.startReconnectPeriodicallyLoop();
|
`Write error indicates BLE is disconnected. Retry count ${this.consecutiveWriteFails}. Reconnecting...`,
|
||||||
} else if (this.consecutiveWriteFails >= 5) {
|
);
|
||||||
logger.warn('Write failed 5 times in a row, reconnecting....');
|
this.startReconnectPeriodicallyLoop();
|
||||||
await this.startReconnectPeriodicallyLoop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -882,7 +890,7 @@ class PlejBLEHandler extends EventEmitter {
|
||||||
state,
|
state,
|
||||||
dim: 0,
|
dim: 0,
|
||||||
};
|
};
|
||||||
logger.verbose(`All states: ${this.plejdDevices}`);
|
logger.silly(`All states: ${JSON.stringify(this.plejdDevices, null, 2)}`);
|
||||||
} else if (cmd === BLE_CMD_SCENE_TRIG) {
|
} else if (cmd === BLE_CMD_SCENE_TRIG) {
|
||||||
const sceneId = state;
|
const sceneId = state;
|
||||||
const sceneName = this.deviceRegistry.getSceneName(sceneId);
|
const sceneName = this.deviceRegistry.getSceneName(sceneId);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue