From ecdffbef23114d62516360a61f61359edabe8bc3 Mon Sep 17 00:00:00 2001 From: Mark Van Holstyn Date: Sat, 24 Oct 2015 23:21:42 -0400 Subject: [PATCH 1/3] adding support for usernames and password in http accessories --- accessories/Http.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/accessories/Http.js b/accessories/Http.js index fb708e3..d64560f 100644 --- a/accessories/Http.js +++ b/accessories/Http.js @@ -14,14 +14,21 @@ function HttpAccessory(log, config) { this.off_url = config["off_url"]; this.brightness_url = config["brightness_url"]; this.http_method = config["http_method"]; + this.username = config["username"]; + this.password = config["password"]; } HttpAccessory.prototype = { - httpRequest: function(url, method, callback) { + httpRequest: function(url, method, username, password, callback) { request({ url: url, - method: method + method: method, + auth: { + user: username, + pass: password, + sendImmediately: false + } }, function (error, response, body) { callback(error, response, body) @@ -40,13 +47,17 @@ HttpAccessory.prototype = { this.log("Setting power state to off"); } - this.httpRequest(url, this.http_method, function(error, response, body) { + this.httpRequest(url, this.http_method, this.username, this.password, function(error, response, body) { if (error) { this.log('HTTP power function failed: %s', error.message); callback(error); } else { this.log('HTTP power function succeeded!'); + this.log(response); + this.log(body); + this.log(this.username); + this.log(this.password); callback(); } }.bind(this)); @@ -57,7 +68,7 @@ HttpAccessory.prototype = { this.log("Setting brightness to %s", level); - this.httpRequest(url, this.http_method, function(error, response, body) { + this.httpRequest(url, this.http_method, this.username, this.password, function(error, response, body) { if (error) { this.log('HTTP brightness function failed: %s', error); callback(error); @@ -68,33 +79,33 @@ HttpAccessory.prototype = { } }.bind(this)); }, - + identify: function(callback) { this.log("Identify requested!"); callback(); // success }, - + 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.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]; } }; From dc6faa97845ad7d5ba5dbf4acd2545ab3152a156 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sun, 25 Oct 2015 21:57:46 +0100 Subject: [PATCH 2/3] fixed netatmo problem with duplicate module names --- platforms/Netatmo.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/platforms/Netatmo.js b/platforms/Netatmo.js index 24fe572..3ff216a 100644 --- a/platforms/Netatmo.js +++ b/platforms/Netatmo.js @@ -49,7 +49,7 @@ function NetAtmoRepository(log, api) { NetAtmoRepository.prototype = { refresh: function(callback) { - var datasource={ + var datasource = { devices: {}, modules: {} }; @@ -69,7 +69,7 @@ NetAtmoRepository.prototype = { }, load: function(callback) { var that = this; - this.cache.get( "datasource", function( err, datasource ){ + this.cache.get( "datasource", function( err, datasource ) { if( !err ){ if ( datasource == undefined ){ that.refresh(callback); @@ -126,7 +126,14 @@ function NetatmoAccessory(log, repository, deviceId, moduleId, device) { if (moduleId) { this.serial = moduleId; } - this.name = device.module_name; + + // add station name to devices to avoid duplicate names + if (device.station_name) { + this.name = device.station_name + " " + device.module_name; + } else { + this.name = device.module_name; + } + this.model = device.type; this.serviceTypes = device.data_type; if (device.battery_vp) { @@ -161,7 +168,7 @@ NetatmoAccessory.prototype = { getAirQuality: function(callback) { this.getData(function(deviceData) { - var level = deviceData.dashboard_data.CO2; + var level = deviceData.dashboard_data.CO2; var quality = 0; if (level > 2000) quality = 5; else if (level > 1500) quality = 4; @@ -391,4 +398,4 @@ NetatmoAccessory.prototype = { }; module.exports.accessory = NetatmoAccessory; -module.exports.platform = NetatmoPlatform; \ No newline at end of file +module.exports.platform = NetatmoPlatform; From 65d732415ec72f9c66e36fbd7463773ed5992649 Mon Sep 17 00:00:00 2001 From: Tommaso Marchionni Date: Mon, 26 Oct 2015 00:32:40 +0100 Subject: [PATCH 3/3] Update Openhab.js --- platforms/Openhab.js | 780 ++++++++++++++++++++++++++++--------------- 1 file changed, 503 insertions(+), 277 deletions(-) diff --git a/platforms/Openhab.js b/platforms/Openhab.js index a148240..4c0e6bd 100644 --- a/platforms/Openhab.js +++ b/platforms/Openhab.js @@ -1,4 +1,4 @@ -// OpenHAB Platform Shim for HomeBridge +// OpenHAB 1 Platform Shim for HomeBridge // Written by Tommaso Marchionni // Based on many of the other HomeBridge platform modules // @@ -7,6 +7,9 @@ // 17 October 2015 [tommasomarchionni] // - Initial release // +// 25 October 2015 [tommasomarchionni] +// - Added WS listener and new OOP structure +// // Remember to add platform to config.json. Example: // "platforms": [ // { @@ -23,14 +26,23 @@ // Switch item=Light_1 label="Light 1" // } // +// Rollershutter is tested with this binding in OpenHAB: +// command=SWITCH_MULTILEVEL,invert_percent=true,invert_state=false" // When you attempt to add a device, it will ask for a "PIN code". // The default code for all HomeBridge accessories is 031-45-154. // -var types = require("hap-nodejs/accessories/types.js"); +//////// LIBS ///////// + +var WebSocket = require('ws'); var request = require("request"); var Service = require("hap-nodejs/lib/Service.js").Service; var Characteristic = require("hap-nodejs").Characteristic; +var currentModule = this; +var util = require('core-util-is'); +util.inherits = require('inherits'); + +//////// PLATFORM ///////// function OpenhabPlatform(log, config){ this.log = log; @@ -38,310 +50,524 @@ function OpenhabPlatform(log, config){ this.password = config["password"]; this.server = config["server"]; this.port = config["port"]; - this.protocol = "http"; - this.sitemap = "demo"; if (typeof config["sitemap"] != 'undefined') { this.sitemap = config["sitemap"]; - } - + } } OpenhabPlatform.prototype = { - - sitemapUrl: function() { - var serverString = this.server; - //TODO da verificare - if (this.user && this.password) { - serverString = this.user + ":" + this.password + "@" + serverString; - } - - return this.protocol + "://" + serverString + ":" + this.port + "/rest/sitemaps/" + this.sitemap + "?type=json"; - }, - - parseSitemap: function(sitemap) { - var widgets = [].concat(sitemap.homepage.widget); - var result = []; - for (var i = 0; i < widgets.length; i++) { - var widget = widgets[i]; - if (!widget.item) { - //TODO to handle frame - this.log("WARN: The widget '" + widget.label + "' does not reference an item."); - continue; - } - - if (widget.item.type=="SwitchItem" || widget.item.type=="DimmerItem" || widget.item.type == "RollershutterItem"){ - accessory = new OpenhabAccessory(this.log,this,widget.widgetId,widget.label,widget.item) - this.log("Accessory Found: " + widget.label); - result.push(accessory); - } - - - - } - return result; - }, - - accessories: function(callback) { - this.log("Fetching OpenHAB devices."); + accessories: function(callback) { var that = this; - - url = that.sitemapUrl(); - this.log("Connecting to " + url); + this.log("Platform - Fetching OpenHAB devices."); + var itemFactory = new ItemFactory(this); + url = itemFactory.sitemapUrl(); + this.log("Platform - Connecting to " + url); request.get({ url: url, json: true }, function(err, response, json) { if (!err && response.statusCode == 200) { - callback(that.parseSitemap(json)); - } else { - that.log("There was a problem connecting to OpenHAB."); + callback(itemFactory.parseSitemap(json)); + } else { + that.log("Platform - There was a problem connecting to OpenHAB."); } }); } }; -function OpenhabAccessory(log, platform, widgetId, label, detail) { - this.log = log; - this.platform = platform; - this.idx = widgetId; - this.name = label; - this.label = label; - this.type = detail.type; - this.deviceURL = detail.link; - this.addressStr = "n/a"; - this.state = detail.state; - - if (this.type == "DimmerItem") { - this.typeSupportsOnOff = true; - this.typeSupportsDim = true; - } - - if (this.type == "SwitchItem") { - this.typeSupportsOnOff = true; - } - - if (this.type == "RollershutterItem") { - this.typeSupportsWindowCovering = true; - } +//////// END PLATFORM ///////// + +///////// ACCESSORY ///////// + +function OpenhabAccessory(widget,platform) {} + +///////// ABSTRACT ITEM ///////// + +function AbstractItem(widget,platform){ + + AbstractItem.super_.call(this,widget,platform); + + this.widget = widget; + this.label = widget.label; + this.name = widget.item.name; + this.url = widget.item.link; + this.state = widget.item.state; + this.platform = platform; + this.log = platform.log; + this.setInitialState = false; + this.setFromOpenHAB = false; + this.informationService = undefined; + this.otherService = undefined; + this.listener = undefined; + this.ws = undefined; +}; + +util.inherits(AbstractItem, OpenhabAccessory); + +AbstractItem.prototype.getInformationServices = function() { + informationService = new Service.AccessoryInformation(); + + informationService + .setCharacteristic(Characteristic.Manufacturer, "OpenHAB") + .setCharacteristic(Characteristic.Model, this.constructor.name) + .setCharacteristic(Characteristic.SerialNumber, "N/A") + .setCharacteristic(Characteristic.Name, this.name); + return informationService; } -OpenhabAccessory.prototype = { +AbstractItem.prototype.checkListener = function() { + + if (typeof this.listener == 'undefined' || typeof this.ws == 'undefined') { + this.ws = undefined; + this.listener = new WSListener(this, this.updateCharacteristics.bind(this)); + this.listener.startListener(); + } +}; - updateStatus: function(command) { - var that = this; - - var options = { - url: this.deviceURL, - method: 'POST', - body: "" + command - }; - if (this.auth) { - options['auth'] = this.auth; - } - - that.log("eseguo post"); - - request(options, function(error, response, body) { - if (error) { - console.trace("Updating Device Status."); - that.log(error); - return error; - } - - that.log("updateStatus of " + that.name + ": " + command); - - }); - }, +///////// END ABSTRACT ITEM ///////// + +///////// SWITCH ITEM ///////// + +function SwitchItem(widget,platform){ + SwitchItem.super_.call(this, widget,platform); +}; + +util.inherits(SwitchItem, AbstractItem); + +SwitchItem.prototype.getServices = function() { + + this.checkListener(); + this.setInitialState = true; + this.informationService = this.getInformationServices(); - getServiceType: function() { - if (this.typeSupportsWindowCovering){ - return new Service.WindowCovering; - } else if (this.typeSupportsDim) { - return new Service.Lightbulb; - } else if (this.typeSupportsOnOff) { - return new Service.Switch; - } - }, + this.otherService = new Service.Lightbulb(); + this.otherService.getCharacteristic(Characteristic.On) + .on('set', this.setItem.bind(this)) + .on('get', this.getItemPowerState.bind(this)) + .setValue(this.state === 'ON'); + + return [this.informationService, this.otherService]; +}; + +SwitchItem.prototype.updateCharacteristics = function(message) { + + this.setFromOpenHAB = true; + this.otherService + .getCharacteristic(Characteristic.On) + .setValue(message === 'ON' ? true : false, + function() { + this.setFromOpenHAB = false; + }.bind(this) + ); +}; - updateStatus: function(command, callback) { - var that = this; - - var options = { - url: this.deviceURL, - method: 'POST', - body: "" + command - }; - if (this.auth) { - options['auth'] = this.auth; - } - - request(options, function(error, response, body) { - if (error) { - //console.trace("Updating Device Status."); - //that.log(error); - //return error; - callback(new Error(error)); - } else { - that.log("updateStatus of " + that.name + ": " + command); - callback(true); - } - }.bind(this)); - }, +SwitchItem.prototype.getItemPowerState = function(callback) { - setPowerState: function(powerOn, callback) { - var that = this; + var self = this; + this.checkListener(); + + this.log("iOS - request power state from " + this.name); + request(this.url + '/state?type=json', function (error, response, body) { + if (!error && response.statusCode == 200) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + callback(undefined,body == "ON" ? true : false); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + }) +}; + +SwitchItem.prototype.setItem = function(value, callback) { + + var self = this; + this.checkListener(); + + if (this.setInitialState) { + this.setInitialState = false; + callback(); + return; + } + + if (this.setFromOpenHAB) { + callback(); + return; + } + + this.log("iOS - send message to " + this.name + ": " + value); + var command = value ? 'ON' : 'OFF'; + request.post( + this.url, + { body: command }, + function (error, response, body) { + if (!error && response.statusCode == 201) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + callback(); + } + ); +}; + +///////// END SWITCH ITEM ///////// + +///////// DIMMER ITEM ///////// + +function DimmerItem(widget,platform){ + DimmerItem.super_.call(this, widget,platform); +}; + +util.inherits(DimmerItem, AbstractItem); + +DimmerItem.prototype.getServices = function() { + + this.checkListener(); + this.setInitialState = true; + + this.informationService = this.getInformationServices(); - if (this.typeSupportsOnOff) { - if (powerOn) { - var command = "ON"; - } else { - var command = "OFF"; - } - - this.log("Setting power state on the '"+this.name+"' to " + command); - this.updateStatus(command, function(noError){ - if (noError) { - that.log("Successfully set '"+that.name+"' to " + command); - callback(); - } else { - callback(new Error('Can not communicate with OpenHAB.')); - } - }.bind(this)); - - }else{ - callback(new Error(this.name + " not supports ONOFF")); - } - }, - - getStatus: function(callback){ - var that = this; - this.log("Fetching status brightness for: " + this.name); + this.otherService = new Service.Lightbulb(); + this.otherService.getCharacteristic(Characteristic.On) + .on('set', this.setItem.bind(this)) + .on('get', this.getItemPowerState.bind(this)) + .setValue(+this.state > 0); + + this.setInitialState = true; + + this.otherService.addCharacteristic(Characteristic.Brightness) + .on('set', this.setItem.bind(this)) + .on('get', this.getItemBrightnessState.bind(this)) + .setValue(+this.state); + + return [this.informationService, this.otherService]; +}; - var options = { - url: this.deviceURL + '/state?type=json', - method: 'GET' - }; - - if (this.auth) { - options['auth'] = this.auth; - } - - request(options, function(error, response, body) { - if (error) { - //console.trace("Requesting Device Status."); - //that.log(error); - //return error; - callback(new Error('Can not communicate with Home Assistant.')); - } else { - that.log("getStatus of " + that.name + ": " + body); - callback(null,body); - } - - - +DimmerItem.prototype.updateCharacteristics = function(message) { + + this.setFromOpenHAB = true; + var brightness = +message; + var steps = 2; + if (brightness >= 0) { + this.otherService.getCharacteristic(Characteristic.Brightness) + .setValue(brightness, + function() { + steps--; + if (!steps) { + this.setFromOpenHAB = false; + } + }.bind(this)); + this.otherService.getCharacteristic(Characteristic.On) + .setValue(brightness > 0 ? true : false, + function() { + steps--; + if (!steps) { + this.setFromOpenHAB = false; + } }.bind(this)); - - }, - - getCurrentPosition: function(callback){ - callback(100); - }, - - getPositionState: function(callback){ - this.log("Fetching position state for: " + this.name); - callback(Characteristic.PositionState.STOPPED); - }, - - setTargetPosition: function(level, callback) { - var that = this; - - this.log("Setting target position on the '"+this.name+"' to " + level); - - this.updateStatus(level, function(noError){ - if (noError) { - that.log("Successfully set position on the '"+that.name+"' to " + level); - callback(); - } else { - callback(new Error('Can not communicate with OpenHAB.')); - } - }.bind(this)); - - }, - - setBrightness: function(level, callback) { - var that = this; - - if (this.typeSupportsDim && level >= 0 && level <= 100) { - - this.log("Setting brightness on the '"+this.name+"' to " + level); - - this.updateStatus(level, function(noError){ - if (noError) { - that.log("Successfully set brightness on the '"+that.name+"' to " + level); - callback(); - } else { - callback(new Error('Can not communicate with OpenHAB.')); - } - }.bind(this)); - } - }, - - getServices: function() { - - var informationService = new Service.AccessoryInformation(); - - informationService - .setCharacteristic(Characteristic.Manufacturer, "OpenHAB") - .setCharacteristic(Characteristic.Model, this.type) - .setCharacteristic(Characteristic.SerialNumber, "1234567890") - .setCharacteristic(Characteristic.Name, this.label); - - var otherService = this.getServiceType(); - - if (this.typeSupportsOnOff) { - otherService - .getCharacteristic(Characteristic.On) - .on('get', this.getStatus.bind(this)) - .on('set', this.setPowerState.bind(this)); - - } - - if (this.typeSupportsDim) { - otherService - .addCharacteristic(Characteristic.Brightness) - .on('get', this.getStatus.bind(this)) - .on('set', this.setBrightness.bind(this)); - } - - if (this.typeSupportsWindowCovering) { - var currentPosition = 100; - - otherService - .getCharacteristic(Characteristic.CurrentPosition) - .on('get', this.getCurrentPosition.bind(this)) - .setValue(currentPosition); - - otherService - .getCharacteristic(Characteristic.PositionState) - .on('get', this.getPositionState.bind(this)) - .setValue(Characteristic.PositionState.STOPPED); - - otherService - .getCharacteristic(Characteristic.TargetPosition) - .on('get', this.getCurrentPosition.bind(this)) - .on('set', this.setTargetPosition.bind(this)); - - } - - console.log(informationService); - - return [informationService, otherService]; - } - + } } + +DimmerItem.prototype.getItemPowerState = function(callback) { + + var self = this; + this.checkListener(); + + this.log("iOS - request power state from " + this.name); + request(this.url + '/state?type=json', function (error, response, body) { + if (!error && response.statusCode == 200) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + callback(undefined,+body > 0 ? true : false); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + }) +}; + +DimmerItem.prototype.setItem = function(value, callback) { + + var self = this; + this.checkListener(); + + if (this.setInitialState) { + this.setInitialState = false; + callback(); + return; + } + + if (this.setFromOpenHAB) { + callback(); + return; + } + + this.log("iOS - send message to " + this.name + ": " + value); + var command = 0; + if (typeof value === 'boolean') { + command = value ? '100' : '0'; + } else { + command = "" + value; + } + request.post( + this.url, + { + body: command, + headers: {'Content-Type': 'text/plain'} + }, + function (error, response, body) { + if (!error && response.statusCode == 201) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + callback(); + } + ); +}; + +DimmerItem.prototype.getItemBrightnessState = function(callback) { + + var self = this; + + this.log("iOS - request brightness state from " + this.name); + request(this.url + '/state?type=json', function (error, response, body) { + if (!error && response.statusCode == 200) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + callback(undefined,+body); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + }) +}; + +///////// END DIMMER ITEM ///////// + +///////// ROLLERSHUTTER ITEM ///////// + +function RollershutterItem(widget,platform){ + RollershutterItem.super_.call(this, widget,platform); + this.positionState = Characteristic.PositionState.STOPPED; + this.currentPosition = 100; + this.targetPosition = 100; + this.startedPosition = 100; +}; + +util.inherits(RollershutterItem, AbstractItem); + +RollershutterItem.prototype.getServices = function() { + + this.checkListener(); + + this.informationService = this.getInformationServices(); + + this.otherService = new Service.WindowCovering(); + + this.otherService.getCharacteristic(Characteristic.CurrentPosition) + .on('get', this.getItemCurrentPosition.bind(this)) + .setValue(this.currentPosition); + + this.setInitialState = true; + + this.otherService.getCharacteristic(Characteristic.TargetPosition) + .on('set', this.setItem.bind(this)) + .on('get', this.getItemTargetPosition.bind(this)) + .setValue(this.currentPosition); + + this.otherService.getCharacteristic(Characteristic.PositionState) + .on('get', this.getItemPositionState.bind(this)) + .setValue(this.positionState); + + return [this.informationService, this.otherService]; +}; + + + +RollershutterItem.prototype.updateCharacteristics = function(message) { + + console.log(message); + console.log(this.targetPosition); + + + + if (parseInt(message) == this.targetPosition) { + var ps = Characteristic.PositionState.STOPPED; + var cs = parseInt(message); + } else if (parseInt(message) > this.targetPosition){ + var ps = Characteristic.PositionState.INCREASING; + var cs = this.startedPosition; + } else { + var ps = Characteristic.PositionState.DECREASING; + var cs = this.startedPosition; + } + + this.otherService + .getCharacteristic(Characteristic.PositionState) + .setValue(ps); + + this.otherService + .getCharacteristic(Characteristic.CurrentPosition) + .setValue(parseInt(cs)); + this.currentPosition = parseInt(cs); +}; + +RollershutterItem.prototype.setItem = function(value, callback) { + + var self = this; + this.checkListener(); + + if (this.setInitialState) { + this.setInitialState = false; + callback(); + return; + } + + this.startedPosition = this.currentPosition; + + this.log("iOS - send message to " + this.name + ": " + value); + + var command = 0; + if (typeof value === 'boolean') { + command = value ? '100' : '0'; + } else { + command = "" + value; + } + request.post( + this.url, + { + body: command, + headers: {'Content-Type': 'text/plain'} + }, + function (error, response, body) { + if (!error && response.statusCode == 201) { + self.log("OpenHAB HTTP - response from " + self.name + ": " + body); + self.targetPosition = parseInt(value); + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + callback(); + } + ); +}; + +RollershutterItem.prototype.getItemPositionState = function(callback) { + this.log("iOS - request position state from " + this.name); + this.log("Platform - response from " + this.name + ": " + this.positionState); + callback(undefined,this.positionState); +}; + +RollershutterItem.prototype.getItemTargetPosition = function(callback) { + this.log("iOS - get target position state from " + this.name); + this.log("Platform - response from " + this.name + ": " + this.targetPosition); + callback(undefined,this.targetPosition); +} + +RollershutterItem.prototype.getItemCurrentPosition = function(callback) { + var self = this; + this.log("iOS - request current position state from " + this.name); + + request(this.url + '/state?type=json', function (error, response, body) { + if (!error && response.statusCode == 200) { + + self.log("OpenHAB HTTP - response from " + self.name + ": " +body); + self.currentPosition = parseInt(body); + callback(undefined,parseInt(body)); + + } else { + self.log("OpenHAB HTTP - error from " + self.name + ": " + error); + } + }) +}; + +///////// END ROLLERSHUTTER ITEM ///////// + +///////// ITEM UTILITY ///////// + +function ItemFactory(openhabPlatform){ + this.platform = openhabPlatform; + this.log = this.platform.log; +} + +ItemFactory.prototype = { + sitemapUrl: function() { + var serverString = this.platform.server; + //TODO da verificare + if (this.platform.user && this.platform.password) { + serverString = this.platform.user + ":" + this.platform.password + "@" + serverString; + } + + return this.platform.protocol + "://" + serverString + ":" + this.platform.port + "/rest/sitemaps/" + this.platform.sitemap + "?type=json"; + }, + + parseSitemap: function(jsonSitemap) { + var widgets = [].concat(jsonSitemap.homepage.widget); + + var result = []; + for (var i = 0; i < widgets.length; i++) { + var widget = widgets[i]; + if (!widget.item) { + //TODO to handle frame + this.log("Platform - The widget '" + widget.label + "' is not an item."); + continue; + } + + if (currentModule[widget.item.type] != undefined) { + var accessory = new currentModule[widget.item.type](widget,this.platform); + } else { + this.log("Platform - The widget '" + widget.label + "' of type "+widget.item.type+" is an item not handled."); + continue; + } + + this.log("Platform - Accessory Found: " + widget.label); + result.push(accessory); + } + return result; + } + +}; + +///////// END ITEM UTILITY ///////// + +///////// WS LISTENER ///////// + +function WSListener(item, callback){ + this.item = item; + this.callback = callback; +} + +WSListener.prototype = { + startListener: function() { + var self = this; + + if (typeof this.item.ws == 'undefined') { + this.item.ws = new WebSocket(this.item.url.replace('http:', 'ws:') + '/state?type=json'); + } + + this.item.ws.on('open', function() { + self.item.log("OpenHAB WS - new connection for "+self.item.name); + }); + + this.item.ws.on('message', function(message) { + self.item.log("OpenHAB WS - message from " +self.item.name+": "+ message); + self.callback(message); + }); + + this.item.ws.on('close', function close() { + self.item.log("OpenHAB WS - closed connection for "+self.item.name); + self.item.listener = undefined; + self.item.ws = undefined; + }); + } + +}; + +///////// END WS LISTENER ///////// + +///////// SUPPORTED ITEMS ///////// +module.exports.SwitchItem = SwitchItem; +module.exports.DimmerItem = DimmerItem; +module.exports.RollershutterItem = RollershutterItem; +///////// END SUPPORTED ITEMS ///////// module.exports.accessory = OpenhabAccessory; module.exports.platform = OpenhabPlatform;