homebridge-fujitsu-airstage
Version:
A Homebridge plugin to control devices that use the Fujitsu Airstage API.
575 lines (448 loc) • 19.3 kB
JavaScript
'use strict';
const accessories = require('./accessories');
const constants = require('./constants');
const settings = require('./settings');
class PlatformAccessoryManager {
constructor(platform) {
this.platform = platform;
this.Service = this.platform.Service;
this.Characteristic = this.platform.Characteristic;
}
registerThermostatAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_THERMOSTAT;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.ThermostatAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.ThermostatAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerFanAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_FAN;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.FanAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.FanAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerVerticalAirflowDirectionAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_VERTICAL_AIRFLOW_DIRECTION;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.VerticalAirflowDirectionAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.VerticalAirflowDirectionAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerDryModeSwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_DRY_MODE_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.DryModeSwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.DryModeSwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerEconomySwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_ECONOMY_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.EconomySwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.EconomySwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerEnergySavingFanSwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_ENERGY_SAVING_FAN_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.EnergySavingFanSwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.EnergySavingFanSwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerFanModeSwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_FAN_MODE_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.FanModeSwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.FanModeSwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerMinimumHeatModeSwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_MINIMUM_HEAT_MODE_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.MinimumHeatModeSwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.MinimumHeatModeSwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
registerPowerfulSwitchAccessory(deviceId, deviceName, model) {
const suffix = constants.ACCESSORY_SUFFIX_POWERFUL_SWITCH;
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (existingAccessory) {
this._updateExistingAccessory(existingAccessory, deviceId, model);
new accessories.PowerfulSwitchAccessory(this.platform, existingAccessory);
} else {
const newAccessory = this._instantiateNewAccessory(
deviceId,
deviceName,
model,
suffix
);
new accessories.PowerfulSwitchAccessory(this.platform, newAccessory);
this._registerNewAccessory(newAccessory, deviceId, model);
}
}
unregisterThermostatAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_THERMOSTAT;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterFanAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_FAN;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
// Deprecated: the VerticalSlatsAccessory was replaced by the
// VerticalAirflowDirectionAccessory
unregisterVerticalSlatsAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_VERTICAL_SLATS;
this._unregisterAccessory(deviceId, deviceName, suffix, false);
}
unregisterVerticalAirflowDirectionAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_VERTICAL_AIRFLOW_DIRECTION;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterDryModeSwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_DRY_MODE_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterEconomySwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_ECONOMY_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterEnergySavingFanSwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_ENERGY_SAVING_FAN_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterFanModeSwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_FAN_MODE_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterMinimumHeatModeSwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_MINIMUM_HEAT_MODE_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
unregisterPowerfulSwitchAccessory(deviceId, deviceName) {
const suffix = constants.ACCESSORY_SUFFIX_POWERFUL_SWITCH;
this._unregisterAccessory(deviceId, deviceName, suffix);
}
refreshAllAccessoryCharacteristics(deviceId) {
this.refreshThermostatAccessoryCharacteristics(deviceId);
this.refreshFanAccessoryCharacteristics(deviceId);
this.refreshVerticalAirflowDirectionAccessoryCharacteristics(deviceId);
this.refreshDryModeSwitchAccessoryCharacteristics(deviceId);
this.refreshEconomySwitchAccessoryCharacteristics(deviceId);
this.refreshEnergySavingFanSwitchAccessoryCharacteristics(deviceId);
this.refreshFanModeSwitchAccessoryCharacteristics(deviceId);
this.refreshMinimumHeatModeSwitchAccessoryCharacteristics(deviceId);
this.refreshPowerfulSwitchAccessoryCharacteristics(deviceId);
}
refreshThermostatAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_THERMOSTAT;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.CurrentHeatingCoolingState,
this.Characteristic.TargetHeatingCoolingState,
this.Characteristic.CurrentTemperature,
this.Characteristic.TargetTemperature,
this.Characteristic.TemperatureDisplayUnits
]
);
}
refreshFanAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_FAN;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.Active,
this.Characteristic.CurrentFanState,
this.Characteristic.TargetFanState,
this.Characteristic.RotationSpeed,
this.Characteristic.SwingMode
]
);
}
refreshVerticalAirflowDirectionAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_VERTICAL_AIRFLOW_DIRECTION;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.Active,
this.Characteristic.CurrentFanState,
this.Characteristic.RotationSpeed
]
);
}
refreshDryModeSwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_DRY_MODE_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshEconomySwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_ECONOMY_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshEnergySavingFanSwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_ENERGY_SAVING_FAN_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshFanModeSwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_FAN_MODE_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshMinimumHeatModeSwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_MINIMUM_HEAT_MODE_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshPowerfulSwitchAccessoryCharacteristics(deviceId) {
const suffix = constants.ACCESSORY_SUFFIX_POWERFUL_SWITCH;
const accessory = this._getExistingAccessory(deviceId, suffix);
if (accessory === null) {
return false;
}
return this._refreshAccessoryCharacteristics(
accessory,
[
this.Characteristic.On
]
);
}
refreshServiceCharacteristics(service, characteristicClasses) {
characteristicClasses.forEach(function(characteristicClass) {
const characteristic = service.getCharacteristic(characteristicClass);
let logMessage = '[' + service.constructor.name + '][' + characteristic.constructor.name + '] Refreshing characteristic';
this.platform.log.debug(logMessage);
characteristic.emit(
'get',
(function(error, value) {
if (error === null) {
characteristic.sendEventNotification(value);
} else {
logMessage = logMessage + ' failed with error: ' + error;
this.platform.log.error(logMessage);
}
}).bind(this)
);
}, this);
return true;
}
_updateExistingAccessory(existingAccessory, deviceId, model) {
this.platform.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
existingAccessory.context.airstageClient = this.platform.airstageClient;
existingAccessory.context.deviceId = deviceId;
existingAccessory.context.model = model;
this.platform.api.updatePlatformAccessories([existingAccessory]);
}
_unregisterAccessory(deviceId, deviceName, suffix, log = true) {
const accessoryName = this._getAccessoryName(deviceName, suffix);
const existingAccessory = this._getExistingAccessory(deviceId, suffix);
if (log === true) {
this.platform.log.info(
'Not adding accessory because it is disabled in the config:',
accessoryName
);
}
if (existingAccessory) {
this._unregisterExistingAccessory(existingAccessory, log);
}
}
_unregisterExistingAccessory(existingAccessory, log) {
if (log === true) {
this.platform.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
}
this.platform.api.unregisterPlatformAccessories(
settings.PLUGIN_NAME,
settings.PLATFORM_NAME,
[existingAccessory]
);
}
_registerNewAccessory(newAccessory, deviceId, model) {
this.platform.log.info('Adding new accessory:', newAccessory.displayName);
newAccessory.context.airstageClient = this.platform.airstageClient;
newAccessory.context.deviceId = deviceId;
newAccessory.context.model = model;
this.platform.api.registerPlatformAccessories(
settings.PLUGIN_NAME,
settings.PLATFORM_NAME,
[newAccessory]
);
this.platform.accessories.push(newAccessory);
}
_instantiateNewAccessory(deviceId, deviceName, model, suffix) {
const accessoryName = this._getAccessoryName(deviceName, suffix);
const accessoryUuid = this._getAccessoryUuid(deviceId, suffix);
const accessory = new this.platform.api.platformAccessory(
accessoryName,
accessoryUuid
);
accessory.context.airstageClient = this.platform.airstageClient;
accessory.context.deviceId = deviceId;
accessory.context.model = model;
return accessory;
}
_getExistingAccessory(deviceId, suffix) {
const accessoryUuid = this._getAccessoryUuid(deviceId, suffix);
return this.platform.accessories.find(
accessory => accessory.UUID === accessoryUuid
) || null;
}
_refreshAccessoryCharacteristics(accessory, characteristicClasses) {
const service = accessory.services.find(
service => (service instanceof this.Service.AccessoryInformation) === false
) || null;
if (service === null) {
return false;
}
return this.refreshServiceCharacteristics(
service,
characteristicClasses
);
}
_getAccessoryName(deviceName, suffix) {
const suffixParts = suffix.split('-');
suffixParts.forEach(function(part, idx, array) {
array[idx] = (part.charAt(0).toUpperCase() + part.substring(1));
});
return deviceName + ' ' + suffixParts.join(' ');
}
_getAccessoryUuid(deviceId, suffix) {
return this.platform.api.hap.uuid.generate(
deviceId + '-' + suffix
);
}
}
module.exports = PlatformAccessoryManager;