UNPKG

homebridge-broadlink-rm-pro

Version:

Broadlink RM plugin (including the mini and pro) for homebridge with AC Pro and TV features

196 lines (150 loc) 5.99 kB
const ServiceManagerTypes = require('../helpers/serviceManagerTypes'); const delayForDuration = require('../helpers/delayForDuration'); const catchDelayCancelError = require('../helpers/catchDelayCancelError'); const ping = require('../helpers/ping') const arp = require('../helpers/arp') const BroadlinkRMAccessory = require('./accessory'); class SwitchAccessory extends BroadlinkRMAccessory { constructor (log, config = {}, serviceManagerType) { super(log, config, serviceManagerType); if (!config.isUnitTest) {this.checkPing(ping)} } setDefaults () { const { config } = this; config.pingFrequency = config.pingFrequency || 1; config.pingGrace = config.pingGrace || 10; config.offDuration = config.offDuration || 60; config.onDuration = config.onDuration || 60; if (config.enableAutoOn === undefined && config.disableAutomaticOn === undefined) { config.enableAutoOn = false; } else if (config.disableAutomaticOn !== undefined) { config.enableAutoOn = !config.disableAutomaticOn; } if (config.enableAutoOff === undefined && config.disableAutomaticOff === undefined) { config.enableAutoOff = false; } else if (config.disableAutomaticOff !== undefined) { config.enableAutoOff = !config.disableAutomaticOff; } } reset () { super.reset(); this.stateChangeInProgress = true; // Clear Timeouts if (this.delayTimeoutPromise) { this.delayTimeoutPromise.cancel(); this.delayTimeoutPromise = null; } if (this.autoOffTimeoutPromise) { this.autoOffTimeoutPromise.cancel(); this.autoOffTimeoutPromise = null; } if (this.autoOnTimeoutPromise) { this.autoOnTimeoutPromise.cancel(); this.autoOnTimeoutPromise = null } if (this.pingGraceTimeout) { this.pingGraceTimeout.cancel(); this.pingGraceTimeout = null; } if (this.serviceManager.getCharacteristic(Characteristic.On) === undefined) { this.state.switchState = false; this.serviceManager.updateCharacteristic(Characteristic.On, this.state.switchState); } } checkAutoOnOff () { this.reset(); this.checkPingGrace(); this.checkAutoOn(); this.checkAutoOff(); } checkPing (ping) { const { config } = this let { pingIPAddress, pingFrequency, pingUseArp } = config; if (!pingIPAddress) {return} // Setup Ping/Arp-based State if(!pingUseArp) { ping(pingIPAddress, pingFrequency, this.pingCallback.bind(this)); } else { arp(pingIPAddress, pingFrequency, this.pingCallback.bind(this)); } } pingCallback (active) { const { config, state, serviceManager, name, log, logLevel } = this; if (this.stateChangeInProgress){ return; } if (state.switchState !== active && logLevel <=2){log(`\x1b[35m[INFO]\x1b[0m ${name} ping detected state change, now ${active}`);} if (config.pingIPAddressStateOnly) { state.switchState = active ? true : false; serviceManager.updateCharacteristic(Characteristic.On,state.switchState); return; } const value = active ? true : false; serviceManager.setCharacteristic(Characteristic.On, value); } async setSwitchState (hexData) { const { data, host, log, name, logLevel, config, state, serviceManager } = this; this.stateChangeInProgress = true; this.reset(); if (hexData) {await this.performSend(hexData);} if (config.stateless === true) { state.switchState = false; serviceManager.updateCharacteristic(Characteristic.On,state.switchState); } else { this.checkAutoOnOff(); } } async checkPingGrace () { await catchDelayCancelError(async () => { const { config, log, name, state, serviceManager } = this; let { pingGrace } = config; if (pingGrace) { this.pingGraceTimeoutPromise = delayForDuration(pingGrace); await this.pingGraceTimeoutPromise; this.stateChangeInProgress = false; } }); } async checkAutoOff () { await catchDelayCancelError(async () => { const { config, log, name, state, serviceManager } = this; let { disableAutomaticOff, enableAutoOff, onDuration } = config; if (state.switchState && enableAutoOff) { log(`${name} setSwitchState: (automatically turn off in ${onDuration} seconds)`); this.autoOffTimeoutPromise = delayForDuration(onDuration); await this.autoOffTimeoutPromise; serviceManager.setCharacteristic(Characteristic.On, false); } }); } async checkAutoOn () { await catchDelayCancelError(async () => { const { config, log, name, state, serviceManager } = this; let { disableAutomaticOn, enableAutoOn, offDuration } = config; if (!state.switchState && enableAutoOn) { log(`${name} setSwitchState: (automatically turn on in ${offDuration} seconds)`); this.autoOnTimeoutPromise = delayForDuration(offDuration); await this.autoOnTimeoutPromise; serviceManager.setCharacteristic(Characteristic.On, true); } }); } setupServiceManager () { const { data, name, config, serviceManagerType } = this; const { on, off } = data || { }; this.serviceManager = new ServiceManagerTypes[serviceManagerType](name, Service.Switch, this.log); this.serviceManager.addToggleCharacteristic({ name: 'switchState', type: Characteristic.On, getMethod: this.getCharacteristicValue, setMethod: this.setCharacteristicValue, bind: this, props: { onData: on || data, offData: off || undefined, setValuePromise: this.setSwitchState.bind(this) } }); } } module.exports = SwitchAccessory;