UNPKG

homebridge-fujitsu-airstage

Version:

A Homebridge plugin to control devices that use the Fujitsu Airstage API.

324 lines (277 loc) 10.1 kB
'use strict'; const ConfigManager = require('./config-manager'); const PlatformAccessoryManager = require('./platform-accessory-manager'); const accessories = require('./accessories'); const airstage = require('./airstage'); const settings = require('./settings'); class Platform { accessories = []; constructor(log, config, api, withSetInterval = true) { this.log = log; this.config = config; this.api = api; // Polyfill for Homebridge < 1.8.0 if (!this.log.success) { this.log.success = this.log.info; } // Initialize platform Airstage client and accessories this._init(withSetInterval); } _init(withSetInterval) { this.Service = this.api.hap.Service; this.Characteristic = this.api.hap.Characteristic; this.configManager = new ConfigManager(this.config, this.api); this.accessoryManager = new PlatformAccessoryManager(this); let tokens = this.configManager.getTokens(); this.airstageClient = new airstage.Client( this.config.region, this.config.country, this.config.language, this.config.email || null, this.config.password || null, null, null, tokens.accessToken || null, tokens.accessTokenExpiry || null, tokens.refreshToken || null ); if (withSetInterval) { setInterval( this._refreshAirstageClientCache.bind(this), (5 * 60 * 1000) // 5 minutes ); setInterval( this._refreshAirstageClientToken.bind(this), (50 * 60 * 1000) // 50 minutes ); } this.api.on('didFinishLaunching', this.discoverDevices.bind(this)); } configureAccessory(accessory) { this.accessories.push(accessory); } discoverDevices(callback = null) { this.airstageClient.refreshTokenOrAuthenticate((function(error) { if (error) { if (callback !== null) { callback(error); } if (error === 'Invalid access token') { this._unsetAccessTokenInConfig(); } return this.log.error('Error when attempting to authenticate with Airstage:', error); } this._updateConfigWithAccessToken(); this._configureAirstageDevices(callback); }).bind(this)); } _updateConfigWithAccessToken() { const accessToken = this.airstageClient.getAccessToken(); const accessTokenExpiry = this.airstageClient.getAccessTokenExpiry(); const refreshToken = this.airstageClient.getRefreshToken(); if (accessToken && accessTokenExpiry && refreshToken) { this.configManager.saveTokens( accessToken, accessTokenExpiry, refreshToken ); } } _unsetAccessTokenInConfig() { this.configManager.saveTokens(null, null, null); } _configureAirstageDevices(callback) { this.airstageClient.getUserMetadata((function(error) { if (error) { if (callback !== null) { callback(error); } return this.log.error('Error when attempting to communicate with Airstage:', error); } this.airstageClient.getDevices(null, (function(error, devices) { if (error) { if (callback !== null) { callback(error); } return this.log.error('Error when attempting to communicate with Airstage:', error); } const deviceIds = Object.keys(devices.metadata); deviceIds.forEach(function(deviceId) { const deviceMetadata = devices.metadata[deviceId]; const deviceParameters = devices.parameters[deviceId]; const deviceName = deviceMetadata.deviceName; const model = deviceParameters[airstage.apiv1.constants.PARAMETER_MODEL] || 'Airstage'; this._configureAirstageDevice( deviceId, deviceName, model ); }, this); if (callback !== null) { callback(null); } }).bind(this)); }).bind(this)); } _configureAirstageDevice( deviceId, deviceName, model ) { // Thermostat if (this.config.enableThermostat) { this.accessoryManager.registerThermostatAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterThermostatAccessory( deviceId, deviceName ); } // Fan if (this.config.enableFan) { this.accessoryManager.registerFanAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterFanAccessory( deviceId, deviceName ); } // Deprecated: the VerticalSlatsAccessory was replaced by the // VerticalAirflowDirectionAccessory this.accessoryManager.unregisterVerticalSlatsAccessory( deviceId, deviceName ); // Vertical airflow direction if (this.config.enableVerticalAirflowDirection) { this.accessoryManager.registerVerticalAirflowDirectionAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterVerticalAirflowDirectionAccessory( deviceId, deviceName ); } // "Dry Mode" switch if (this.config.enableDryModeSwitch) { this.accessoryManager.registerDryModeSwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterDryModeSwitchAccessory( deviceId, deviceName ); } // "Economy" switch if (this.config.enableEconomySwitch) { this.accessoryManager.registerEconomySwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterEconomySwitchAccessory( deviceId, deviceName ); } // "Energy Saving Fan" switch if (this.config.enableEnergySavingFanSwitch) { this.accessoryManager.registerEnergySavingFanSwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterEnergySavingFanSwitchAccessory( deviceId, deviceName ); } // "Fan Mode" switch if (this.config.enableFanModeSwitch) { this.accessoryManager.registerFanModeSwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterFanModeSwitchAccessory( deviceId, deviceName ); } // "Minimum Heat Mode" switch if (this.config.enableMinimumHeatModeSwitch) { this.accessoryManager.registerMinimumHeatModeSwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterMinimumHeatModeSwitchAccessory( deviceId, deviceName ); } // "Powerful" switch if (this.config.enablePowerfulSwitch) { this.accessoryManager.registerPowerfulSwitchAccessory( deviceId, deviceName, model ); } else { this.accessoryManager.unregisterPowerfulSwitchAccessory( deviceId, deviceName ); } } _refreshAirstageClientToken() { this.airstageClient.refreshToken((function(error) { if (error) { return this.log.error('Error when attempting to refresh Airstage access token:', error); } this._updateConfigWithAccessToken(); this.log.debug('Refreshed Airstage client token'); }).bind(this)); } _refreshAirstageClientCache() { this.airstageClient.refreshUserMetadataCache( (function(error) { if (error) { return this.log.error('Error when attempting to communicate with Airstage:', error); } this.log.debug('Refreshed Airstage client user metadata cache'); this.airstageClient.refreshDeviceCache( (function(error, devices) { if (error) { return this.log.error('Error when attempting to communicate with Airstage:', error); } this.log.debug('Refreshed Airstage client device cache'); const deviceIds = Object.keys(devices.metadata); deviceIds.forEach(function(deviceId) { this.accessoryManager.refreshAllAccessoryCharacteristics(deviceId); }, this); }).bind(this) ); }).bind(this) ); } } module.exports = Platform;