From 1fe7833062f25d535232b25c9648ab200a67c433 Mon Sep 17 00:00:00 2001 From: George Talusan Date: Fri, 6 Sep 2024 13:06:08 -0400 Subject: [PATCH] set volume --- src/platform.ts | 13 +++++ src/speakerAccessory.ts | 121 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/speakerAccessory.ts diff --git a/src/platform.ts b/src/platform.ts index 0e289af..6fa3344 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -2,6 +2,7 @@ import type { API, Characteristic, DynamicPlatformPlugin, Logging, PlatformAcces import { DefaultPlatformAccessory } from './defaultAccessory.js'; import { CleanRoomsPlatformAccessory } from './cleanRoomsAccessory.js'; +import { SpeakerPlatformAccessory } from './speakerAccessory.js'; import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'; import { createRequire } from 'module'; @@ -86,6 +87,18 @@ export class EufyRobovacHomebridgePlatform implements DynamicPlatformPlugin { new DefaultPlatformAccessory(this, accessory); }, }, + { + displayName: () => { + return `${this.config.name} Speaker`; + }, + uuid: () => { + return this.api.hap.uuid.generate(`${this.config.name}-${this.config.ip}-speaker`); + }, + make: (accessory: PlatformAccessory) => { + new SpeakerPlatformAccessory(this, accessory); + }, + }, + ]; const roomSwitches = this.config.roomSwitches; diff --git a/src/speakerAccessory.ts b/src/speakerAccessory.ts new file mode 100644 index 0000000..cc82e3a --- /dev/null +++ b/src/speakerAccessory.ts @@ -0,0 +1,121 @@ +import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; + +import type { EufyRobovacHomebridgePlatform } from './platform.js'; + +interface RobovacEvent { + command: string; + value: boolean | number | string | object | null; +}; + +export class SpeakerPlatformAccessory { + volume: number = 0; + + constructor( + private readonly platform: EufyRobovacHomebridgePlatform, + private readonly accessory: PlatformAccessory, + ) { + const displayName = this.accessory.context.displayName; + + this.accessory.getService(this.platform.Service.AccessoryInformation)! + .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Eufy') + .setCharacteristic(this.platform.Characteristic.Model, 'Robovac') + .setCharacteristic(this.platform.Characteristic.SerialNumber, 'Default-Serial'); + + const main: Service = this.accessory.getService(`${displayName}`) || + this.accessory.addService(this.platform.Service.Speaker, `${displayName}`, 'volume'); + main.getCharacteristic(this.platform.Characteristic.Active) + .onSet(this.setActive.bind(this)) + .onGet(this.getActive.bind(this)); + main.getCharacteristic(this.platform.Characteristic.Volume) + .onSet(this.setVolume.bind(this)) + .onGet(this.getVolume.bind(this)); + main.getCharacteristic(this.platform.Characteristic.Mute) + .onSet(this.setMute.bind(this)) + .onGet(this.getMute.bind(this)); + + const updateVolumeLevel = () => { + if (!this.connected()) { + return; + } + try { + this.volume = this.platform.robovac.volume(); + main.updateCharacteristic(this.platform.Characteristic.Volume, this.volume); + } catch (error: unknown) { + this.platform.log.error(error as string); + } + }; + + this.platform.robovac.on('tuya.data', updateVolumeLevel); + + this.platform.robovac.on('event', (event: RobovacEvent) => { + if (event.command === 'volume') { + updateVolumeLevel(); + } + }); + } + + connected(): boolean { + if (!this.platform.connected) { + this.platform.log.warn('not connected'); + } + return this.platform.connected; + } + + async setActive() { + } + + async getActive(): Promise { + return true; + } + + async setVolume(value: CharacteristicValue) { + if (!this.connected()) { + return; + } + if (this.volume === value as number) { + return; + } + try { + await this.platform.robovac.setVolume(value as number); + } catch (error: unknown) { + this.platform.log.error(error as string); + } + } + + async getVolume(): Promise { + if (!this.connected()) { + return 0; + } + try { + return this.volume; + } catch (error: unknown) { + this.platform.log.error(error as string); + return 0; + } + } + + async setMute(value: CharacteristicValue) { + if (!this.connected()) { + return; + } + try { + const on: boolean = value as boolean; + await this.platform.robovac.setVolume(on? 0 : this.volume); + } catch (error: unknown) { + this.platform.log.error(error as string); + } + } + + async getMute(): Promise { + if (!this.connected()) { + return false; + } + try { + return this.volume === 0; + } catch (error: unknown) { + this.platform.log.error(error as string); + return false; + } + } + +}