From b6d763d3a3d3f38ea94d4fb258b03f2f3e99d76d Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Sun, 19 Apr 2015 22:42:04 -0400 Subject: [PATCH 1/6] Add X10 support --- accessories/X10.js | 152 +++++++++++++++++++++++++++++++++++++++++++++ config-sample.json | 8 +++ 2 files changed, 160 insertions(+) create mode 100644 accessories/X10.js diff --git a/accessories/X10.js b/accessories/X10.js new file mode 100644 index 0000000..6340b67 --- /dev/null +++ b/accessories/X10.js @@ -0,0 +1,152 @@ +var types = require("../lib/HAP-NodeJS/accessories/types.js"); +var request = require("request"); + +function X10(log, config) { + this.log = log; + this.ip_address = config["ip_address"]; + this.name = config["name"]; + this.deviceID = config["device_id"]; + this.protocol = config["protocol"]; + this.canDim = config["can_dim"]; +} + +X10.prototype = { + + setPowerState: function(powerOn) { + + var binaryState = powerOn ? "on" : "off"; + var that = this; + + this.log("Setting power state of " + this.deviceID + " to " + powerOn); + this.log("http://"+this.ip_address+"/x10/"+this.deviceID+"/power/"+binaryState+"?protocol="+this.protocol); + request.put({ + url: "http://"+this.ip_address+"/x10/"+this.deviceID+"/power/"+binaryState+"?protocol="+this.protocol, + }, function(err, response, body) { + + if (!err && response.statusCode == 200) { + that.log("State change complete."); + } + else { + that.log("Error '"+err+"' setting power state: " + body); + } + }); + }, + + setBrightnessLevel: function(value) { + + var that = this; + + this.log("Setting brightness level of " + this.deviceID + " to " + value); + request.put({ + url: "http://"+this.ip_address+"/x10/"+this.deviceID+"/brightness/?protocol="+this.protocol+"&value="+value, + }, function(err, response, body) { + + if (!err && response.statusCode == 200) { + that.log("State change complete."); + } + else { + that.log("Error '"+err+"' setting brightness level: " + body); + } + }); + }, + + getServices: function() { + var that = this; + var services = [{ + 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: "X10", + 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.SWITCH_STYPE, + characteristics: [{ + cType: types.NAME_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.name, + supportEvents: false, + 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: false, + supportEvents: false, + supportBonjour: false, + manfDescription: "Change the power state of a Variable", + designedMaxLength: 1 + }] + }]; + if (that.canDim) { + services.characteristics.push({ + cType: types.BRIGHTNESS_CTYPE, + onUpdate: function(value) { that.setBrightnessLevel(value); }, + perms: ["pw","pr","ev"], + format: "int", + initialValue: 0, + supportEvents: false, + supportBonjour: false, + manfDescription: "Adjust Brightness of Light", + designedMinValue: 0, + designedMaxValue: 100, + designedMinStep: 1, + unit: "%" + }); + } + return services; + } +}; + +module.exports.accessory = X10; diff --git a/config-sample.json b/config-sample.json index c5f4243..ef9d467 100644 --- a/config-sample.json +++ b/config-sample.json @@ -50,6 +50,14 @@ "description": "Control HomeMatic devices (The XMP-API addon for the CCU is required)", "ccu_id": "The XMP-API id of your HomeMatic device", "ccu_ip": "The IP-Adress of your HomeMatic CCU device" + }, + { + "accessory": "X10", + "name": "Lamp", + "ip_address": "localhost:3000", + "device_id": "E1", + "protocol": "pl", + "can_dim": true } ] } From b68051d3b0bbaee4d6ff9118b4fd19041f14c07d Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Mon, 20 Apr 2015 23:05:47 -0400 Subject: [PATCH 2/6] fix brightness --- accessories/X10.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessories/X10.js b/accessories/X10.js index 6340b67..6a04227 100644 --- a/accessories/X10.js +++ b/accessories/X10.js @@ -130,7 +130,7 @@ X10.prototype = { }] }]; if (that.canDim) { - services.characteristics.push({ + services[0].characteristics.push({ cType: types.BRIGHTNESS_CTYPE, onUpdate: function(value) { that.setBrightnessLevel(value); }, perms: ["pw","pr","ev"], From 410f3bb588d1ebb5a5c9d81a4cf50e38c515b132 Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Wed, 22 Apr 2015 22:28:59 -0400 Subject: [PATCH 3/6] Fix brightness --- accessories/X10.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessories/X10.js b/accessories/X10.js index 6a04227..6764fc2 100644 --- a/accessories/X10.js +++ b/accessories/X10.js @@ -130,7 +130,7 @@ X10.prototype = { }] }]; if (that.canDim) { - services[0].characteristics.push({ + services[1].characteristics.push({ cType: types.BRIGHTNESS_CTYPE, onUpdate: function(value) { that.setBrightnessLevel(value); }, perms: ["pw","pr","ev"], From 298ed58f1499a18b7693dcff3bd24a221a28828c Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Wed, 22 Apr 2015 22:30:05 -0400 Subject: [PATCH 4/6] Use lightbulb type --- accessories/X10.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessories/X10.js b/accessories/X10.js index 6764fc2..3978e59 100644 --- a/accessories/X10.js +++ b/accessories/X10.js @@ -106,7 +106,7 @@ X10.prototype = { designedMaxLength: 1 }] },{ - sType: types.SWITCH_STYPE, + sType: types.LIGHTBULB_STYPE, characteristics: [{ cType: types.NAME_CTYPE, onUpdate: null, From 7cf26e6c456f62c1c642312e0c11c9da0ea1cbd7 Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Thu, 23 Apr 2015 22:35:55 -0400 Subject: [PATCH 5/6] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e550ae7..e7de33e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Since Siri supports devices added through HomeKit, this means that with HomeBrid * _Siri, turn off the Speakers._ ([Sonos](http://www.sonos.com)) * _Siri, turn on the Dehumidifier._ ([WeMo](http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/)) * _Siri, turn on Away Mode._ ([Xfinity Home](http://www.comcast.com/home-security.html)) + * _Siri, turn on the living room lights._ ([X10 via rest-mochad](http://github.com/edc1591/rest-mochad)) 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. From cb0ac829088b9fdaddd43b5e1e65fe5ceb18c89c Mon Sep 17 00:00:00 2001 From: Evan Coleman Date: Thu, 23 Apr 2015 22:55:25 -0400 Subject: [PATCH 6/6] Remove log --- accessories/X10.js | 1 - 1 file changed, 1 deletion(-) diff --git a/accessories/X10.js b/accessories/X10.js index 3978e59..14d39df 100644 --- a/accessories/X10.js +++ b/accessories/X10.js @@ -18,7 +18,6 @@ X10.prototype = { var that = this; this.log("Setting power state of " + this.deviceID + " to " + powerOn); - this.log("http://"+this.ip_address+"/x10/"+this.deviceID+"/power/"+binaryState+"?protocol="+this.protocol); request.put({ url: "http://"+this.ip_address+"/x10/"+this.deviceID+"/power/"+binaryState+"?protocol="+this.protocol, }, function(err, response, body) {