From c292225f4ccfea2cd0ef83ee5cc72846c1d31f1e Mon Sep 17 00:00:00 2001 From: Alexander Herlin Date: Tue, 9 Jul 2024 21:36:03 +0200 Subject: [PATCH] Minor refacor of reconnect logic --- CHANGELOG.md | 4 +++ package.json | 2 +- src/PlejdHbPlatform.ts | 1 + src/plejdService.ts | 76 ++++++++++++++++++++++++------------------ 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb5fa60..f15232b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +#### 1.4.2 (2024-07-09) + +Attempt to fix issue with reconnection to mesh. + #### 1.4.1 (2024-06-30) Bug fix: Re-scan when unable to connect to Plejd device diff --git a/package.json b/package.json index cc7b8f1..a11dea0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Plejd", "name": "homebridge-plejd", "author": "Herlix", - "version": "1.4.1", + "version": "1.4.2", "description": "HomeKit support for the Plejd BLE platform using Homebridge", "license": "Apache-2.0", "type": "module", diff --git a/src/PlejdHbPlatform.ts b/src/PlejdHbPlatform.ts index 3672f78..8a18702 100644 --- a/src/PlejdHbPlatform.ts +++ b/src/PlejdHbPlatform.ts @@ -164,6 +164,7 @@ export class PlejdHbPlatform implements DynamicPlatformPlugin { log, this.onPlejdUpdates.bind(this), ); + this.plejdService.configureBLE(); this.discoverDevices(); }; diff --git a/src/plejdService.ts b/src/plejdService.ts index 637d03a..22e298b 100644 --- a/src/plejdService.ts +++ b/src/plejdService.ts @@ -10,6 +10,7 @@ import { randomBytes } from 'crypto'; import noble from '@abandonware/noble'; import { PLEJD_PING_TIMEOUT, PLEJD_WRITE_TIMEOUT } from './settings.js'; import { delay } from './utils.js'; +import EventEmitter from 'events'; const NOBLE_IS_POWER_ON = 'poweredOn'; @@ -38,10 +39,12 @@ enum PlejdCommand { } export class PlejdService { - private connectedPeripheral: noble.Peripheral | null; - private addressBuffer: Buffer | null; - private dataCharacteristic: noble.Characteristic | null; - private sendQueue: Buffer[]; + private connectedPeripheral: noble.Peripheral | null = null; + private addressBuffer: Buffer | null = null; + private dataCharacteristic: noble.Characteristic | null = null; + + private sendQueue: Buffer[] = []; + private eventEmitters: Map = new Map(); constructor( private readonly config: UserInputConfig, @@ -51,25 +54,7 @@ export class PlejdService { isOn: boolean, dim?: number, ) => void, - ) { - this.addressBuffer = null; - this.dataCharacteristic = null; - this.connectedPeripheral = null; - this.sendQueue = []; - - noble.on('stateChange', async (state) => { - await this.startScanning(state); - }); - - noble.on('warning', (msg: string) => { - this.log.warn('Noble warning: ', msg); - }); - - noble.on( - 'discover', - async (peripheral) => await this.onDiscover(peripheral), - ); - } + ) {} /** * @@ -89,7 +74,7 @@ export class PlejdService { !this.dataCharacteristic || !this.addressBuffer ) { - await this.startScanning(); + await this.resetBLE(); return; } @@ -118,8 +103,38 @@ export class PlejdService { this.sendToDeviceQueued(data); }; + configureBLE = () => { + noble.on('stateChange', async (state) => this.connectedPeripheral === null && await this.startScanning(state)); + noble.on('warning', (msg: string) => + this.log.warn('Noble warning: ', msg), + ); + noble.on( + 'discover', + async (peripheral) => await this.onDiscover(peripheral), + ); + }; + // -------------- Private -------------- \\ + + private resetPeripheral = async () => { + if (this.connectedPeripheral?.state === 'connected') { + this.connectedPeripheral.removeAllListeners(); + await this.connectedPeripheral.disconnectAsync(); + } + this.connectedPeripheral = null; + this.addressBuffer = null; + this.dataCharacteristic?.removeAllListeners(); + this.dataCharacteristic = null; + }; + + private resetBLE = async () => { + await this.resetPeripheral(); + await this.startScanning(); + }; + private onDiscover = async (peripheral: noble.Peripheral) => { + this.resetPeripheral(); + this.log.debug( `Discovered | ${peripheral.advertisement.localName} | addr: ${peripheral.address} | RSSI: ${peripheral.rssi} dB`, ); @@ -131,25 +146,21 @@ export class PlejdService { this.log.error( `Connecting failed | ${peripheral.advertisement.localName} | addr: ${peripheral.address}) - err: ${error}`, ); - await this.startScanning(); + this.resetBLE(); return; } this.connectedPeripheral = peripheral; peripheral.once('disconnect', async () => { - this.connectedPeripheral?.removeAllListeners(); - this.connectedPeripheral = null; - this.addressBuffer = null; - this.dataCharacteristic = null; this.log.info('Disconnected from mesh'); - await this.startScanning(); + await this.resetBLE(); }); const characteristics = await this.discoverCaracteristics(peripheral); if (!characteristics) { this.log.error('Failed to discover characteristics, disconnecting...'); - await peripheral.disconnectAsync(); + await this.resetBLE(); return; } await this.setupDevice(peripheral, characteristics); @@ -263,7 +274,7 @@ export class PlejdService { 'Ping failed, device disconnected, will retry to connect to mesh: ', error, ); - await this.startScanning(); + await this.resetBLE(); } } }; @@ -277,6 +288,7 @@ export class PlejdService { !this.addressBuffer || this.addressBuffer?.byteLength === 0 ) { + await this.resetBLE(); return; }