import { API , Logger , Service , AccessoryConfig , AccessoryPlugin , } from 'homebridge' ; import miio from '@rifat/miio' ; import { retry , isDefined } from './utils' ; import { add as addActive } from './characteristics/air-purifier/active' ; import { add as addCurrentAirPurifierState } from './characteristics/air-purifier/current-air-purifier-state' ; import { add as addTargetAirPurifierState } from './characteristics/air-purifier/target-air-purifier-state' ; import { add as addFilterLifeLevel } from './characteristics/air-purifier/filter-life-level' ; import { add as addFilterChangeIndication , DEFAULT_FILTER_CHANGE_THRESHOLD , } from './characteristics/air-purifier/filter-change-indication' ; import { add as addRotationSpeed } from './characteristics/air-purifier/rotation-speed' ; import { add as addLockPhysicalControls } from './characteristics/air-purifier/lock-physical-controls' ; import { add as addAirQuality } from './characteristics/air-quality' ; import { add as addPm2_5Density } from './characteristics/pm2_5-density' ; import { add as addCurrentTemperature } from './characteristics/current-temperature' ; import { add as addCurrentRelativeHumidity } from './characteristics/current-relative-humidity' ; const RETRY_DELAY = 5000 ; export interface XiaomiMiAirPurifierAccessoryConfig extends AccessoryConfig { token : string ; address : string ; enableAirQuality : boolean ; enableTemperature : boolean ; enableHumidity : boolean ; enableFanSpeedControl : boolean ; enableChildLockControl : boolean ; filterChangeThreshold : number ; } function isValidConfig ( config ) { return ! ! config . token && ! ! config . address ; } export class XiaomiMiAirPurifierAccessory implements AccessoryPlugin { private readonly name ? : string ; protected readonly config ? : XiaomiMiAirPurifierAccessoryConfig ; private readonly airPurifierService ? : Service ; private readonly accessoryInformationService ? : Service ; private readonly filterMaintenanceService ? : Service ; private readonly airQualitySensorService ? : Service ; private readonly temperatureSensorService ? : Service ; private readonly humiditySensorService ? : Service ; private connection ? : Promise < any > ; protected readonly maybeDevice ? : Promise < any > ; constructor ( protected readonly log , config , protected readonly api ) { if ( isValidConfig ( config ) ) { this . config = config ; const { Service : { AirPurifier , HumiditySensor , AirQualitySensor , TemperatureSensor , AccessoryInformation , } , Characteristic , } = api . hap ; this . name = config . name ; this . maybeDevice = this . connect ( config ) . then ( ( device ) => { log . info ( `Connected to "${ this . name }" @ ${ config . address }!` ) ; return device ; } ) ; this . airPurifierService = new AirPurifier ( this . name ) ; addActive ( this . maybeDevice , this . airPurifierService , Characteristic . Active ) ; addCurrentAirPurifierState ( this . maybeDevice , this . airPurifierService , Characteristic . CurrentAirPurifierState ) ; addTargetAirPurifierState ( this . maybeDevice , this . airPurifierService , Characteristic . TargetAirPurifierState ) ; if ( config . enableFanSpeedControl ) { addRotationSpeed ( this . maybeDevice , this . airPurifierService , Characteristic . RotationSpeed ) ; } if ( config . enableChildLockControl ) { addLockPhysicalControls ( this . maybeDevice , this . airPurifierService , Characteristic . LockPhysicalControls ) ; } if ( config . enableAirQuality ) { this . airQualitySensorService = new AirQualitySensor ( `Air Quality on ${ this . name }` ) ; addAirQuality ( this . maybeDevice , this . airQualitySensorService , Characteristic . AirQuality ) ; addPm2_5Density ( this . maybeDevice , this . airQualitySensorService , Characteristic . PM2_5Density ) ; addFilterLifeLevel ( this . maybeDevice , this . airQualitySensorService , Characteristic . FilterLifeLevel ) ; addFilterChangeIndication ( this . maybeDevice , this . airQualitySensorService , Characteristic . FilterChangeIndication , { filterChangeThreshold : config . filterChangeThreshold | DEFAULT_FILTER_CHANGE_THRESHOLD , } ) ; } if ( config . enableTemperature ) { this . temperatureSensorService = new TemperatureSensor ( `Temperature on ${ this . name }` ) ; addCurrentTemperature ( this . maybeDevice , this . temperatureSensorService , Characteristic . CurrentTemperature ) ; } if ( config . enableHumidity ) { this . humiditySensorService = new HumiditySensor ( `Humidity on ${ this . name }` ) ; addCurrentRelativeHumidity ( this . maybeDevice , this . humiditySensorService , Characteristic . CurrentRelativeHumidity ) ; } this . accessoryInformationService = new AccessoryInformation ( ) . setCharacteristic ( Characteristic . Manufacturer , 'Xiaomi Corporation' ) ; log . info ( `${ this . name } finished initializing!` ) ; } else { log . error ( 'Your must provide IP address and token of the Air Purifier.' ) ; } } connect ( config ) { if ( ! this . connection ) { this . connection = new Promise ( ( resolve ) => { const { address , token } = config ; retry ( ( ) => miio . device ( { address , token } ) , RETRY_DELAY ) . then ( resolve ) . catch ( ( e ) => { this . log . error ( 'Error occurred during retry:' , e ) ; } ) ; } ) ; } return this . connection ; } identify ( ) { this . log . info ( `Identifying "${ this . name }" @ ${ this . config ?. address }` ) ; } getServices ( ) { return [ this . airPurifierService , this . airQualitySensorService , this . temperatureSensorService , this . humiditySensorService , this . filterMaintenanceService , this . accessoryInformationService , ] . filter ( isDefined ) ; } }