Merge branch 'nfarina/master' into z-way-server-2

This commit is contained in:
S'pht'Kr
2015-08-25 20:23:33 +02:00
4 changed files with 179 additions and 189 deletions

View File

@@ -1,6 +1,11 @@
var types = require("HAP-NodeJS/accessories/types.js");
var Service = require("HAP-NodeJS").Service;
var Characteristic = require("HAP-NodeJS").Characteristic;
var request = require("request");
module.exports = {
accessory: HttpAccessory
}
function HttpAccessory(log, config) {
this.log = log;
@@ -9,9 +14,6 @@ function HttpAccessory(log, config) {
this.off_url = config["off_url"];
this.brightness_url = config["brightness_url"];
this.http_method = config["http_method"];
// device info
this.name = config["name"];
}
HttpAccessory.prototype = {
@@ -26,135 +28,73 @@ HttpAccessory.prototype = {
})
},
setPowerState: function(powerOn) {
setPowerState: function(powerOn, callback) {
var url;
if (powerOn) {
url = this.on_url
this.log("Setting power state on the '"+this.name+"' to on");
}else{
url = this.off_url
this.log("Setting power state on the '"+this.name+"' to off");
url = this.on_url;
this.log("Setting power state to on");
}
else {
url = this.off_url;
this.log("Setting power state to off");
}
this.httpRequest(url, this.http_method, function(error, response, body){
this.httpRequest(url, this.http_method, function(error, response, body) {
if (error) {
return console.error('http power function failed:', error);
}else{
return console.log('http power function succeeded!');
this.log('HTTP power function failed: %s', error.message);
callback(error);
}
});
else {
this.log('HTTP power function succeeded!');
callback();
}
}.bind(this));
},
setBrightness: function(level) {
setBrightness: function(level, callback) {
var url = this.brightness_url.replace("%b", level)
this.log("Setting brightness on the '"+this.name+"' to " + level);
this.log("Setting brightness to %s", level);
this.httpRequest(url, this.http_method, function(error, response, body){
this.httpRequest(url, this.http_method, function(error, response, body) {
if (error) {
return console.error('http brightness function failed:', error);
}else{
return console.log('http brightness function succeeded!');
this.log('HTTP brightness function failed: %s', error);
callback(error);
}
});
else {
this.log('HTTP brightness function succeeded!');
callback();
}
}.bind(this));
},
identify: function(callback) {
this.log("Identify requested!");
callback(); // success
},
getServices: function() {
var that = this;
return [{
sType: types.ACCESSORY_INFORMATION_STYPE,
characteristics: [{
cType: types.NAME_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: this.name,
supportEvents: false,
supportBonjour: false,
manfDescription: "Name of the accessory",
designedMaxLength: 255
},{
cType: types.MANUFACTURER_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "Http",
supportEvents: false,
supportBonjour: false,
manfDescription: "Manufacturer",
designedMaxLength: 255
},{
cType: types.MODEL_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "Rev-1",
supportEvents: false,
supportBonjour: false,
manfDescription: "Model",
designedMaxLength: 255
},{
cType: types.SERIAL_NUMBER_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "A1S2NASF88EW",
supportEvents: false,
supportBonjour: false,
manfDescription: "SN",
designedMaxLength: 255
},{
cType: types.IDENTIFY_CTYPE,
onUpdate: null,
perms: ["pw"],
format: "bool",
initialValue: false,
supportEvents: false,
supportBonjour: false,
manfDescription: "Identify Accessory",
designedMaxLength: 1
}]
},{
sType: types.LIGHTBULB_STYPE,
characteristics: [{
cType: types.NAME_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: this.name,
supportEvents: true,
supportBonjour: false,
manfDescription: "Name of service",
designedMaxLength: 255
},{
cType: types.POWER_STATE_CTYPE,
onUpdate: function(value) { that.setPowerState(value); },
perms: ["pw","pr","ev"],
format: "bool",
initialValue: 0,
supportEvents: true,
supportBonjour: false,
manfDescription: "Change the power state",
designedMaxLength: 1
},{
cType: types.BRIGHTNESS_CTYPE,
onUpdate: function(value) { that.setBrightness(value); },
perms: ["pw","pr","ev"],
format: "int",
initialValue: 0,
supportEvents: true,
supportBonjour: false,
manfDescription: "Adjust Brightness",
designedMinValue: 0,
designedMaxValue: 100,
designedMinStep: 1,
unit: "%"
}]
}];
// you can OPTIONALLY create an information service if you wish to override
// the default values for things like serial number, model, etc.
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Manufacturer, "HTTP Manufacturer")
.setCharacteristic(Characteristic.Model, "HTTP Model")
.setCharacteristic(Characteristic.SerialNumber, "HTTP Serial Number");
var lightbulbService = new Service.Lightbulb();
lightbulbService
.getCharacteristic(Characteristic.On)
.on('set', this.setPowerState.bind(this));
lightbulbService
.addCharacteristic(new Characteristic.Brightness())
.on('set', this.setBrightness.bind(this));
return [informationService, lightbulbService];
}
};
module.exports.accessory = HttpAccessory;

