From 608328e9b3182d7b56e78fb2750f2648f5346a3f Mon Sep 17 00:00:00 2001 From: George Talusan Date: Sat, 31 Aug 2024 18:35:45 -0400 Subject: [PATCH] set up eufy-robovac-js and first service/characteristics --- package-lock.json | 133 +++++++++++++++++++++++++++++++++++-- package.json | 3 + src/defaultAccessory.ts | 72 ++++++++++++++++++++ src/index.ts | 7 +- src/platform.ts | 122 +++++++++++++++++----------------- src/platformAccessory.ts | 139 --------------------------------------- 6 files changed, 262 insertions(+), 214 deletions(-) create mode 100644 src/defaultAccessory.ts delete mode 100644 src/platformAccessory.ts diff --git a/package-lock.json b/package-lock.json index 2499e02..189745c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,16 @@ { - "name": "homebridge-plugin-name", - "version": "1.0.0", + "name": "homebridge-plugin-eufy-robovac", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "homebridge-plugin-name", - "version": "1.0.0", - "license": "Apache-2.0", + "name": "homebridge-plugin-eufy-robovac", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "@george.talusan/eufy-robovac-js": "^0.0.4" + }, "devDependencies": { "@eslint/js": "^9.9.0", "@types/eslint__js": "^8.42.3", @@ -136,6 +139,17 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@george.talusan/eufy-robovac-js": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@george.talusan/eufy-robovac-js/-/eufy-robovac-js-0.0.4.tgz", + "integrity": "sha512-35xkxX6xcifG7ret7e819swDdO7J2+nenIQMBz4TM5i7YxEgpvmk3pOlogUy9uRu4BUX9dgKvebry/o/YghBPQ==", + "license": "ISC", + "dependencies": { + "debug": "^4.3.5", + "net-ping": "^1.2.4", + "tuyapi": "github:codetheweb/tuyapi" + } + }, "node_modules/@homebridge/ciao": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.3.1.tgz", @@ -423,6 +437,12 @@ "undici-types": "~6.13.0" } }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", @@ -1021,7 +1041,6 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -1395,6 +1414,12 @@ "through": "^2.3.8" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2493,7 +2518,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, "license": "MIT" }, "node_modules/multicast-dns": { @@ -2517,6 +2541,12 @@ "dev": true, "license": "MIT" }, + "node_modules/nan": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "license": "MIT" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2524,6 +2554,15 @@ "dev": true, "license": "MIT" }, + "node_modules/net-ping": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/net-ping/-/net-ping-1.2.4.tgz", + "integrity": "sha512-9IbIgPonxYj5HMkgCYXFqHF/pz462qsxA7RVLA6sI604eQyaecxVKl3yrDGHajjKZpUL1r2VBMwd0KVMnPO5Rw==", + "license": "MIT", + "dependencies": { + "raw-socket": "*" + } + }, "node_modules/node-persist": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.12.tgz", @@ -2674,6 +2713,15 @@ "node": ">= 0.8.0" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2706,6 +2754,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", @@ -2878,6 +2967,16 @@ ], "license": "MIT" }, + "node_modules/raw-socket": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/raw-socket/-/raw-socket-1.8.1.tgz", + "integrity": "sha512-AjadKwsmroOZkAy/t9xm3wkHWN/WOJZMSryHAqABwE8A2j5DmqJevgdYR1das5xOWyoL11UFPRu7TYEDFs9vdw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "nan": "2.19.*" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2920,6 +3019,15 @@ "node": ">=4" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3417,6 +3525,17 @@ "dev": true, "license": "0BSD" }, + "node_modules/tuyapi": { + "version": "7.5.2", + "resolved": "git+ssh://git@github.com/codetheweb/tuyapi.git#99d25828f14a78ff839166d7e50119e426572cb4", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "p-queue": "6.6.2", + "p-retry": "4.6.2", + "p-timeout": "3.2.0" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", diff --git a/package.json b/package.json index a8166eb..e518a45 100644 --- a/package.json +++ b/package.json @@ -44,5 +44,8 @@ "ts-node": "^10.9.2", "typescript": "^5.5.4", "typescript-eslint": "^8.0.1" + }, + "dependencies": { + "@george.talusan/eufy-robovac-js": "^0.0.4" } } diff --git a/src/defaultAccessory.ts b/src/defaultAccessory.ts new file mode 100644 index 0000000..f9aeb53 --- /dev/null +++ b/src/defaultAccessory.ts @@ -0,0 +1,72 @@ +import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; + +import type { EufyRobovacHomebridgePlatform } from './platform.js'; + +interface RobovacEvent { + command: string; + value: number | string | object | null; +}; + +export class DefaultPlatformAccessory { + private service: Service; + + constructor( + private readonly platform: EufyRobovacHomebridgePlatform, + private readonly accessory: PlatformAccessory, + ) { + const displayName = this.accessory.context.displayName; + + // set accessory information + 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'); + + this.service = this.accessory.getService(this.platform.Service.Switch) || this.accessory.addService(this.platform.Service.Switch); + this.service.setCharacteristic(this.platform.Characteristic.Name, `${displayName}`); + this.service.getCharacteristic(this.platform.Characteristic.On) + .onSet(this.setOn.bind(this)) + .onGet(this.getOn.bind(this)); + + const batteryLevelService = this.accessory.getService(`${displayName} Battery Level`) || + this.accessory.addService(this.platform.Service.Battery, `${displayName} Battery Level`); + + const updateBatteryLevel = () => { + try { + batteryLevelService.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.platform.robovac.batteryLevel()); + } catch (error: unknown) { + this.platform.log.error(error as string); + } + }; + + this.platform.robovac.on('tuya.data', updateBatteryLevel); + this.platform.robovac.on('event', (event: RobovacEvent) => { + this.platform.log('battery', event.command, event.value); + if (event.command === 'battery') { + updateBatteryLevel(); + } + }); + } + + async setOn(value: CharacteristicValue) { + try { + const on: boolean = value as boolean; + if (on) { + await this.platform.robovac.clean(); + } else { + await this.platform.robovac.goHome(); + } + } catch (error: unknown) { + this.platform.log.error(error as string); + } + } + + async getOn(): Promise { + try { + return !this.platform.robovac.docked(); + } catch (error: unknown) { + this.platform.log.error(error as string); + return false; + } + } +} diff --git a/src/index.ts b/src/index.ts index 0b43006..5fae28b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,8 @@ import type { API } from 'homebridge'; -import { ExampleHomebridgePlatform } from './platform.js'; +import { EufyRobovacHomebridgePlatform } from './platform.js'; import { PLATFORM_NAME } from './settings.js'; -/** - * This method registers the platform with Homebridge - */ export default (api: API) => { - api.registerPlatform(PLATFORM_NAME, ExampleHomebridgePlatform); + api.registerPlatform(PLATFORM_NAME, EufyRobovacHomebridgePlatform); }; diff --git a/src/platform.ts b/src/platform.ts index 94b8a8d..5819f7c 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,20 +1,27 @@ import type { API, Characteristic, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig, Service } from 'homebridge'; -import { ExamplePlatformAccessory } from './platformAccessory.js'; +import { DefaultPlatformAccessory } from './defaultAccessory.js'; import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'; +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); + +const { RoboVac } = require('@george.talusan/eufy-robovac-js'); + /** * HomebridgePlatform * This class is the main constructor for your plugin, this is where you should * parse the user config and discover/register accessories with Homebridge. */ -export class ExampleHomebridgePlatform implements DynamicPlatformPlugin { +export class EufyRobovacHomebridgePlatform implements DynamicPlatformPlugin { public readonly Service: typeof Service; public readonly Characteristic: typeof Characteristic; // this is used to track restored cached accessories public readonly accessories: PlatformAccessory[] = []; + public robovac: typeof RoboVac; + constructor( public readonly log: Logging, public readonly config: PlatformConfig, @@ -23,23 +30,36 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin { this.Service = api.hap.Service; this.Characteristic = api.hap.Characteristic; + if (!this.parseConfig()) { + return; + } + this.log.debug('Finished initializing platform:', this.config.name); - // When this event is fired it means Homebridge has restored all cached accessories from disk. - // Dynamic Platform plugins should only register new accessories after this event was fired, - // in order to ensure they weren't added to homebridge already. This event can also be used - // to start discovery of new accessories. - this.api.on('didFinishLaunching', () => { + this.api.on('didFinishLaunching', async () => { log.debug('Executed didFinishLaunching callback'); - // run the method to discover / register your devices as accessories + + try { + this.robovac = new RoboVac({ ip: config.ip, deviceId: config.deviceId, localKey: config.deviceKey }); + this.robovac.on('tuya.disconnected', async () => { + const id = setInterval(async () => { + try { + this.log.debug('reconnecting...'); + await this.robovac.connect(); + clearInterval(id); + } catch (error: unknown) { + this.log.error(error as string); + } + }, 2000); + }); + await this.robovac.initialize(); + } catch (error: unknown) { + this.log.error(error as string); + } this.discoverDevices(); }); } - /** - * This function is invoked when homebridge restores cached accessories from disk at startup. - * It should be used to set up event handlers for characteristics and update respective values. - */ configureAccessory(accessory: PlatformAccessory) { this.log.info('Loading accessory from cache:', accessory.displayName); @@ -47,71 +67,47 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin { this.accessories.push(accessory); } - /** - * This is an example method showing how to register discovered accessories. - * Accessories must only be registered once, previously created accessories - * must not be registered again to prevent "duplicate UUID" errors. - */ discoverDevices() { - // EXAMPLE ONLY - // A real plugin you would discover accessories from the local network, cloud services - // or a user-defined array in the platform config. - const exampleDevices = [ + const accessories = [ { - exampleUniqueId: 'ABCD', - exampleDisplayName: 'Bedroom', - }, - { - exampleUniqueId: 'EFGH', - exampleDisplayName: 'Kitchen', + displayName: () => { + return `${this.config.name} Clean`; + }, + uuid: () => { + return this.api.hap.uuid.generate(`${this.config.name}-${this.config.ip}-Clean`); + }, + make: (accessory: PlatformAccessory) => { + new DefaultPlatformAccessory(this, accessory); + }, }, ]; // loop over the discovered devices and register each one if it has not already been registered - for (const device of exampleDevices) { - // generate a unique id for the accessory this should be generated from - // something globally unique, but constant, for example, the device serial - // number or MAC address - const uuid = this.api.hap.uuid.generate(device.exampleUniqueId); - - // see if an accessory with the same uuid has already been registered and restored from - // the cached devices we stored in the `configureAccessory` method above + for (const a of accessories) { + const uuid = a.uuid(); const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid); if (existingAccessory) { - // the accessory already exists this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName); - - // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. e.g.: - // existingAccessory.context.device = device; - // this.api.updatePlatformAccessories([existingAccessory]); - - // create the accessory handler for the restored accessory - // this is imported from `platformAccessory.ts` - new ExamplePlatformAccessory(this, existingAccessory); - - // it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, e.g.: - // remove platform accessories when no longer present - // this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]); - // this.log.info('Removing existing accessory from cache:', existingAccessory.displayName); + a.make(existingAccessory); } else { - // the accessory does not yet exist, so we need to create it - this.log.info('Adding new accessory:', device.exampleDisplayName); - - // create a new accessory - const accessory = new this.api.platformAccessory(device.exampleDisplayName, uuid); - - // store a copy of the device object in the `accessory.context` - // the `context` property can be used to store any data about the accessory you may need - accessory.context.device = device; - - // create the accessory handler for the newly create accessory - // this is imported from `platformAccessory.ts` - new ExamplePlatformAccessory(this, accessory); + this.log.info('Adding new accessory:', a.displayName()); - // link the accessory to your platform + const accessory = new this.api.platformAccessory(a.displayName(), uuid); + accessory.context.displayName = a.displayName(); + a.make(accessory); this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); } } } + + parseConfig(): boolean { + ['name', 'ip', 'deviceId', 'deviceKey'].forEach((required: string) => { + if (!this.config[required]) { + this.log.error(`Please configure ${PLATFORM_NAME} correctly. Missing key '${required}'`); + return false; + } + }); + return true; + } } diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts deleted file mode 100644 index fa4266d..0000000 --- a/src/platformAccessory.ts +++ /dev/null @@ -1,139 +0,0 @@ -import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; - -import type { ExampleHomebridgePlatform } from './platform.js'; - -/** - * Platform Accessory - * An instance of this class is created for each accessory your platform registers - * Each accessory may expose multiple services of different service types. - */ -export class ExamplePlatformAccessory { - private service: Service; - - /** - * These are just used to create a working example - * You should implement your own code to track the state of your accessory - */ - private exampleStates = { - On: false, - Brightness: 100, - }; - - constructor( - private readonly platform: ExampleHomebridgePlatform, - private readonly accessory: PlatformAccessory, - ) { - // set accessory information - this.accessory.getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Default-Manufacturer') - .setCharacteristic(this.platform.Characteristic.Model, 'Default-Model') - .setCharacteristic(this.platform.Characteristic.SerialNumber, 'Default-Serial'); - - // get the LightBulb service if it exists, otherwise create a new LightBulb service - // you can create multiple services for each accessory - this.service = this.accessory.getService(this.platform.Service.Lightbulb) || this.accessory.addService(this.platform.Service.Lightbulb); - - // set the service name, this is what is displayed as the default name on the Home app - // in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method. - this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.exampleDisplayName); - - // each service must implement at-minimum the "required characteristics" for the given service type - // see https://developers.homebridge.io/#/service/Lightbulb - - // register handlers for the On/Off Characteristic - this.service.getCharacteristic(this.platform.Characteristic.On) - .onSet(this.setOn.bind(this)) // SET - bind to the `setOn` method below - .onGet(this.getOn.bind(this)); // GET - bind to the `getOn` method below - - // register handlers for the Brightness Characteristic - this.service.getCharacteristic(this.platform.Characteristic.Brightness) - .onSet(this.setBrightness.bind(this)); // SET - bind to the 'setBrightness` method below - - /** - * Creating multiple services of the same type. - * - * To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error, - * when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id: - * this.accessory.getService('NAME') || this.accessory.addService(this.platform.Service.Lightbulb, 'NAME', 'USER_DEFINED_SUBTYPE_ID'); - * - * The USER_DEFINED_SUBTYPE must be unique to the platform accessory (if you platform exposes multiple accessories, each accessory - * can use the same subtype id.) - */ - - // Example: add two "motion sensor" services to the accessory - const motionSensorOneService = this.accessory.getService('Motion Sensor One Name') - || this.accessory.addService(this.platform.Service.MotionSensor, 'Motion Sensor One Name', 'YourUniqueIdentifier-1'); - - const motionSensorTwoService = this.accessory.getService('Motion Sensor Two Name') - || this.accessory.addService(this.platform.Service.MotionSensor, 'Motion Sensor Two Name', 'YourUniqueIdentifier-2'); - - /** - * Updating characteristics values asynchronously. - * - * Example showing how to update the state of a Characteristic asynchronously instead - * of using the `on('get')` handlers. - * Here we change update the motion sensor trigger states on and off every 10 seconds - * the `updateCharacteristic` method. - * - */ - let motionDetected = false; - setInterval(() => { - // EXAMPLE - inverse the trigger - motionDetected = !motionDetected; - - // push the new value to HomeKit - motionSensorOneService.updateCharacteristic(this.platform.Characteristic.MotionDetected, motionDetected); - motionSensorTwoService.updateCharacteristic(this.platform.Characteristic.MotionDetected, !motionDetected); - - this.platform.log.debug('Triggering motionSensorOneService:', motionDetected); - this.platform.log.debug('Triggering motionSensorTwoService:', !motionDetected); - }, 10000); - } - - /** - * Handle "SET" requests from HomeKit - * These are sent when the user changes the state of an accessory, for example, turning on a Light bulb. - */ - async setOn(value: CharacteristicValue) { - // implement your own code to turn your device on/off - this.exampleStates.On = value as boolean; - - this.platform.log.debug('Set Characteristic On ->', value); - } - - /** - * Handle the "GET" requests from HomeKit - * These are sent when HomeKit wants to know the current state of the accessory, for example, checking if a Light bulb is on. - * - * GET requests should return as fast as possible. A long delay here will result in - * HomeKit being unresponsive and a bad user experience in general. - * - * If your device takes time to respond you should update the status of your device - * asynchronously instead using the `updateCharacteristic` method instead. - - * @example - * this.service.updateCharacteristic(this.platform.Characteristic.On, true) - */ - async getOn(): Promise { - // implement your own code to check if the device is on - const isOn = this.exampleStates.On; - - this.platform.log.debug('Get Characteristic On ->', isOn); - - // if you need to return an error to show the device as "Not Responding" in the Home app: - // throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE); - - return isOn; - } - - /** - * Handle "SET" requests from HomeKit - * These are sent when the user changes the state of an accessory, for example, changing the Brightness - */ - async setBrightness(value: CharacteristicValue) { - // implement your own code to set the brightness - this.exampleStates.Brightness = value as number; - - this.platform.log.debug('Set Characteristic Brightness -> ', value); - } -}