Init Plugin 2.0

This commit is contained in:
Khaos Tian
2016-01-30 18:36:55 -08:00
parent 1a356a1783
commit e1334c5196
10 changed files with 717 additions and 117 deletions

View File

@@ -1,6 +1,7 @@
var path = require('path');
var fs = require('fs');
var uuid = require("hap-nodejs").uuid;
var accessoryStorage = require('node-persist').create();
var Bridge = require("hap-nodejs").Bridge;
var Accessory = require("hap-nodejs").Accessory;
var Service = require("hap-nodejs").Service;
@@ -10,6 +11,8 @@ var once = require("hap-nodejs/lib/util/once").once;
var Plugin = require('./plugin').Plugin;
var User = require('./user').User;
var API = require('./api').API;
var PlatformAccessory = require("./platformAccessory").PlatformAccessory;
var BridgeSetupManager = require("./bridgeSetupManager").BridgeSetupManager;
var log = require("./logger")._system;
var Logger = require('./logger').Logger;
@@ -20,10 +23,32 @@ module.exports = {
}
function Server() {
// Setup Accessory Cache Storage
accessoryStorage.initSync({ dir: User.cachedAccessoryPath() });
this._api = new API(); // object we feed to Plugins
this._api.on('registerPlatformAccessories', function(accessories) {
this._handleRegisterPlatformAccessories(accessories);
}.bind(this));
this._api.on('unregisterPlatformAccessories', function(accessories) {
this._handleUnregisterPlatformAccessories(accessories);
}.bind(this));
this._plugins = this._loadPlugins(); // plugins[name] = Plugin instance
this._config = this._loadConfig();
this._config = this._loadConfig();
this._cachedPlatformAccessories = this._loadCachedPlatformAccessories();
this._bridge = this._createBridge();
this._activeDynamicPlugins = {};
this._configurablePlatformPlugins = {};
this._setupManager = new BridgeSetupManager();
this._setupManager.on('newConfig', this._handleNewConfig.bind(this));
this._setupManager.on('requestCurrentConfig', function(callback) {
callback(this._config);
}.bind(this));
}
Server.prototype.run = function() {
@@ -34,12 +59,18 @@ Server.prototype.run = function() {
if (this._config.platforms) this._loadPlatforms();
if (this._config.accessories) this._loadAccessories();
this._loadDynamicPlatforms();
this._configCachedPlatformAccessories();
this._setupManager.configurablePlatformPlugins = this._configurablePlatformPlugins;
this._bridge.addService(this._setupManager.service);
this._asyncWait = false;
// publish now unless we're waiting on anyone
if (this._asyncCalls == 0)
this._publish();
this._api.emit('didFinishLaunching');
}
Server.prototype._publish = function() {
@@ -108,8 +139,18 @@ Server.prototype._loadConfig = function() {
// Complain and exit if it doesn't exist yet
if (!fs.existsSync(configPath)) {
log.error("Couldn't find a config.json file at '"+configPath+"'. Look at config-sample.json for examples of how to format your config.js and add your home accessories.");
process.exit(1);
var config = {};
config.bridge = {
"name": "Homebridge",
"username": "CC:22:3D:E3:CE:30",
"port": 51826,
"pin": "031-45-154"
};
return config;
// log.error("Couldn't find a config.json file at '"+configPath+"'. Look at config-sample.json for examples of how to format your config.js and add your home accessories.");
// process.exit(1);
}
// Load up the configuration file
@@ -142,6 +183,23 @@ Server.prototype._loadConfig = function() {
return config;
}
Server.prototype._loadCachedPlatformAccessories = function() {
var cachedAccessories = accessoryStorage.getItem("cachedAccessories");
var platformAccessories = [];
if (cachedAccessories) {
for (var index in cachedAccessories) {
var serializedAccessory = cachedAccessories[index];
var platformAccessory = new PlatformAccessory(serializedAccessory.displayName, serializedAccessory.UUID, serializedAccessory.category);
platformAccessory._configFromData(serializedAccessory);
platformAccessories.push(platformAccessory);
}
}
return platformAccessories;
}
Server.prototype._createBridge = function() {
// pull out our custom Bridge settings from config.json, if any
var bridgeConfig = this._config.bridge || {};
@@ -201,11 +259,64 @@ Server.prototype._loadPlatforms = function() {
platformLogger("Initializing %s platform...", platformType);
var platformInstance = new platformConstructor(platformLogger, platformConfig);
this._loadPlatformAccessories(platformInstance, platformLogger, platformType);
var platformInstance = new platformConstructor(platformLogger, platformConfig, this._api);
if (platformInstance.configureAccessory == undefined) {
// Plugin 1.0, load accessories
this._loadPlatformAccessories(platformInstance, platformLogger, platformType);
} else {
this._activeDynamicPlugins[platformType] = platformInstance;
}
if (platformInstance.configurationRequestHandler != undefined) {
this._configurablePlatformPlugins[platformType] = platformInstance;
}
}
}
Server.prototype._loadDynamicPlatforms = function() {
for (var dynamicPluginName in this._api._dynamicPlatforms) {
if (!this._activeDynamicPlugins[dynamicPluginName] && !this._activeDynamicPlugins[dynamicPluginName.split(".")[1]]) {
console.log("Load " + dynamicPluginName);
var platformConstructor = this._api._dynamicPlatforms[dynamicPluginName];
var platformLogger = Logger.withPrefix(dynamicPluginName);
var platformInstance = new platformConstructor(platformLogger, null, this._api);
this._activeDynamicPlugins[dynamicPluginName] = platformInstance;
if (platformInstance.configurationRequestHandler != undefined) {
this._configurablePlatformPlugins[dynamicPluginName] = platformInstance;
}
}
}
}
Server.prototype._configCachedPlatformAccessories = function() {
for (var index in this._cachedPlatformAccessories) {
var accessory = this._cachedPlatformAccessories[index];
if (!(accessory instanceof PlatformAccessory)) {
console.log("Unexpected Accessory!");
continue;
}
var fullName = accessory._associatedPlugin + "." + accessory._associatedPlatform;
var platformInstance = this._activeDynamicPlugins[fullName];
if (!platformInstance) {
platformInstance = this._activeDynamicPlugins[accessory._associatedPlatform];
}
if (platformInstance) {
platformInstance.configureAccessory(accessory);
} else {
console.log("Failed to find plugin to handle accessory " + accessory.displayName);
}
accessory._prepareAssociatedHAPAccessory();
this._bridge.addBridgedAccessory(accessory._associatedHAPAccessory);
}
}
Server.prototype._loadPlatformAccessories = function(platformInstance, log, platformType) {
this._asyncCalls++;
platformInstance.accessories(once(function(foundAccessories){
@@ -280,6 +391,128 @@ Server.prototype._createAccessory = function(accessoryInstance, displayName, acc
}
}
Server.prototype._handleRegisterPlatformAccessories = function(accessories) {
var hapAccessories = [];
for (var index in accessories) {
var accessory = accessories[index];
accessory._prepareAssociatedHAPAccessory();
hapAccessories.push(accessory._associatedHAPAccessory);
this._cachedPlatformAccessories.push(accessory);
}
this._bridge.addBridgedAccessories(hapAccessories);
this._updateCachedAccessories();
}
Server.prototype._handleUnregisterPlatformAccessories = function(accessories) {
var hapAccessories = [];
for (var index in accessories) {
var accessory = accessories[index];
if (accessory._associatedHAPAccessory) {
hapAccessories.push(accessory._associatedHAPAccessory);
}
for (var targetIndex in this._cachedPlatformAccessories) {
var existing = this._cachedPlatformAccessories[targetIndex];
if (existing.UUID === accessory.UUID) {
this._cachedPlatformAccessories.splice(targetIndex, 1);
break;
}
}
}
this._bridge.removeBridgedAccessories(hapAccessories);
this._updateCachedAccessories();
}
Server.prototype._updateCachedAccessories = function() {
var serializedAccessories = [];
for (var index in this._cachedPlatformAccessories) {
var accessory = this._cachedPlatformAccessories[index];
serializedAccessories.push(accessory._dictionaryPresentation());
}
accessoryStorage.setItemSync("cachedAccessories", serializedAccessories);
}
Server.prototype._handleNewConfig = function(type, name, replace, config) {
if (type === "accessory") {
// TODO: Load new accessory
if (!this._config.accessories) {
this._config.accessories = [];
}
if (!replace) {
this._config.accessories.push(config);
} else {
var targetName;
if (name.indexOf('.') == -1) {
targetName = name.split(".")[1];
}
var found = false;
for (var index in this._config.accessories) {
var accessoryConfig = this._config.accessories[index];
if (accessoryConfig.accessory === name) {
this._config.accessories[index] = config;
found = true;
break;
}
if (targetName && (accessoryConfig.accessory === targetName)) {
this._config.accessories[index] = config;
found = true;
break;
}
}
if (!found) {
this._config.accessories.push(config);
}
}
} else if (type === "platform") {
if (!this._config.platforms) {
this._config.platforms = [];
}
if (!replace) {
this._config.platforms.push(config);
} else {
var targetName;
if (name.indexOf('.') == -1) {
targetName = name.split(".")[1];
}
var found = false;
for (var index in this._config.platforms) {
var platformConfig = this._config.platforms[index];
if (platformConfig.platform === name) {
this._config.platforms[index] = config;
found = true;
break;
}
if (targetName && (platformConfig.platform === targetName)) {
this._config.platforms[index] = config;
found = true;
break;
}
}
if (!found) {
this._config.platforms.push(config);
}
}
}
var serializedConfig = JSON.stringify(this._config, null, ' ');
var configPath = User.configPath();
fs.writeFileSync(configPath, serializedConfig, 'utf8');
}
// Returns the setup code in a scannable format.
Server.prototype._printPin = function(pin) {
console.log("Scan this code with your HomeKit App on your iOS device to pair with Homebridge:");