├── .gitignore ├── .npmignore ├── README.md ├── admin ├── homekit.png └── index.html ├── img └── admin_settings.png ├── io-package.json ├── lib └── utils.js ├── main.js ├── package.json └── postinstall.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | config 3 | www/_socket 4 | .idea 5 | npm-debug.log 6 | persist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .gitignore 4 | npm-debug.log 5 | persist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](admin/homekit.png) 2 | ioBroker HomeKit Adapter 3 | =============================== 4 | [![NPM version](http://img.shields.io/npm/v/iobroker.homekit2.svg)](https://www.npmjs.com/package/iobroker.homekit2) 5 | [![Downloads](https://img.shields.io/npm/dm/iobroker.homekit2.svg)](https://www.npmjs.com/package/iobroker.homekit2) 6 | 7 | [![NPM](https://nodei.co/npm/iobroker.homekit2.png?downloads=true)](https://nodei.co/npm/iobroker.homekit2/) 8 | 9 | HomeKit Adapter for ioBroker 10 | 11 | With this Adapter it is possible to use your iOS Device native for ioBroker Home Automation. 12 | 13 | Within Admin Settings you can set following Attributes 14 | - username 15 | - port 16 | - pincode 17 | - bridge name 18 | 19 | ![admin-settings](img/admin_settings.png) 20 | 21 | ## Installation 22 | - Enums are no longer needed, Objects were included cause of ioBroker roles. 23 | 24 | Note: on some systems additional package is required ```sudo apt-get install libavahi-compat-libdnssd-dev``` 25 | 26 | (For Usage you must define a enum named enum.homekit. 27 | There you must include all needed Objects. 28 | Set a common Name for all Objects e.g. hm-rpc.0.JEQ0225305.1.TEMPERATURE = Kinderzimmer) 29 | 30 | You can use every Homekit App on iOS. These Version is tested with Elgato Eve cause it's free. 31 | 32 | Currently implemented are: 33 | - Homematic Thermostat 34 | - Homematic Switch 35 | - zWave Temperature 36 | - zWave Switch 37 | 38 | Supported Roles from ioBroker: 39 | - value.temperature 40 | - indicator.battery (Not tested) 41 | - value.battery (Not tested) 42 | - alarm 43 | - level.temperature 44 | - switch 45 | - value.humidity 46 | - level.dimmer 47 | 48 | If iobroker.weatherground is used, forecast Objects are explicit removed from homekit. 49 | 50 | Within Homekit you can see the actual temperature and humidity from the Thermostat. 51 | The Switch can be used within Homekit. 52 | 53 | ## Changelog 54 | ### 0.1.6 (2016-10-29) 55 | - (PArns) Fix compatibility issues 56 | 57 | ### 0.1.4 (2016-03-05) 58 | - (husky-koglhof) 59 | Fixed Exception (error: TypeError: Cannot read property 'val' of null) 60 | 61 | ### 0.1.3 (2016-03-05) 62 | - (husky-koglhof) 63 | Fixed Exception (error exception: Cannot read property 'CurrentTemperature' of undefined) 64 | Added Debug log for Types 65 | 66 | ### 0.1.2 (2016-02-23) 67 | - (husky-koglhof) 68 | Added Dependency hap-nodejs 0.2.4 (No longer Reload / Timeout Failure available) 69 | Tested alarm role (With zwave Adapter) 70 | 71 | ### 0.1.1 (2016-01-31) 72 | - (husky-koglhof) 73 | fixed: Error when weatherground Adapter not found 74 | added: Role level.dimmer (Switch and Brightness) 75 | 76 | ### 0.1.0 (2016-01-29) 77 | - (husky-koglhof) 78 | fixed: timeout of homekit protocol 79 | fixed: zwave states change loop 80 | added: States are updated automatically in iOS 81 | added: zWave Objects 82 | 83 | ### 0.0.10 (2016-01-23) 84 | - (husky-koglhof) changed Store to correct path 85 | 86 | ### 0.0.8 (2016-01-22) 87 | - (husky-koglhof) Moved persistent Store to iobroker-data/homekit.0 88 | removed sensor.* Types 89 | added WeatherUnderGround Feature (forecast Objects are disabled) 90 | 91 | ### 0.0.7 (2015-12-13) 92 | - (husky-koglhof) Fixed saving admin Settings 93 | 94 | ### 0.0.6 (2015-12-12) 95 | - (husky-koglhof) Added new Devices 96 | Temperature can now be a negative Value (Needed for Outdoor Temperature) 97 | Package Name changed to lowercase 98 | Removed Dependency for installation of Packages 99 | 100 | ### 0.0.5 (2015-12-07) 101 | - (husky-koglhof) Added admin Table for Devices 102 | 103 | ### 0.0.4 (2015-12-05) 104 | - (husky-koglhof) Replaced hardcoded Values for Homematic 105 | Added Configuration for generic Objects. 106 | Currently tested: 107 | Homematic 108 | HM-CC-TC, HM-CC-RT-DN (CurrentTemperature, Setpoint, Humidity) 109 | HM-LC-Sw1-FM, HM-LC-Sw2-FM, HM-LC-Sw4-DR (Switch) 110 | MAX 111 | BC-RT-TRX-CyG-3 (CurrentTemperature, Setpoint) 112 | ZWave 113 | FGWPE (Switch), FGSS101 (Temperature), Danfoss Living Connect Radiator Thermostat (Temperature) 114 | 115 | ### 0.0.3 (2015-09-27) 116 | - (husky-koglhof) added Support for HM-CC-TC, HM-CC-RT-DN and BC-RT-TRX-CyG-3 Thermostat 117 | Supported now Actual Temperature, Set Temperature, Humidity 118 | 119 | ### 0.0.2 (2015-09-27) 120 | - (husky-koglhof) Refresh States if "Room" is refreshed. 121 | 122 | ### 0.0.1 (2015-09-26) 123 | - (husky-koglhof) Initial commit. Still non-functional. 124 | 125 | ## Todo 126 | Implement set Temperature for Homematic, etc. 127 | 128 | ## License 129 | 130 | ## Lizenz 131 | 132 | Copyright (c) 2015 husky-koglhof 133 | 134 | [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) 135 | 136 | Der obige Urheberrechtsvermerk ist in allen Kopien oder Teilkopien der Software beizulegen. 137 | 138 | DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN. 139 | 140 | HomeMatic und BidCoS sind eingetragene Warenzeichen der [eQ-3 AG](http://eq-3.de) 141 | -------------------------------------------------------------------------------- /admin/homekit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioBroker/ioBroker.homekit2/6fc6d96e68a9fba908ba7380a2abfbe8a2a7da9e/admin/homekit.png -------------------------------------------------------------------------------- /admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 24 | 25 | 231 | 232 | 233 |
234 | 235 | 236 | 237 |

HomeKit Adapter settings

238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
Bridge Name:
Username:
Pincode:
Port:
Configuration Objects
261 | 262 | 263 |
264 | 265 | -------------------------------------------------------------------------------- /img/admin_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ioBroker/ioBroker.homekit2/6fc6d96e68a9fba908ba7380a2abfbe8a2a7da9e/img/admin_settings.png -------------------------------------------------------------------------------- /io-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "common": { 3 | "name": "homekit2", 4 | "title": "homekit", 5 | "desc": "Apple HomeKit based on HAP-NodeJS", 6 | "version": "0.1.6", 7 | "mode": "daemon", 8 | "platform": "javascript/Node.js", 9 | "os": ["darwin", "linux"], 10 | "loglevel": "debug", 11 | "keywords": ["ioBroker", "homekit", "Siri", "home automation"], 12 | "main": "main.js", 13 | "authors": [ 14 | "Christian Baumgartner", "husky-koglhof " 15 | ], 16 | "license": "CC BY-NC-SA", 17 | "singletonHost": true, 18 | "readme": "https://github.com/husky-koglhof/ioBroker.homekit/blob/master/README.md", 19 | "icon": "homekit.png", 20 | "extIcon": "https://raw.githubusercontent.com/husky-koglhof/ioBroker.homekit/master/admin/homekit.png", 21 | "singleton": true, 22 | "type": "common adapters", 23 | "messagebox": true 24 | }, 25 | "native": { 26 | "username": "CC:22:3D:E3:CE:F6", 27 | "port": 51826, 28 | "pincode": "031-45-154", 29 | "category": "Accessory.Categories.BRIDGE", 30 | "bridgename": "ioBroker Bridge", 31 | "Accessories": { 32 | "Switch": { 33 | "State": { 34 | "HM-LC-Sw1-FM": ".STATE", 35 | "HM-LC-Sw2-FM": ".STATE", 36 | "HM-LC-Sw4-DR": ".STATE", 37 | "FGWPE": "", 38 | "HM-LC-Sw1-Pl": ".STATE", 39 | "HM-LC-Sw4-PCB": ".STATE" 40 | } 41 | }, 42 | "Dimmer": { 43 | "State": { 44 | "HM-LC-Dim1PWM-CV": ".STATE", 45 | "HM-LC-Sw2-FM": ".STATE", 46 | "HM-LC-Sw4-DR": ".STATE", 47 | "FGWPE": "", 48 | "HM-LC-Sw1-Pl": ".STATE", 49 | "HM-LC-Sw4-PCB": ".STATE" 50 | } 51 | }, 52 | "Thermostat": { 53 | "CurrentTemperature": { 54 | "HM-CC-TC": "1.TEMPERATURE", 55 | "BC-RT-TRX-CyG-3": "1.ACTUAL_TEMPERATURE", 56 | "HM-CC-RT-DN": "4.ACTUAL_TEMPERATURE", 57 | "OpenWeatherMap": "1.TEMPERATURE", 58 | "HM-WDS10-TH-O": "1.TEMPERATURE" 59 | }, 60 | "TargetTemperature": { 61 | "HM-CC-TC": "2.SETPOINT", 62 | "BC-RT-TRX-CyG-3": "1.SET_TEMPERATURE", 63 | "HM-CC-RT-DN": "4.SET_TEMPERATURE" 64 | }, 65 | "State": { 66 | "HM-CC-TC": "2.STATE" 67 | }, 68 | "CurrentRelativeHumidity": { 69 | "HM-CC-TC": "1.HUMIDITY", 70 | "OpenWeatherMap": "1.HUMIDITY", 71 | "HM-WDS10-TH-O": "1.HUMIDITY" 72 | } 73 | }, 74 | "Temperature": { 75 | "CurrentTemperature": { 76 | "OpenWeatherMap": "1.TEMPERATURE", 77 | "HM-WDS10-TH-O": "1.TEMPERATURE" 78 | } 79 | }, 80 | "Humidity": { 81 | "CurrentRelativeHumidity": { 82 | "OpenWeatherMap": "1.HUMIDITY", 83 | "HM-WDS10-TH-O": "1.HUMIDITY" 84 | } 85 | } 86 | } 87 | }, 88 | "objects": [ 89 | ], 90 | "instanceObjects": [ 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | var controllerDir; 2 | var appName; 3 | 4 | function getAppName() { 5 | var parts = __dirname.replace(/\\/g, '/').split('/'); 6 | return parts[parts.length - 2].split('.')[0]; 7 | } 8 | 9 | // Get js-controller directory to load libs 10 | function getControllerDir(isInstall) { 11 | var fs = require('fs'); 12 | // Find the js-controller location 13 | var controllerDir = __dirname.replace(/\\/g, '/'); 14 | controllerDir = controllerDir.split('/'); 15 | if (controllerDir[controllerDir.length - 3] == 'adapter') { 16 | controllerDir.splice(controllerDir.length - 3, 3); 17 | controllerDir = controllerDir.join('/'); 18 | } else if (controllerDir[controllerDir.length - 3] == 'node_modules') { 19 | controllerDir.splice(controllerDir.length - 3, 3); 20 | controllerDir = controllerDir.join('/'); 21 | if (fs.existsSync(controllerDir + '/node_modules/' + appName + '.js-controller')) { 22 | controllerDir += '/node_modules/' + appName + '.js-controller'; 23 | } else if (fs.existsSync(controllerDir + '/node_modules/' + appName.toLowerCase() + '.js-controller')) { 24 | controllerDir += '/node_modules/' + appName.toLowerCase() + '.js-controller'; 25 | } else if (!fs.existsSync(controllerDir + '/controller.js')) { 26 | if (!isInstall) { 27 | console.log('Cannot find js-controller'); 28 | process.exit(10); 29 | } else { 30 | process.exit(); 31 | } 32 | } 33 | } else { 34 | if (!isInstall) { 35 | console.log('Cannot find js-controller'); 36 | process.exit(10); 37 | } else { 38 | process.exit(); 39 | } 40 | } 41 | return controllerDir; 42 | } 43 | 44 | // Read controller configuration file 45 | function getConfig() { 46 | var fs = require('fs'); 47 | if (fs.existsSync(controllerDir + '/conf/' + appName + '.json')) { 48 | return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName + '.json')); 49 | } else if (fs.existsSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json')) { 50 | return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json')); 51 | } else { 52 | throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json'); 53 | } 54 | } 55 | appName = getAppName(); 56 | controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1); 57 | 58 | exports.controllerDir = controllerDir; 59 | exports.getConfig = getConfig; 60 | exports.adapter = require(controllerDir + '/lib/adapter.js'); 61 | exports.appName = appName; 62 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * HomeKit Adapter 3 | * 4 | * License: GNU LGPL 5 | */ 6 | 7 | var utils = require(__dirname + '/lib/utils'); // Get common adapter utils 8 | var objects = {}; 9 | var states = {}; 10 | var enums = []; 11 | 12 | var adapter = utils.adapter({ 13 | name: 'homekit2', 14 | 15 | ready: function () { 16 | getData(function () { 17 | adapter.subscribeForeignStates("*"); 18 | main(); 19 | adapter.log.debug(JSON.stringify(allSensors)); 20 | }); 21 | }, 22 | objectChange: function (id, obj) { 23 | // adapter.log.debug("objectChange for " + id + " found"); 24 | }, 25 | stateChange: function (id, state) { 26 | // adapter.log.debug("stateChange for " + id + ", state: " + JSON.stringify(state)); 27 | states[id] = state; 28 | 29 | var address = createAddress(objects[id]); 30 | //adapter.log.debug("ADDRESS = " + address); 31 | var sensorObject = allSensors[address]; 32 | 33 | if (sensorObject != undefined && state.val != undefined) { 34 | var value = state.val; 35 | adapter.log.debug(" VALUE: " + value + " id = " + id); 36 | var service = eval(sensorObject[0]); 37 | var characteristic = eval(sensorObject[1]); 38 | var sensor = sensorObject[2]; 39 | 40 | var oldValue = sensor.getService(service).getCharacteristic(characteristic).value; 41 | 42 | // Bugfix: zwave Switch comes with State 0 / 1 43 | if (sensorObject[0] == 'Service.Switch') { 44 | adapter.log.debug("is Switch = true"); 45 | var i = parseInt(value); 46 | if (i == 0) { 47 | value = false; 48 | } else if (i == 1) { 49 | value = true; 50 | } 51 | 52 | var o = parseInt(oldValue); 53 | if (o == 0) { 54 | oldValue = false; 55 | } else if (o == 1) { 56 | oldValue = true; 57 | } 58 | } else if (sensorObject[0] == 'Service.Lightbulb') { 59 | adapter.log.debug("is Lightbulb = true"); 60 | var i = parseInt(value); 61 | if (sensorObject[1] == 'Characteristic.Brightness') { 62 | adapter.log.debug("brightness"); 63 | } else { 64 | if (i == 0) { 65 | value = false; 66 | } else if (i > 0) { 67 | value = true; 68 | } 69 | } 70 | } else { 71 | // If value has decimal, convert to Float 72 | if (value !== true && value !== false && value !== "true" && value !== "false") { 73 | value = parseFloat(value); 74 | if (value % 1 == 0) value = parseInt(value); 75 | } 76 | } 77 | 78 | adapter.log.debug("OLDVALUE: " + oldValue); 79 | adapter.log.debug("NEWVALUE: " + value); 80 | if (oldValue != value) { 81 | adapter.log.debug("1. Change state for " + address + " to " + value + " ack = " + state.ack); 82 | 83 | adapter.log.debug("2. Change state for " + address + " to " + value + " ack = " + state.ack); 84 | 85 | if (value !== NaN && value !== null && value !== "NaN") { 86 | adapter.log.debug("3. Change state for " + address + " to " + value + " ack = " + state.ack); 87 | /* 88 | sensor 89 | .getService(service) 90 | .setCharacteristic(characteristic, value); 91 | 92 | if (sensorObject[1] == 'Characteristic.Brightness') { 93 | if (value == 0) { 94 | sensor 95 | .getService(service) 96 | .setCharacteristic(Characteristic.On, false); 97 | } else if (value > 0 ) { 98 | sensor 99 | .getService(service) 100 | .setCharacteristic(Characteristic.On, true); 101 | } 102 | } 103 | */ 104 | } 105 | } else if (sensorObject[1] == 'Characteristic.Brightness') { 106 | if (value !== NaN && value !== null && value !== "NaN") { 107 | adapter.log.debug("4. Change state for " + address + " to " + value + " ack = " + state.ack); 108 | 109 | sensor 110 | .getService(service) 111 | .setCharacteristic(characteristic, value); 112 | if (value == 0) { 113 | sensor 114 | .getService(service) 115 | .setCharacteristic(Characteristic.On, false); 116 | } else if (value > 0 ) { 117 | sensor 118 | .getService(service) 119 | .setCharacteristic(Characteristic.On, true); 120 | } 121 | } 122 | 123 | } 124 | } 125 | }, 126 | unload: function (callback) { 127 | callback(); 128 | }, 129 | }); 130 | 131 | var thermostat = []; 132 | var humidity = []; 133 | var battery = []; 134 | var alarm = []; 135 | var setpoint = []; 136 | var switches = []; 137 | var temperature = []; 138 | var lightbulb = []; 139 | 140 | function getParent(address) { 141 | var a = address.split('.'); 142 | var l = a.length; 143 | var b = ""; 144 | for (var i = 0; i < a.length - 1; i++) { 145 | b += a[i] + "."; 146 | } 147 | return b.substr(0, b.length-1); 148 | } 149 | 150 | function getRoot(address) { 151 | var a = address.split('.'); 152 | if (a.length >= 3) { 153 | return a[0]+"."+a[1]+"."+a[2]; 154 | } else { 155 | return address; 156 | } 157 | } 158 | 159 | function getData(callback) { 160 | var statesReady; 161 | var objectsReady; 162 | 163 | adapter.log.debug('requesting all states'); 164 | adapter.getForeignStates('*', function (err, res) { 165 | states = res; 166 | statesReady = true; 167 | adapter.log.debug('received all states'); 168 | if (objectsReady && typeof callback === 'function') callback(); 169 | }); 170 | 171 | adapter.log.debug('requesting all objects'); 172 | adapter.objects.getObjectList({include_docs: true}, function (err, res) { 173 | res = res.rows; 174 | objects = {}; 175 | for (var i = 0; i < res.length; i++) { 176 | objects[res[i].doc._id] = res[i].doc; 177 | if (res[i].doc.type === 'enum') enums.push(res[i].doc._id); 178 | var obj = res[i].doc; 179 | // TODO: Remove hardcoded WeatherUnderGround 180 | if (obj._id != undefined && obj._id.search("forecast") < 0) { 181 | if (obj.common !== undefined && obj.common.role == "value.humidity") { 182 | var parent = getParent(obj._id); 183 | var pobj = objects[parent]; 184 | if (pobj.native.PARENT_TYPE != undefined && pobj.native.PARENT_TYPE != "HM-CC-TC") { 185 | humidity.push(obj._id); 186 | } 187 | } 188 | if (obj.common !== undefined && obj.common.role == "value.temperature") thermostat.push(obj._id); 189 | if (obj.common !== undefined && obj.common.role == "indicator.battery") battery.push(obj._id); 190 | if (obj.common !== undefined && obj.common.role == "value.battery") battery.push(obj._id); 191 | if (obj.common !== undefined && obj.common.role == "alarm") alarm.push(obj._id); 192 | if (obj.common !== undefined && obj.common.role == "level.temperature") setpoint.push(obj._id); 193 | if (obj.common !== undefined && obj.common.role == "switch") switches.push(obj._id); 194 | if (obj.common !== undefined && obj.common.role == "level.dimmer") lightbulb.push(obj._id); 195 | } 196 | } 197 | 198 | objectsReady = true; 199 | adapter.log.debug('received all objects'); 200 | if (statesReady && typeof callback === 'function') callback(); 201 | }); 202 | } 203 | 204 | var HAP = require('hap-nodejs'); 205 | var uuid = HAP.uuid; 206 | var Bridge = HAP.Bridge; 207 | var Accessory = HAP.Accessory; 208 | var Service = HAP.Service; 209 | var Characteristic = HAP.Characteristic; 210 | var bridge; 211 | 212 | function main() { 213 | adapter.log.info("hap-nodejs starting..."); 214 | 215 | var storage = require('hap-nodejs/node_modules/node-persist'); 216 | var types = require('hap-nodejs/accessories/types'); 217 | var bridgename = adapter.config.bridgename; 218 | 219 | // Initialize our storage system 220 | 221 | var store = adapter.adapterDir + "/../../iobroker-data/homekit.0"; 222 | storage.initSync({ dir: store }); 223 | //storage.initSync(); 224 | 225 | // Start by creating our Bridge which will host all loaded Accessories 226 | bridge = new Bridge(bridgename, uuid.generate(bridgename)); 227 | 228 | // Listen for bridge identification event 229 | bridge.on('identify', function (paired, callback) { 230 | adapter.log.info("Node Bridge identify:" + paired); 231 | callback(); // success 232 | }); 233 | 234 | var accessories = adapter.config.Accessories; 235 | var types = {}; 236 | 237 | var map = new Object(); 238 | 239 | for (var acc_name in accessories) { 240 | var accessory = accessories[acc_name]; 241 | for (var obj_name in accessory) { 242 | var object = accessory[obj_name]; 243 | adapter.log.debug("Accessory: " + acc_name + " Object: " + obj_name); 244 | for (var addr_name in object) { 245 | var address = object[addr_name]; 246 | // TODO: Check if this accessory is already defined 247 | if (types[addr_name] == undefined) { 248 | types[addr_name] = {}; 249 | } 250 | types[addr_name][acc_name] = acc_name; 251 | } 252 | } 253 | } 254 | 255 | for (var i = 0; i < alarm.length; i++) { 256 | var temp = alarm[i]; 257 | if (createAccessory['SecuritySystem']) { 258 | object = objects[temp]; 259 | accessory = accessories['SecuritySystem']; 260 | map.object = object; 261 | map.accessory = accessory; 262 | map.types = types; 263 | 264 | bridge.addBridgedAccessory(createAccessory['SecuritySystem'](map)); 265 | } else { 266 | adapter.log.error("UNKNOWN SERVICE"); 267 | } 268 | map = new Object(); 269 | } 270 | 271 | for (var i = 0; i < humidity.length; i++) { 272 | var temp = humidity[i]; 273 | if (createAccessory['Humidity']) { 274 | object = objects[temp]; 275 | accessory = accessories['Humidity']; 276 | map.object = object; 277 | map.accessory = accessory; 278 | map.types = types; 279 | 280 | bridge.addBridgedAccessory(createAccessory['Humidity'](map)); 281 | } else { 282 | adapter.log.error("UNKNOWN SERVICE"); 283 | } 284 | map = new Object(); 285 | } 286 | 287 | for (var i = 0; i < temperature.length; i++) { 288 | var temp = temperature[i]; 289 | if (createAccessory['Temperature']) { 290 | object = objects[temp]; 291 | accessory = accessories['Temperature']; 292 | map.object = object; 293 | map.accessory = accessory; 294 | map.types = types; 295 | 296 | bridge.addBridgedAccessory(createAccessory['Temperature'](map)); 297 | } else { 298 | adapter.log.error("UNKNOWN SERVICE"); 299 | } 300 | map = new Object(); 301 | } 302 | 303 | for (var i = 0; i < thermostat.length; i++) { 304 | var temp = thermostat[i]; 305 | if (createAccessory['Thermostat']) { 306 | object = objects[temp]; 307 | accessory = accessories['Thermostat']; 308 | map.object = object; 309 | map.accessory = accessory; 310 | map.types = types; 311 | 312 | bridge.addBridgedAccessory(createAccessory['Thermostat'](map)); 313 | } else { 314 | adapter.log.error("UNKNOWN SERVICE"); 315 | } 316 | map = new Object(); 317 | } 318 | 319 | for (var i = 0; i < switches.length; i++) { 320 | var sw = switches[i]; 321 | 322 | object = objects[sw]; 323 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 324 | if (object && object.native && object.native.PARENT_TYPE != undefined) { 325 | if (createAccessory['Switch']) { 326 | accessory = accessories['Switch']; 327 | map.object = object; 328 | map.accessory = accessory; 329 | 330 | bridge.addBridgedAccessory(createAccessory['Switch'](map)); 331 | } else { 332 | adapter.log.error("UNKNOWN SERVICE"); 333 | } 334 | } 335 | if (object.common.type == "boolean") { 336 | if (createAccessory['Switch']) { 337 | accessory = accessories['Switch']; 338 | map.object = object; 339 | map.accessory = accessory; 340 | 341 | bridge.addBridgedAccessory(createAccessory['Switch'](map)); 342 | } else { 343 | adapter.log.error("UNKNOWN SERVICE"); 344 | } 345 | } 346 | map = new Object(); 347 | } 348 | 349 | for (var i = 0; i < lightbulb.length; i++) { 350 | var di = lightbulb[i]; 351 | 352 | object = objects[di]; 353 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 354 | if (object.native.PARENT_TYPE != undefined) { 355 | if (createAccessory['Lightbulb']) { 356 | accessory = accessories['Lightbulb']; 357 | map.object = object; 358 | map.accessory = accessory; 359 | 360 | bridge.addBridgedAccessory(createAccessory['Lightbulb'](map)); 361 | } else { 362 | adapter.log.error("UNKNOWN SERVICE"); 363 | } 364 | } 365 | if (object.common.type == "number") { 366 | if (createAccessory['Lightbulb']) { 367 | accessory = accessories['Lightbulb']; 368 | map.object = object; 369 | map.accessory = accessory; 370 | 371 | bridge.addBridgedAccessory(createAccessory['Lightbulb'](map)); 372 | } else { 373 | adapter.log.error("UNKNOWN SERVICE"); 374 | } 375 | } 376 | map = new Object(); 377 | 378 | } 379 | // Publish the Bridge on the local network. 380 | bridge.publish({ 381 | username: adapter.config.username, 382 | port: parseInt(adapter.config.port), 383 | pincode: adapter.config.pincode, 384 | category: adapter.config.category 385 | }); 386 | 387 | adapter.log.info("Bridge '" + bridgename + "' successfully published"); 388 | adapter.log.debug("UserName: " + adapter.config.username); 389 | adapter.log.debug("PinCode: " + adapter.config.pincode); 390 | adapter.log.debug("Port: " + adapter.config.port); 391 | adapter.log.debug("Category: " + adapter.config.category); 392 | } 393 | 394 | function identify(settings, paired, callback) { 395 | adapter.log.debug('< hap ' + settings.name + ' identify ' + paired); 396 | if (settings.topic.identify) { 397 | adapter.log.debug('> iobroker ' + settings.topic.identify + " " + settings.payload.identify); 398 | // TODO: mqtt.publish(settings.topic.identify, settings.payload.identify); 399 | } 400 | callback(); 401 | } 402 | 403 | function setInfos(acc, settings) { 404 | if (settings) { 405 | if (settings.ADDRESS || settings.TYPE) { 406 | acc.getService(Service.AccessoryInformation) 407 | .setCharacteristic(Characteristic.Manufacturer, "Homematic" || "-") 408 | .setCharacteristic(Characteristic.Model, settings.TYPE || "-") 409 | .setCharacteristic(Characteristic.SerialNumber, settings.ADDRESS || "-"); 410 | } 411 | } 412 | } 413 | 414 | var allSensors = {}; 415 | 416 | var createAccessory = { 417 | SecuritySystem: function createAccessory_SecuritySystem(settings) { 418 | var object = settings.object; 419 | var accessory = settings.accessory; 420 | var types = settings.types; 421 | 422 | var s = object._id.split("."); 423 | var a; 424 | for (var i = 0; i < s.length-2; i++) { 425 | if (a === undefined) { 426 | a = s[i]; 427 | } else { 428 | a = a + "." + s[i]; 429 | } 430 | } 431 | var p = objects[a]; 432 | var t; 433 | if (p !== undefined && p.native.TYPE !== undefined) { 434 | t = p.native.TYPE; 435 | adapter.log.debug("< hap Type for SecuritySystem = " + t); 436 | } 437 | var objName = createName(object); 438 | var address = createAddress(object); 439 | 440 | var sensorUUID = uuid.generate('hap-nodejs:accessories:securitysystem:' + address + "_" + objName); 441 | var sensor = new Accessory(objName, sensorUUID); 442 | setInfos(sensor, object.native); 443 | 444 | adapter.log.debug('> iobroker subscribe SecuritySystem ' + address ); 445 | 446 | if (t !== undefined && accessory['SecuritySystem'][t] !== undefined) { 447 | sensor.addService(Service.SecuritySystem) 448 | .getCharacteristic(Characteristic.SecuritySystemCurrentState) 449 | .on('get', function (callback) { 450 | var addr = p._id + "." + accessory['SecuritySystemCurrentState'][t]; 451 | adapter.log.debug('< hap ' + objName + ' get SecuritySystemCurrentState for ' + addr); 452 | 453 | if (states[addr] != undefined && states[addr].val > 0) { 454 | value = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; 455 | } else { 456 | value = Characteristic.SecuritySystemCurrentState.STAY_ARM; 457 | } 458 | //value = states[addr].val; 459 | //adapter.subscribeForeignStates(addr); 460 | if (callback) callback(null, value); 461 | }); 462 | var addr = p._id + "." + accessory['SecuritySystemCurrentState'][t]; 463 | } else { 464 | sensor.addService(Service.SecuritySystem) 465 | .getCharacteristic(Characteristic.SecuritySystemCurrentState) 466 | .on('get', function(callback) { 467 | var addr = object._id; 468 | adapter.log.debug('< hap ' + objName + ' get SecuritySystemCurrentState for ' + addr); 469 | 470 | if (states[addr] != undefined && states[addr].val > 0) { 471 | value = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; 472 | } else { 473 | value = Characteristic.SecuritySystemCurrentState.STAY_ARM; 474 | } 475 | //value = parseFloat(states[addr].val); 476 | //adapter.subscribeForeignStates(addr); 477 | if (callback) callback(null, value); 478 | }); 479 | var addr = object._id; 480 | } 481 | allSensors[addr] = ['Service.SecuritySystem', 'Characteristic.SecuritySystemCurrentState', sensor]; 482 | return sensor; 483 | }, 484 | Humidity: function createAccessory_Humidity(settings) { 485 | var object = settings.object; 486 | var accessory = settings.accessory; 487 | var types = settings.types; 488 | 489 | var s = object._id.split("."); 490 | var a; 491 | for (var i = 0; i < s.length-2; i++) { 492 | if (a === undefined) { 493 | a = s[i]; 494 | } else { 495 | a = a + "." + s[i]; 496 | } 497 | } 498 | var p = objects[a]; 499 | var t; 500 | if (p !== undefined && p.native.TYPE !== undefined) { 501 | t = p.native.TYPE; 502 | adapter.log.debug("< hap Type for Humidity = " + t); 503 | } 504 | var objName = createName(object); 505 | var address = createAddress(object); 506 | 507 | var sensorUUID = uuid.generate('hap-nodejs:accessories:humidity:' + address + "_" + objName); 508 | var sensor = new Accessory(objName, sensorUUID); 509 | setInfos(sensor, object.native); 510 | 511 | adapter.log.debug('> iobroker subscribe Humidity ' + address ); 512 | 513 | if (t !== undefined && accessory['CurrentRelativeHumidity'][t] !== undefined) { 514 | sensor.addService(Service.HumiditySensor) 515 | .getCharacteristic(Characteristic.CurrentRelativeHumidity) 516 | .on('get', function (callback) { 517 | var addr = p._id + "." + accessory['CurrentRelativeHumidity'][t]; 518 | adapter.log.debug('< hap ' + objName + ' get CurrentRelativeHumidity for ' + addr); 519 | 520 | value = parseFloat(states[addr].val); 521 | //adapter.subscribeForeignStates(addr); 522 | if (callback) callback(null, value); 523 | }); 524 | var addr = p._id + "." + accessory['CurrentRelativeHumidity'][t]; 525 | } else { 526 | sensor.addService(Service.HumiditySensor) 527 | .getCharacteristic(Characteristic.CurrentRelativeHumidity) 528 | .on('get', function(callback) { 529 | var addr = object._id; 530 | adapter.log.debug('< hap ' + objName + ' get CurrentRelativeHumidity for ' + addr); 531 | 532 | value = parseFloat(states[addr].val); 533 | //adapter.subscribeForeignStates(addr); 534 | if (callback) callback(null, value); 535 | }); 536 | var addr = object._id; 537 | } 538 | allSensors[addr] = ['Service.HumiditySensor', 'Characteristic.CurrentRelativeHumidity', sensor]; 539 | return sensor; 540 | }, 541 | Temperature: function createAccessory_Temperature(settings) { 542 | var object = settings.object; 543 | var accessory = settings.accessory; 544 | var types = settings.types; 545 | 546 | var s = object._id.split("."); 547 | var a; 548 | for (var i = 0; i < s.length-2; i++) { 549 | if (a === undefined) { 550 | a = s[i]; 551 | } else { 552 | a = a + "." + s[i]; 553 | } 554 | } 555 | var p = objects[a]; 556 | var t; 557 | if (p !== undefined && p.native.TYPE !== undefined) { 558 | t = p.native.TYPE; 559 | adapter.log.debug("< hap Type for Temperature = " + t); 560 | } 561 | var objName = createName(object); 562 | var address = createAddress(object); 563 | 564 | var sensorUUID = uuid.generate('hap-nodejs:accessories:temperature:' + address + "_" + objName); 565 | var sensor = new Accessory(objName, sensorUUID); 566 | setInfos(sensor, object.native); 567 | 568 | adapter.log.debug('> iobroker subscribe Temperature ' + address ); 569 | 570 | if (t !== undefined && accessory['CurrentTemperature'][t] !== undefined) { 571 | var service = sensor.addService(Service.TemperatureSensor); 572 | var char = service.getCharacteristic(Characteristic.CurrentTemperature); 573 | char.setProps({minValue: -100}); 574 | 575 | var action = char.on('get', function (callback) { 576 | var addr = p._id + "." + accessory['CurrentTemperature'][t]; 577 | adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 578 | 579 | value = parseFloat(states[addr].val); 580 | //adapter.subscribeForeignStates(addr); 581 | if (callback) callback(null, value); 582 | }); 583 | var addr = p._id + "." + accessory['CurrentTemperature'][t]; 584 | } else { 585 | var service = sensor.addService(Service.TemperatureSensor); 586 | var char = service.getCharacteristic(Characteristic.CurrentTemperature); 587 | char.setProps({minValue: -100}); 588 | 589 | var action = char.on('get', function (callback) { 590 | var addr = object._id; 591 | adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 592 | 593 | value = parseFloat(states[addr].val); 594 | //adapter.subscribeForeignStates(addr); 595 | if (callback) callback(null, value); 596 | }); 597 | var addr = object._id; 598 | } 599 | allSensors[addr] = ['Service.TemperatureSensor', 'Characteristic.CurrentTemperature', sensor]; 600 | return sensor; 601 | }, 602 | Thermostat: function createAccessory_Thermostat(settings) { 603 | 604 | var object = settings.object; 605 | var accessory = settings.accessory; 606 | var types = settings.types; 607 | 608 | // TODO: Try to get Parent Device so we can check which Type this Temperature is 609 | // Homematic Devices have alway PARENT_TYPE set e.g. HM-CC-TC 610 | var s = object._id.split("."); 611 | var a; 612 | for (var i = 0; i < s.length-2; i++) { 613 | if (a === undefined) { 614 | a = s[i]; 615 | } else { 616 | a = a + "." + s[i]; 617 | } 618 | } 619 | var p = objects[a]; 620 | var t; 621 | // WORKAROUND: UVR61-3 Devices are generated with Type UVR61-3 622 | if (p !== undefined && p.native.TYPE !== undefined && p.native.TYPE !== "UVR61-3") { 623 | t = p.native.TYPE; 624 | adapter.log.debug("< hap Type for Thermostat = " + t); 625 | } 626 | 627 | var objName = createName(object); 628 | var address = createAddress(object); 629 | 630 | var sensorUUID = uuid.generate('hap-nodejs:accessories:thermostat:' + address + "_" + objName); 631 | var sensor = new Accessory(objName, sensorUUID); 632 | setInfos(sensor, object.native); 633 | 634 | adapter.log.debug('> iobroker subscribe Thermostat ' + address ); 635 | 636 | if (p != undefined && p._id != undefined) { 637 | // var addr = p._id + "." + accessory['CurrentTemperature'][t]; 638 | // adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 639 | 640 | if (t !== undefined) { 641 | if (accessory['CurrentTemperature'][t] !== undefined) { 642 | sensor.addService(Service.Thermostat) 643 | .getCharacteristic(Characteristic.CurrentTemperature) 644 | .on('get', function (callback) { 645 | // BUGFIX: If there are multiple Objects, use settings.object._id as correct address 646 | var addr; 647 | if (accessory['CurrentTemperature'][t] == "*") { 648 | addr = settings.object._id; 649 | } else { 650 | addr = p._id + "." + accessory['CurrentTemperature'][t]; 651 | } 652 | adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 653 | 654 | value = parseFloat(states[addr].val); 655 | //adapter.subscribeForeignStates(addr); 656 | if (callback) callback(null, value); 657 | }); 658 | var addr = p._id + "." + accessory['CurrentTemperature'][t]; 659 | allSensors[addr] = ['Service.Thermostat', 'Characteristic.CurrentTemperature', sensor]; 660 | } 661 | if (accessory['TargetTemperature'][t] !== undefined) { 662 | sensor.getService(Service.Thermostat) 663 | .getCharacteristic(Characteristic.TargetTemperature) 664 | .on('get', function (callback) { 665 | var addr = p._id + "." + accessory['TargetTemperature'][t]; 666 | adapter.log.debug('< hap ' + objName + ' get TargetTemperature for ' + addr); 667 | 668 | value = parseFloat(states[addr].val); 669 | //adapter.subscribeForeignStates(addr); 670 | if (callback) callback(null, value); 671 | }); 672 | var addr = p._id + "." + accessory['TargetTemperature'][t]; 673 | allSensors[addr] = ['Service.Thermostat', 'Characteristic.TargetTemperature', sensor]; 674 | 675 | sensor.getService(Service.Thermostat) 676 | .getCharacteristic(Characteristic.TargetTemperature) 677 | .on('set', function (value, callback) { 678 | var addr = p._id + "." + accessory['TargetTemperature'][t]; 679 | adapter.log.debug('< hap ' + objName + ' get TargetTemperature for ' + addr); 680 | 681 | adapter.setForeignState(addr, {val: value, ack: false}); 682 | callback(); 683 | }); 684 | } 685 | 686 | if (accessory['CurrentRelativeHumidity'][t] !== undefined) { 687 | sensor.getService(Service.Thermostat) 688 | .addCharacteristic(new Characteristic.CurrentRelativeHumidity()) 689 | .on('get', function (callback) { 690 | var addr = p._id + "." + accessory['CurrentRelativeHumidity'][t]; 691 | adapter.log.debug('< hap ' + objName + ' get CurrentRelativeHumidity for ' + addr); 692 | 693 | value = parseFloat(states[addr].val); 694 | //adapter.subscribeForeignStates(addr); 695 | if (callback) callback(null, value); 696 | }); 697 | var addr = p._id + "." + accessory['CurrentRelativeHumidity'][t]; 698 | allSensors[addr] = ['Service.Thermostat', 'Characteristic.CurrentRelativeHumidity', sensor]; 699 | 700 | } 701 | } else { 702 | var service = sensor.addService(Service.TemperatureSensor); 703 | var char = service.getCharacteristic(Characteristic.CurrentTemperature); 704 | char.setProps({minValue: -100}); 705 | 706 | var action = char.on('get', function (callback) { 707 | var addr = object._id; 708 | adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 709 | 710 | value = parseFloat(states[addr].val); 711 | //adapter.subscribeForeignStates(addr); 712 | if (callback) callback(null, value); 713 | }); 714 | var addr = object._id; 715 | allSensors[addr] = ['Service.TemperatureSensor', 'Characteristic.CurrentTemperature', sensor]; 716 | } 717 | } else { 718 | var service = sensor.addService(Service.TemperatureSensor); 719 | var char = service.getCharacteristic(Characteristic.CurrentTemperature); 720 | char.setProps({minValue: -100}); 721 | 722 | var action = char.on('get', function (callback) { 723 | var addr = object._id; 724 | adapter.log.debug('< hap ' + objName + ' get CurrentTemperature for ' + addr); 725 | 726 | value = parseFloat(states[addr].val); 727 | //adapter.subscribeForeignStates(addr); 728 | if (callback) callback(null, value); 729 | }); 730 | var addr = object._id; 731 | allSensors[addr] = ['Service.TemperatureSensor', 'Characteristic.CurrentTemperature', sensor]; 732 | } 733 | return sensor; 734 | }, 735 | Switch: function createAccessory_Switch(settings) { 736 | 737 | var object = settings.object; 738 | var accessory = settings.accessory; 739 | 740 | var objName = createName(object); 741 | var address = createAddress(object); 742 | 743 | var sensorUUID = uuid.generate('hap-nodejs:accessories:switch:' + address + "_" + objName); 744 | var sensor = new Accessory(objName, sensorUUID); 745 | setInfos(sensor, object.native); 746 | 747 | adapter.log.debug('> iobroker subscribe Switch ' + address ); 748 | 749 | sensor.addService(Service.Switch) 750 | .getCharacteristic(Characteristic.On) 751 | .on('get', function (callback) { 752 | var addr; 753 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 754 | if (object && object.native && object.native.PARENT_TYPE != undefined) { 755 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 756 | } else { 757 | addr = object._id; 758 | } 759 | adapter.log.debug('< hap ' + objName + ' get Switch for ' + addr); 760 | 761 | if (!states[addr]) { 762 | adapter.log.warn('Request for nonexisting state "' + addr + '"!'); 763 | if (callback) callback(null, null); 764 | } else { 765 | value = states[addr].val; 766 | if (value === true || value === 0 || value === "0") { 767 | value = true; 768 | } else if (value === false || value === 1 || value === "1") { 769 | value = false; 770 | } else { 771 | value = false; 772 | } 773 | 774 | //adapter.subscribeForeignStates(addr); 775 | if (callback) callback(null, value); 776 | } 777 | }); 778 | 779 | sensor.getService(Service.Switch) 780 | .getCharacteristic(Characteristic.On) 781 | .on('change', function(values) { 782 | var addr; 783 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 784 | if (object.native.PARENT_TYPE != undefined) { 785 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 786 | } else { 787 | addr = object._id; 788 | } 789 | var value; 790 | 791 | // Bugfix: zwave Switch comes with State 0 / 1 792 | var i = parseInt(values.newValue); 793 | if (i === 0) { 794 | value = false; 795 | } else if (i === 1) { 796 | value = true; 797 | } else { 798 | value = values.newValue; 799 | } 800 | 801 | adapter.log.debug("CHANGED: " + addr + " = " + value); 802 | if (values.context !== undefined) { 803 | adapter.setForeignState(addr, {val: value, ack: false}); 804 | } 805 | }); 806 | var addr; 807 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 808 | if (object && object.native && object.native.PARENT_TYPE != undefined) { 809 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 810 | } else { 811 | addr = object._id; 812 | } 813 | adapter.log.debug("ADDRESS FOR SWITCH = " + addr); 814 | allSensors[addr] = ['Service.Switch', 'Characteristic.On', sensor]; 815 | return sensor; 816 | }, 817 | Lightbulb: function createAccessory_Lightbulb(settings) { 818 | 819 | var object = settings.object; 820 | var accessory = settings.accessory; 821 | 822 | var objName = createName(object); 823 | var address = createAddress(object); 824 | 825 | var sensorUUID = uuid.generate('hap-nodejs:accessories:lightbulb:' + address + "_" + objName); 826 | var sensor = new Accessory(objName, sensorUUID); 827 | setInfos(sensor, object.native); 828 | 829 | adapter.log.debug('> iobroker subscribe LightBulb ' + address ); 830 | 831 | sensor.addService(Service.Lightbulb) 832 | .getCharacteristic(Characteristic.On) 833 | .on('get', function (callback) { 834 | var addr; 835 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 836 | if (object.native.PARENT_TYPE != undefined) { 837 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 838 | } else { 839 | addr = object._id; 840 | } 841 | adapter.log.debug('< hap ' + objName + ' get Lightbulb(on) for ' + addr); 842 | 843 | value = states[addr].val; 844 | if (callback) callback(null, value); 845 | }); 846 | 847 | sensor.getService(Service.Lightbulb) 848 | .getCharacteristic(Characteristic.On) 849 | .on('change', function(values) { 850 | var addr; 851 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 852 | if (object.native.PARENT_TYPE != undefined) { 853 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 854 | } else { 855 | addr = object._id; 856 | } 857 | var value; 858 | 859 | // Bugfix: Homematic Dimmer comes with State true / false, convert to 100 / 0 860 | var i = eval(values.newValue); 861 | if (i === true) { 862 | value = 100; 863 | } else if (i === false) { 864 | value = 0; 865 | } else { 866 | value = values.newValue; 867 | } 868 | 869 | adapter.log.debug("CHANGED: " + addr + " = " + value); 870 | if (values.context !== undefined) { 871 | adapter.log.debug("CHANGED: " + addr + " = " + value); 872 | adapter.setForeignState(addr, {val: value, ack: false}); 873 | } 874 | }); 875 | 876 | sensor.getService(Service.Lightbulb) 877 | .getCharacteristic(Characteristic.Brightness) 878 | .on('get', function(callback) { 879 | var addr; 880 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 881 | if (object.native.PARENT_TYPE != undefined) { 882 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 883 | } else { 884 | addr = object._id; 885 | } 886 | adapter.log.debug('< hap ' + objName + ' get Lightbulb(brightness) for ' + addr); 887 | 888 | value = states[addr].val; 889 | if (callback) callback(null, value); 890 | }); 891 | 892 | sensor.getService(Service.Lightbulb) 893 | .getCharacteristic(Characteristic.Brightness) 894 | .on('change', function(values) { 895 | adapter.log.debug(JSON.stringify(values)); 896 | 897 | var value; 898 | value = values.newValue; 899 | 900 | if (values.context !== undefined) { 901 | adapter.setForeignState(addr, {val: value, ack: false}); 902 | } 903 | }); 904 | 905 | var addr; 906 | // Homematic Switches have PARENT_TYPE e.g. HM-LC-Sw2-FM 907 | if (object.native.PARENT_TYPE != undefined) { 908 | addr = object._id + accessory['State'][object.native.PARENT_TYPE]; 909 | } else { 910 | addr = object._id; 911 | } 912 | adapter.log.debug("ADDRESS FOR LIGHTBULB = " + addr); 913 | allSensors[addr] = ['Service.Lightbulb', 'Characteristic.Brightness', sensor]; 914 | return sensor; 915 | } 916 | }; 917 | 918 | function createAddress(object) { 919 | if (object == undefined) { 920 | return ""; 921 | } 922 | var address; 923 | if (object.native !== undefined && object.native.ADDRESS !== undefined) { 924 | address = object.native.ADDRESS; 925 | } else { 926 | address = object._id; 927 | } 928 | 929 | return address; 930 | } 931 | 932 | function createName(object) { 933 | var objName; 934 | if (object.common.name !== undefined && object.common.name !== "") { 935 | objName = object.common.name; 936 | } else { 937 | var root = getRoot(object._id); 938 | var robj = objects[root]; 939 | if (robj.common.name !== undefined && robj.common.name !== "") { 940 | objName = robj.common.name; 941 | } else { 942 | objName = object._id; 943 | } 944 | } 945 | return objName; 946 | } 947 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iobroker.homekit2", 3 | "description": "Apple HomeKit based on HAP-NodeJS", 4 | "version": "0.1.6", 5 | "author": { 6 | "name": "versteckt", 7 | "email": "husky.koglhof@icloud.com" 8 | }, 9 | "homepage": "https://github.com/husky-koglhof/ioBroker.homekit", 10 | "license": "CC BY-NC-SA", 11 | "keywords": [ 12 | "ioBroker", 13 | "homekit", 14 | "Siri", 15 | "home automation" 16 | ], 17 | "scripts": { 18 | "postinstall": "node postinstall.js" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/husky-koglhof/ioBroker.homekit.git" 23 | }, 24 | "dependencies": { 25 | "hap-nodejs": "^0.3.2", 26 | "yalm": "^4.0.2", 27 | "yargs": "^4.8.1" 28 | }, 29 | "devDependencies": {}, 30 | "os": [ 31 | "darwin", 32 | "linux" 33 | ], 34 | "bugs": { 35 | "url": "https://github.com/husky-koglhof/ioBroker.homekit/issues" 36 | }, 37 | "main": "main.js", 38 | "maintainers": [ 39 | { 40 | "name": "versteckt", 41 | "email": "husky.koglhof@icloud.com" 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /postinstall.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var walk = function (dir, done) { 3 | var results = []; 4 | fs.readdir(dir, function (err, list) { 5 | if (err) return done(err); 6 | var i = 0; 7 | (function next() { 8 | var file = list[i++]; 9 | if (!file) return done(null, results); 10 | file = dir + '/' + file; 11 | fs.stat(file, function (err, stat) { 12 | if (stat && stat.isDirectory()) { 13 | walk(file, function (err, res) { 14 | results = results.concat(res); 15 | next(); 16 | }); 17 | } else { 18 | results.push(file); 19 | next(); 20 | } 21 | }); 22 | })(); 23 | }); 24 | }; 25 | 26 | // Check if already persisent store exists. If so, move it to the correct path 27 | var dir = '/persist'; 28 | var store = __dirname + '/../../iobroker-data/homekit.0'; 29 | 30 | var mkdirSync = function (path) { 31 | try { 32 | fs.mkdirSync(path); 33 | } catch(e) { 34 | if ( e.code !== 'EEXIST' ) console.log(e); 35 | } 36 | }; 37 | 38 | walk(dir, function (err, results) { 39 | if (err) { 40 | //console.log(err); 41 | return; 42 | } 43 | 44 | mkdirSync( store ); 45 | 46 | for (var f = 0; f < results.length; f++) { 47 | var source = fs.createReadStream(results[f]); 48 | var d = results[f].replace(dir, store); 49 | console.log('--------> ' + d); 50 | var dest = fs.createWriteStream(d); 51 | 52 | source.pipe(dest); 53 | source.on('end', function () { /* copied */ 54 | }); 55 | source.on('error', function (err) { /* error */ 56 | console.log('MOVE ERROR: ' + err); 57 | }); 58 | fs.unlinkSync(results[f]); 59 | } 60 | }); 61 | --------------------------------------------------------------------------------