UNPKG

node-rc6

Version:

Small home automation project. Controls Fire TV + Kodi (via adb) and hue lights (via API) using a Harmony One + RC6 USB IR receiver (on a Raspberry Pi).

163 lines (143 loc) 5.14 kB
exports = module.exports = (function(){ var request = require('request-json'); var hue_user = 'node-rc6-user'; var ALL_GROUP = 'all'; function hue(ev, hue_ip) { var client = request.createClient('http://' + hue_ip + '/'); function api(path, options, cb) { options = options || {}; options.url = path ? 'api/' + hue_user + path : 'api'; ev.debug('call ' + path||'/api', options); var method = 'get', params = [options.url]; if ('post' in options) { method = 'post'; params.push(options.post); } else if ('put' in options) { method = 'put'; params.push(options.put); } params.push(function(error, response, body){ if (error !== null) { ev.error(error, options); } else { if (body[0] && body[0].error) { if (body[0].error.type === 1 || body[0].error.type === 101) { ev.debug('unauthorized', { options: options, body: body }); if (body[0].error.type === 101) ev.info(body[0].error.description); api(null, { post: { devicetype: hue_user+'#nodejs', username: hue_user } }, path === null ? cb : (function(p,o,c){ return function(){api(p,o,c)}; })(path, options, cb)); } else { ev.error('[' + body[0].error.type + '] ' + body[0].error.description, { options: options, body: body }); } } else { ev.debug(path||'/api', body); if (cb) cb(body); } } }); client[method].apply(client, params); } var lightIds = [], groupId = null; api('/lights', {}, function(lights){ for (var lightId in lights) lightIds.push(lightId); ev.debug('found lights', lightIds); api('/groups', function(groups){ for (var group in groups) { if (groups[group].name === ALL_GROUP) { groupId = group; ev.debug('found group', group); break; } } if (groupId === null) { ev.debug('create group', ALL_GROUP); api('/groups', { post: { lights: lightIds, name: ALL_GROUP } }, function(){ api('/groups', function(groups){ for (var group in groups) { if (groups[group].name === ALL_GROUP) { groupId = group; ev.debug('found group', group); break; } } }); }); } }); }); var randomMode = false; function setLightState(id, state, cb) { return api('/lights/' + id + '/state', { put: state }, cb); } function setGroupState(state, cb) { return api('/groups/' + groupId + '/action', { put: state }, cb); } this.stop = function() { randomMode = false; }; this.on = function(on) { randomMode = false; setGroupState({ on:on===true }); }; this.scene = function(no) { randomMode = false; api('/scenes', {}, function(scenes){ var i=0; if (scenes) for (var scene in scenes) if (++i === no) setGroupState({ scene: scene }); }); }; function calcBri(op, val, cur) { var bri = op==='=' ? val : (op==='-' ? cur - val : (op==='+' ? cur + val : cur)); return Math.min(Math.max(bri, 1), 254); } this.bri = function(op, val) { api('/lights', {}, function(lights){ if (lights) for (light in lights) setLightState(light, { bri: calcBri(op, val, lights[light].state.bri) }); }); }; function rand(min, max, prec) { var pow = Math.pow(10, prec||0); return Math.round(Math.floor(Math.random() * (max * pow - min * pow + 1)) + min * pow) / pow; } function moodLight(lightId, duration, transition) { if (randomMode) { _duration = typeof(duration) === 'object' ? rand(duration[0], duration[1]) : duration; _transition = transition ? transition : _duration; setLightState(lightId, { transitiontime: Math.round(_transition/100), xy: [rand(0,1,4),rand(0,1,4)] } ); setTimeout(moodLight, _duration, lightId, duration, transition); } } function moodLights(duration, transition) { if (randomMode) { _duration = typeof(duration) === 'object' ? rand(duration[0], duration[1]) : duration; _transition = transition ? transition : _duration; setGroupState( { transitiontime: Math.round(_transition/100), xy: [rand(0,1,4),rand(0,1,4)] } ); setTimeout(moodLights, _duration, duration, transition); } } this.random = function(sync, duration, transition) { randomMode = true; setGroupState({ on: true, bri: 254 }); if (sync) { moodLights(duration, transition); } else { lightIds.forEach(function(lightId){ moodLight(lightId, duration, transition); }); } }; } return { getInstance: function(ev, hue_ip) { return new hue(ev, hue_ip); } }; })();