diff --git a/README.md b/README.md index 430ae9c..ab4c1c2 100644 --- a/README.md +++ b/README.md @@ -2,37 +2,56 @@ [Homebridge GREE Air Conditioner Platform Plugin](https://github.com/eibenp/homebridge-gree-airconditioner) is a dynamic platform plugin for [Homebridge](https://github.com/homebridge/homebridge) which allows control of GREE Air Conditioner devices from [Apple's Home app](https://www.apple.com/home-app/). (Make GREE Air Conditioner HomeKit compatible.) -You can add all of your GREE Air Conditioner devices to the Home App by specifying the network broadcast address, and Homebridge will find all connected devices. Each device appears in the Home App as a Heater Cooler device and also as a separate Termperature Sensor (if temperature sensor is supported by the physical device). This allows to define automations (e.g. turn on) based on current temperature in the room. +You can add all of your GREE Air Conditioner devices to the Home App by specifying the network broadcast address, and Homebridge will find all connected devices. Each device appears in the Home App as a Heater Cooler device. It is also possible to add a separate Termperature Sensor (if temperature sensor is supported by the physical device). This allows to define automations (e.g. turn on) based on current temperature in the room. Be careful, if the device does not support internal temperature sensor but is added as a separate accessory, Home App will display the target temperature not the measured one. Child accessory does not appear in Home App if physical sensor is not available in the AC unit. -Quiet / Auto / Powerful mode is supported by the fan speed control. Minimum value turns on Quite mode. Next value is Auto mode. Maximum value is Powerful mode. All other values between them are exact fan speeds (Low, MediumLow**, Medium, MediumHigh**, High) +Quiet / Auto / Powerful mode is supported by the fan speed control. Minimum value turns on Quiet mode. Next value is Auto mode. Maximum value is Powerful mode. All other values between them are exact fan speeds (Low, MediumLow**, Medium, MediumHigh**, High) ** these values are supported only on 5-speed units -It is recommended, to add all devices to the Homebridge configuration. So you can control all parameters of the devices and also disable them, if not all of them should be controlled using the Home App. Devices are identified by MAC Address (Serial Number). It can be queried by the official [GREE+ mobile app](https://apps.apple.com/us/app/gree/id1167857672). (The app is required to connect the devices to the local WiFi network for the first time.) +It is recommended to add all devices to the Homebridge configuration, so that you can control all their parameters. If you don't want to control all of the devices in Home App, then you need to add to the configuration and disable the ones you don't need. Devices are identified by MAC Address (Serial Number). It can be queried using the official [GREE+ mobile app](https://apps.apple.com/us/app/gree/id1167857672). (The app is required to connect the devices to the local WiFi network for the first time.) -xFan function is also supported, but it works automatically if enabled in Homebridge configuration. If xFan is enabled for the device it is automatically turned on when you select a supported operating mode in Home App. If xFan is disabled then the Home App will not modify it's actual setting in any case. +xFan function is also supported, but it works automatically if enabled in Homebridge configuration. If xFan is enabled for the device, it is automatically turned on when you select a supported operating mode in Home App. If xFan is disabled, the Home App will not modify its actual setting in any case. + +Temperature display units in the Home App are in sync with the AC unit's display. (Configuration settings are required to be specified always in Degrees Celsius, independently from the display units.) + +Vertical swing mode can be turned on/off, but special swing settings can't be controlled using the Home App. + +This plugin is designed to be as simple and clear as possible and supports primarily the functions of the Home App's Heater Cooler accessory. ## Requirements -* Node.js (>= 18.17.0) with NPM +* Node.js (>= 18.15.0) with NPM * Homebridge (>= 1.6.0) -You need to specify the local network broadcast address (192.168.1.255 in many home environments) and also recommended to add the device and specify it's MAC address (Serial Number) in configuration file. +You need to specify the local network broadcast address (192.168.1.255 in many home environments) and it's also recommended to add the device and specify its MAC address (Serial Number) in the configuration file. + +It is highly recommended to use static IP addresses for connected devices. Using a dynamic IP address may require a restart of the Homebridge service on an address change to reconnect the device. Most routers offer static DHCP leases. (Please look at your router's documentation!) + +## Supported devices + +* GREE Air Conditioners with WiFi support +* May work with other GREE compatible AC units -It is highly recommended to use static IP addresses for connected devices. Using dynamic IP address may require restarting the Homebridge service on address change to reconnect the device. Most routers offer static DHCP leases. (Please see your router documentation!) +## Known limitations + +This plugin was designed to support the Home App's Heater Cooler functionality using GREE Air Conditioners. Some special features of GREE AC's are not supported natively by Apple and also dismiss support in this plugin. +* Fan and dry modes are not supported. They may work if set directly on the device until you change operating mode. They can't be turned on using Home App. +* Lights of the AC unit can't be controlled. +* Additional device functions (e.g. health mode, sleep, SE) are not supported. +* Horizontal swing control is not supported, it remains the same as set directly on the device. ## Installation instructions -It is recommended to install the plugin using the graphical user interface of Homebridge ([Homebridge Config UI X](https://www.npmjs.com/package/homebridge-config-ui-x)). You can find the plugin if you search on the Plugins page for GREE Air Conditioner. It is recommended to configure the plugin using the same GUI controls. +It is recommended to install the plugin using the graphical user interface of Homebridge ([Homebridge Config UI X](https://www.npmjs.com/package/homebridge-config-ui-x)). You can find the plugin if you search on the Plugins page for GREE Air Conditioner ('GREE AC' or '@eibenp/homebridge-gree-airconditioner' if you'd like an exact match). It is recommended to configure the plugin using the same GUI controls. Command line install: ``` npm install @eibenp/homebridge-gree-airconditioner -g ``` -If successfully installed and configured then your devices will appear on the Homebridge GUI Accessories page (2 items for supported devices (Heater Cooler and Temperature Sensor)) and also in Home App (if Homebridge is already connected to the Home App). +If successfully installed and configured, your devices will appear on the Homebridge GUI Accessories page and also in Home App (if Homebridge is already connected to the Home App). (If the additional temperature sensor is enabled, then 2 items will be displayed for supported devices (Heater Cooler and Temperature Sensor).) ## Example configuration -_Only relevant part of the configuration file is displayed:_ +_Only the relevant part of the configuration file is displayed:_ ``` "platforms": [ { @@ -53,6 +72,7 @@ _Only relevant part of the configuration file is displayed:_ "minimumTargetTemperature": 16, "maximumTargetTemperature": 30, "xFanEnabled": true, + "temperatureSensor": "disabled", "disabled": false } ] @@ -61,8 +81,8 @@ _Only relevant part of the configuration file is displayed:_ ``` * name - Unique name of the platform plugin * platform - **GREEAirConditioner** (fixed name, it identifies the plugin) -* port - free UDP port (homebridge will use this port for network communication; it is recommended to select a port which is not used and the next 256 ports are also available because devices will be bound to a separate port based on the last part of the device IPv4 address and the port specified in the configuration) -* scanAddress - local network broadcast address (some network knowledge is required to determine this address; in many cases it is default to 192.168.1.255) +* port - free UDP port (homebridge will use this port for network communication; it is recommended to select a port which is not used and the next 256 ports are also available because devices will be bound to a separate port based on the last part of the device's IPv4 address and the port specified in the configuration) +* scanAddress - local network broadcast address (some network knowledge is required to determine this address; in many cases its default value is 192.168.1.255) * scanCount - number of retries for locating devices on the network (minimum 3 retries have to be specified) * scanTimeout - time period in seconds between device query retries * devices - devices should be listed in this block (specify as many devices as you have on your network) @@ -70,20 +90,29 @@ _Only relevant part of the configuration file is displayed:_ * name - custom name of the device (optional) * model - model name, information only (optional) * speedSteps - fan speed steps of the unit (valid values are: 3 and 5) -* statusUpdateInterval - device status will be refreshed based in this interval (in seconds) -* sensorOffset - device temperature sensor offset value for current temperature calibration (default is 40 celsius, must be specified in celsius) -* minimumTargetTemperature - minimum target temperature accepted by the device (default is 16 celsius, must be specified in celsius) -* maximumTargetTemperature - maximum target temperature accepted by the device (default is 30 celsius, must be specified in celsius) +* statusUpdateInterval - device status will be refreshed based on this interval (in seconds) +* sensorOffset - device temperature sensor offset value for current temperature calibration (default is 40 °C, must be specified in Degrees Celsius) +* minimumTargetTemperature - minimum target temperature accepted by the device (default is 16 °C, must be specified in Degrees Celsius) +* maximumTargetTemperature - maximum target temperature accepted by the device (default is 30 °C, must be specified in Degrees Celsius) * xFanEnabled - automatically turn on xFan functionality in supported device modes (xFan actual setting is not modified by the Home App if disabled) +* temperatureSensor - control additional temperature sensor accessory in Home App (disabled = do not add to Home App / child = add as a child accessory / separate = add as a separate (independent) accessory) * disabled - set to true if you do not want to control this device in the Home App (old devices can be removed using this parameter) +![Homebridge UI](./uiconfig.jpg) + ## Tips +### MAC Address in GREE+ mobile app + +Open selected device and in the upper right corner select menu symbol: + +![AC device](./greedevice.jpg)![MAC Address](./greemac.jpg) + ### Network broadcast address -All devices on the local network use the same broadcast address. Broadcast address can be calculated from the IP address and the subnet mask of any device which is connected to the LAN. (E.g. your router or computer) You can find several online calculators which help to determine the broadcast address. +All devices on the local network use the same broadcast address. The broadcast address can be calculated from the IP address and the subnet mask of any device which is connected to the LAN. (E.g. your router or computer) You can find several online calculators which help to determine the broadcast address. -On Unix like systems you can query the broadcast address using the following command: +On Unix-like systems you can query the broadcast address using the following command: ```bash ifconfig | grep broadcast # result diff --git a/config.schema.json b/config.schema.json index 482aa49..f8f76d2 100644 --- a/config.schema.json +++ b/config.schema.json @@ -96,6 +96,31 @@ "type": "boolean", "default": false }, + "temperatureSensor": { + "type": "string", + "required": true, + "default": "disabled", + "oneOf": [ + { + "title": "Disabled", + "enum": [ + "disabled" + ] + }, + { + "title": "Child accessory", + "enum": [ + "child" + ] + }, + { + "title": "Separate accessory", + "enum": [ + "separate" + ] + } + ] + }, "disabled": { "type": "boolean" } @@ -197,7 +222,7 @@ "key": "devices[].sensorOffset", "flex": "1 1 50%", "title": "Temperature offset:", - "description": "Temperature sensor calibration (in Celsius)", + "description": "Temperature sensor calibration (in Degrees Celsius)", "condition": { "functionBody": "return model.devices[arrayIndices].disabled !== true;" } @@ -206,7 +231,7 @@ "key": "devices[].minimumTargetTemperature", "flex": "1 1 50%", "title": "Minimum target temperature:", - "description": "Minimum target temperature (in Celsius)", + "description": "Minimum target temperature (in Degrees Celsius)", "condition": { "functionBody": "return model.devices[arrayIndices].disabled !== true;" } @@ -215,7 +240,7 @@ "key": "devices[].maximumTargetTemperature", "flex": "1 1 50%", "title": "Maximum target temperature:", - "description": "Maximum target temperature (in Celsius)", + "description": "Maximum target temperature (in Degrees Celsius)", "condition": { "functionBody": "return model.devices[arrayIndices].disabled !== true;" } @@ -224,7 +249,16 @@ "key": "devices[].xFanEnabled", "flex": "1 1 50%", "title": "xFan enabled", - "description": "If enabled then xFan functionality is turned on automatically on device", + "description": "If enabled, then xFan functionality is turned on automatically on the device", + "condition": { + "functionBody": "return model.devices[arrayIndices].disabled !== true;" + } + }, + { + "key": "devices[].temperatureSensor", + "flex": "1 1 50%", + "title": "Temperature sensor:", + "description": "Additional temperature sensor in Home App", "condition": { "functionBody": "return model.devices[arrayIndices].disabled !== true;" } diff --git a/greedevice.jpg b/greedevice.jpg new file mode 100644 index 0000000..2ddc8f2 Binary files /dev/null and b/greedevice.jpg differ diff --git a/greemac.jpg b/greemac.jpg new file mode 100644 index 0000000..08b5754 Binary files /dev/null and b/greemac.jpg differ diff --git a/package.json b/package.json index ec08bf3..34886b2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": false, "displayName": "GREE Air Conditioner", "name": "@eibenp/homebridge-gree-airconditioner", - "version": "1.0.0", + "version": "1.0.1", "description": "Control GREE Air Conditioners from Homebridge", "license": "Apache-2.0", "repository": { diff --git a/src/platform.ts b/src/platform.ts index 2e54741..96582fd 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -4,6 +4,7 @@ import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, import { PLATFORM_NAME, PLUGIN_NAME, UDP_SCAN_PORT, DEFAULT_DEVICE_CONFIG } from './settings'; import { GreeAirConditioner } from './platformAccessory'; +import { GreeAirConditionerTS } from './tsAccessory'; /** * HomebridgePlatform @@ -53,7 +54,14 @@ export class GreeACPlatform implements DynamicPlatformPlugin { // add the restored accessory to the accessories cache so we can track if it has already been registered if (accessory.context.device?.mac) { - this.devices[accessory.context.device.mac] = accessory; + if (accessory.context.deviceType === undefined || accessory.context.deviceType === 'HeaterCooler') { + // this is the main accessory + this.devices[accessory.context.device.mac] = accessory; + } + if (accessory.context.deviceType === 'TemperatureSensor') { + // this is the temperature sensor + this.devices[accessory.context.device.mac + '_ts'] = accessory; + } } } @@ -71,6 +79,14 @@ export class GreeACPlatform implements DynamicPlatformPlugin { this.log.info('Scan finished.'); clearInterval(this.timer); this.socket.close(); + // remove accessories not found on network + Object.entries(this.devices).forEach(([key, value]) => { + // this.log.debug('Cleanup', key); + if (!this.initializedDevices[value.UUID]) { + this.log.debug('Cleanup -> Remove', value.displayName, key, value.UUID); + delete this.config.devices[key]; + } + }); } else { this.broadcastScan(); } @@ -104,6 +120,8 @@ export class GreeACPlatform implements DynamicPlatformPlugin { ...devcfg, ...((devcfg.speedSteps && devcfg.speedSteps !== 3 && devcfg.speedSteps !== 5) || devcfg.speedSteps === 0 ? {speedSteps: 5} : {}), + ...((devcfg.temperatureSensor && ['disabled', 'child', 'separate'].includes((devcfg.temperatureSensor as string).toLowerCase())) ? + {temperatureSensor: (devcfg.temperatureSensor as string).toLowerCase()} : {temperatureSensor: 'disabled'}), }; Object.entries(DEFAULT_DEVICE_CONFIG).forEach(([key, value]) => { if (deviceConfig[key] === undefined) { @@ -111,6 +129,7 @@ export class GreeACPlatform implements DynamicPlatformPlugin { } }); let accessory = this.devices[deviceInfo.mac]; + let accessory_ts = this.devices[deviceInfo.mac + '_ts']; if (deviceConfig?.disabled) { this.log.info(`accessory ${deviceInfo.mac} skipped`); @@ -118,10 +137,15 @@ export class GreeACPlatform implements DynamicPlatformPlugin { this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); delete this.devices[deviceConfig.mac]; } + if (accessory_ts) { + this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory_ts]); + delete this.devices[deviceConfig.mac + '_ts']; + } return; } if (accessory && this.initializedDevices[accessory.UUID]) { + // already initalized return; } @@ -135,11 +159,36 @@ export class GreeACPlatform implements DynamicPlatformPlugin { this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); } + if (!accessory_ts && deviceConfig.temperatureSensor === 'separate') { + const deviceName_ts = 'Temperature Sensor - ' + (deviceConfig?.name ?? (deviceInfo.name || deviceInfo.mac)); + this.log.debug(`Initializing new accessory ${deviceInfo.mac} with name ${deviceName_ts}...`); + const uuid = this.api.hap.uuid.generate(deviceInfo.mac + '_ts'); + accessory_ts = new this.api.platformAccessory(deviceName_ts, uuid, Categories.SENSOR); + + this.devices[deviceInfo.mac + '_ts'] = accessory_ts; + this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory_ts]); + } + + if (accessory_ts && deviceConfig.temperatureSensor !== 'separate') { + this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory_ts]); + delete this.devices[deviceConfig.mac + '_ts']; + } + + let tsService; + if (accessory_ts && deviceConfig.temperatureSensor === 'separate') { + // mark temperature sensor devices as initialized + accessory_ts.context.device = deviceInfo; + accessory_ts.context.deviceType = 'TemperatureSensor'; + this.initializedDevices[accessory_ts.UUID] = true; + tsService = new GreeAirConditionerTS(this, accessory_ts, deviceConfig); + } + if (accessory) { - // mark devices as initialized. + // mark devices as initialized accessory.context.device = deviceInfo; + accessory.context.deviceType = 'HeaterCooler'; this.initializedDevices[accessory.UUID] = true; - return new GreeAirConditioner(this, accessory, deviceConfig, this.config.port as number); + return new GreeAirConditioner(this, accessory, deviceConfig, this.config.port as number, tsService); } }; diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts index 9d627e5..d30e079 100644 --- a/src/platformAccessory.ts +++ b/src/platformAccessory.ts @@ -3,6 +3,7 @@ import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'; import { GreeACPlatform } from './platform'; import { DeviceConfig } from './settings'; +import { GreeAirConditionerTS } from './tsAccessory'; import crypto from './crypto'; import commands from './commands'; @@ -26,6 +27,7 @@ export class GreeAirConditioner { private readonly accessory: PlatformAccessory, private readonly deviceConfig: DeviceConfig, private readonly port: number, + private readonly platform_ts: GreeAirConditionerTS, ) { this.platform.log.debug(`[${this.getDeviceLabel()}] deviceConfig -> %j`, deviceConfig); // set accessory information @@ -49,9 +51,22 @@ export class GreeAirConditioner { this.accessory.addService(this.platform.Service.HeaterCooler, this.accessory.displayName, undefined); this.HeaterCooler.displayName = this.accessory.displayName; - this.TemperatureSensor = this.accessory.getService(this.platform.Service.TemperatureSensor) || - this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature Sensor - ' + this.accessory.displayName, undefined); - this.TemperatureSensor.displayName = 'Temperature Sensor - ' + this.accessory.displayName; + if (deviceConfig.temperatureSensor === 'child') { + this.platform.log.debug(`[${this.getDeviceLabel()}] Add Temperature Sensor child service`); + this.TemperatureSensor = this.accessory.getService(this.platform.Service.TemperatureSensor) || + this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature Sensor - ' + this.accessory.displayName, undefined); + this.TemperatureSensor.displayName = 'Temperature Sensor - ' + this.accessory.displayName; + } else { + const ts = this.accessory.getService(this.platform.Service.TemperatureSensor); + this.platform.log.debug(`[${this.getDeviceLabel()}] Temperature Sensor child service not allowed (%s)`, ts?.displayName); + if (ts !== undefined) { + this.platform.log.debug(`[${this.getDeviceLabel()}] Remove Temperature Sensor child service (%s)`, ts.displayName); + this.accessory.removeService(ts); + } + } + + this.HeaterCooler.setPrimaryService(true); + this.TemperatureSensor?.setPrimaryService(false); // each service must implement at-minimum the "required characteristics" for the given service type // see https://developers.homebridge.io/#/service/HeaterCooler @@ -676,6 +691,9 @@ export class GreeAirConditioner { .updateValue(this.currentTemperature); this.TemperatureSensor?.getCharacteristic(this.platform.Characteristic.CurrentTemperature) .updateValue(this.currentTemperature); + this.platform_ts?.setCurrentTemperature(this.currentTemperature); + this.platform_ts?.TemperatureSensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature) + .updateValue(this.currentTemperature); } else if (props.includes(commands.targetTemperature.code) && this.TemperatureSensor === undefined) { // temperature is not accessible -> targetTemperature is saved as currentTemperature this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature); diff --git a/src/settings.ts b/src/settings.ts index c65687c..712d1e2 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -17,6 +17,7 @@ export interface DeviceConfig { minimumTargetTemperature: number; maximumTargetTemperature: number; xFanEnabled: boolean; + temperatureSensor: string; disabled?: boolean; } @@ -27,6 +28,7 @@ export const DEFAULT_DEVICE_CONFIG: DeviceConfig = { minimumTargetTemperature: 16, maximumTargetTemperature: 30, xFanEnabled: true, + temperatureSensor: 'disabled', }; export const UDP_SCAN_PORT = 7000; diff --git a/src/tsAccessory.ts b/src/tsAccessory.ts new file mode 100644 index 0000000..d569c17 --- /dev/null +++ b/src/tsAccessory.ts @@ -0,0 +1,79 @@ +import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'; + +import { GreeACPlatform } from './platform'; +import { DeviceConfig } from './settings'; + +/** + * 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 GreeAirConditionerTS { + public TemperatureSensor: Service; + private currentTemperature: number; + + constructor( + private readonly platform: GreeACPlatform, + private readonly accessory: PlatformAccessory, + private readonly deviceConfig: DeviceConfig, + ) { + this.currentTemperature = 25; + + // set accessory information + this.accessory.getService(this.platform.Service.AccessoryInformation)! + .setCharacteristic(this.platform.Characteristic.Manufacturer, this.accessory.context.device.brand || 'Gree') + .setCharacteristic(this.platform.Characteristic.Model, + this.deviceConfig?.model || this.accessory.context.device.model || this.accessory.context.device.name || 'Air Conditioner') + .setCharacteristic(this.platform.Characteristic.SerialNumber, this.accessory.context.device.mac) + .setCharacteristic(this.platform.Characteristic.FirmwareRevision, + this.accessory.context.device.hid && this.accessory.context.device.hid.lastIndexOf('V') >= 0 && + this.accessory.context.device.hid.lastIndexOf('V') < this.accessory.context.device.hid.lastIndexOf('.') ? + this.accessory.context.device.hid.substring(this.accessory.context.device.hid.lastIndexOf('V') + 1, + this.accessory.context.device.hid.lastIndexOf('.')) : '1.0.0') + .setCharacteristic(this.platform.Characteristic.HardwareRevision, + this.accessory.context.device.ver ? + this.accessory.context.device.ver.substring(this.accessory.context.device.ver.lastIndexOf('V') + 1) : '1.0.0'); + + // get the TemperatureSensor service if it exists, otherwise create a new TemperatureSensor service + // we don't use subtype because we add only one service with this type + this.TemperatureSensor = this.accessory.getService(this.platform.Service.TemperatureSensor) || + this.accessory.addService(this.platform.Service.TemperatureSensor, this.accessory.displayName, undefined); + this.TemperatureSensor.displayName = this.accessory.displayName; + + // register handlers for the Current Temperature Characteristic + this.TemperatureSensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature) + .onGet(this.getCurrentTemperature.bind(this)); + } + + /** + * Handle the "GET" requests from HomeKit + * These are sent when HomeKit wants to know the current state of the accessory + * + * GET requests should return as fast as possbile. 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) + + * 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); + */ + async getCurrentTemperature(): Promise { + this.platform.log.debug(`[${this.getDeviceLabel()}] Get CurrentTemperature ->`, this.currentTemperature); + return this.currentTemperature; + } + + // helper functions + + public setCurrentTemperature(value: number) { + this.currentTemperature = value; + this.platform.log.debug(`[${this.getDeviceLabel()}] updateStatus (Current Temperature) ->`, this.currentTemperature); + } + + getDeviceLabel() { + return `${this.accessory.displayName} -- ${this.accessory.context.device.address}:${this.accessory.context.device.port}`; + } +} diff --git a/uiconfig.jpg b/uiconfig.jpg new file mode 100644 index 0000000..bdd0a58 Binary files /dev/null and b/uiconfig.jpg differ