From 126c393cee34de329ccf03d94bacaaf38d020e6c Mon Sep 17 00:00:00 2001 From: John Lindahl Date: Wed, 13 Jan 2021 01:47:05 +0100 Subject: [PATCH 1/3] 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. --- plejd/ble.bluez.js | 49 ++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/plejd/ble.bluez.js b/plejd/ble.bluez.js index 4303e61..a4ea356 100644 --- a/plejd/ble.bluez.js +++ b/plejd/ble.bluez.js @@ -60,7 +60,7 @@ class PlejdService extends EventEmitter { this.writeQueueWaitTime = writeQueueWaitTime; this.writeQueue = []; this.writeQueueRef = null; - + this.maxQueueLengthTarget = MAX_WRITEQUEUE_LENGTH_TARGET || this.devices.length || 5; logger('Max global transition queue length target', this.maxQueueLengthTarget) @@ -85,8 +85,9 @@ class PlejdService extends EventEmitter { this.objectManager.removeAllListeners(); } + this.bleDevices = []; this.connectedDevice = null; - + this.characteristics = { data: 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.'); return; } - - setTimeout(async () => { - await this._internalInit(); - }, this.connectionTimeout * 1000); + return new Promise(resolve => setTimeout(() => resolve(this._internalInit()), this.connectionTimeout * 1000)); } async _internalInit() { @@ -277,7 +275,7 @@ class PlejdService extends EventEmitter { logger('transitioning from', initialBrightness, 'to', targetBrightness, 'in', transition, 'seconds.'); logger('delta brightness', deltaBrightness, ', steps ', transitionSteps, ', interval', transitionInterval, 'ms'); - + const dtStart = new Date(); let nSteps = 0; @@ -286,7 +284,7 @@ class PlejdService extends EventEmitter { this.bleDeviceTransitionTimers[id] = setInterval(() => { let tElapsedMs = (new Date().getTime() - dtStart.getTime()); let tElapsed = tElapsedMs / 1000; - + if (tElapsed > transition || tElapsed < 0) { tElapsed = transition; } @@ -310,7 +308,7 @@ class PlejdService extends EventEmitter { } }, transitionInterval); - } + } else { if (transition && isDimmable) { 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.'); var payload = Buffer.from((id).toString(16).padStart(2, '0') + '0110009701', 'hex'); this.writeQueue.unshift(payload); - } + } else { if (brightness <= 0) { this._turnOff(id); @@ -333,7 +331,7 @@ class PlejdService extends EventEmitter { if (brightness > 255) { brightness = 255; } - + logger('Setting ', id, 'brightness to ' + brightness); brightness = brightness << 8 | brightness; 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(); } + 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) { - if (!this.plejdService || !this.characteristics.data) { + if (!data || !this.plejdService || !this.characteristics.data) { return; } @@ -393,16 +403,13 @@ class PlejdService extends EventEmitter { setTimeout(() => this.write(data, retry), 1000); return; } - console.log('plejd-ble: write failed ' + err); - setTimeout(async () => { - await this.init(); + await this.throttledInit(this.connectionTimeout * 1000); - if (retry) { - logger('reconnected and retrying to write'); - await this.write(data, false); - } - }, this.connectionTimeout * 1000); + if(retry){ + logger('reconnected and retrying to write'); + await this.write(data, false); + } } } @@ -683,4 +690,4 @@ class PlejdService extends EventEmitter { } } -module.exports = PlejdService; \ No newline at end of file +module.exports = PlejdService; From 8fda4a8d6136b03ce78f33f8205ef44848034714 Mon Sep 17 00:00:00 2001 From: John Lindahl Date: Wed, 13 Jan 2021 10:00:07 +0100 Subject: [PATCH 2/3] Define delayedInit in constructor --- plejd/ble.bluez.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plejd/ble.bluez.js b/plejd/ble.bluez.js index a4ea356..c4b1bec 100644 --- a/plejd/ble.bluez.js +++ b/plejd/ble.bluez.js @@ -60,6 +60,7 @@ class PlejdService extends EventEmitter { this.writeQueueWaitTime = writeQueueWaitTime; this.writeQueue = []; this.writeQueueRef = null; + this.delayedInit = null; this.maxQueueLengthTarget = MAX_WRITEQUEUE_LENGTH_TARGET || this.devices.length || 5; logger('Max global transition queue length target', this.maxQueueLengthTarget) From 7bc4801289cd2a16cdeac0f1c16cb078d66e4cf0 Mon Sep 17 00:00:00 2001 From: John Lindahl Date: Wed, 13 Jan 2021 19:43:11 +0100 Subject: [PATCH 3/3] Cleanup of clearTimeout and nonasync funcs --- plejd/ble.bluez.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plejd/ble.bluez.js b/plejd/ble.bluez.js index c4b1bec..825cb01 100644 --- a/plejd/ble.bluez.js +++ b/plejd/ble.bluez.js @@ -98,7 +98,7 @@ class PlejdService extends EventEmitter { }; clearInterval(this.pingRef); - clearInterval(this.writeQueueRef); + clearTimeout(this.writeQueueRef); console.log('init()'); const bluez = await this.bus.getProxyObject(BLUEZ_SERVICE_NAME, '/'); @@ -369,8 +369,8 @@ class PlejdService extends EventEmitter { } // auth done, start ping - await this.startPing(); - await this.startWriteQueue(); + this.startPing(); + this.startWriteQueue(); // After we've authenticated, we need to hook up the event listener // for changes to lastData. @@ -414,7 +414,7 @@ class PlejdService extends EventEmitter { } } - async startPing() { + startPing() { console.log('startPing()'); clearInterval(this.pingRef); @@ -460,9 +460,9 @@ class PlejdService extends EventEmitter { this.emit('pingSuccess', pong[0]); } - async startWriteQueue() { + startWriteQueue() { console.log('startWriteQueue()'); - clearInterval(this.writeQueueRef); + clearTimeout(this.writeQueueRef); this.writeQueueRef = setTimeout(() => this.runWriteQueue(), this.writeQueueWaitTime); }