homebridge-smarthomeng/index.js
2016-07-01 22:13:37 +02:00

213 lines
7.9 KiB
JavaScript
Executable File

// SmartHomeNG Platform Shim for HomeBridge
var Accessory, Service, Characteristic, UUIDGen;
var fs = require('fs');
var path = require('path');
var SmartHomeNGConnection = require("./SmartHomeNGConnection.js").SmartHomeNGConnection;
module.exports = function(homebridge) {
// Accessory must be created from PlatformAccessory Constructor
Accessory = homebridge.platformAccessory;
// Service and Characteristic are from hap-nodejs
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
UUIDGen = homebridge.hap.uuid;
homebridge.registerPlatform("homebridge-smarthomeng", "SmartHomeNG", SmartHomeNGPlatform);
}
// Platform constructor
function SmartHomeNGPlatform(log, config, api) {
this.log = log;
this.config = config;
this.accessoriesCache = [];
this.supportedFunctions = ['onoff', 'brightness'];
if (this.config["host"] != undefined) {
this.shng_host = this.config["host"];
} else {
this.shng_host = "localhost";
}
if (this.config["port"] != undefined) {
this.shng_port = this.config["port"];
} else {
this.shng_port = 2424;
}
var that = this
this.log("SmartHomeNG Platform Plugin Version " + this.getVersion())
this.shngcon = new SmartHomeNGConnection(this, this.log, this.shng_host, this.shng_port);
this.shngcon.updateCallback = this.update;
if (api) {
this.api = api;
// Listen to event "didFinishLaunching", this means homebridge already finished loading cached accessories
// Platform Plugin should only register new accessory that doesn't exist in homebridge after this event.
// Or start discover new accessories
this.api.on('didFinishLaunching', function() {
this.log("Finished loading " + this.accessoriesCache.length + " accessories");
// Add supported SHNG items to monitoring
var tomonitor = [];
for(i = 0; i < this.accessoriesCache.length; i++) {
var device = this.accessoriesCache[i].device;
for (var key in device) {
if (this.supportedFunctions.indexOf(key) >= 0) {
tomonitor.push(device[key]);
}
}
}
this.shngcon.tomonitor = tomonitor;
}.bind(this));
}
this.shngcon.init();
}
// Accessory constructor
function SmartHomeNGAccessory(log, device, shngcon) {
this.name = device.name;
this.device = device;
this.log = log;
this.shngcon = shngcon;
this.value = undefined;
/*this.log("CONSTRUCTOR: ");
this.log(device);
this.log("------")*/
}
SmartHomeNGPlatform.prototype = {
// Return our accessories to homebridge
accessories: function(callback) {
var that = this;
var foundAccessories = [];
this.log("Building list of accessories");
var configAccessories = this.config.accessories;
for (var i = 0; i < configAccessories.length; i++) {
this.log("Parsing accessory: '" + configAccessories[i].name + "'.");
var accessory = new SmartHomeNGAccessory(that.log, configAccessories[i], that.shngcon);
foundAccessories.push(accessory);
}
//this.log(foundAccessories)
this.accessoriesCounter = foundAccessories.length;
this.accessoriesCache = foundAccessories;
callback(foundAccessories);
},
update: function (item, value) {
//this.log("CALLBACK: item " + item + " with value " + value);
for (i = 0; i < this.platform.accessoriesCache.length; i++) {
accessory = this.platform.accessoriesCache[i].device;
// loop through accessories and services to find modified one
for (var key in accessory) {
if (accessory[key] == item) {
this.log("Updating item '" + item + "' with value " + value);
accessory[key + '_value'] = value;
break;
}
}
}
},
// Get version info from package.json file
getVersion: function() {
var pjPath = path.join(__dirname, './package.json');
var pj = JSON.parse(fs.readFileSync(pjPath));
return pj.version;
}
}
SmartHomeNGAccessory.prototype = {
// Enumerate accessory services and characteristics
getServices: function() {
var that = this;
this.log("Setting services for '" + this.name + "'");
// check if device type is set in config
if (!this.device.type) {
this.log("Ignoring '" + this.name + "' because no device type found, make sure to have the 'type' parameter in your config.json !");
return [];
}
// construct service and characteristics according to device type
switch (this.device.type.toLowerCase()) {
// Lightbulb service
case 'lightbulb':
var myService = new Service.Lightbulb(this.name);
// On / Off characteristic
if (this.device.onoff) {
this.log("Adding on/off characteristic to " + this.name);
myService
.getCharacteristic(Characteristic.On)
.on('get', function(callback) { that.getValue("onoff", callback);})
.on('set', function(value, callback) { that.setValue("onoff", value, callback);});
}
// Dimmable characteristic
if (this.device.brightness) {
this.log("Adding brightness characteristic to " + this.name);
myService
.addCharacteristic(Characteristic.Brightness)
.on('get', function(callback) { that.getValue("brightness", callback);})
.on('set', function(value, callback) { that.setValue("brightness", value, callback);});
}
break;
// If no supported type is found warn user and return empty services
default:
this.log("Ignoring '" + this.name + "' because device type '" + this.device.type + "' is not supported !");
return [];
break;
}
// device information service
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Manufacturer, this.manufacturername)
.setCharacteristic(Characteristic.Model, this.model)
.setCharacteristic(Characteristic.SerialNumber, this.device.uniqueid);
return [informationService, myService];
},
// Get value
getValue: function(characteristic, callback) {
this.log("Get value for " + this.device.name + ", characteristic: " + characteristic + ".");
//this.log(this.device);
if (this.device[characteristic + "_value"] != undefined) {
this.log("Found value '" + this.device[characteristic + "_value"] + "' for '" + characteristic + "' of device '" + this.device.name + "'.");
if (callback) callback(null, this.device[characteristic + "_value"]);
} else {
if (callback) callback("Oh oh :-(");
}
},
// Set value
setValue: function(characteristic, value, callback) {
this.log("Set " + this.device.name + ", characteristic: " + characteristic + ", value: " + value + ".");
// If item for characteristic exists then send value to it
if (this.device[characteristic] != undefined) {
this.shngcon.setValue(this.device[characteristic], value);
}
// Check if callback required
if (callback) callback(); // Success
callback = null;
},
// Respond to identify request
identify: function(callback) {
this.log("Identify request for '" + this.device.name + "'.");
}
}