more cleanups

handle sonos volume caching
added garage door opener
started with homematic keymatic (HM-SEC-KEY)
even more cleanups :)
rgb hue/sat/bri fix
added identify for lightbulbs
This commit is contained in:
Andre Schröter
2015-08-06 10:02:09 +02:00
parent 86322c30c8
commit 7cb835e4ea

View File

@@ -20,17 +20,16 @@ var types = require('HAP-NodeJS/accessories/types.js');
var util = require('util'); var util = require('util');
// cached readings from longpoll & query
var FHEM_cached = {};
// subscriptions to fhem longpoll evens // subscriptions to fhem longpoll evens
var FHEM_subscriptions = {}; var FHEM_subscriptions = {};
function function
FHEM_subscribe(characteristic, inform_id, accessory) { FHEM_subscribe(characteristic, inform_id, accessory) {
FHEM_subscriptions[inform_id] = { 'characteristic': characteristic, 'accessory': accessory }; FHEM_subscriptions[inform_id] = { 'characteristic': characteristic, 'accessory': accessory };
//FHEM_subscriptions[inform_id] = characteristic;
} }
// cached readings from longpoll & query
var FHEM_cached = {};
//var FHEM_internal = {};
function function
FHEM_update(inform_id, value, no_update) { FHEM_update(inform_id, value, no_update) {
var subscription = FHEM_subscriptions[inform_id]; var subscription = FHEM_subscriptions[inform_id];
@@ -39,6 +38,18 @@ FHEM_update(inform_id, value, no_update) {
|| FHEM_cached[inform_id] === value ) || FHEM_cached[inform_id] === value )
return; return;
//if( FHEM_internal['.'+subscription.accessory.device+'-homekitID'] == undefined ) {
// var info = subscription.characteristic.accessoryController.tcpServer.accessoryInfo;
// if( info.username ) {
// var accessory = subscription.accessory;
// var cmd = '{$defs{'+ accessory.device +'}->{homekitID} = "'+info.username+'" if(defined($defs{'+ accessory.device +'}));;}';
// //accessory.execute( cmd );
// FHEM_internal['.'+accessory.device+'-homekitID'] = info.username;
// }
//}
FHEM_cached[inform_id] = value; FHEM_cached[inform_id] = value;
//FHEM_cached[inform_id] = { 'value': value, 'timestamp': Date.now() }; //FHEM_cached[inform_id] = { 'value': value, 'timestamp': Date.now() };
console.log(" caching: " + inform_id + ": " + value + " as " + typeof(value) ); console.log(" caching: " + inform_id + ": " + value + " as " + typeof(value) );
@@ -118,14 +129,25 @@ function FHEM_startLongpoll(connection) {
continue; continue;
if( reading == 'state') { if( reading == 'state') {
if( accessory.isWindow ) { if( accessory.mappings.window ) {
var level = 50; var level = 50;
if( match = value.match(/^(\d+)/ ) ) if( match = value.match(/^(\d+)/ ) )
level = parseInt( match[1] ); level = parseInt( match[1] );
else if( value == 'locked' ) else if( value == 'locked' )
level = 0; level = 0;
FHEM_update( device+'-level', level ); FHEM_update( accessory.mappings.window.informId, level );
continue;
} else if( accessory.mappings.lock ) {
var lock = 0;
if( value.match( /^locked/ ) )
lock = 1;
if( value.match( /uncertain/ ) )
level = 4;
FHEM_update( accessory.mappings.lock.informId, lock );
continue; continue;
} else if( match = value.match(/dim(\d+)%/ ) ) { } else if( match = value.match(/dim(\d+)%/ ) ) {
@@ -134,7 +156,7 @@ function FHEM_startLongpoll(connection) {
FHEM_update( device+'-pct', pct ); FHEM_update( device+'-pct', pct );
} }
} else if(reading == accessory.hasRGB) { } else if(accessory.mappings.rgb && reading == accessory.mappings.rgb.reading) {
var hsv = FHEM_rgb2hsv(value); var hsv = FHEM_rgb2hsv(value);
var hue = parseInt( hsv[0] * 360 ); var hue = parseInt( hsv[0] * 360 );
var sat = parseInt( hsv[1] * 100 ); var sat = parseInt( hsv[1] * 100 );
@@ -354,6 +376,9 @@ FHEMPlatform.prototype = {
} else if( s.Attributes.model == 'HM-SEC-WIN' ) { } else if( s.Attributes.model == 'HM-SEC-WIN' ) {
accessory = new FHEMAccessory(that.log, that.connection, s); accessory = new FHEMAccessory(that.log, that.connection, s);
} else if( s.Attributes.model == 'HM-SEC-KEY' ) {
accessory = new FHEMAccessory(that.log, that.connection, s);
} else if( s.Internals.TYPE == 'PRESENCE' ) { } else if( s.Internals.TYPE == 'PRESENCE' ) {
accessory = new FHEMAccessory(that.log, that.connection, s); accessory = new FHEMAccessory(that.log, that.connection, s);
@@ -396,7 +421,7 @@ FHEMAccessory(log, connection, s) {
var match; var match;
if( match = s.PossibleSets.match(/[\^ ]pct\b/) ) { if( match = s.PossibleSets.match(/[\^ ]pct\b/) ) {
this.mappings.pct = { reading: 'pct', cmd: 'pct', min: 0, max: 100 }; this.mappings.pct = { reading: 'pct', cmd: 'pct' };
} else if( match = s.PossibleSets.match(/[\^ ]dim\d+%/) ) { } else if( match = s.PossibleSets.match(/[\^ ]dim\d+%/) ) {
s.hasDim = true; s.hasDim = true;
s.pctMax = 100; s.pctMax = 100;
@@ -418,12 +443,12 @@ FHEMAccessory(log, connection, s) {
if( s.PossibleSets.match(/[\^ ]rgb\b/) ) { if( s.PossibleSets.match(/[\^ ]rgb\b/) ) {
s.isLight = true; s.isLight = true;
s.hasRGB = 'rgb'; this.mappings.rgb = { reading: 'rgb', cmd: 'rgb' };
if( s.Internals.TYPE == 'SWAP_0000002200000003' ) if( s.Internals.TYPE == 'SWAP_0000002200000003' )
s.hasRGB = '0B-RGBlevel'; this.mappings.rgb = { reading: '0B-RGBlevel', cmd: 'rgb' };
} else if( s.PossibleSets.match(/[\^ ]RGB\b/) ) { } else if( s.PossibleSets.match(/[\^ ]RGB\b/) ) {
s.isLight = true; s.isLight = true;
s.hasRGB = 'RGB'; this.mappings.rgb = { reading: 'RGB', cmd: 'RGB' };
} }
if( s.Readings['measured-temp'] ) if( s.Readings['measured-temp'] )
@@ -433,8 +458,11 @@ FHEMAccessory(log, connection, s) {
if( s.Readings.volume ) if( s.Readings.volume )
this.mappings.volume = { reading: 'volume', cmd: 'volume' }; this.mappings.volume = { reading: 'volume', cmd: 'volume' };
else if( s.Readings.Volume ) else if( s.Readings.Volume ) {
this.mappings.volume = { reading: 'Volume', cmd: 'Volume' }; this.mappings.volume = { reading: 'Volume', cmd: 'Volume', nocache: true };
if( s.Attributes.generateVolumeEvent == 1 )
delete this.mappings.volume.nocache;
}
if( s.Readings.humidity ) if( s.Readings.humidity )
this.mappings.humidity = { reading: 'humidity' }; this.mappings.humidity = { reading: 'humidity' };
@@ -453,39 +481,48 @@ FHEMAccessory(log, connection, s) {
if( genericType == 'switch' ) if( genericType == 'switch' )
s.isSwitch = true; s.isSwitch = true;
else if( genericType == 'garage' )
this.mappings.garage = { cmdOpen: 'on', cmdClose: 'off' };
else if( genericType == 'light' ) else if( genericType == 'light' )
s.isLight = true; s.isLight = true;
else if( genericType == 'blind' else if( genericType == 'blind'
|| s.Attributes.subType == 'blindActuator' ) { || s.Attributes.subType == 'blindActuator' ) {
s.isBlind = 'pct'; delete this.mappings.pct;
this.mappings.blind = { reading: 'pct', cmd: 'pct' };
} else if( genericType == 'window' } else if( genericType == 'window'
|| s.Attributes.model == 'HM-SEC-WIN' ) { || s.Attributes.model == 'HM-SEC-WIN' ) {
s.isWindow = 'level'; this.mappings.window = { reading: 'level', cmd: 'level' };
} else if( genericType == 'lock'
|| s.Attributes.model == 'HM-SEC-KEY' ) {
this.mappings.lock = { reading: 'lock' };
} else if( genericType == 'thermostat' } else if( genericType == 'thermostat'
|| s.Attributes.subType == 'thermostat' ) { || s.Attributes.subType == 'thermostat' ) {
s.isThermostat = true; s.isThermostat = true;
} else if( s.Internals.TYPE == 'CUL_FHTTK' ) { } else if( s.Internals.TYPE == 'CUL_FHTTK' ) {
s.isContactSensor = 'Window'; this.mappings.contact = { reading: 'Window' };
} else if( s.Attributes.subType == 'threeStateSensor' ) { } else if( s.Attributes.subType == 'threeStateSensor' ) {
s.isContactSensor = 'contact'; this.mappings.contact = { reading: 'contact' };
} else if( s.Internals.TYPE == 'PRESENCE' ) } else if( s.Internals.TYPE == 'PRESENCE' )
s.isOccupancySensor = true; this.mappings.occupancy = { reading: 'state' };
else if( s.Attributes.model == 'fs20di' ) else if( s.Attributes.model == 'fs20di' )
s.isLight = true; s.isLight = true;
if( s.PossibleSets.match(/[\^ ]desired-temp\b/) ) if( s.PossibleSets.match(/[\^ ]desired-temp\b/) )
s.isThermostat = 'desired-temp'; this.mappings.thermostat = { reading: 'desired-temp', cmd: 'desired-temp' };
else if( s.PossibleSets.match(/[\^ ]desiredTemperature\b/) ) else if( s.PossibleSets.match(/[\^ ]desiredTemperature\b/) )
s.isThermostat = 'desiredTemperature'; this.mappings.thermostat = { reading: 'desiredTemperature', cmd: 'desiredTemperature' };
else if( s.isThermostat ) { else if( s.isThermostat ) {
s.isThermostat = false; s.isThermostat = false;
delete this.mappings.thermostat;
log( s.Internals.NAME + ' is NOT a thermostat. set for target temperature missing' ); log( s.Internals.NAME + ' is NOT a thermostat. set for target temperature missing' );
} }
@@ -509,20 +546,26 @@ FHEMAccessory(log, connection, s) {
} }
} }
if( s.isBlind ) if( this.mappings.door )
log( s.Internals.NAME + ' is blind ['+ s.isBlind +']' ); log( s.Internals.NAME + ' is door' );
else if( s.isWindow ) else if( this.mappings.garage )
log( s.Internals.NAME + ' is garage' );
else if( this.mappings.lock )
log( s.Internals.NAME + ' is lock ['+ this.mappings.lock.reading +']' );
else if( this.mappings.window )
log( s.Internals.NAME + ' is window' ); log( s.Internals.NAME + ' is window' );
else if( s.isThermostat ) else if( this.mappings.blind )
log( s.Internals.NAME + ' is thermostat ['+ s.isThermostat +']' ); log( s.Internals.NAME + ' is blind ['+ this.mappings.blind.reading +']' );
else if( s.isContactSensor ) else if( this.mappings.thermostat )
log( s.Internals.NAME + ' is contactsensor [' + s.isContactSensor +']' ); log( s.Internals.NAME + ' is thermostat ['+ this.mappings.thermostat.reading +']' );
else if( s.isOccupancySensor ) else if( this.mappings.contact )
log( s.Internals.NAME + ' is contactsensor [' + this.mappings.contact.reading +']' );
else if( this.mappings.occupancy )
log( s.Internals.NAME + ' is occupancysensor' ); log( s.Internals.NAME + ' is occupancysensor' );
else if( s.hasRGB ) else if( this.mappings.rgb )
log( s.Internals.NAME + ' has RGB [0-' + s.hasRGB +']'); log( s.Internals.NAME + ' has RGB [0-' + this.mappings.rgb.reading +']');
else if( this.mappings.pct ) else if( this.mappings.pct )
log( s.Internals.NAME + ' is dimable [0-'+ this.mappings.pct.max +']' ); log( s.Internals.NAME + ' is dimable ['+ this.mappings.pct.reading +']' );
else if( s.hasDim ) else if( s.hasDim )
log( s.Internals.NAME + ' is dimable [0-'+ s.pctMax +']' ); log( s.Internals.NAME + ' is dimable [0-'+ s.pctMax +']' );
else if( s.isLight ) else if( s.isLight )
@@ -530,7 +573,7 @@ FHEMAccessory(log, connection, s) {
else else
log( s.Internals.NAME + ' is switchable' ); log( s.Internals.NAME + ' is switchable' );
if( this.hasOnOff ) if( this.hasOnOff )
log( s.Internals.NAME + ' has OnOff [' + this.hasOnOff + ']' ); log( s.Internals.NAME + ' has OnOff [' + this.hasOnOff + ']' );
if( this.mappings.hue ) if( this.mappings.hue )
@@ -573,19 +616,13 @@ FHEMAccessory(log, connection, s) {
this.hasDim = s.hasDim; this.hasDim = s.hasDim;
this.pctMax = s.pctMax; this.pctMax = s.pctMax;
this.hasRGB = s.hasRGB;
this.isLight = s.isLight; this.isLight = s.isLight;
this.isBlind = s.isBlind; this.isSwitch = s.isSwitch;
this.isWindow = s.isWindow;
this.isThermostat = s.isThermostat;
this.isContactSensor = s.isContactSensor;
this.isOccupancySensor = s.isOccupancySensor;
this.isWindow = s.isWindow;
//log( util.inspect(s.Readings) ); //log( util.inspect(s.Readings) );
if( this.isBlind || this.isDoor || this.isWindow || this.isThermostat ) if( this.mappings.blind || this.mappings.door || this.mappings.garage || this.mappings.window || this.mappings.thermostat )
delete this.mappings.onOff; delete this.mappings.onOff;
var that = this; var that = this;
@@ -598,7 +635,8 @@ FHEMAccessory(log, connection, s) {
if( value != undefined ) { if( value != undefined ) {
var inform_id = that.device +'-'+ reading; var inform_id = that.device +'-'+ reading;
that.mappings[key].informId = inform_id; that.mappings[key].informId = inform_id;
FHEM_cached[inform_id] = value; if( !that.mappings[key].nocache )
FHEM_cached[inform_id] = value;
} }
} }
} ); } );
@@ -612,10 +650,10 @@ FHEM_dim_values = [ 'dim06%', 'dim12%', 'dim18%', 'dim25%', 'dim31%', 'dim37%',
FHEMAccessory.prototype = { FHEMAccessory.prototype = {
reading2homekit: function(reading,value) { reading2homekit: function(reading,value) {
if( reading == 'hue' ) { if( reading == 'hue' ) {
value = Math.round(value * 360 / this.mappings.hue.max); value = Math.round(value * 360 / this.mappings.hue ? this.mappings.hue.max : 360);
} else if( reading == 'sat' ) { } else if( reading == 'sat' ) {
value = Math.round(value * 100 / this.mappings.sat.max); value = Math.round(value * 100 / this.mappings.sat ? this.mappings.sat.max : 100);
} else if( reading == 'pct' ) { } else if( reading == 'pct' ) {
value = parseInt( value ); value = parseInt( value );
@@ -628,8 +666,6 @@ FHEMAccessory.prototype = {
else else
value = 2; value = 2;
value = parseInt(value);
} else if(reading == 'motor') { } else if(reading == 'motor') {
if( value.match(/^opening/)) if( value.match(/^opening/))
value = 1; value = 1;
@@ -638,16 +674,12 @@ FHEMAccessory.prototype = {
else else
value = 2; value = 2;
value = parseInt(value);
} else if( reading == 'transportState' ) { } else if( reading == 'transportState' ) {
if( value == 'PLAYING' ) if( value == 'PLAYING' )
value = 1; value = 1;
else else
value = 0; value = 0;
value = parseInt(value);
} else if( reading == 'volume' } else if( reading == 'volume'
|| reading == 'Volume' ) { || reading == 'Volume' ) {
value = parseInt( value ); value = parseInt( value );
@@ -658,15 +690,20 @@ FHEMAccessory.prototype = {
else else
value = 0; value = 0;
value = parseInt(value);
} else if( reading == 'Window' ) { } else if( reading == 'Window' ) {
if( value.match( /^Closed/ ) ) if( value.match( /^Closed/ ) )
value = 1; value = 1;
else else
value = 0; value = 0;
value = parseInt(value); } else if( reading == 'lock' ) {
if( value.match( /^locked/ ) )
value = 1;
else
value = 0;
if( value.match( /uncertain/ ) )
value = 4;
} else if( reading == 'temperature' } else if( reading == 'temperature'
|| reading == 'measured-temp' || reading == 'measured-temp'
@@ -695,13 +732,11 @@ FHEMAccessory.prototype = {
value = 0; value = 0;
else if( value == '000000' ) else if( value == '000000' )
value = 0; value = 0;
else if( value.match( /^[A-D]0$/ ) ) else if( value.match( /^[A-D]0$/ ) ) // FIXME: should be handled by event_map now
value = 0; value = 0;
else else
value = 1; value = 1;
value = parseInt( value );
} }
return(value); return(value);
@@ -721,21 +756,14 @@ FHEMAccessory.prototype = {
command: function(c,value) { command: function(c,value) {
this.log(this.name + " sending command " + c + " with value " + value); this.log(this.name + " sending command " + c + " with value " + value);
if( c == 'on' ) { if( c == 'identify' ) {
if( this.PossibleSets.match(/[\^ ]play\b/i) ) if( this.type == 'HUEDevice' )
cmd = "set " + this.device + " play"; cmd = "set " + this.device + "alert select";
else if( this.PossibleSets.match(/[\^ ]on\b/) )
cmd = "set " + this.device + " on";
else else
this.log(this.name + " Unhandled command! cmd=" + c + ", value=" + value); cmd = "set " + this.device + " toggle;; sleep 1;; set "+ this.device + " toggle";
} else if( c == 'off' ) { } else if( c == 'set' ) {
if( this.PossibleSets.match(/[\^ ]pause\b/i) ) cmd = "set " + this.device + " " + value;
cmd = "set " + this.device + " pause";
else if( this.PossibleSets.match(/[\^ ]off\b/) )
cmd = "set " + this.device + " off";
else
this.log(this.device + " Unhandled command! cmd=" + c + ", value=" + value);
} else if( c == 'volume' ) { } else if( c == 'volume' ) {
cmd = "set " + this.device + " volume " + value; cmd = "set " + this.device + " volume " + value;
@@ -776,10 +804,7 @@ FHEMAccessory.prototype = {
value = FHEM_hsv2rgb( h, s, v ); value = FHEM_hsv2rgb( h, s, v );
//this.log( this.name + ' rgb : [' + value + ']' ); //this.log( this.name + ' rgb : [' + value + ']' );
if( this.PossibleSets.match(/[\^ ]RGB\b/) ) cmd = "set " + this.device + " " + this.mappings.rgb.cmd + " " + value;
cmd = "set " + this.device + " RGB " + value;
else
cmd = "set " + this.device + " rgb " + value;
} else if( c == 'hue' ) { } else if( c == 'hue' ) {
value = Math.round(value * this.mappings.hue.max / 360); value = Math.round(value * this.mappings.hue.max / 360);
@@ -790,17 +815,17 @@ FHEMAccessory.prototype = {
cmd = "set " + this.device + " sat " + value; cmd = "set " + this.device + " sat " + value;
} else if( c == 'targetTemperature' ) { } else if( c == 'targetTemperature' ) {
cmd = "set " + this.device + " " + this.isThermostat + " " + value; cmd = "set " + this.device + " " + this.mappings.thermostat.cmd + " " + value;
} else if( c == 'targetPosition' ) { } else if( c == 'targetPosition' ) {
if( this.isWindow ) { if( this.mappings.window ) {
if( value == 0 ) if( value == 0 )
value = 'lock'; value = 'lock';
cmd = "set " + this.device + " level " + value; cmd = "set " + this.device + " " + this.mappings.window.cmd + " " + value;
} else if( this.isBlind ) } else if( this.mappings.blind )
cmd = "set " + this.device + " " + this.isBlind + " " + value; cmd = "set " + this.device + " " + this.mappings.blind.cmd + " " + value;
else else
this.log(this.name + " Unhandled command! cmd=" + c + ", value=" + value); this.log(this.name + " Unhandled command! cmd=" + c + ", value=" + value);
@@ -851,19 +876,22 @@ FHEMAccessory.prototype = {
this.log(" not cached" ); this.log(" not cached" );
var query_reading = reading; var query_reading = reading;
if( reading == 'hue' && !this.mappings.hue && this.hasRGB ) { if( reading == 'hue' && !this.mappings.hue && this.mappings.rgb ) {
query_reading = this.hasRGB; query_reading = this.mappings.rgb.reading;
} else if( reading == 'sat' && !this.mappings.sat && this.hasRGB ) { } else if( reading == 'sat' && !this.mappings.sat && this.mappings.rgb ) {
query_reading = this.hasRGB; query_reading = this.mappings.rgb.reading;
} else if( reading == 'bri' && !this.mappings.pct && this.hasRGB ) { } else if( reading == 'bri' && !this.mappings.pct && this.mappings.rgb ) {
query_reading = this.hasRGB; query_reading = this.mappings.rgb.reading;
} else if( reading == 'pct' && !this.mappings.pct && this.hasDim ) { } else if( reading == 'pct' && !this.mappings.pct && this.hasDim ) {
query_reading = 'state'; query_reading = 'state';
} else if( reading == 'level' && this.isWindow ) { } else if( reading == 'level' && this.mappings.window ) {
query_reading = 'state';
} else if( reading == 'lock' && this.mappings.lock ) {
query_reading = 'state'; query_reading = 'state';
} }
@@ -900,17 +928,28 @@ FHEMAccessory.prototype = {
else else
value = 50; value = 50;
} else if(reading == 'hue' && query_reading == that.hasRGB) { } else if( reading == 'lock'
&& query_reading == 'state') {
if( value.match( /^locked/ ) )
value = 1;
else
value = 0;
if( value.match( /uncertain/ ) )
value = 4;
} else if(reading == 'hue' && query_reading == that.mappings.rgb) {
//FHEM_update( that.device+'-'+query_reading, value ); //FHEM_update( that.device+'-'+query_reading, value );
value = parseInt( FHEM_rgb2hsv(value)[0] * 360 ); value = parseInt( FHEM_rgb2hsv(value)[0] * 360 );
} else if(reading == 'sat' && query_reading == that.hasRGB) { } else if(reading == 'sat' && query_reading == that.mappings.rgb) {
//FHEM_update( that.device+'-'+query_reading, value ); //FHEM_update( that.device+'-'+query_reading, value );
value = parseInt( FHEM_rgb2hsv(value)[1] * 100 ); value = parseInt( FHEM_rgb2hsv(value)[1] * 100 );
} else if(reading == 'bri' && query_reading == that.hasRGB) { } else if(reading == 'bri' && query_reading == that.mappings.rgb) {
//FHEM_update( that.device+'-'+query_reading, value ); //FHEM_update( that.device+'-'+query_reading, value );
value = parseInt( FHEM_rgb2hsv(value)[2] * 100 ); value = parseInt( FHEM_rgb2hsv(value)[2] * 100 );
@@ -969,14 +1008,17 @@ FHEMAccessory.prototype = {
onUpdate: null, onUpdate: null,
perms: ["pr"], perms: ["pr"],
format: "string", format: "string",
initialValue: this.serial ? this.serial : "A1S2NASF88EW", initialValue: this.serial ? this.serial : "<unknown>",
supportEvents: false, supportEvents: false,
supportBonjour: false, supportBonjour: false,
manfDescription: "SN", manfDescription: "SN",
designedMaxLength: 255 designedMaxLength: 255
},{ },{
cType: types.IDENTIFY_CTYPE, cType: types.IDENTIFY_CTYPE,
onUpdate: null, onUpdate: function(value) {
if( this.mappings.onOff )
that.command( 'identify' );
},
perms: ["pw"], perms: ["pw"],
format: "bool", format: "bool",
initialValue: false, initialValue: false,
@@ -984,8 +1026,7 @@ FHEMAccessory.prototype = {
supportBonjour: false, supportBonjour: false,
manfDescription: "Identify Accessory", manfDescription: "Identify Accessory",
designedMaxLength: 1 designedMaxLength: 1
} }];
]
}, },
controlCharacteristics: function(that) { controlCharacteristics: function(that) {
@@ -1009,7 +1050,7 @@ FHEMAccessory.prototype = {
FHEM_subscribe(characteristic, that.mappings.onOff.informId, that); FHEM_subscribe(characteristic, that.mappings.onOff.informId, that);
}, },
onUpdate: function(value) { onUpdate: function(value) {
that.command( value == 0 ? 'off' : 'on' ); that.command( 'set', value == 0 ? that.mappings.onOff.cmdOff : that.mappings.onOff.cmdOn );
}, },
onRead: function(callback) { onRead: function(callback) {
that.query( that.mappings.onOff.reading, function(state){ callback(state) } ); that.query( that.mappings.onOff.reading, function(state){ callback(state) } );
@@ -1024,7 +1065,7 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.mappings.pct && !this.isBlind ) { if( this.mappings.pct ) {
cTypes.push({ cTypes.push({
cType: types.BRIGHTNESS_CTYPE, cType: types.BRIGHTNESS_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
@@ -1053,6 +1094,7 @@ FHEMAccessory.prototype = {
cType: types.BRIGHTNESS_CTYPE, cType: types.BRIGHTNESS_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
// state is alreadi subscribed from POWER_STATE_CTYPE
FHEM_subscribe(characteristic, that.name+'-pct', that); FHEM_subscribe(characteristic, that.name+'-pct', that);
}, },
onUpdate: function(value) { that.delayed('dim', value); }, onUpdate: function(value) { that.delayed('dim', value); },
@@ -1099,13 +1141,13 @@ FHEMAccessory.prototype = {
designedMinStep: 1, designedMinStep: 1,
unit: "arcdegrees" unit: "arcdegrees"
}); });
} else if( this.hasRGB ) { } else if( this.mappings.rgb ) {
cTypes.push({ cTypes.push({
cType: types.HUE_CTYPE, cType: types.HUE_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-hue', that); FHEM_subscribe(characteristic, that.name+'-hue', that);
FHEM_subscribe(characteristic, that.name+'-'+that.hasRGB, that); FHEM_subscribe(characteristic, that.mappings.rgb.informId, that);
}, },
onUpdate: function(value) { that.command('H-rgb', value); }, onUpdate: function(value) { that.command('H-rgb', value); },
onRead: function(callback) { onRead: function(callback) {
@@ -1208,8 +1250,10 @@ FHEMAccessory.prototype = {
cType: types.OUTPUTVOLUME_CTYPE, cType: types.OUTPUTVOLUME_CTYPE,
onUpdate: function(value) { that.delayed('volume', value); }, onUpdate: function(value) { that.delayed('volume', value); },
onRegister: function(characteristic) { onRegister: function(characteristic) {
//characteristic.eventEnabled = true; if( !that.mappings.volume.nocache ) {
//FHEM_subscribe(characteristic, that.mappings.volume.informId, that); characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.mappings.volume.informId, that);
}
}, },
onRead: function(callback) { onRead: function(callback) {
that.query(that.mappings.volume.reading, function(volume){ that.query(that.mappings.volume.reading, function(volume){
@@ -1230,23 +1274,22 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.isBlind ) { if( this.mappings.blind ) {
cTypes.push({ cTypes.push({
cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE, cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE,
onUpdate: function(value) { that.delayed('targetPosition', value, 1500); }, onUpdate: function(value) { that.delayed('targetPosition', value, 1500); },
//onRegister: function(characteristic) { //onRegister: function(characteristic) {
// characteristic.eventEnabled = true; // characteristic.eventEnabled = true;
// FHEM_subscribe(characteristic, that.name+'-'+that.isBlind, that); // FHEM_subscribe(characteristic, that.mappings.blind.informId, that);
//}, //},
onRead: function(callback) { onRead: function(callback) {
that.query(that.isBlind, function(pct){ that.query(that.mappings.blind.reading, function(pct){
callback(pct); callback(pct);
}); });
}, },
perms: ["pw","pr","ev"], perms: ["pw","pr","ev"],
format: "int", format: "int",
//initialValue: 100, initialValue: FHEM_cached[that.mappings.blind.informId],
initialValue: FHEM_cached[that.device +'-'+ that.isBlind],
supportEvents: false, supportEvents: false,
supportBonjour: false, supportBonjour: false,
manfDescription: "Target Blind Position", manfDescription: "Target Blind Position",
@@ -1259,16 +1302,16 @@ FHEMAccessory.prototype = {
cType: types.WINDOW_COVERING_CURRENT_POSITION_CTYPE, cType: types.WINDOW_COVERING_CURRENT_POSITION_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-'+that.isBlind, that); FHEM_subscribe(characteristic, that.mappings.blind.informId, that);
}, },
onRead: function(callback) { onRead: function(callback) {
that.query(that.isBlind, function(pos){ that.query(that.mappings.blind.reading, function(pos){
callback(pos); callback(pos);
}); });
}, },
perms: ["pr","ev"], perms: ["pr","ev"],
format: "int", format: "int",
initialValue: FHEM_cached[that.name+'-'+that.isBlind], initialValue: FHEM_cached[that.mappings.blind.informId],
supportEvents: true, supportEvents: true,
supportBonjour: false, supportBonjour: false,
manfDescription: "Current Blind Position", manfDescription: "Current Blind Position",
@@ -1304,16 +1347,12 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.isWindow ) { if( this.mappings.window ) {
cTypes.push({ cTypes.push({
cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE, cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE,
onUpdate: function(value) { that.delayed('targetPosition', value, 1500); }, onUpdate: function(value) { that.delayed('targetPosition', value, 1500); },
//onRegister: function(characteristic) {
// characteristic.eventEnabled = true;
// FHEM_subscribe(characteristic, that.name+'-'+that.isBlind, that);
//},
onRead: function(callback) { onRead: function(callback) {
that.query(that.isWindow, function(level){ that.query(that.mappings.window.reading, function(level){
callback(level); callback(level);
}); });
}, },
@@ -1333,17 +1372,16 @@ FHEMAccessory.prototype = {
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-state', that); FHEM_subscribe(characteristic, that.name+'-state', that);
FHEM_subscribe(characteristic, that.name+'-'+that.isWindow, that); FHEM_subscribe(characteristic, that.mappings.window.informId, that);
}, },
onRead: function(callback) { onRead: function(callback) {
that.query(that.isWindow, function(pos){ that.query(that.mappings.window.reading, function(pos){
callback(pos); callback(pos);
}); });
}, },
perms: ["pr","ev"], perms: ["pr","ev"],
format: "int", format: "int",
initialValue: 50, initialValue: FHEM_cached[that.mappings.window.informId],
//initialValue: FHEM_cached[that.name+'-'+that.isWindow],
supportEvents: true, supportEvents: true,
supportBonjour: false, supportBonjour: false,
manfDescription: "Current Window Position", manfDescription: "Current Window Position",
@@ -1379,23 +1417,75 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.mappings.garage ) {
cTypes.push({
onUpdate: function(value) {
that.command( 'set', value == 0 ? that.mappings.garage.cmdOpen : that.mappings.garage.cmdClose );
},
cType: types.TARGET_DOORSTATE_CTYPE,
onRead: function(callback) {
callback(1);
},
perms: ["pw","pr","ev"],
format: "int",
initialValue: 1,
supportEvents: false,
supportBonjour: false,
manfDescription: "Target GarageDoor Position",
designedMinValue: 0,
designedMaxValue: 1,
designedMinStep: 1,
designedMaxLength: 1
});
cTypes.push({
cType: types.CURRENT_DOOR_STATE_CTYPE,
onRead: function(callback) {
callback(4);
},
perms: ["pr","ev"],
format: "int",
initialValue: 4,
supportEvents: true,
supportBonjour: false,
manfDescription: "Current GarageDoor State",
designedMinValue: 0,
designedMaxValue: 4,
designedMinStep: 1,
designedMaxLength: 1
});
cTypes.push({
cType: types.OBSTRUCTION_DETECTED_CTYPE,
onRead: function(callback) {
callback(false);
},
perms: ["pr","ev"],
format: "bool",
initialValue: 0,
supportEvents: false,
supportBonjour: false,
manfDescription: "Obstruction Detected",
designedMaxLength: 1
});
}
//FIXME: parse range and set designedMinValue & designedMaxValue & designedMinStep //FIXME: parse range and set designedMinValue & designedMaxValue & designedMinStep
if( this.isThermostat ) { if( this.mappings.thermostat ) {
cTypes.push({ cTypes.push({
cType: types.TARGET_TEMPERATURE_CTYPE, cType: types.TARGET_TEMPERATURE_CTYPE,
onUpdate: function(value) { that.delayed('targetTemperature', value, 1500); }, onUpdate: function(value) { that.delayed('targetTemperature', value, 1500); },
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-'+that.isThermostat, that); FHEM_subscribe(characteristic, that.mappings.thermostat.informId, that);
}, },
onRead: function(callback) { onRead: function(callback) {
that.query(that.isThermostat, function(temperature){ that.query(that.mappings.thermostat.reading, function(temperature){
callback(temperature); callback(temperature);
}); });
}, },
perms: ["pw","pr","ev"], perms: ["pw","pr","ev"],
format: "float", format: "float",
initialValue: 20, initialValue: FHEM_cached[that.mappings.thermostat.informId],
supportEvents: false, supportEvents: false,
supportBonjour: false, supportBonjour: false,
manfDescription: "Target Temperature", manfDescription: "Target Temperature",
@@ -1442,21 +1532,21 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.isContactSensor ) { if( this.mappings.contact ) {
cTypes.push({ cTypes.push({
cType: types.CONTACT_SENSOR_STATE_CTYPE, cType: types.CONTACT_SENSOR_STATE_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-'+that.isContactSensor, that); FHEM_subscribe(characteristic, that.mappings.contact.informId, that);
}, },
onRead: function(callback) { onRead: function(callback) {
that.query(that.isContactSensor, function(state){ that.query(that.mappings.contact.reading, function(state){
callback(state); callback(state);
}); });
}, },
perms: ["pr","ev"], perms: ["pr","ev"],
format: "bool", format: "bool",
initialValue: 0, initialValue: FHEM_cached[that.mappings.contact.informId],
supportEvents: false, supportEvents: false,
supportBonjour: false, supportBonjour: false,
manfDescription: "Contact State", manfDescription: "Contact State",
@@ -1464,21 +1554,21 @@ FHEMAccessory.prototype = {
}); });
} }
if( this.isOccupancySensor ) { if( this.mappings.occupancy ) {
cTypes.push({ cTypes.push({
cType: types.OCCUPANCY_DETECTED_CTYPE, cType: types.OCCUPANCY_DETECTED_CTYPE,
onRegister: function(characteristic) { onRegister: function(characteristic) {
characteristic.eventEnabled = true; characteristic.eventEnabled = true;
FHEM_subscribe(characteristic, that.name+'-state', that); FHEM_subscribe(characteristic, that.mappings.occupancy.informId, that);
}, },
onRead: function(callback) { onRead: function(callback) {
that.query('state', function(state){ that.query(that.mappings.occupancy.reading, function(state){
callback(state); callback(state);
}); });
}, },
perms: ["pr","ev"], perms: ["pr","ev"],
format: "bool", format: "bool",
initialValue: 0, initialValue: FHEM_cached[that.mappings.occupancy.informId],
supportEvents: false, supportEvents: false,
supportBonjour: false, supportBonjour: false,
manfDescription: "Occupancy State", manfDescription: "Occupancy State",
@@ -1541,17 +1631,19 @@ FHEMAccessory.prototype = {
return types.SPEAKER_STYPE; return types.SPEAKER_STYPE;
} else if( this.isSwitch ) { } else if( this.isSwitch ) {
return types.SWITCH_STYPE; return types.SWITCH_STYPE;
} else if( this.isBlind ) { } else if( this.mappings.garage ) {
return types.WINDOW_COVERING_STYPE; return types.GARAGE_DOOR_OPENER_STYPE;
} else if( this.isThermostat ) { } else if( this.mappings.window ) {
return types.THERMOSTAT_STYPE;
} else if( this.isWindow ) {
return types.WINDOW_STYPE; return types.WINDOW_STYPE;
} else if( this.isContactSensor ) { } else if( this.mappings.blind ) {
return types.WINDOW_COVERING_STYPE;
} else if( this.mappings.thermostat ) {
return types.THERMOSTAT_STYPE;
} else if( this.mappings.contact ) {
return types.CONTACT_SENSOR_STYPE; return types.CONTACT_SENSOR_STYPE;
} else if( this.isOccupancySensor ) { } else if( this.mappings.occupancy ) {
return types.OCCUPANCY_SENSOR_STYPE; return types.OCCUPANCY_SENSOR_STYPE;
} else if( this.isLight || this.mappings.pct || this.mappings.hue || this.hasRGB ) { } else if( this.isLight || this.mappings.pct || this.mappings.hue || this.mappings.rgb ) {
return types.LIGHTBULB_STYPE; return types.LIGHTBULB_STYPE;
} else if( this.mappings.temperature ) { } else if( this.mappings.temperature ) {
return types.TEMPERATURE_SENSOR_STYPE; return types.TEMPERATURE_SENSOR_STYPE;
@@ -1591,17 +1683,17 @@ function FHEMdebug_handleRequest(request, response){
//console.log( request ); //console.log( request );
if( request.url == "/cached" ) { if( request.url == "/cached" ) {
response.write( "<a href='/'>home</a><br>" ); response.write( "<a href='/'>home</a><br><br>" );
if( FHEM_lastEventTimestamp ) if( FHEM_lastEventTimestamp )
response.write( "FHEM_lastEventTime: "+ new Date(FHEM_lastEventTimestamp) +"<br>" ); response.write( "FHEM_lastEventTime: "+ new Date(FHEM_lastEventTimestamp) +"<br><br>" );
response.end( "cached: " + util.inspect(FHEM_cached).replace(/\n/g, '<br>') ); response.end( "cached: " + util.inspect(FHEM_cached).replace(/\n/g, '<br>') );
} else if( request.url == "/subscriptions" ) { } else if( request.url == "/subscriptions" ) {
response.write( "<a href='/'>home</a><br>" ); response.write( "<a href='/'>home</a><br><br>" );
response.end( "subscriptions: " + util.inspect(FHEM_subscriptions, {depth: 4}).replace(/\n/g, '<br>') ); response.end( "subscriptions: " + util.inspect(FHEM_subscriptions, {depth: 4}).replace(/\n/g, '<br>') );
} else if( request.url == "/persist" ) { } else if( request.url == "/persist" ) {
response.write( "<a href='/'>home</a><br>" ); response.write( "<a href='/'>home</a><br><br>" );
var unique = {}; var unique = {};
Object.keys(FHEM_subscriptions).forEach(function(key) { Object.keys(FHEM_subscriptions).forEach(function(key) {
var characteristic = FHEM_subscriptions[key].characteristic; var characteristic = FHEM_subscriptions[key].characteristic;