multiple fixes for improved lifecycle and errors

* Init and _internalInit is actually awaitable
* this.bleDevices is reset on init
* check for actual data in write to preven length of undefined
* Throttled re-inits on write-errors.
This commit is contained in:
John Lindahl 2021-01-13 01:47:05 +01:00 committed by GitHub
parent aa46579f7a
commit 126c393cee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -60,7 +60,7 @@ class PlejdService extends EventEmitter {
this.writeQueueWaitTime = writeQueueWaitTime; this.writeQueueWaitTime = writeQueueWaitTime;
this.writeQueue = []; this.writeQueue = [];
this.writeQueueRef = null; this.writeQueueRef = null;
this.maxQueueLengthTarget = MAX_WRITEQUEUE_LENGTH_TARGET || this.devices.length || 5; this.maxQueueLengthTarget = MAX_WRITEQUEUE_LENGTH_TARGET || this.devices.length || 5;
logger('Max global transition queue length target', this.maxQueueLengthTarget) logger('Max global transition queue length target', this.maxQueueLengthTarget)
@ -85,8 +85,9 @@ class PlejdService extends EventEmitter {
this.objectManager.removeAllListeners(); this.objectManager.removeAllListeners();
} }
this.bleDevices = [];
this.connectedDevice = null; this.connectedDevice = null;
this.characteristics = { this.characteristics = {
data: null, data: null,
lastData: null, lastData: null,
@ -146,10 +147,7 @@ class PlejdService extends EventEmitter {
console.log('plejd-ble: error: failed to start discovery. Make sure no other add-on is currently scanning.'); console.log('plejd-ble: error: failed to start discovery. Make sure no other add-on is currently scanning.');
return; return;
} }
return new Promise(resolve => setTimeout(() => resolve(this._internalInit()), this.connectionTimeout * 1000));
setTimeout(async () => {
await this._internalInit();
}, this.connectionTimeout * 1000);
} }
async _internalInit() { async _internalInit() {
@ -277,7 +275,7 @@ class PlejdService extends EventEmitter {
logger('transitioning from', initialBrightness, 'to', targetBrightness, 'in', transition, 'seconds.'); logger('transitioning from', initialBrightness, 'to', targetBrightness, 'in', transition, 'seconds.');
logger('delta brightness', deltaBrightness, ', steps ', transitionSteps, ', interval', transitionInterval, 'ms'); logger('delta brightness', deltaBrightness, ', steps ', transitionSteps, ', interval', transitionInterval, 'ms');
const dtStart = new Date(); const dtStart = new Date();
let nSteps = 0; let nSteps = 0;
@ -286,7 +284,7 @@ class PlejdService extends EventEmitter {
this.bleDeviceTransitionTimers[id] = setInterval(() => { this.bleDeviceTransitionTimers[id] = setInterval(() => {
let tElapsedMs = (new Date().getTime() - dtStart.getTime()); let tElapsedMs = (new Date().getTime() - dtStart.getTime());
let tElapsed = tElapsedMs / 1000; let tElapsed = tElapsedMs / 1000;
if (tElapsed > transition || tElapsed < 0) { if (tElapsed > transition || tElapsed < 0) {
tElapsed = transition; tElapsed = transition;
} }
@ -310,7 +308,7 @@ class PlejdService extends EventEmitter {
} }
}, transitionInterval); }, transitionInterval);
} }
else { else {
if (transition && isDimmable) { if (transition && isDimmable) {
logger('Could not transition light change. Either initial value is unknown or change is too small. Requested from', initialBrightness, 'to', targetBrightness) logger('Could not transition light change. Either initial value is unknown or change is too small. Requested from', initialBrightness, 'to', targetBrightness)
@ -324,7 +322,7 @@ class PlejdService extends EventEmitter {
logger('no brightness specified, setting ', id, ' to previous known.'); logger('no brightness specified, setting ', id, ' to previous known.');
var payload = Buffer.from((id).toString(16).padStart(2, '0') + '0110009701', 'hex'); var payload = Buffer.from((id).toString(16).padStart(2, '0') + '0110009701', 'hex');
this.writeQueue.unshift(payload); this.writeQueue.unshift(payload);
} }
else { else {
if (brightness <= 0) { if (brightness <= 0) {
this._turnOff(id); this._turnOff(id);
@ -333,7 +331,7 @@ class PlejdService extends EventEmitter {
if (brightness > 255) { if (brightness > 255) {
brightness = 255; brightness = 255;
} }
logger('Setting ', id, 'brightness to ' + brightness); logger('Setting ', id, 'brightness to ' + brightness);
brightness = brightness << 8 | brightness; brightness = brightness << 8 | brightness;
var payload = Buffer.from((id).toString(16).padStart(2, '0') + '0110009801' + (brightness).toString(16).padStart(4, '0'), 'hex'); var payload = Buffer.from((id).toString(16).padStart(2, '0') + '0110009801' + (brightness).toString(16).padStart(4, '0'), 'hex');
@ -379,8 +377,20 @@ class PlejdService extends EventEmitter {
this.characteristics.lastData.StartNotify(); this.characteristics.lastData.StartNotify();
} }
async throttledInit(delay) {
if(this.delayedInit){
return this.delayedInit;
}
this.delayedInit = new Promise((resolve) => setTimeout(async () => {
const result = await this.init();
this.delayedInit = null;
resolve(result)
}, delay))
return this.delayedInit;
}
async write(data, retry = true) { async write(data, retry = true) {
if (!this.plejdService || !this.characteristics.data) { if (!data || !this.plejdService || !this.characteristics.data) {
return; return;
} }
@ -393,16 +403,13 @@ class PlejdService extends EventEmitter {
setTimeout(() => this.write(data, retry), 1000); setTimeout(() => this.write(data, retry), 1000);
return; return;
} }
console.log('plejd-ble: write failed ' + err); console.log('plejd-ble: write failed ' + err);
setTimeout(async () => { await this.throttledInit(this.connectionTimeout * 1000);
await this.init();
if (retry) { if(retry){
logger('reconnected and retrying to write'); logger('reconnected and retrying to write');
await this.write(data, false); await this.write(data, false);
} }
}, this.connectionTimeout * 1000);
} }
} }
@ -683,4 +690,4 @@ class PlejdService extends EventEmitter {
} }
} }
module.exports = PlejdService; module.exports = PlejdService;