homebridge-miot
Version:
Homebridge plugin for devices supporting the miot protocol
278 lines (220 loc) • 10.8 kB
JavaScript
let Service, Characteristic, Accessory, HapStatusError, HAPStatus;
const BaseAccessory = require('../../base/BaseAccessory.js');
const Constants = require('../../constants/Constants.js');
const DevTypes = require('../../constants/DevTypes.js');
const Properties = require('../../constants/Properties.js');
class AirConditionerAccessory extends BaseAccessory {
constructor(name, miotDevice, uuid, config, api, logger) {
super(name, miotDevice, uuid, config, api, logger);
}
/*----------========== SETUP ACCESSORY ==========----------*/
initHapConstants() {
Service = this.api.hap.Service;
Characteristic = this.api.hap.Characteristic;
Accessory = this.api.platformAccessory;
HapStatusError = this.api.hap.HapStatusError;
HAPStatus = this.api.hap.HAPStatus;
}
initConfigProperties(config) {
this.buzzerControl = this.getPropValue(config['buzzerControl'], true);
this.ledControl = this.getPropValue(config['ledControl'], true);
this.actionButtons = this.getPropValue(config['actionButtons'], false);
this.fanLevelControl = this.getPropValue(config['fanLevelControl'], true);
this.modeControl = this.getPropValue(config['modeControl'], true);
this.swingControl = this.getPropValue(config['swingControl'], false);
}
getAccessoryType() {
return DevTypes.AIR_CONDITIONER;
}
/*----------========== SETUP SERVICES ==========----------*/
initAccessory() {
return new Accessory(this.getName(), this.getUuid(), this.api.hap.Accessory.Categories.AIR_CONDITIONER);
}
setupMainAccessoryService() {
this.airConditionerService = new Service.HeaterCooler(this.getName(), 'airConditionerService');
this.airConditionerService
.getCharacteristic(Characteristic.Active)
.onGet(this.getHeaterCoolerActiveState.bind(this))
.onSet(this.setHeaterCoolerActiveState.bind(this));
this.airConditionerService
.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
.onGet(this.getCurrentHeaterCoolerState.bind(this));
this.airConditionerService
.getCharacteristic(Characteristic.TargetHeaterCoolerState)
.onGet(this.getTargetHeaterCoolerState.bind(this))
.onSet(this.setTargetHeaterCoolerState.bind(this));
this.airConditionerService
.getCharacteristic(Characteristic.CurrentTemperature)
.onGet(this.getCurrentTemperature.bind(this));
this.airConditionerService
.getCharacteristic(Characteristic.HeatingThresholdTemperature)
.onGet(this.getHeatingThresholdTemperature.bind(this))
.onSet(this.setHeatingThresholdTemperature.bind(this))
.setProps({
minValue: this.getDevice().targetTemperatureRange()[0],
maxValue: this.getDevice().targetTemperatureRange()[1],
minStep: this.getDevice().targetTemperatureRange()[2]
});
this.airConditionerService
.getCharacteristic(Characteristic.CoolingThresholdTemperature)
.onGet(this.getCoolingThresholdTemperature.bind(this))
.onSet(this.setCoolingThresholdTemperature.bind(this))
.setProps({
minValue: this.getDevice().targetTemperatureRange()[0],
maxValue: this.getDevice().targetTemperatureRange()[1],
minStep: this.getDevice().targetTemperatureRange()[2]
});
this.airConditionerService
.getCharacteristic(Characteristic.TemperatureDisplayUnits)
.setProps({
maxValue: Characteristic.TemperatureDisplayUnits.CELSIUS,
validValues: [
Characteristic.TemperatureDisplayUnits.CELSIUS
]
})
.setValue(Characteristic.TemperatureDisplayUnits.CELSIUS);
this.addChildLockCharacteristic(this.airConditionerService);
// if supports vertical swing then add them
if (this.getDevice().supportsVerticalSwing()) {
this.airConditionerService
.addCharacteristic(Characteristic.SwingMode)
.onGet(this.getSwingModeState.bind(this))
.onSet(this.setSwingModeState.bind(this));
}
this.addAccessoryService(this.airConditionerService);
}
setupAdditionalAccessoryServices() {
if (this.buzzerControl) this.prepareBuzzerControlService();
if (this.ledControl) this.prepareLedControlService();
if (this.actionButtons) this.prepareActionButtonServices(this.actionButtons);
if (this.fanLevelControl) this.prepareFanLevelControlServices();
if (this.modeControl) this.prepareModeControlServices();
if (this.swingControl) this.prepareSwingControlService();
}
/*----------========== CREATE ADDITIONAL SERVICES ==========----------*/
prepareSwingControlService() {
if (this.getDevice().supportsVerticalSwing()) {
this.verticalSwingControlService = this.createStatefulSwitch('Vertical Swing', 'verticalSwingControlService', this.isVerticalSwingSwitchOn, this.setVerticalSwingSwitchOn);
this.addAccessoryService(this.verticalSwingControlService);
}
}
/*----------========== HOMEBRIDGE STATE SETTERS/GETTERS ==========----------*/
getHeaterCoolerActiveState() {
if (this.isMiotDeviceConnected()) {
return this.getDevice().isPowerOn() ? Characteristic.Active.ACTIVE : Characteristic.Active.INACTIVE;
}
return Characteristic.Active.INACTIVE;
}
setHeaterCoolerActiveState(state) {
if (this.isMiotDeviceConnected()) {
let isPowerOn = state === Characteristic.Active.ACTIVE;
this.getDevice().setPowerOn(isPowerOn);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
getCurrentHeaterCoolerState() {
if (this.isMiotDeviceConnected()) {
if (this.getDevice().isHeating()) return Characteristic.CurrentHeaterCoolerState.HEATING;
if (this.getDevice().isCooling()) return Characteristic.CurrentHeaterCoolerState.COOLING;
return Characteristic.CurrentHeaterCoolerState.IDLE;
}
return Characteristic.CurrentHeaterCoolerState.INACTIVE;
}
getTargetHeaterCoolerState() {
if (this.getDevice().isAutoModeEnabled()) return Characteristic.TargetHeaterCoolerState.AUTO;
if (this.getDevice().isHeatModeEnabled()) return Characteristic.TargetHeaterCoolerState.HEAT;
if (this.getDevice().isCoolModeEnabled()) return Characteristic.TargetHeaterCoolerState.COOL;
return Characteristic.TargetHeaterCoolerState.AUTO;
}
setTargetHeaterCoolerState(state) {
if (this.isMiotDeviceConnected()) {
if (state === Characteristic.TargetHeaterCoolerState.AUTO) this.getDevice().enableAutoMode();
else if (state === Characteristic.TargetHeaterCoolerState.HEAT) this.getDevice().enableHeatMode();
else if (state === Characteristic.TargetHeaterCoolerState.COOL) this.getDevice().enableCoolMode();
else this.getDevice().enableAutoMode();
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
getCurrentTemperature() {
if (this.isMiotDeviceConnected()) {
if (this.getDevice().supportsTemperatureReporting()) {
return this.getDevice().getTemperature();
} else {
return this.getDevice().getTargetTemperature(); // override temperature for devices which does not spport temperature reporting
}
}
return 0;
}
getHeatingThresholdTemperature() {
if (this.isMiotDeviceConnected()) {
return this.getDevice().getTargetTemperature();
}
return this.getDevice().targetTemperatureRange()[0]; // return minimum value
}
setHeatingThresholdTemperature(temp) {
if (this.isMiotDeviceConnected()) {
this.getDevice().setTargetTemperature(temp);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
getCoolingThresholdTemperature() {
if (this.isMiotDeviceConnected()) {
return this.getDevice().getTargetTemperature();
}
return this.getDevice().targetTemperatureRange()[0]; // return minimum value
}
setCoolingThresholdTemperature(temp) {
if (this.isMiotDeviceConnected()) {
this.getDevice().setTargetTemperature(temp);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
getSwingModeState() {
if (this.isMiotDeviceConnected()) {
return this.getDevice().isVerticalSwingEnabled() ? Characteristic.SwingMode.SWING_ENABLED : Characteristic.SwingMode.SWING_DISABLED;
}
return Characteristic.SwingMode.SWING_DISABLED;
}
setSwingModeState(state) {
if (this.isMiotDeviceConnected()) {
let isSwingModeActive = state === Characteristic.SwingMode.SWING_ENABLED;
this.getDevice().setVerticalSwingEnabled(isSwingModeActive);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
// ----- additional services
isVerticalSwingSwitchOn() {
if (this.isMiotDeviceConnected()) {
return this.getDevice().isVerticalSwingEnabled();
}
return false;
}
setVerticalSwingSwitchOn(state) {
if (this.isMiotDeviceConnected()) {
this.getDevice().setVerticalSwingEnabled(state);
} else {
throw new HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
/*----------========== STATUS ==========----------*/
updateDeviceStatus() {
if (this.airConditionerService) this.airConditionerService.getCharacteristic(Characteristic.Active).updateValue(this.getHeaterCoolerActiveState());
if (this.airConditionerService && this.getDevice().supportsVerticalSwing()) this.airConditionerService.getCharacteristic(Characteristic.SwingMode).updateValue(this.getSwingModeState());
if (this.airConditionerService) this.airConditionerService.getCharacteristic(Characteristic.CurrentHeaterCoolerState).updateValue(this.getCurrentHeaterCoolerState());
if (this.airConditionerService) this.airConditionerService.getCharacteristic(Characteristic.TargetHeaterCoolerState).updateValue(this.getTargetHeaterCoolerState());
if (this.airConditionerService && this.getDevice().supportsTemperatureReporting()) this.airConditionerService.getCharacteristic(Characteristic.CurrentTemperature).updateValue(this.getCurrentTemperature());
if (this.airConditionerService) this.airConditionerService.getCharacteristic(Characteristic.HeatingThresholdTemperature).updateValue(this.getHeatingThresholdTemperature());
if (this.airConditionerService) this.airConditionerService.getCharacteristic(Characteristic.CoolingThresholdTemperature).updateValue(this.getCoolingThresholdTemperature());
if (this.verticalSwingControlService) this.verticalSwingControlService.getCharacteristic(Characteristic.On).updateValue(this.isVerticalSwingSwitchOn());
super.updateDeviceStatus();
}
/*----------========== MULTI-SWITCH SERVICE HELPERS ==========----------*/
/*----------========== GETTERS ==========----------*/
/*----------========== HELPERS ==========----------*/
}
module.exports = AirConditionerAccessory;