diff --git a/package-lock.json b/package-lock.json index 8e89c64..6a193d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "license": "Apache-2.0", "dependencies": { "bonjour-service": "^1.2.1", + "debounce": "^2.1.0", "eventsource": "^2.0.2", "node-fetch": "^3.3.2", "strip-ansi": "^7.1.0" @@ -925,6 +926,17 @@ "node": ">= 12" } }, + "node_modules/debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz", + "integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", diff --git a/package.json b/package.json index 0d5041c..f100f18 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ ], "dependencies": { "bonjour-service": "^1.2.1", + "debounce": "^2.1.0", "eventsource": "^2.0.2", "node-fetch": "^3.3.2", "strip-ansi": "^7.1.0" diff --git a/src/accessory/base.ts b/src/accessory/base.ts index 24ee800..6ea2305 100644 --- a/src/accessory/base.ts +++ b/src/accessory/base.ts @@ -1,4 +1,5 @@ import { CharacteristicValue, Logger, PlatformAccessory, Service, WithUUID } from 'homebridge'; +import debounce, { DebouncedFunction } from 'debounce'; import { LogMessageEvent, PingMessageEvent, StateUpdateMessageEvent, StateUpdateRecord } from '../utils/eventsource'; import { BlaQHomebridgePluginPlatform } from '../platform'; import { BlaQTextSensorEvent } from '../types'; @@ -8,6 +9,7 @@ export interface BaseBlaQAccessoryInterface { handleStateEvent: (stateEvent: StateUpdateMessageEvent) => void; handleLogEvent?: (logEvent: LogMessageEvent) => void; handlePingEvent?: (pingEvent: PingMessageEvent) => void; + resetSyncState: () => void; } export type BaseBlaQAccessoryConstructorParams = { @@ -29,6 +31,11 @@ export const correctAPIBaseURL = (inputURL: string) => { return correctedAPIBaseURL; }; +type DebouncedService = (typeof Service | Service) & { + setCharacteristic: DebouncedFunction<(name: string, value: CharacteristicValue) => Service>; + updateCharacteristic: DebouncedFunction<(name: string, value: CharacteristicValue) => Service>; +}; + export class BaseBlaQAccessory implements BaseBlaQAccessoryInterface { protected apiBaseURL: string; protected firmwareVersion?: string; @@ -77,9 +84,10 @@ export class BaseBlaQAccessory implements BaseBlaQAccessoryInterface { return this.constructor.name; } - protected getOrAddService(service: WithUUID | Service): Service{ - return this.accessory.getService(service as WithUUID) || + protected getOrAddService(service: WithUUID | Service): Service { + const retService = this.accessory.getService(service as WithUUID) || this.accessory.addService(service as Service); + return this.debounceService(retService); } protected removeService(service: WithUUID | Service): void{ @@ -89,6 +97,21 @@ export class BaseBlaQAccessory implements BaseBlaQAccessoryInterface { } } + protected debounceService(service: Service): Service { + const originalSet = service.setCharacteristic.bind(service); + const originalUpdate = service.updateCharacteristic.bind(service); + const retService: DebouncedService = service as DebouncedService; + retService.setCharacteristic = debounce( + (name: string, value: CharacteristicValue) => originalSet(name, value), + 100, + ); + retService.updateCharacteristic = debounce( + (name: string, value: CharacteristicValue) => originalUpdate(name, value), + 100, + ); + return retService as Service; + } + processQueuedEvents() { while(this.queuedEvents.length){ const event = this.queuedEvents.shift()!; @@ -103,6 +126,10 @@ export class BaseBlaQAccessory implements BaseBlaQAccessoryInterface { } } + resetSyncState(){ + this.synced = false; + } + handlePingEvent(pingEvent: PingMessageEvent){ if(!this.synced){ this.queuedEvents.push({type: 'ping', event: pingEvent}); diff --git a/src/hub.ts b/src/hub.ts index 6762d46..b485034 100644 --- a/src/hub.ts +++ b/src/hub.ts @@ -75,6 +75,7 @@ export class BlaQHub { if(this.eventSource){ this.eventSource.close(); } + this.accessories.forEach(accessory => accessory.resetSyncState()); this.eventSource = new AutoReconnectingEventSource({ host: this.host, port: this.port,