homebridge-miot
Version:
Homebridge plugin for devices supporting the miot protocol
181 lines (133 loc) • 5.24 kB
JavaScript
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 PropValueListWrapper 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 'Value List';
}
/*----------========== SETUP SERVICE ==========----------*/
prepareWrapper() {
if (!this.hasValueList()) {
return false;
}
if (this.valueList().length < 1) {
return false;
}
this.propValueListServices = new Array();
this.valueList().forEach((item, i) => {
let itemVal = item.value;
let itemDesc = item.description;
let propName = this.getProp().getName();
let name = this.getWrapperName() || propName;
let switchName = name + ' - ' + itemDesc;
let switchId = propName + 'ControlService' + itemVal;
let tmpSwitch = null;
if (this.isWriteOnly()) {
tmpSwitch = this.createStatlessSwitch(switchName, switchId, itemVal);
} else {
tmpSwitch = this.createStatefulSwitch(switchName, switchId, itemVal);
}
this.addAccessoryService(tmpSwitch);
this.propValueListServices.push(tmpSwitch);
});
return true;
}
/*----------========== STATE SETTERS/GETTERS ==========----------*/
isSwitchOn(itemVal) {
if (this.isMiotDeviceConnected() && this.checkLinkedPropStatus()) {
return this.getProp().getValue() === itemVal;
}
return false;
}
setSwitchOn(state, itemVal) {
if (this.isMiotDeviceConnected()) {
if (state) {
this.enableLinkedPropIfNecessary();
this.getDevice().setPropertyValue(this.getProp(), itemVal);
this.updateValueListSwitches(itemVal);
} else {
// if user tries to turn off active switch, then reset the state of all switches
setTimeout(() => {
this.updateValueListSwitches();
}, Constants.BUTTON_RESET_TIMEOUT);
}
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
// write only value list
setStatlessSwitchOn(state, itemVal) {
if (this.isMiotDeviceConnected()) {
this.enableLinkedPropIfNecessary();
this.getDevice().setPropertyValue(this.getProp(), itemVal);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
isStatelessSwitchOn() {
return false;
}
/*----------========== SERVICE PROTOCOL ==========----------*/
updateWrapperStatus() {
super.updateWrapperStatus(); // call super implementation
this.updateValueListSwitches();
}
/*----------========== STATE HELPERS ==========----------*/
updateValueListSwitches(activeVal) {
if (this.propValueListServices) {
activeVal = activeVal !== undefined ? activeVal : this.getProp().getValue(); // if activeVal specified from outside then use that, else get current prop value
this.propValueListServices.forEach((tmpValSwitch, i) => {
let item = this.valueList()[i];
let itemVal = item.value;
let isSwitchOn = (activeVal === itemVal) && this.checkLinkedPropStatus();
tmpValSwitch.getCharacteristic(Characteristic.On).updateValue(isSwitchOn);
});
}
}
/*----------========== GETTERS ==========----------*/
/*----------========== CONVENIENCE ==========----------*/
/*----------========== HELPERS ==========----------*/
createStatefulSwitch(switchName, switchId, itemVal) {
let tmpStatefulSwitch = new Service.Switch(this.sanitizeName(switchName), switchId);
this.setServiceConfiguredName(tmpStatefulSwitch, switchName);
tmpStatefulSwitch
.getCharacteristic(Characteristic.On)
.onGet(() => {
return this.isSwitchOn(itemVal);
})
.onSet((value) => {
this.setSwitchOn(value, itemVal);
});
return tmpStatefulSwitch;
}
createStatlessSwitch(switchName, switchId, itemVal) {
let tmpStatlessSwitch = new Service.Switch(this.sanitizeName(switchName), switchId);
this.setServiceConfiguredName(tmpStatlessSwitch, switchName);
tmpStatlessSwitch
.getCharacteristic(Characteristic.On)
.onGet(() => {
return this.isStatelessSwitchOn();
})
.onSet((value) => {
this.setStatlessSwitchOn(value, itemVal);
setTimeout(() => {
if (tmpStatlessSwitch) tmpStatlessSwitch.getCharacteristic(Characteristic.On).updateValue(false);
}, Constants.BUTTON_RESET_TIMEOUT);
});
return tmpStatlessSwitch;
}
/*----------========== LINKED PROP HELPERS ==========----------*/
}
module.exports = PropValueListWrapper;