diff --git a/platforms/FHEM.js b/platforms/FHEM.js
index a40120b..cfd1d80 100644
--- a/platforms/FHEM.js
+++ b/platforms/FHEM.js
@@ -14,8 +14,17 @@
// }
// ],
-var Service = require("HAP-NodeJS").Service;
-var Characteristic = require("HAP-NodeJS").Characteristic;
+try {
+ var Service = require("hap-nodejs").Service;
+} catch(err) {
+ Service = require("HAP-NodeJS").Service;
+}
+
+try {
+ var Characteristic = require("HAP-NodeJS").Characteristic;
+} catch(err) {
+ Characteristic = require("hap-nodejs").Characteristic;
+}
var util = require('util');
@@ -66,18 +75,21 @@ FHEM_update(inform_id, value, no_update) {
}
-var FHEM_lastEventTime;
-var FHEM_longpoll_running = false;
+var FHEM_lastEventTime = {};
+var FHEM_longpoll_running = {};
//FIXME: add filter
function FHEM_startLongpoll(connection) {
- if( FHEM_longpoll_running )
+ if( FHEM_longpoll_running[connection.base_url] )
return;
- FHEM_longpoll_running = true;
+ FHEM_longpoll_running[connection.base_url] = true;
+
+ if( connection.disconnects == undefined )
+ connection.disconnects = 0;
var filter = ".*";
var since = "null";
- if( FHEM_lastEventTime )
- since = FHEM_lastEventTime/1000;
+ if( FHEM_lastEventTime[connection.base_url] )
+ since = FHEM_lastEventTime[connection.base_url]/1000;
var query = "/fhem.pl?XHR=1"+
"&inform=type=status;filter="+filter+";since="+since+";fmt=JSON"+
"×tamp="+Date.now()
@@ -122,7 +134,7 @@ function FHEM_startLongpoll(connection) {
var subscription = FHEM_subscriptions[d[0]];
if( subscription != undefined ) {
//console.log( "Rcvd: "+(l.length>132 ? l.substring(0,132)+"...("+l.length+")":l) );
- FHEM_lastEventTime = lastEventTime;
+ FHEM_lastEventTime[connection.base_url] = lastEventTime;
var accessory = subscription.accessory;
var value = d[1];
@@ -227,17 +239,27 @@ function FHEM_startLongpoll(connection) {
input = input.substr(FHEM_longpollOffset);
FHEM_longpollOffset = 0;
- } ).on( 'end', function() {
- console.log( "longpoll ended" );
+ connection.disconnects = 0;
- FHEM_longpoll_running = false;
- setTimeout( function(){FHEM_startLongpoll(connection)}, 2000 );
+ } ).on( 'end', function() {
+ FHEM_longpoll_running[connection.base_url] = false;
+
+ connection.disconnects++;
+ var timeout = 500 * connection.disconnects - 300;
+ if( timeout > 30000 ) timeout = 30000;
+
+ console.log( "longpoll ended, reconnect in: " + timeout + "msec" );
+ setTimeout( function(){FHEM_startLongpoll(connection)}, timeout );
} ).on( 'error', function(err) {
- console.log( "longpoll error: " + err );
+ FHEM_longpoll_running[connection.base_url] = false;
- FHEM_longpoll_running = false;
- setTimeout( function(){FHEM_startLongpoll(connection)}, 5000 );
+ connection.disconnects++;
+ var timeout = 5000 * connection.disconnects;
+ if( timeout > 30000 ) timeout = 30000;
+
+ console.log( "longpoll error: " + err + ", retry in: " + timeout + "msec" );
+ setTimeout( function(){FHEM_startLongpoll(connection)}, timeout );
} );
}
@@ -740,10 +762,12 @@ FHEMAccessory(log, connection, s) {
this.mappings.window = { reading: 'level', cmd: 'level' };
else if( genericType == 'lock'
- || ( s.Attributes.model && s.Attributes.model.match(/^HM-SEC-KEY/ ) ) )
- this.mappings.lock = { reading: 'lock', cmdLock: 'lock', cmdUnlock: 'unlock' };
+ || ( s.Attributes.model && s.Attributes.model.match(/^HM-SEC-KEY/ ) ) ) {
+ this.mappings.lock = { reading: 'lock', cmdLock: 'lock', cmdUnlock: 'unlock', cmdOpen: 'open' };
+ if( s.Internals.TYPE == 'dummy' )
+ this.mappings.lock = { reading: 'lock', cmdLock: 'lock locked', cmdUnlock: 'lock unlocked', cmdOpen: 'open' };
- else if( genericType == 'thermostat'
+ } else if( genericType == 'thermostat'
|| s.Attributes.subType == 'thermostat' )
s.isThermostat = true;
@@ -1245,27 +1269,6 @@ FHEMAccessory.prototype = {
},
execute: function(cmd,callback) {FHEM_execute(this.log, this.connection, cmd, callback)},
- executexxx: function(cmd,callback) {
- var url = encodeURI( this.connection.base_url + "/fhem?cmd=" + cmd + "&XHR=1");
- this.log( ' executing: ' + url );
-
- this.connection.request
- .get( { url: url, gzip: true },
- function(err, response, result) {
- if( !err && response.statusCode == 200 ) {
- if( callback )
- callback( result );
-
- } else {
- this.log("There was a problem connecting to FHEM ("+ url +").");
- if( response )
- this.log( " " + response.statusCode + ": " + response.statusMessage );
-
- }
-
- }.bind(this) )
- .on( 'error', function(err) { this.log("There was a problem connecting to FHEM ("+ url +"):"+ err); }.bind(this) );
- },
query: function(reading, callback) {
if( reading == undefined ) {
@@ -1865,6 +1868,26 @@ FHEMAccessory.prototype = {
.on('get', function(callback) {
this.query(this.mappings.lock.reading, callback);
}.bind(this) );
+
+ if( this.mappings.lock.cmdOpen ) {
+ this.log(" target door state characteristic for " + this.name)
+
+ var characteristic = controlService.addCharacteristic(Characteristic.TargetDoorState);
+
+ characteristic.value = Characteristic.TargetDoorState.CLOSED;
+
+ characteristic
+ .on('set', function(characteristic,value, callback, context) {
+ if( context !== 'fromFHEM' ) {
+ this.command( 'set', this.mappings.lock.cmdOpen );
+ setTimeout( function(){characteristic.setValue(Characteristic.TargetDoorState.CLOSED, undefined, 'fromFHEM');}, 500 );
+ }
+ if( callback ) callback();
+ }.bind(this,characteristic) )
+ .on('get', function(callback) {
+ callback(undefined,Characteristic.TargetDoorState.CLOSED);
+ }.bind(this) );
+ }
}
if( this.mappings.garage ) {
@@ -1897,6 +1920,7 @@ FHEMAccessory.prototype = {
}.bind(this) );
+ if( 0 ) {
this.log(" obstruction detected characteristic for " + this.name)
var characteristic = controlService.getCharacteristic(Characteristic.ObstructionDetected);
@@ -1908,6 +1932,7 @@ FHEMAccessory.prototype = {
.on('get', function(callback) {
callback(undefined,1);
}.bind(this) );
+ }
}
if( this.mappings.temperature ) {
@@ -2056,6 +2081,19 @@ FHEMAccessory.prototype = {
.on('get', function(callback) {
this.query(this.mappings.contact.reading, callback);
}.bind(this) );
+
+ if( 1 ) {
+ this.log(" current door state characteristic for " + this.name)
+
+ var characteristic = controlService.addCharacteristic(Characteristic.CurrentDoorState);
+
+ characteristic.value = FHEM_cached[this.mappings.contact.informId]==Characteristic.ContactSensorState.CONTACT_DETECTED?Characteristic.CurrentDoorState.CLOSED:Characteristic.CurrentDoorState.OPEN;
+
+ characteristic
+ .on('get', function(callback) {
+ callback(undefined, FHEM_cached[this.mappings.contact.informId]==Characteristic.ContactSensorState.CONTACT_DETECTED?Characteristic.CurrentDoorState.CLOSED:Characteristic.CurrentDoorState.OPEN);
+ }.bind(this) );
+ }
}
if( this.mappings.occupancy ) {
@@ -2093,7 +2131,9 @@ function FHEMdebug_handleRequest(request, response){
if( request.url == "/cached" ) {
response.write( "home
" );
if( FHEM_lastEventTime )
- response.write( "FHEM_lastEventTime: "+ new Date(FHEM_lastEventTime) +"
" );
+ var keys = Object.keys(FHEM_lastEventTime);
+ for( var i = 0; i < keys.length; i++ )
+ response.write( "FHEM_lastEventTime " + keys[i] + ": "+ new Date(FHEM_lastEventTime[keys[i]]) +"
" );
response.end( "cached: " + util.inspect(FHEM_cached).replace(/\n/g, '
') );
} else if( request.url == "/subscriptions" ) {