153
app.js
View File

@@ -5,6 +5,8 @@ var hap = require('HAP-NodeJS');
var uuid = require('HAP-NodeJS').uuid;
var Bridge = require('HAP-NodeJS').Bridge;
var Accessory = require('HAP-NodeJS').Accessory;
var Service = require('HAP-NodeJS').Service;
var Characteristic = require('HAP-NodeJS').Characteristic;
var accessoryLoader = require('HAP-NodeJS').AccessoryLoader;
console.log("Starting HomeBridge server...");
@@ -72,28 +74,19 @@ function loadAccessories() {
var accessoryConfig = config.accessories[i];
// Load up the class for this accessory
var accessoryName = accessoryConfig["accessory"]; // like "WeMo"
var accessoryModule = require('./accessories/' + accessoryName + ".js"); // like "./accessories/WeMo.js"
var accessoryType = accessoryConfig["accessory"]; // like "WeMo"
var accessoryModule = require('./accessories/' + accessoryType + ".js"); // like "./accessories/WeMo.js"
var accessoryConstructor = accessoryModule.accessory; // like "WeMoAccessory", a JavaScript constructor
// Create a custom logging function that prepends the device display name for debugging
var name = accessoryConfig["name"];
var log = function(name) { return function(s) { console.log("[" + name + "] " + s); }; }(name);
var accessoryName = accessoryConfig["name"];
var log = createLog(accessoryName);
log("Initializing " + accessoryName + " accessory...");
log("Initializing %s accessory...", accessoryType);
var accessoryInstance = new accessoryConstructor(log, accessoryConfig);
// Extract the raw "services" for this accessory which is a big array of objects describing the various
// hooks in and out of HomeKit for the HAP-NodeJS server.
var services = accessoryInstance.getServices();
var accessory = createAccessory(accessoryInstance, accessoryName);
// Create the actual HAP-NodeJS "Accessory" instance
var accessory = accessoryLoader.parseAccessoryJSON({
displayName: name,
services: services
});
// add it to the bridge
bridge.addBridgedAccessory(accessory);
}
@@ -108,54 +101,104 @@ function loadPlatforms() {
var platformConfig = config.platforms[i];
// Load up the class for this accessory
var platformName = platformConfig["platform"]; // like "Wink"
var platformModule = require('./platforms/' + platformName + ".js"); // like "./platforms/Wink.js"
var platformType = platformConfig["platform"]; // like "Wink"
var platformName = platformConfig["name"];
var platformModule = require('./platforms/' + platformType + ".js"); // like "./platforms/Wink.js"
var platformConstructor = platformModule.platform; // like "WinkPlatform", a JavaScript constructor
// Create a custom logging function that prepends the platform display name for debugging
var name = platformConfig["name"];
var log = function(name) { return function(s) { console.log("[" + name + "] " + s); }; }(name);
// Create a custom logging function that prepends the platform name for debugging
var log = createLog(platformName);
log("Initializing " + platformName + " platform...");
log("Initializing %s platform...", platformType);
var platformInstance = new platformConstructor(log, platformConfig);
// wrap name and log in a closure so they don't change in the callback
function getAccessories(name, log) {
asyncCalls++;
platformInstance.accessories(function(foundAccessories){
asyncCalls--;
// loop through accessories adding them to the list and registering them
for (var i = 0; i < foundAccessories.length; i++) {
var accessoryInstance = foundAccessories[i];
log("Initializing device with name " + accessoryInstance.name + "...")
// Extract the raw "services" for this accessory which is a big array of objects describing the various
// hooks in and out of HomeKit for the HAP-NodeJS server.
var services = accessoryInstance.getServices();
// Create the actual HAP-NodeJS "Accessory" instance
var accessory = accessoryLoader.parseAccessoryJSON({
displayName: name,
services: services
});
// add it to the bridge
bridge.addBridgedAccessory(accessory);
}
// were we the last callback?
if (asyncCalls === 0 && !asyncWait)
publish();
})
}
// query for devices
getAccessories(name, log);
loadPlatformAccessories(platformInstance, log);
}
}
function loadPlatformAccessories(platformInstance, log) {
asyncCalls++;
platformInstance.accessories(function(foundAccessories){
asyncCalls--;
// loop through accessories adding them to the list and registering them
for (var i = 0; i < foundAccessories.length; i++) {
var accessoryInstance = foundAccessories[i];
var accessoryName = accessoryInstance.name; // assume this property was set
log("Initializing platform accessory '%s'...", accessoryName);
var accessory = createAccessory(accessoryInstance, accessoryName);
// add it to the bridge
bridge.addBridgedAccessory(accessory);
}
// were we the last callback?
if (asyncCalls === 0 && !asyncWait)
publish();
});
}
function createAccessory(accessoryInstance, displayName) {
var services = accessoryInstance.getServices();
if (!(services[0] instanceof Service)) {
// The returned "services" for this accessory is assumed to be the old style: a big array
// of JSON-style objects that will need to be parsed by HAP-NodeJS's AccessoryLoader.
// Create the actual HAP-NodeJS "Accessory" instance
return accessoryLoader.parseAccessoryJSON({
displayName: displayName,
services: services
});
}
else {
// The returned "services" for this accessory are simply an array of new-API-style
// Service instances which we can add to a created HAP-NodeJS Accessory directly.
var accessoryUUID = uuid.generate(accessoryInstance.constructor.name + ":" + displayName);
var accessory = new Accessory(displayName, accessoryUUID);
// listen for the identify event if the accessory instance has defined an identify() method
if (accessoryInstance.identify)
accessory.on('identify', function(paired, callback) { accessoryInstance.identify(callback); });
services.forEach(function(service) {
// if you returned an AccessoryInformation service, merge its values with ours
if (service instanceof Service.AccessoryInformation) {
var existingService = accessory.getService(Service.AccessoryInformation);
// pull out any values you may have defined
var manufacturer = service.getCharacteristic(Characteristic.Manufacturer).value;
var model = service.getCharacteristic(Characteristic.Model).value;
var serialNumber = service.getCharacteristic(Characteristic.SerialNumber).value;
if (manufacturer) existingService.setCharacteristic(Characteristic.Manufacturer, manufacturer);
if (model) existingService.setCharacteristic(Characteristic.Model, model);
if (serialNumber) existingService.setCharacteristic(Characteristic.SerialNumber, serialNumber);
}
else {
accessory.addService(service);
}
});
return accessory;
}
}
// Returns a logging function that prepends messages with the given name in [brackets].
function createLog(name) {
return function(message) {
var rest = Array.prototype.slice.call(arguments, 1 ); // any arguments after message
var args = ["[%s] " + message, name].concat(rest);
console.log.apply(console, args);
}
}
function publish() {
bridge.publish({
username: bridgeConfig.username || "CC:22:3D:E3:CE:30",

View File

@@ -15,7 +15,7 @@
"carwingsjs": "0.0.x",
"color": "0.10.x",
"elkington": "kevinohara80/elkington",
"hap-nodejs": "git+https://github.com/KhaosT/HAP-NodeJS#187174846dc4b8970efba74b9eb2968b35f15d87",
"hap-nodejs": "git+https://github.com/KhaosT/HAP-NodeJS#46ba0597eb339983a14d98c53764a58a5516fcd2",
"harmonyhubjs-client": "^1.1.4",
"harmonyhubjs-discover": "git+https://github.com/swissmanu/harmonyhubjs-discover.git",
"mdns": "^2.2.4",

View File

@@ -66,11 +66,17 @@ DomoticzPlatform.prototype = {
},
accessories: function(callback) {
this.log("Fetching Domoticz lights and switches...");
var that = this;
var foundAccessories = [];
if (this.roomid == 0) {
this.log("Fetching Domoticz lights and switches...");
var that = this;
var foundAccessories = [];
// mechanism to ensure callback is only executed once all requests complete
var asyncCalls = 0;
function callbackLater() { if (--asyncCalls == 0) callback(foundAccessories); }
if (this.roomid == 0) {
//Get Lights
asyncCalls++;
request.get({
url: this.urlForQuery("type=devices&filter=light&used=true&order=Name"),
json: true
@@ -83,14 +89,15 @@ DomoticzPlatform.prototype = {
foundAccessories.push(accessory);
})
}
callback(foundAccessories);
callbackLater();
} else {
that.log("There was a problem connecting to Domoticz. (" + err + ")");
}
});
}
else {
}
else {
//Get all devices specified in the room
asyncCalls++;
request.get({
url: this.urlForQuery("type=devices&plan=" + this.roomid),
json: true
@@ -106,30 +113,30 @@ DomoticzPlatform.prototype = {
}
})
}
callback(foundAccessories);
callbackLater();
} else {
that.log("There was a problem connecting to Domoticz.");
}
});
}
}
//Get Scenes
foundAccessories = [];
asyncCalls++;
request.get({
url: this.urlForQuery("type=scenes"),
json: true
}, function(err, response, json) {
json: true
}, function(err, response, json) {
if (!err && response.statusCode == 200) {
if (json['result'] != undefined) {
var sArray=sortByKey(json['result'],"Name");
sArray.map(function(s) {
accessory = new DomoticzAccessory(that.log, that, true, s.idx, s.Name, false, 0, false);
foundAccessories.push(accessory);
})
})
}
callback(foundAccessories);
callbackLater();
} else {
that.log("There was a problem connecting to Domoticz.");
}
}
});
}
}