UNPKG

homebridge-miot

Version:

Homebridge plugin for devices supporting the miot protocol

200 lines (151 loc) 6.06 kB
let Service, Characteristic, Accessory, HapStatusError, HAPStatus; const AbstractPropertyWrapper = require('./AbstractPropertyWrapper.js'); const Constants = require('../constants/Constants.js'); const PropFormat = require('../constants/PropFormat.js'); const PropUnit = require('../constants/PropUnit.js'); const PropAccess = require('../constants/PropAccess.js'); class OffDelayWrapper extends AbstractPropertyWrapper { constructor(wrapperName, prop, device, accessory, api, logger) { Service = api.hap.Service; Characteristic = api.hap.Characteristic; Accessory = api.platformAccessory; HapStatusError = api.hap.HapStatusError; HAPStatus = api.hap.HAPStatus; super(wrapperName, prop, device, accessory, api, logger); } /*----------========== PROPERTY WRAPPER INFO ==========----------*/ getWrapperType() { return 'Off Delay'; } /*----------========== SETUP SERVICE ==========----------*/ prepareWrapper() { if (this.isBoolean()) { this.handleBoolean(); this.getLogger().deepDebug('<-W-> Off delay is a boolean!'); return true; } if (this.hasValueRange()) { this.handleValueRange(); this.getLogger().deepDebug('<-W-> Off delay is a value range!'); return true; } return false; } // boolean handleBoolean() { // simple on/off switch let propName = this.getProp().getName(); let serviceName = this.getWrapperName() || propName; let serviceId = this.generateServiceId(); this.offDelayBooleanService = new Service.Switch(this.sanitizeName(serviceName), serviceId); this.setServiceConfiguredName(this.offDelayBooleanService, serviceName); this.offDelayBooleanService .getCharacteristic(Characteristic.On) .onGet(this.isOffDelayBooleanSwitchOn.bind(this)) .onSet(this.setOffDelayBooleanSwitchOn.bind(this)); this.addAccessoryService(this.offDelayBooleanService); } // value range handleValueRange() { // create a lightbulb where the value is a percentage representation let propName = this.getProp().getName(); let serviceName = this.getWrapperName() || propName; let serviceId = this.generateServiceId(); this.offDelayLightbulbService = new Service.Lightbulb(this.sanitizeName(serviceName), serviceId); this.setServiceConfiguredName(this.offDelayLightbulbService, serviceName); this.offDelayLightbulbService .getCharacteristic(Characteristic.On) .onGet(this.isOffDelayLightbulbOn.bind(this)) .onSet(this.setOffDelayLightbulbOn.bind(this)); this.offDelayLightbulbService .addCharacteristic(new Characteristic.Brightness()) .onGet(this.getOffDelayBrightness.bind(this)) .onSet(this.setOffDelayBrightness.bind(this)); this.addAccessoryService(this.offDelayLightbulbService); } /*----------========== STATE SETTERS/GETTERS ==========----------*/ // boolean isOffDelayBooleanSwitchOn() { if (this.isMiotDeviceConnected() && this.checkLinkedPropStatus()) { return this.getPropValue(); } return false; } setOffDelayBooleanSwitchOn(value) { if (this.isMiotDeviceConnected()) { this.setPropValue(value); } else { throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); } } // value range isOffDelayLightbulbOn() { if (this.isMiotDeviceConnected() && this.checkLinkedPropStatus()) { return this.getOffDelayInMinutes() > 0; } return false; } setOffDelayLightbulbOn(value) { if (this.isMiotDeviceConnected()) { if (value === false) { // only if disabling, enabling will automatically set it to 100% this.setOffDelayInMinutes(0); } } else { throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); } } getOffDelayBrightness() { if (this.isMiotDeviceConnected() && this.checkLinkedPropStatus()) { return Math.min(this.getOffDelayInMinutes(), 100); } return 0; } setOffDelayBrightness(value) { if (this.isMiotDeviceConnected()) { if (this.offDelayTimeout) clearTimeout(this.offDelayTimeout); this.offDelayTimeout = setTimeout(() => this.setOffDelayInMinutes(value), Constants.SLIDER_DEBOUNCE); } else { throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); } } /*----------========== SERVICE PROTOCOL ==========----------*/ updateWrapperStatus() { super.updateWrapperStatus(); // call super implementation if (this.offDelayBooleanService) this.offDelayBooleanService.getCharacteristic(Characteristic.On).updateValue(this.isOffDelayBooleanSwitchOn()); if (this.offDelayLightbulbService) this.offDelayLightbulbService.getCharacteristic(Characteristic.On).updateValue(this.isOffDelayLightbulbOn()); if (this.offDelayLightbulbService) this.offDelayLightbulbService.getCharacteristic(Characteristic.Brightness).updateValue(this.getOffDelayBrightness()); } /*----------========== STATE HELPERS ==========----------*/ /*----------========== GETTERS ==========----------*/ /*----------========== CONVENIENCE ==========----------*/ getOffDelayInMinutes() { let value = this.getPropValue(); value = this.getDevice().convertToMinutes(value, this.getUnit()); return value; } setOffDelayInMinutes(minutes) { let value = this.getDevice().convertMinutesToUnit(minutes, this.getUnit()); this.setPropValue(value); } /*----------========== HELPERS ==========----------*/ getUnit() { let unit = super.getUnit(); if (unit === PropUnit.NONE) { let valRange = this.valueRange(); if (valRange && valRange.length > 1) { let maxVal = valRange[1]; let maxValDiv = maxVal / 60; if (maxValDiv <= 1) { unit = PropUnit.HOURS; } else if (maxValDiv <= 60) { unit = PropUnit.MINUTES; } else { unit = PropUnit.SECONDS; } } } return unit; } /*----------========== LINKED PROP HELPERS ==========----------*/ } module.exports = OffDelayWrapper;