reworked ble connection handling

This commit is contained in:
Marcus Westin 2019-12-14 14:11:39 +01:00
parent aa71c9ec4c
commit 43e3a8b8af

View file

@ -3,6 +3,7 @@ const crypto = require('crypto');
const xor = require('buffer-xor'); const xor = require('buffer-xor');
const _ = require('lodash'); const _ = require('lodash');
const EventEmitter = require('events'); const EventEmitter = require('events');
const sleep = require('sleep');
let debug = ''; let debug = '';
@ -63,6 +64,24 @@ class Controller extends EventEmitter {
self.peripherals.push(peripheral); self.peripherals.push(peripheral);
} }
}); });
noble.on('disconnect', async () => {
if (self.peripherals.length) {
logger('peripherals already scanned.');
this.connectedIndex = 0;
await self.connect();
}
});
}
async reinit() {
console.log('reinitializing the Plejd add-on.');
this.once('scanComplete', async (peripherals) => {
console.log('found Plejd devices, reconnecting');
await this.connect();
});
await this.scan();
} }
async scan() { async scan() {
@ -88,9 +107,9 @@ class Controller extends EventEmitter {
return Promise.resolve(false); return Promise.resolve(false);
} }
if (!this.peripherals.length) { // if (!this.peripherals.length) {
await this.scan(); // await this.scan();
} // }
this.isConnecting = true; this.isConnecting = true;
@ -114,7 +133,7 @@ class Controller extends EventEmitter {
} }
self.peripheral = self.peripherals[idx]; self.peripheral = self.peripherals[idx];
console.log('connected to Plejd device with addr ' + self.peripheral.address); console.log('connected to Plejd device with addr ' + self.peripheral.address + ' with rssi ' + self.peripheral.rssi);
self.peripheral_address = self._reverseBuffer(Buffer.from(String(self.peripheral.address).replace(/\-/g, '').replace(/\:/g, ''), 'hex')); self.peripheral_address = self._reverseBuffer(Buffer.from(String(self.peripheral.address).replace(/\-/g, '').replace(/\:/g, ''), 'hex'));
@ -149,7 +168,7 @@ class Controller extends EventEmitter {
&& this.authCharacteristic && this.authCharacteristic
&& this.pingCharacteristic) { && this.pingCharacteristic) {
this.on('authenticated', () => { this.once('authenticated', () => {
logger('Plejd is connected and authenticated.'); logger('Plejd is connected and authenticated.');
this.connectedIndex = idx; this.connectedIndex = idx;
@ -173,6 +192,11 @@ class Controller extends EventEmitter {
this.isConnected = true; this.isConnected = true;
this.isConnecting = false; this.isConnecting = false;
// make sure to write any queued up messages to the Plejd devices
if (this.writeQueue && this.writeQueue.length > 0) {
this.flush();
}
} }
return Promise.resolve(true); return Promise.resolve(true);
@ -230,7 +254,16 @@ class Controller extends EventEmitter {
if (this.peripheral) { if (this.peripheral) {
try { try {
// disconnect
await this.peripheral.disconnect(); await this.peripheral.disconnect();
// we need to reset the ble adapter too
noble._bindings._hci.reset();
// wait 200 ms for reset command to take effect :)
sleep.msleep(200);
// now we're ready to connect again
} }
catch (error) { catch (error) {
console.log('error: unable to disconnect from Plejd: ' + error); console.log('error: unable to disconnect from Plejd: ' + error);
@ -253,10 +286,10 @@ class Controller extends EventEmitter {
} }
async turnOn(id, brightness) { async turnOn(id, brightness) {
if (!this.isConnected) { // if (this.peripheral.state !== 'connected') {
console.log('warning: not connected, will connect. might take a few seconds.'); // console.log('warning: not connected, will connect. might take a few seconds.');
await this.connect(); // await this.reinit();
} // }
logger('turning on ' + id + ' at brightness ' + brightness); logger('turning on ' + id + ' at brightness ' + brightness);
@ -273,10 +306,10 @@ class Controller extends EventEmitter {
} }
async turnOff(id) { async turnOff(id) {
if (!this.isConnected) { // if (this.peripheral.state !== 'connected') {
console.log('warning: not connected, will connect. might take a few seconds.'); // console.log('warning: not connected, will connect. might take a few seconds.');
await this.connect(); // await this.reinit();
} // }
logger('turning off ' + id); logger('turning off ' + id);
@ -291,13 +324,13 @@ class Controller extends EventEmitter {
logger('starting ping'); logger('starting ping');
this.pingRef = setInterval(async () => { this.pingRef = setInterval(async () => {
logger('ping'); logger('ping');
if (self.isConnected) { if (self.peripheral.state == 'connected') {
await self.plejdPing(async (pingOk) => { await self.plejdPing(async (pingOk) => {
if (!pingOk) { if (!pingOk) {
logger('ping failed'); console.log('error: ping failed');
await self.disconnect(); await self.disconnect();
await self.connect(); // await self.reinit();
} }
else { else {
logger('pong'); logger('pong');
@ -306,7 +339,7 @@ class Controller extends EventEmitter {
} }
else { else {
await self.disconnect(); await self.disconnect();
await self.connect(); // await self.reinit();
} }
}, 3000); }, 3000);
} }
@ -316,7 +349,7 @@ class Controller extends EventEmitter {
try { try {
// make sure we're connected, otherwise, return false and reconnect // make sure we're connected, otherwise, return false and reconnect
if (this.peripheral.state !== 'connected') { if (this.peripheral.state != 'connected') {
callback(false); callback(false);
return; return;
} }
@ -344,8 +377,7 @@ class Controller extends EventEmitter {
} }
catch (error) { catch (error) {
console.log('error: writing to plejd: ' + error); console.log('error: writing to plejd: ' + error);
await self.disconnect(); callback(false);
await self.connect();
} }
} }
@ -383,7 +415,7 @@ class Controller extends EventEmitter {
const self = this; const self = this;
try { try {
if (this.isConnecting) { if (this.peripheral.state !== 'connected') {
logger('adding message to queue.'); logger('adding message to queue.');
this.writeQueue.push(data); this.writeQueue.push(data);
return Promise.resolve(true); return Promise.resolve(true);
@ -395,11 +427,7 @@ class Controller extends EventEmitter {
} }
this.dataCharacteristic.write(this._encryptDecrypt(this.cryptoKey, this.peripheral_address, data), false); this.dataCharacteristic.write(this._encryptDecrypt(this.cryptoKey, this.peripheral_address, data), false);
this.flush();
let writeData;
while ((writeData = this.writeQueue.shift()) !== undefined) {
this.dataCharacteristic.write(this._encryptDecrypt(this.cryptoKey, this.peripheral_address, writeData), false);
}
if (!this.keepAlive) { if (!this.keepAlive) {
clearTimeout(this.disconnectIntervalRef); clearTimeout(this.disconnectIntervalRef);
@ -411,7 +439,14 @@ class Controller extends EventEmitter {
catch (error) { catch (error) {
console.log('error: writing to plejd: ' + error); console.log('error: writing to plejd: ' + error);
await self.disconnect(); await self.disconnect();
await self.connect(); // await self.connect();
}
}
async flush() {
let writeData;
while ((writeData = this.writeQueue.shift()) !== undefined) {
this.dataCharacteristic.write(this._encryptDecrypt(this.cryptoKey, this.peripheral_address, writeData), false);
} }
} }