Merge branch 'master' into osx-launchd

This commit is contained in:
Jon Maddox
2015-09-16 10:49:13 -04:00
5 changed files with 787 additions and 801 deletions

76
accessories/FileSensor.js Normal file
View File

@@ -0,0 +1,76 @@
var Service = require("HAP-NodeJS").Service;
var Characteristic = require("HAP-NodeJS").Characteristic;
var chokidar = require("chokidar");
var debug = require("debug")("FileSensorAccessory");
var crypto = require("crypto");
module.exports = {
accessory: FileSensorAccessory
}
function FileSensorAccessory(log, config) {
this.log = log;
// url info
this.name = config["name"];
this.path = config["path"];
this.window_seconds = config["window_seconds"] || 5;
this.sensor_type = config["sensor_type"] || "m";
this.inverse = config["inverse"] || false;
if(config["sn"]){
this.sn = config["sn"];
} else {
var shasum = crypto.createHash('sha1');
shasum.update(this.path);
this.sn = shasum.digest('base64');
debug('Computed SN ' + this.sn);
}
}
FileSensorAccessory.prototype = {
getServices: function() {
// 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.Name, this.name)
.setCharacteristic(Characteristic.Manufacturer, "Homebridge")
.setCharacteristic(Characteristic.Model, "File Sensor")
.setCharacteristic(Characteristic.SerialNumber, this.sn);
var service, changeAction;
if(this.sensor_type === "c"){
service = new Service.ContactSensor();
changeAction = function(newState){
service.getCharacteristic(Characteristic.ContactSensorState)
.setValue(newState ? Characteristic.ContactSensorState.CONTACT_DETECTED : Characteristic.ContactSensorState.CONTACT_NOT_DETECTED);
};
} else {
service = new Service.MotionSensor();
changeAction = function(newState){
service.getCharacteristic(Characteristic.MotionDetected)
.setValue(newState);
};
}
var changeHandler = function(path, stats){
var d = new Date();
if(d.getTime() - stats.mtime.getTime() <= (this.window_seconds * 1000)){
var newState = this.inverse ? false : true;
changeAction(newState);
if(this.timer !== undefined) clearTimeout(this.timer);
this.timer = setTimeout(function(){changeAction(!newState);}, this.window_seconds * 1000);
}
}.bind(this);
var watcher = chokidar.watch(this.path, {alwaysStat: true});
watcher.on('add', changeHandler);
watcher.on('change', changeHandler);
return [informationService, service];
}
};

View File

@@ -94,7 +94,8 @@
"platform": "HomeAssistant",
"name": "HomeAssistant",
"host": "http://192.168.1.10:8123",
"password": "XXXXX"
"password": "XXXXX",
"supported_types": ["light", "switch", "media_player", "scene"]
}
],
@@ -196,6 +197,15 @@
"host" : "localhost",
"port" : 6600,
"description": "Allows some control of an MPD server"
},
{
"accessory": "FileSensor",
"name": "File Time Motion Sensor",
"path": "/tmp/CameraDump/",
"window_seconds": 5,
"sensor_type": "m",
"inverse": false
}
]
}

View File

