├── .gitignore ├── LICENSE ├── README.md ├── examples ├── discovery.js ├── listDevices.js └── toggleValue.js ├── lib └── fibaro.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | _* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Leeroy Brun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-fibaro-api 2 | =========== 3 | 4 | Interact with Fibaro Home Center API 5 | 6 | ## How it works 7 | 8 | Instantiate a new client : 9 | ```javascript 10 | var Fibaro = require('fibaro-api'); 11 | var fibaro = new Fibaro('xxx.xxx.xxx.xxx', 'username', 'password'); 12 | ``` 13 | 14 | Alternatively, to attempt auto discovery : 15 | ```javascript 16 | Fibaro.discover(function(info) { 17 | var fibaro = new Fibaro(info.ip, 'username', 'password'); 18 | }); 19 | ``` 20 | 21 | Make your calls : 22 | 23 | ```javascript 24 | fibaro.call(action, params, callback); 25 | ``` 26 | 27 | ### Shortcuts 28 | 29 | There is some shortcuts too : 30 | 31 | #### fibaro.api.devices.list(callback) 32 | #### fibaro.api.devices.get(deviceId, callback) 33 | #### fibaro.api.devices.turnOn(deviceId, callback) 34 | #### fibaro.api.devices.turnOff(deviceId, callback) 35 | #### fibaro.api.devices.toggleValue(deviceId, callback) 36 | 37 | I will add shortcuts as needed, don't hesitate to add yours and send me a pull request. :-) 38 | 39 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/leeroybrun/node-fibaro-api/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 40 | -------------------------------------------------------------------------------- /examples/discovery.js: -------------------------------------------------------------------------------- 1 | var Fibaro = require('../lib/fibaro'); 2 | 3 | Fibaro.discover(function(info) { 4 | 5 | console.log('Discovered device', info.serial, 'at', info.ip); 6 | 7 | var fibaro = new Fibaro(info.ip, 'username', 'password'); 8 | 9 | fibaro.api.devices.list(function(err, data) { 10 | console.log(data); 11 | }); 12 | }); -------------------------------------------------------------------------------- /examples/listDevices.js: -------------------------------------------------------------------------------- 1 | var Fibaro = require('../lib/fibaro'); 2 | 3 | var fibaro = new Fibaro('xxx.xxx.xxx.xxx', 'username', 'password'); 4 | 5 | fibaro.api.devices.list(function(err, data) { 6 | console.log(data); 7 | }); -------------------------------------------------------------------------------- /examples/toggleValue.js: -------------------------------------------------------------------------------- 1 | var Fibaro = require('../lib/fibaro'); 2 | 3 | var fibaro = new Fibaro('xxx.xxx.xxx.xxx', 'username', 'password'); 4 | 5 | // Toggle devices ON/OFF 6 | fibaro.api.devices.toggleValue(6, function(err, newVal) { 7 | console.log(err); 8 | console.log(newVal); 9 | }); -------------------------------------------------------------------------------- /lib/fibaro.js: -------------------------------------------------------------------------------- 1 | var request = require('request'), 2 | async = require('async'), 3 | util = require('util'); 4 | 5 | var FibaroClient = module.exports = function(host, user, pass) { 6 | this.rootUrl = 'http://'+ host +'/api'; 7 | this.username = user; 8 | this.password = pass; 9 | this.cookies = request.jar(); 10 | 11 | this.setCredentials = function(user, pass) { 12 | this.username = user; 13 | this.password = pass; 14 | } 15 | 16 | this.call = function(action, params, callback) { 17 | // If no params was passed 18 | if(typeof params == 'function') { 19 | callback = params; 20 | params = {}; 21 | } 22 | 23 | var reqOptions = { 24 | 'method': 'GET', 25 | 'uri': this.rootUrl +'/'+ action, 26 | 'auth': { 27 | 'user': this.username, 28 | 'pass': this.password, 29 | 'sendImmediately': false 30 | }, 31 | 'jar': this.cookies, 32 | 'qs': params 33 | }; 34 | 35 | var req = request(reqOptions, function(err, res, body) { 36 | if(err) { 37 | if('code' in err && err.code == 'ECONNREFUSED') { 38 | callback(new Error('Fibaro not running...')); 39 | } else { 40 | callback(err); 41 | } 42 | 43 | } else if(typeof body == 'object' && 'error' in body) { 44 | callback(new Error(body.error)); 45 | 46 | } else if(res.statusCode != 200 && res.statusCode != 202) { 47 | if(res.statusCode == 401) { 48 | callback(new AuthError('Bad username or password.')); 49 | } else { 50 | callback(new Error('Fibaro API returned status code : '+ res.statusCode)); 51 | } 52 | 53 | } else { 54 | try { 55 | body = JSON.parse(body); 56 | } catch (e) {} 57 | 58 | callback(null, body); 59 | } 60 | }); 61 | } 62 | 63 | // TODO: put shortcuts in a separate file 64 | var client = this; 65 | var shortcuts = this.api = { 66 | // --------------------------------------------------------------- 67 | // Rooms 68 | // --------------------------------------------------------------- 69 | rooms: { 70 | list: function(callback) { 71 | client.call('rooms', callback); 72 | } 73 | }, 74 | 75 | // --------------------------------------------------------------- 76 | // Scenes 77 | // --------------------------------------------------------------- 78 | scenes: { 79 | list: function(callback) { 80 | client.call('scenes', callback); 81 | } 82 | }, 83 | 84 | // --------------------------------------------------------------- 85 | // Devices 86 | // --------------------------------------------------------------- 87 | devices: { 88 | list: function(callback) { 89 | client.call('devices', callback); 90 | }, 91 | get: function(id, callback) { 92 | client.call('devices', { 'id': id }, callback); 93 | }, 94 | turnOn: function(id, callback) { 95 | client.call('callAction', { 'deviceID': id, 'name': 'turnOn' }, callback); 96 | }, 97 | turnOff: function(id, callback) { 98 | client.call('callAction', { 'deviceID': id, 'name': 'turnOff' }, callback); 99 | }, 100 | toggleValue: function(id, callback) { 101 | var self = this; 102 | var newVal = null; 103 | 104 | async.waterfall([ 105 | function getDeviceStatus(cb) { 106 | self.get(id, cb); 107 | }, 108 | 109 | function setDeviceStatus(device, cb) { 110 | if(device.properties.value == 0) { 111 | newVal = 1; 112 | self.turnOn(id, cb); 113 | } else { 114 | newVal = 0; 115 | self.turnOff(id, cb); 116 | } 117 | } 118 | ], function(err) { 119 | callback(err, newVal); 120 | }); 121 | } 122 | } 123 | }; 124 | } 125 | 126 | FibaroClient.discover = function (callback, timeout) { 127 | 128 | var re = /^ACK (HC2-[0-9]+) ([0-9a-f:]+)$/; 129 | 130 | var server = require('dgram').createSocket("udp4"); 131 | 132 | server.on('message', function (packet, rinfo) { 133 | 134 | var matches = re.exec(packet.toString()); 135 | 136 | if (matches) { 137 | callback({ 138 | ip: rinfo.address, 139 | serial: matches[1], 140 | mac: matches[2] 141 | }); 142 | } 143 | }); 144 | 145 | server.bind(44444, function () { 146 | var message = new Buffer("FIBARO"); 147 | server.setBroadcast(true); 148 | server.send(message, 0, message.length, 44444, "255.255.255.255"); 149 | }); 150 | 151 | setTimeout(function () { 152 | server.close(); 153 | }, timeout || 5000); 154 | }; 155 | 156 | /* Custom error objects */ 157 | var AbstractError = function (msg, constr) { 158 | Error.captureStackTrace(this, constr || this) 159 | this.message = msg || 'Error' 160 | } 161 | util.inherits(AbstractError, Error); 162 | AbstractError.prototype.name = 'Abstract Error'; 163 | 164 | var AuthError = function (msg) { 165 | AuthError.super_.call(this, msg, this.constructor) 166 | } 167 | util.inherits(AuthError, AbstractError) 168 | AuthError.prototype.message = 'Authentification Error' 169 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fibaro-api", 3 | "version": "0.1.1", 4 | "author": "Leeroy Brun ", 5 | "description": "Interact with Fibaro Home Center API", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/leeroybrun/node-fibaro-api.git" 9 | }, 10 | "keywords": [ 11 | "fibaro", 12 | "api" 13 | ], 14 | "license": "MIT", 15 | "dependencies" : { 16 | "request": "*", 17 | "async": "*" 18 | }, 19 | "engines": [ 20 | "node" 21 | ], 22 | "main": "./lib/fibaro.js" 23 | } 24 | --------------------------------------------------------------------------------