Merge pull request #12 from maddox/platforms

Platforms
This commit is contained in:
Nick Farina
2015-05-19 12:20:39 -07:00
4 changed files with 105 additions and 28 deletions

View File

@@ -1,7 +1,7 @@
# HomeBridge
HomeBridge is a lightweight NodeJS server you can run on your home network that emulates the iOS HomeKit API. It includes a set of "shims" (found in the [accessories](accessories/) folder) that provide a basic bridge from HomeKit to various 3rd-party APIs provided by manufacturers of "smart home" devices.
HomeBridge is a lightweight NodeJS server you can run on your home network that emulates the iOS HomeKit API. It includes a set of "shims" (found in the [accessories](accessories/) and [platforms](platforms/) folders) that provide a basic bridge from HomeKit to various 3rd-party APIs provided by manufacturers of "smart home" devices.
Since Siri supports devices added through HomeKit, this means that with HomeBridge you can ask Siri to control devices that don't have any support for HomeKit at all. For instance, using the included shims, you can say things like:
@@ -15,6 +15,24 @@ Since Siri supports devices added through HomeKit, this means that with HomeBrid
If you would like to support any other devices, please write a shim and create a pull request and I'd be happy to add it to this official list.
# Shim types
There are 2 types of shims supported in HomeBridge.
* Accessory - Individual device
* Platform - A full bridge to another system
## Accessories
Accessories are individual devices you would like to bridge to HomeKit. You set them up by declaring them individually in your `config.json` file. Generally, you specify them by `name` or `id` and which system they use.
## Platforms
Platforms bridge entire systems to HomeKit. Platforms can be things like Wink or SmartThings or Vera. By adding a platform to your `config.json`, HomeBridge will automatically detect all of your devices for you.
Wink is currently the only supported platform at the moment.
All you have to do is add the right config options so HomeBridge can authenticate and communicate with your other system, and voila, your devices will be available to HomeKit via HomeBridge.
# Why?
Technically, the device manufacturers should be the ones implementing the HomeKit API. And I'm sure they will - eventually. When they do, these shims will be obsolete, and I hope that happens soon. In the meantime, this server is a fun way to get a taste of the future, for those who just can't bear to wait until "real" HomeKit devices are on the market.
@@ -58,15 +76,20 @@ Now you should be able to run the homebridge server:
Starting HomeBridge server...
Couldn't find a config.json file [snip]
The server won't do anything until you've created a `config.json` file containing your home devices (or _accessories_ in HomeKit parlance) you wish to make available to iOS.
The server won't do anything until you've created a `config.json` file containing your home devices (or _accessories_ in HomeKit parlance) or platforms you wish to make available to iOS.
One you've added your devices, you should be able to run the server again and see them initialize:
Once you've added your devices or platforms, you should be able to run the server again and see them initialize:
$ npm run start
Starting HomeBridge server...
Loading 6 accessories...
[Speakers] Initializing 'Sonos' accessory...
[Coffee Maker] Initializing 'WeMo' accessory...
[Speakers] Initializing 'Sonos' accessory...
[Coffee Maker] Initializing 'WeMo' accessory...
[Wink] Initializing Wink platform...
[Wink] Fetching Wink devices.
[Wink] Initializing device with name Living Room Lamp...
Your server is now ready to receive commands from iOS.

39
app.js
View File

@@ -21,11 +21,46 @@ storage.initSync();
var config = JSON.parse(fs.readFileSync(configPath));
function loadAccessories() {
console.log("Loading " + config.accessories.length + " accessories...");
var accessories = [];
console.log("Loading " + config.platforms.length + " platforms...");
for (var i=0; i<config.platforms.length; i++) {
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 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);
log("Initializing " + platformName + " platform...");
var platform = new platformConstructor(log, platformConfig);
// query for devices
platform.accessories(function(foundAccessories){
// loop through accessories adding them to the list and registering them
for (var i = 0; i < foundAccessories.length; i++) {
accessory = foundAccessories[i]
accessories.push(accessory);
log("Initializing device with name " + accessory.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 = accessory.getServices();
// Create the HAP server for this accessory
createHAPServer(accessory.name, services);
}
accessories.push.apply(accessories, foundAccessories);
})
}
// Instantiate all accessories in the config
console.log("Loading " + config.accessories.length + " accessories...");
for (var i=0; i<config.accessories.length; i++) {
var accessoryConfig = config.accessories[i];
@@ -140,4 +175,4 @@ function createUsername(str) {
hash[10] + hash[11];
}
loadAccessories();
loadAccessories();

View File

@@ -1,6 +1,17 @@
{
"description": "This is an example configuration file with all supported devices. You can use this as a template for creating your own configuration file containing devices you actually own.",
"platforms": [
{
"platform": "Wink",
"name": "Wink",
"client_id": "YOUR_WINK_API_CLIENT_ID",
"client_secret": "YOUR_WINK_API_CLIENT_SECRET",
"username": "your@email.com",
"password": "WINK_PASSWORD"
}
],
"accessories": [
{
"accessory": "WeMo",
@@ -58,15 +69,6 @@
"device_id": "E1",
"protocol": "pl",
"can_dim": true
},
{
"accessory": "Wink",
"client_id": "YOUR_WINK_API_CLIENT_ID",
"client_secret": "YOUR_WINK_API_CLIENT_SECRET",
"username": "your@email.com",
"password": "WINK_PASSWORD",
"name": "Family Room Lamp",
"description": "Lamp on the left side of the room"
}
]
}

View File

@@ -1,8 +1,12 @@
var types = require("../lib/HAP-NodeJS/accessories/types.js");
var wink = require('wink-js');
function WinkAccessory(log, config) {
this.log = log;
var model = {
light_bulbs: require('wink-js/lib/model/light')
};
function WinkPlatform(log, config){
// auth info
this.client_id = config["client_id"];
@@ -10,18 +14,15 @@ function WinkAccessory(log, config) {
this.username = config["username"];
this.password = config["password"];
// device info
this.name = config["name"];
this.device = null;
this.log("Searching for Wink device with exact name '" + this.name + "'...");
this.search();
this.log = log;
}
WinkAccessory.prototype = {
WinkPlatform.prototype = {
accessories: function(callback) {
this.log("Fetching Wink devices.");
search: function() {
var that = this;
var foundAccessories = [];
wink.init({
"client_id": this.client_id,
@@ -33,13 +34,28 @@ WinkAccessory.prototype = {
that.log("There was a problem authenticating with Wink.");
} else {
// success
wink.user().device(that.name, function(device) {
that.device = device
wink.user().devices('light_bulbs', function(devices) {
for (var i=0; i<devices.data.length; i++){
device = model.light_bulbs(devices.data[i], wink)
accessory = new WinkAccessory(that.log, device);
foundAccessories.push(accessory);
}
callback(foundAccessories);
});
}
});
},
}
}
function WinkAccessory(log, device) {
// device info
this.name = device.name;
this.device = device;
this.log = log;
}
WinkAccessory.prototype = {
setPowerState: function(powerOn) {
if (!this.device) {
@@ -79,7 +95,7 @@ WinkAccessory.prototype = {
var that = this;
this.log("Setting brightness on the '"+this.name+"' to on");
this.log("Setting brightness on the '"+this.name+"' to " + level);
this.device.brightness(level, function(response) {
if (response === undefined) {
that.log("Error setting brightness on the '"+that.name+"'")
@@ -185,3 +201,4 @@ WinkAccessory.prototype = {
};
module.exports.accessory = WinkAccessory;
module.exports.platform = WinkPlatform;