@@ -13,10 +13,11 @@
"dependencies": {
"ad2usb": "git+https://github.com/alistairg/node-ad2usb.git#local",
"carwingsjs": "0.0.x",
"chokidar": "^1.0.5",
"color": "0.10.x",
"eibd": "^0.3.1",
"elkington": "kevinohara80/elkington",
"hap-nodejs": "git+https://github.com/KhaosT/HAP-NodeJS#6bf0f9eaaa2d87db8d1768114c61f4acbb095c41",
"hap-nodejs": "git+https://github.com/KhaosT/HAP-NodeJS#0030b35856e04ee2b42f0d05839feaa5c44cbd1f",
"harmonyhubjs-client": "^1.1.4",
"harmonyhubjs-discover": "git+https://github.com/swissmanu/harmonyhubjs-discover.git",
"lifx-api": "^1.0.1",

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,27 @@
// URL: http://home-assistant.io
// GitHub: https://github.com/balloob/home-assistant
//
// HA accessories supported: Lights, Switches, Media Players.
// HA accessories supported: Lights, Switches, Media Players, Scenes.
//
// Optional Devices - Edit the supported_types key in the config to pick which
// of the 4 types you would like to expose to HomeKit from
// Home Assistant. light, switch, media_player, scene.
//
//
// Scene Support
//
// You can optionally import your Home Assistant scenes. These will appear to
// HomeKit as switches. You can simply say "turn on party time". In some cases
// scenes names are already rerved in HomeKit...like "Good Morning" and
// "Good Night". You will be able to just say "Good Morning" or "Good Night" to
// have these triggered.
//
// You might want to play with the wording to figure out what ends up working well
// for your scene names. It's also important to not populate any actual HomeKit
// scenes with the same names, as Siri will pick these instead of your Home
// Assistant scenes.
//
//
//
// Media Player Support
//
@@ -25,6 +45,8 @@
// will need to use the same language you use to set the brighness of a light.
// You can play around with language to see what fits best.
//
//
//
// Examples
//
// Dim the Kitchen Speaker to 40% - sets volume to 40%
@@ -37,7 +59,8 @@
// "platform": "HomeAssistant",
// "name": "HomeAssistant",
// "host": "http://192.168.1.50:8123",
// "password": "xxx"
// "password": "xxx",
// "supported_types": ["light", "switch", "media_player", "scene"]
// }
// ]
//
@@ -56,6 +79,7 @@ function HomeAssistantPlatform(log, config){
// auth info
this.host = config["host"];
this.password = config["password"];
this.supportedTypes = config["supported_types"];
this.log = log;
}
@@ -121,22 +145,26 @@ HomeAssistantPlatform.prototype = {
var that = this;
var foundAccessories = [];
var lightsRE = /^light\./i
var switchRE = /^switch\./i
var mediaPlayerRE = /^media_player\./i
this._request('GET', '/states', {}, function(error, response, data){
for (var i = 0; i < data.length; i++) {
entity = data[i]
entity_type = entity.entity_id.split('.')[0]
if (that.supportedTypes.indexOf(entity_type) == -1) {
continue;
}
var accessory = null
if (entity.entity_id.match(lightsRE)) {
if (entity_type == 'light') {
accessory = new HomeAssistantLight(that.log, entity, that)
}else if (entity.entity_id.match(switchRE)){
}else if (entity_type == 'switch'){
accessory = new HomeAssistantSwitch(that.log, entity, that)
}else if (entity.entity_id.match(mediaPlayerRE) && entity.attributes && entity.attributes.supported_media_commands){
}else if (entity_type == 'scene'){
accessory = new HomeAssistantSwitch(that.log, entity, that, 'scene')
}else if (entity_type == 'media_player' && entity.attributes && entity.attributes.supported_media_commands){
accessory = new HomeAssistantMediaPlayer(that.log, entity, that)
}
@@ -240,6 +268,12 @@ HomeAssistantLight.prototype = {
},
getServices: function() {
var lightbulbService = new Service.Lightbulb();
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Manufacturer, "Home Assistant")
.setCharacteristic(Characteristic.Model, "Light")
.setCharacteristic(Characteristic.SerialNumber, "xxx");
lightbulbService
.getCharacteristic(Characteristic.On)
@@ -251,7 +285,7 @@ HomeAssistantLight.prototype = {
.on('get', this.getBrightness.bind(this))
.on('set', this.setBrightness.bind(this));
return [lightbulbService];
return [informationService, lightbulbService];
}
}
@@ -375,6 +409,12 @@ HomeAssistantMediaPlayer.prototype = {
},
getServices: function() {
var lightbulbService = new Service.Lightbulb();
var informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Manufacturer, "Home Assistant")
.setCharacteristic(Characteristic.Model, "Media Player")
.setCharacteristic(Characteristic.SerialNumber, "xxx");
lightbulbService
.getCharacteristic(Characteristic.On)
@@ -389,15 +429,15 @@ HomeAssistantMediaPlayer.prototype = {
.on('set', this.setVolume.bind(this));
}
return [lightbulbService];
return [informationService, lightbulbService];
}
}
function HomeAssistantSwitch(log, data, client) {
function HomeAssistantSwitch(log, data, client, type) {
// device info
this.domain = "switch"
this.domain = type || "switch"
this.data = data
this.entity_id = data.entity_id
if (data.attributes && data.attributes.friendly_name) {
@@ -454,13 +494,35 @@ HomeAssistantSwitch.prototype = {
},
getServices: function() {
var switchService = new Service.Switch();
var informationService = new Service.AccessoryInformation();
var model;
switchService
.getCharacteristic(Characteristic.On)
.on('get', this.getPowerState.bind(this))
.on('set', this.setPowerState.bind(this));
switch (this.domain) {
case "scene":
model = "Scene"
break;
default:
model = "Switch"
}
return [switchService];
informationService
.setCharacteristic(Characteristic.Manufacturer, "Home Assistant")
.setCharacteristic(Characteristic.Model, model)
.setCharacteristic(Characteristic.SerialNumber, "xxx");
if (this.domain == 'switch') {
switchService
.getCharacteristic(Characteristic.On)
.on('get', this.getPowerState.bind(this))
.on('set', this.setPowerState.bind(this));
}else{
switchService
.getCharacteristic(Characteristic.On)
.on('set', this.setPowerState.bind(this));
}
return [informationService, switchService];
}
}