diff --git a/platforms/HomeMatic.js b/platforms/HomeMatic.js index a451451..6f3a6aa 100644 --- a/platforms/HomeMatic.js +++ b/platforms/HomeMatic.js @@ -2,9 +2,25 @@ // // Homematic Platform Shim for HomeBridge // +// to add the homematic platform add this to config.json. Example: +// "platforms": [ +// { +// "platform": "HomeMatic", +// "name": "HomeMatic", +// "filter_device":[], +// "filter_channel":["BidCos-RF.KEQXXXXXXX:4", "BidCos-RF.LEQXXXXXXX:2"], +// "outlets":[ "BidCos-RF.KEQXXXXXXX:4","BidCos-RF.IEQXXXXXXX:1"] +// +// } +// // V0.1 - 2015/10/29 // - initial version // - reintegrated Homematic Platform fork from https://github.com/thkl/homebridge/tree/xmlrpc +// 2015/10/30 thkl +// - added Rotary Sensors ; fixed thermostat + +// ], + var types = require("hap-nodejs/accessories/types.js"); @@ -292,14 +308,15 @@ HomeMaticPlatform.prototype = { // that.log('name', ch.name, ' -> address:', ch.address); if ((ch.address !== undefined) && (!isChannelFiltered)) { - if ((ch.type == "SWITCH") || (ch.type == "BLIND") || (ch.type == "SHUTTER_CONTACT") || (ch.type == "DIMMER") || (ch.type == "CLIMATECONTROL_RT_TRANSCEIVER") ||  (ch.type == "MOTION_DETECTOR") ||  (ch.type == "KEYMATIC")) { + // Switch found // Check if marked as Outlet var special = (that.outlets.indexOf(ch.address) > -1) ? "OUTLET" : undefined; var accessory = new HomeMaticGenericChannel(that.log, that, ch.id, ch.name, ch.type, ch.address, special); - that.foundAccessories.push(accessory); - } - + if (accessory.sType()!=undefined) { + // support exists for this channel + that.foundAccessories.push(accessory); + } } else { that.log(device.name + " has no address"); @@ -313,7 +330,7 @@ HomeMaticPlatform.prototype = { }); /* - accessory = new HomeMaticGenericChannel(that.log, that, "1234" , "DummyKM" , "KEYMATIC" , "1234"); + var accessory = new HomeMaticGenericChannel(that.log, that, "1234" , "DummyKM" , "SMOKE_DETECTOR" , "1234"); that.foundAccessories.push(accessory); accessory = new HomeMaticGenericChannel(that.log, that, "5678" , "DummyBLIND" , "BLIND" , "5678"); @@ -343,6 +360,12 @@ HomeMaticPlatform.prototype = { }, + setRegaValue: function(channel, datapoint, value) { + var rega = new RegaRequest(this.log, this.ccuIP); + rega.setValue(channel, datapoint, value); + return; + }, + getValue: function(channel, datapoint, callback) { if (channel.indexOf("BidCos-RF.") > -1)  { diff --git a/platforms/HomematicChannel.js b/platforms/HomematicChannel.js index 5b6cff2..f15eb58 100644 --- a/platforms/HomematicChannel.js +++ b/platforms/HomematicChannel.js @@ -1,180 +1,189 @@ -"use strict"; var types = require("hap-nodejs/accessories/types.js"); -function HomeMaticGenericChannel(log, platform, id, name, type, adress, special) { - this.name = name; - this.type = type; - this.adress = adress; - this.log = log; +function HomeMaticGenericChannel(log,platform, id ,name, type ,adress,special) { + this.name = name; + this.type = type; + this.adress = adress; + this.log = log; this.platform = platform; - this.state = []; + this.state = []; this.eventupdate = false; - this.special = special; + this.special = special; this.currentStateCharacteristic = []; - this.reverseDP = []; + this.datapointMappings = []; } + HomeMaticGenericChannel.prototype = { - // Return current States - query: function(dp, callback) { - if (this.state[dp] !== undefined) { - callback(this.state[dp]); + addValueMapping: function(dp,value,mappedvalue) { + if (this.datapointMappings[dp]==undefined) { + this.datapointMappings[dp] = []; + } + this.datapointMappings[dp][value] = mappedvalue; + } , + + // Return current States + query: function(dp,callback) { + var that = this; + + if (this.state[dp] != undefined) { + if (callback!=undefined){callback(this.state[dp]);} } else { - // that.log("No cached Value found start fetching and send temp 0 back"); +// that.log("No cached Value found start fetching and send temp 0 back"); this.remoteGetValue(dp); - callback(0); + if (callback!=undefined){callback(0);} } }, - dpvalue: function(dp, fallback) { - if (this.state[dp] !== undefined) { - return (this.state[dp]); + dpvalue:function(dp,fallback) { + if (this.state[dp] != undefined) { + return(this.state[dp]); } else { return fallback; } }, - remoteGetValue: function(dp) { - var that = this; - that.platform.getValue(that.adress, dp, function(newValue) { - that.log("Remote Value Response for " + that.adress + "." + dp + "->" + newValue); - that.eventupdate = true; - that.cache(dp, newValue); - that.eventupdate = false; - }); + remoteGetValue:function(dp) { + var that = this; + that.platform.getValue(that.adress,dp,function(newValue) { + that.log("Remote Value Response for " + that.adress + "." + dp + "->" + newValue); + that.eventupdate = true; + that.cache(dp,newValue); + that.eventupdate = false; + }); }, - - event: function(dp, newValue) { - - if (dp == "LEVEL") { - newValue = newValue * 100; + + event:function(dp,newValue) { + + if (dp=="LEVEL") { + newValue = newValue*100; } this.eventupdate = true; - this.cache(dp, newValue); + this.cache(dp,newValue); this.eventupdate = false; }, - reverse: function(value) { - if (value == "true") return "false"; - if (value == "false") return "true"; - if (value === 0) return 1; - if (value === 1) return 0; - if (value == "0") return "1"; - if (value == "1") return "0"; - return value; - }, - - cache: function(dp, value) { + cache:function(dp,value) { var that = this; - if ((that.reverseDP[dp] !== undefined) && (that.reverseDP[dp] === true)) { - value = that.reverse(value); - } - if (that.currentStateCharacteristic[dp] !== undefined) { - that.currentStateCharacteristic[dp].updateValue(value, null); + // Check custom Mapping from HM to HomeKit + var map = this.datapointMappings[dp]; + if (map != undefined) { + if (map[value]!=undefined) { + value = map[value]; + } + } + + if (that.currentStateCharacteristic[dp]!=undefined) { + that.currentStateCharacteristic[dp].updateValue(value, null); } this.state[dp] = value; }, - delayed: function(mode, dp, value, delay) { - - if (this.eventupdate === true) { - return; - } - + delayed: function(mode, dp,value,delay) { + + if (this.eventupdate==true) { + return; + } + var timer = this.delayed[delay]; - if (timer) { - clearTimeout(timer); + if( timer ) { + clearTimeout( timer ); } - this.log(this.name + " delaying command " + mode + " " + dp + " with value " + value); + this.log(this.name + " delaying command "+mode + " " + dp +" with value " + value); var that = this; - this.delayed[delay] = setTimeout(function() { - clearTimeout(that.delayed[delay]); - that.command(mode, dp, value); - }, delay ? delay : 100); + this.delayed[delay] = setTimeout( function(){clearTimeout(that.delayed[delay]);that.command(mode,dp,value)}, delay?delay:100 ); }, - command: function(mode, dp, value, callback) { + command: function(mode,dp,value,callback) { + + if (this.eventupdate==true) { + return; + } + var that = this; - if (this.eventupdate === true) { - return; - } - var that = this; + if (mode == "set") { + this.log("Send " + value + " to Datapoint " + dp + " at " + that.adress); + that.platform.setValue(that.adress,dp,value); + } + + if (mode == "setrega") { + this.log("Send " + value + " to Datapoint " + dp + " at " + that.adress); + that.platform.setRegaValue(that.adress,dp,value); + } - if (mode == "set") { - //this.log("Send " + value + " to Datapoint " + dp + " at " + that.adress); - that.platform.setValue(that.adress, dp, value); - } }, informationCharacteristics: function() { - return [{ - 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: "EQ-3", - supportEvents: false, - supportBonjour: false, - manfDescription: "Manufacturer", - designedMaxLength: 255 - }, { - cType: types.MODEL_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: this.type, - supportEvents: false, - supportBonjour: false, - manfDescription: "Model", - designedMaxLength: 255 - }, { - cType: types.SERIAL_NUMBER_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: this.adress, - 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 - }]; + return [ + { + 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: "EQ-3", + supportEvents: false, + supportBonjour: false, + manfDescription: "Manufacturer", + designedMaxLength: 255 + },{ + cType: types.MODEL_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.type, + supportEvents: false, + supportBonjour: false, + manfDescription: "Model", + designedMaxLength: 255 + },{ + cType: types.SERIAL_NUMBER_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.adress , + 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 + } + ] }, controlCharacteristics: function(that) { - - var cTypes = [{ + + cTypes = [{ cType: types.NAME_CTYPE, onUpdate: null, perms: ["pr"], @@ -184,174 +193,183 @@ HomeMaticGenericChannel.prototype = { supportBonjour: false, manfDescription: "Name of service", designedMaxLength: 255 - }]; - - - if (this.type == "SWITCH") { - cTypes.push({ + }] + + + if (this.type=="SWITCH") { + cTypes.push({ cType: types.POWER_STATE_CTYPE, onUpdate: function(value) { - that.command("set", "STATE", (value == 1) ? true : false); + that.command("set","STATE" , (value==1)?true:false) }, onRead: function(callback) { - that.query("STATE", callback); + that.query("STATE",callback); }, - - onRegister: function(characteristic) { - that.currentStateCharacteristic["STATE"] = characteristic; - characteristic.eventEnabled = true; - that.remoteGetValue("STATE"); + + onRegister: function(characteristic) { + that.currentStateCharacteristic["STATE"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("STATE"); }, - - perms: ["pw", "pr", "ev"], + + perms: ["pw","pr","ev"], format: "bool", - initialValue: that.dpvalue("STATE", 0), + initialValue: that.dpvalue("STATE",0), supportEvents: false, supportBonjour: false, manfDescription: "Change the power state", designedMaxLength: 1 }); - - if (this.special == "OUTLET") { + + if (this.special=="OUTLET") { cTypes.push({ cType: types.OUTLET_IN_USE_CTYPE, - + onRead: function(callback) { - callback(true); + callback(true); }, - perms: ["pr", "ev"], - format: "bool", - initialValue: true, - supportEvents: false, - supportBonjour: false, - manfDescription: "Is Outlet in Use", - designedMaxLength: 1 - }); - } + perms: ["pr","ev"], + format: "bool", + initialValue: true, + supportEvents: false, + supportBonjour: false, + manfDescription: "Is Outlet in Use", + designedMaxLength: 1 + }) + } } - - - if (this.type == "KEYMATIC") { - cTypes.push({ + + + if (this.type=="KEYMATIC") { + cTypes.push( + { cType: types.CURRENT_LOCK_MECHANISM_STATE_CTYPE, - + onRead: function(callback) { - that.query("STATE", callback); - }, - - onRegister: function(characteristic) { + that.query("STATE",callback); + }, + + onRegister: function(characteristic) { that.currentStateCharacteristic["STATE"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("STATE"); - }, + }, - perms: ["pr", "ev"], + perms: ["pr","ev"], format: "bool", - initialValue: that.dpvalue("STATE", 0), + initialValue: that.dpvalue("STATE",0), supportEvents: false, supportBonjour: false, manfDescription: "Current State of your Lock", - designedMaxLength: 1 - }, { - cType: types.TARGET_LOCK_MECHANISM_STATE_CTYPE, - - onUpdate: function(value) { - that.command("set", "STATE", (value == 1) ? "true" : "false"); - }, - - onRead: function(callback) { - that.query("STATE", callback); - }, - - onRegister: function(characteristic) { - that.reverseDP["STATE"] = true; + designedMaxLength: 1 + }, + { + cType: types.TARGET_LOCK_MECHANISM_STATE_CTYPE, + + onUpdate: function(value) { + that.command("set","STATE",(value==1)?"true":"false") + }, + + onRead: function(callback) { + that.query("STATE",callback); + }, + + onRegister: function(characteristic) { + that.addValueMapping("STATE","1",0); + that.addValueMapping("STATE","0",1); that.currentStateCharacteristic["STATE"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("STATE"); - }, - - - perms: ["pw", "pr", "ev"], - format: "bool", - initialValue: that.dpvalue("STATE", 0), - supportEvents: false, - supportBonjour: false, - manfDescription: "Target State of your Lock", - designedMaxLength: 1 }, - { - cType: types.TARGET_DOORSTATE_CTYPE, - - onUpdate: function(value) { - that.command("set", "OPEN", "true"); - }, - - onRead: function(callback) { - callback(1); - }, - - onRegister: function(characteristic) { - that.currentStateCharacteristic["OPEN"] = characteristic; - characteristic.eventEnabled = true; - }, - - perms: ["pw", "pr", "ev"], - format: "bool", - initialValue: 1, - supportEvents: false, - supportBonjour: false, - manfDescription: "Open the Lock", - designedMaxLength: 1 - } - ); - } - - if (this.type == "DIMMER") { - cTypes.push({ - cType: types.POWER_STATE_CTYPE, - onUpdate: function(value) { - that.command("set", "LEVEL", (value == true) ? "1" : "0"); + + perms: ["pw","pr","ev"], + format: "bool", + initialValue: that.dpvalue("STATE",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Target State of your Lock", + designedMaxLength: 1 + } + + , + { + cType: types.TARGET_DOORSTATE_CTYPE, + + onUpdate: function(value) { + that.command("set","OPEN" , "true") }, onRead: function(callback) { - that.query("LEVEL", callback); + callback(1); }, - - onRegister: function(characteristic) { - that.currentStateCharacteristic["LEVEL"] = characteristic; - characteristic.eventEnabled = true; - that.remoteGetValue("LEVEL"); + + onRegister: function(characteristic) { + that.currentStateCharacteristic["OPEN"] = characteristic; + characteristic.eventEnabled = true; }, - - perms: ["pw", "pr", "ev"], + + perms: ["pw","pr","ev"], format: "bool", - initialValue: (that.dpvalue("LEVEL") > 0, 0), + initialValue: 1, + supportEvents: false, + supportBonjour: false, + manfDescription: "Open the Lock", + designedMaxLength: 1 + } + ); + + + } + + + + if (this.type=="DIMMER") { + cTypes.push({ + cType: types.POWER_STATE_CTYPE, + onUpdate: function(value) { + that.command("set","LEVEL" , (value==true) ? "1" : "0") + }, + + onRead: function(callback) { + that.query("LEVEL",callback); + }, + + onRegister: function(characteristic) { + that.currentStateCharacteristic["LEVEL"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("LEVEL"); + }, + + perms: ["pw","pr","ev"], + format: "bool", + initialValue: (that.dpvalue("LEVEL")>0,0), supportEvents: false, supportBonjour: false, manfDescription: "Change the power state", designedMaxLength: 1 - }, { + }, + { cType: types.BRIGHTNESS_CTYPE, onUpdate: function(value) { - that.delayed("set", "LEVEL", String(value / 100), 100); + that.delayed("set","LEVEL" , String(value/100),100); }, - + onRead: function(callback) { - that.query("LEVEL", callback); + that.query("LEVEL",callback); + }, + + onRegister: function(characteristic) { + that.currentStateCharacteristic["LEVEL"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("LEVEL"); }, - onRegister: function(characteristic) { - that.currentStateCharacteristic["LEVEL"] = characteristic; - characteristic.eventEnabled = true; - that.remoteGetValue("LEVEL"); - }, - - - perms: ["pw", "pr", "ev"], + + perms: ["pw","pr","ev"], format: "int", - initialValue: that.dpvalue("LEVEL", 0), + initialValue: that.dpvalue("LEVEL",0), supportEvents: false, supportBonjour: false, manfDescription: "Adjust Brightness of Light", @@ -362,23 +380,26 @@ HomeMaticGenericChannel.prototype = { }); } - if (this.type == "BLIND") { - cTypes.push({ + + + if (this.type=="BLIND") { + cTypes.push( + { cType: types.WINDOW_COVERING_CURRENT_POSITION_CTYPE, - + onRead: function(callback) { - that.query("LEVEL", callback); - }, - - onRegister: function(characteristic) { + that.query("LEVEL",callback); + }, + + onRegister: function(characteristic) { that.currentStateCharacteristic["LEVEL"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("LEVEL"); - }, + }, - perms: ["pr", "ev"], + perms: ["pr","ev"], format: "int", - initialValue: that.dpvalue("LEVEL", 0), + initialValue: that.dpvalue("LEVEL",0), supportEvents: false, supportBonjour: false, manfDescription: "Current Blind Position", @@ -387,271 +408,303 @@ HomeMaticGenericChannel.prototype = { designedMinStep: 1, unit: "%" }, + + { + cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE, + + onUpdate: function(value) { + that.delayed("set","LEVEL" , String(value/100),100); + }, + - { - cType: types.WINDOW_COVERING_TARGET_POSITION_CTYPE, - - onUpdate: function(value) { - that.delayed("set", "LEVEL", String(value / 100), 100); - }, - - - onRead: function(callback) { - that.query("LEVEL", callback); - }, - - onRegister: function(characteristic) { + onRead: function(callback) { + that.query("LEVEL",callback); + }, + + onRegister: function(characteristic) { that.currentStateCharacteristic["LEVEL"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("LEVEL"); - }, + }, - perms: ["pw", "pr", "ev"], - format: "int", - initialValue: that.dpvalue("LEVEL", 0), - supportEvents: false, - supportBonjour: false, - manfDescription: "Target Blind Position", - designedMinValue: 0, - designedMaxValue: 100, - designedMinStep: 1, - unit: "%" - }, { - cType: types.WINDOW_COVERING_OPERATION_STATE_CTYPE, - - onRead: function(callback) { - that.query("DIRECTION", callback); - }, - - onRegister: function(characteristic) { + perms: ["pw","pr","ev"], + format: "int", + initialValue: that.dpvalue("LEVEL",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Target Blind Position", + designedMinValue: 0, + designedMaxValue: 100, + designedMinStep: 1, + unit: "%" + }, + { + cType: types.WINDOW_COVERING_OPERATION_STATE_CTYPE, + + onRead: function(callback) { + that.query("DIRECTION",callback); + }, + + onRegister: function(characteristic) { that.currentStateCharacteristic["DIRECTION"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("DIRECTION"); - }, - - perms: ["pr", "ev"], - format: "int", - initialValue: that.dpvalue("DIRECTION", 0), - supportEvents: false, - supportBonjour: false, - manfDescription: "Operating State ", - designedMinValue: 0, - designedMaxValue: 2, - designedMinStep: 1 - } + }, + perms: ["pr","ev"], + format: "int", + initialValue: that.dpvalue("DIRECTION",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Operating State ", + designedMinValue: 0, + designedMaxValue: 2, + designedMinStep: 1 + } + ); } - - if (this.type == "SHUTTER_CONTACT") { - cTypes.push({ - cType: types.CONTACT_SENSOR_STATE_CTYPE, - + + // Simple Contact (Magnet) + + if (this.type=="SHUTTER_CONTACT") { + cTypes.push( + { + cType: types.CONTACT_SENSOR_STATE_CTYPE, + onRead: function(callback) { - that.query("STATE", callback); + that.query("STATE",callback); }, - - onRegister: function(characteristic) { - that.currentStateCharacteristic["STATE"] = characteristic; - characteristic.eventEnabled = true; - that.remoteGetValue("STATE"); + + onRegister: function(characteristic) { + that.currentStateCharacteristic["STATE"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("STATE"); }, - - perms: ["pr", "ev"], - format: "bool", - initialValue: that.dpvalue("STATE", 0), - supportEvents: false, - supportBonjour: false, - manfDescription: "Current State" - }); - } - - if (this.type == "MOTION_DETECTOR") { - cTypes.push({ - cType: types.MOTION_DETECTED_CTYPE, - + + perms: ["pr","ev"], + format: "bool", + initialValue: that.dpvalue("STATE",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Current State" + }); + } + + // Rotary Handle + if (this.type=="ROTARY_HANDLE_SENSOR") { + cTypes.push( + { + cType: types.CONTACT_SENSOR_STATE_CTYPE, + onRead: function(callback) { - that.query("MOTION", callback); + that.query("STATE",callback); }, - - onRegister: function(characteristic) { - that.currentStateCharacteristic["MOTION"] = characteristic; - characteristic.eventEnabled = true; - that.remoteGetValue("MOTION"); + + onRegister: function(characteristic) { + that.addValueMapping("STATE","2",1); + that.currentStateCharacteristic["STATE"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("STATE"); }, - - perms: ["pr", "ev"], - format: "bool", - initialValue: that.dpvalue("MOTION", 0), - supportEvents: false, - supportBonjour: false, - manfDescription: "Current Motion State" - }); - } - - if (this.type == "CLIMATECONTROL_RT_TRANSCEIVER") { - - cTypes.push({ - cType: types.NAME_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: this.name, - supportEvents: true, - supportBonjour: false, - manfDescription: "Name of service", - designedMaxLength: 255 + + perms: ["pr","ev"], + format: "bool", + initialValue: that.dpvalue("STATE",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Current State" + }); + } + + + // Motion Detector + + if (this.type=="MOTION_DETECTOR") { + cTypes.push( + { + cType: types.MOTION_DETECTED_CTYPE, + + onRead: function(callback) { + that.query("MOTION",callback); + }, + + onRegister: function(characteristic) { + that.currentStateCharacteristic["MOTION"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("MOTION"); + }, + + perms: ["pr","ev"], + format: "bool", + initialValue: that.dpvalue("MOTION",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Current Motion State" + }); + } + + // Smoke Detector + if (this.type=="SMOKE_DETECTOR") { + cTypes.push( + { + cType: "00000076-0000-1000-8000-0026BB765291", + + onRead: function(callback) { + that.query("STATE",callback); + }, + + onRegister: function(characteristic) { + that.currentStateCharacteristic["STATE"] = characteristic; + characteristic.eventEnabled = true; + that.remoteGetValue("STATE"); + }, + + perms: ["pr","ev"], + format: "bool", + initialValue: that.dpvalue("STATE",0), + supportEvents: false, + supportBonjour: false, + manfDescription: "Smoke detected" + }); + } + + // Heating Device + + if ((this.type=="CLIMATECONTROL_RT_TRANSCEIVER") || (this.type=="THERMALCONTROL_TRANSMIT")) { + + cTypes.push({ + cType: types.NAME_CTYPE,onUpdate: null,perms: ["pr"],format: "string", + initialValue: this.name,supportEvents: true,supportBonjour: false,manfDescription: "Name of service",designedMaxLength: 255 + }, + + { + cType: types.CURRENTHEATINGCOOLING_CTYPE,onUpdate: null, + perms: ["pr"],format: "int",initialValue: 1,supportEvents: false, + supportBonjour: false,manfDescription: "Current Mode",designedMaxLength: 1,designedMinValue: 1,designedMaxValue: 1,designedMinStep: 1 + }, + + { + cType: types.TARGETHEATINGCOOLING_CTYPE,onUpdate: null,perms: ["pw","pr"], + format: "int",initialValue: 1,supportEvents: false,supportBonjour: false,manfDescription: "Target Mode", + designedMinValue: 1,designedMaxValue: 1,designedMinStep: 1 + }, + + { + cType: types.CURRENT_TEMPERATURE_CTYPE, + onUpdate: null, + + onRead: function(callback) { + that.query("ACTUAL_TEMPERATURE",callback); }, - - { - cType: types.CURRENTHEATINGCOOLING_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "int", - initialValue: 1, - supportEvents: false, - supportBonjour: false, - manfDescription: "Current Mode", - designedMaxLength: 1, - designedMinValue: 1, - designedMaxValue: 1, - designedMinStep: 1 - }, - - { - cType: types.TARGETHEATINGCOOLING_CTYPE, - onUpdate: null, - perms: ["pw", "pr"], - format: "int", - initialValue: 1, - supportEvents: false, - supportBonjour: false, - manfDescription: "Target Mode", - designedMinValue: 1, - designedMaxValue: 1, - designedMinStep: 1 - }, - - { - cType: types.CURRENT_TEMPERATURE_CTYPE, - onUpdate: null, - - onRead: function(callback) { - that.query("ACTUAL_TEMPERATURE", callback); - }, - - onRegister: function(characteristic) { + + onRegister: function(characteristic) { that.currentStateCharacteristic["ACTUAL_TEMPERATURE"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("ACTUAL_TEMPERATURE"); - }, - perms: ["pr", "ev"], - format: "double", - initialValue: that.dpvalue("ACTUAL_TEMPERATURE", 20), - supportEvents: false, - supportBonjour: false, - manfDescription: "Current Temperature", - unit: "celsius" - }, - - { - cType: types.TARGET_TEMPERATURE_CTYPE, - onUpdate: function(value) { - that.delayed("set", "SET_TEMPERATURE", value, 500); - }, - onRead: function(callback) { - that.query("SET_TEMPERATURE", callback); - - }, - onRegister: function(characteristic) { + }, + perms: ["pw","pr","ev"], perms: ["pr"],format: "double", + initialValue: that.dpvalue("ACTUAL_TEMPERATURE",20), + supportEvents: false,supportBonjour: false,manfDescription: "Current Temperature",unit: "celsius" + }, + + { + cType: types.TARGET_TEMPERATURE_CTYPE, + onUpdate: function(value) { + if (that.state["CONTROL_MODE"]!=1) { + that.delayed("setrega", "MANU_MODE",value,500); + that.state["CONTROL_MODE"]=1; // set to Manual Mode + } else { + that.delayed("setrega", "SET_TEMPERATURE", value,500); + } + }, + onRead: function(callback) { + that.query("SET_TEMPERATURE",callback); + that.query("CONTROL_MODE",undefined); + + }, + onRegister: function(characteristic) { that.currentStateCharacteristic["SET_TEMPERATURE"] = characteristic; characteristic.eventEnabled = true; that.remoteGetValue("SET_TEMPERATURE"); - }, - perms: ["pw", "pr", "ev"], - format: "double", - initialValue: that.dpvalue("SET_TEMPERATURE", 16), - supportEvents: false, - supportBonjour: false, - manfDescription: "Target Temperature", - designedMinValue: 16, - designedMaxValue: 38, - designedMinStep: 1, - unit: "celsius" - }, - - { - cType: types.TEMPERATURE_UNITS_CTYPE, - onRead: null, - perms: ["pr"], - format: "int", - initialValue: 0, - supportEvents: false, - supportBonjour: false, - manfDescription: "Current Temperature Unit", - unit: "celsius" - } - - ); + that.remoteGetValue("CONTROL_MODE"); + }, + perms: ["pw","pr","ev"],format: "double", + initialValue: that.dpvalue("SET_TEMPERATURE",16), + supportEvents: false,supportBonjour: false, manfDescription: "Target Temperature", + designedMinValue: 16,designedMaxValue: 38,designedMinStep: 1,unit: "celsius" + }, + + { + cType: types.TEMPERATURE_UNITS_CTYPE,onRead: null, + perms: ["pr"],format: "int",initialValue: 0,supportEvents: false, + supportBonjour: false,manfDescription: "Current Temperature Unit",unit: "celsius" } - - return cTypes; + ); + } + + + return cTypes }, sType: function() { - - if (this.type == "SWITCH") { - - if (this.special == "OUTLET") { - return types.OUTLET_STYPE; - } else { - return types.LIGHTBULB_STYPE; - } - } - - if (this.type == "DIMMER") { + + if (this.type=="SWITCH") { + + if (this.special=="OUTLET") { + return types.OUTLET_STYPE; + } else { return types.LIGHTBULB_STYPE; - } + } + } + + if (this.type=="DIMMER") { + return types.LIGHTBULB_STYPE; + } - if (this.type == "BLIND") { + if (this.type=="BLIND") { return types.WINDOW_COVERING_STYPE; - } + } - if (this.type == "CLIMATECONTROL_RT_TRANSCEIVER") { + if ((this.type=="CLIMATECONTROL_RT_TRANSCEIVER") || (this.type=="THERMALCONTROL_TRANSMIT")) { return types.THERMOSTAT_STYPE; - } - - if (this.type == "SHUTTER_CONTACT") { + } + + if ((this.type=="SHUTTER_CONTACT") || (this.type=="ROTARY_HANDLE_SENSOR")) { return types.CONTACT_SENSOR_STYPE; - } - - if (this.type == "MOTION_DETECTOR") { - return types.MOTION_SENSOR_STYPE; - } - - - if (this.type == "KEYMATIC") { - return types.LOCK_MECHANISM_STYPE; - } - + } + + if (this.type=="MOTION_DETECTOR") { + return types.MOTION_SENSOR_STYPE + } + if (this.type=="KEYMATIC") { + return types.LOCK_MECHANISM_STYPE + } + + if (this.type=="SMOKE_DETECTOR") { + return "00000087-0000-1000-8000-0026BB765291"; + } + + }, getServices: function() { var that = this; var services = [{ sType: types.ACCESSORY_INFORMATION_STYPE, - characteristics: this.informationCharacteristics() - }, { + characteristics: this.informationCharacteristics(), + }, + { sType: this.sType(), characteristics: this.controlCharacteristics(that) }]; - this.log("Loaded services for " + this.name); + this.log("Loaded services for " + this.name) return services; } }; -module.exports = HomeMaticGenericChannel; \ No newline at end of file +module.exports = HomeMaticGenericChannel;