Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: node_js
node_js:
- "0.10"
- "0.8"
- "5.5"
- "4.2"
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

## [1.0.0] - 2016-02-05

* Switching irsend from callbacks to promises. Breaking change.
* Removing `Makefile` and just using `package.json` for running tests.

## [0.0.4] - 2015-12-30
Expand Down
36 changes: 24 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ It is a part of the [Open Source Universal Remote](http://opensourceuniversalrem

[![Build Status](https://travis-ci.org/alexbain/lirc_node.png)](https://travis-ci.org/alexbain/lirc_node)

Node.js >= v4.2 (LTS) required.

## What is this?

LIRC is a fantastic open source software package that allows you to send and
Expand Down Expand Up @@ -62,13 +64,17 @@ answer any ambiguities. There are additional options that are not shown here.

// Sending commands
lirc_node = require('lirc_node');
lirc_node.init();

// To see all of the remotes and commands that LIRC knows about:
console.log(lirc_node.remotes);
// After lirc_node has initialized, see all of the remotes and commands that LIRC knows about:
lirc_node.init().then(function(remotes) {
console.log(remotes);

// or
// console.log(lirc_node.remotes)
})

/*
Let's pretend that the output of lirc_node.remotes looks like this:
Output of lirc_node.remotes will look like this:

{
"tv": ["Power", "VolumeUp", "VolumeDown"],
Expand All @@ -77,31 +83,37 @@ answer any ambiguities. There are additional options that are not shown here.
*/

// Tell the TV to turn on
lirc_node.irsend.send_once("tv", "power", function() {
lirc_node.irsend.send_once("tv", "Power").then(function() {
console.log("Sent TV power command!");
});

// Tell the Xbox360 to turn on
lirc_node.irsend.send_once("xbox360", "power", function() {
lirc_node.irsend.send_once("xbox360", "Power").then(function() {
console.log("Sent Xbox360 power command!");
});

// Turn the volume up for 2 seconds
lirc_node.irsend.send_start("tv", "VolumeUp");
setTimeout(function() {
lirc_node.irsend.send_stop("tv", "VolumeUp");
}, 2000);

// Listening for commands
// Listen for all IR commands
var listenerId = lirc_node.addListener(function(data) {
console.log("Received IR keypress '" + data.key + "'' from remote '" + data.remote +"'");
});

// Listen for a specific IR command
lirc_node.addListener('KEY_UP', 'remote1', function(data) {
// `data` also has `code` and `repeat` properties from output of `irw`

console.log("Received IR keypress 'KEY_UP' from remote 'remote1'");
// data also has `code` and `repeat` properties from the output of `irw`
// The final argument after this callback is a throttle allowing you to

// The final argument after this callback is a throttle allowing you to
// specify to only execute this callback once every x milliseconds.
}, 400);




## Development

Would you like to contribute to and improve this module? Fantastic. To contribute
Expand Down Expand Up @@ -142,7 +154,7 @@ The exception to this would be refactoring existing code or changing documentati

(The MIT License)

Copyright (c) 2013-2015 Alex Bain <alex@alexba.in>
Copyright (c) 2013-2016 Alex Bain <alex@alexba.in>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand Down
35 changes: 19 additions & 16 deletions lib/irsend.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
var exec = require('child_process').exec;
var Promise = require('bluebird');
var exec = Promise.promisify(require('child_process').exec, { multiArgs: true });

exports = module.exports = IRSend;

function IRSend () {
// TODO: execOverride is used for testing. I don't like it.
function IRSend (execOverride) {
this.command = 'irsend';
this.exec = execOverride || exec;
};

// In some cases the default lirc socket does not work
Expand All @@ -16,34 +17,34 @@ IRSend.prototype.setSocket = function(socket) {
}
};

IRSend.prototype.list = function(remote, code, callback) {
IRSend.prototype.list = function(remote, code) {
var command = this._list(remote, code);
return exec(command, callback);
return this.exec(command);
};

IRSend.prototype.send_once = function(remote, code, callback) {
IRSend.prototype.send_once = function(remote, code) {
var command = this._send_once(remote, code);
return exec(command, callback);
return this.exec(command);
};

IRSend.prototype.send_start = function(remote, code, callback) {
IRSend.prototype.send_start = function(remote, code) {
var command = this._send_start(remote, code);
return exec(command, callback);
return this.exec(command);
};

IRSend.prototype.send_stop = function(remote, code, callback) {
IRSend.prototype.send_stop = function(remote, code) {
var command = this._send_stop(remote, code);
return exec(command, callback);
return this.exec(command);
};

IRSend.prototype.set_transmitters = function(transmitters, callback) {
IRSend.prototype.set_transmitters = function(transmitters) {
var command = this._set_transmitters(transmitters);
return exec(command, callback);
return this.exec(command);
};

IRSend.prototype.simulate = function(code, callback) {
IRSend.prototype.simulate = function(code) {
var command = this._simulate(code);
return exec(command, callback);
return this.exec(command);
};

// Internal methods
Expand Down Expand Up @@ -103,3 +104,5 @@ IRSend.prototype._set_transmitters = function(transmitters) {
IRSend.prototype._simulate = function(code) {
return this.command + ' SIMULATE "' + code + '"';
};

exports = module.exports = IRSend;
84 changes: 54 additions & 30 deletions lib/lirc_node.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
exports.version = '0.0.2';
var Promise = require('bluebird');

// Setup irsend
exports.IRSend = require('./irsend');
exports.irsend = new exports.IRSend();
exports.remotes = {};

// Setup irreceive
exports.IRReceive = require('./irreceive');
var irreceive = new exports.IRReceive();

// Setup event listeners for irreceive
exports.addListener = irreceive.addListener.bind(irreceive);
exports.on = exports.addListener;
exports.removeListener = irreceive.removeListener.bind(irreceive);
Expand All @@ -15,45 +20,64 @@ exports.setSocket = function(socket) {
exports.irsend.setSocket(socket);
}

exports.init = function(callback) {
exports.irsend.list('', '', irsendCallback);
exports.init = function() {
return exports.irsend.list('', '')
.then(exports._populateRemotes)
.then(exports._populateCommands)
.then(function(remotes) {
return exports.remotes = remotes;
});
};

function irsendCallback(error, stdout, stderr) {
exports._populateRemotes(error, stdout, stderr);
exports._populateCommands();
if (callback) callback();
}
// Parse the list of remotes that irsend knows about
exports._populateRemotes = function (irsendResult) {
var remotes = {};

irsendResult[1].split('\n').forEach(function (remote) {
var remoteName = remote.match(/\s(.*)$/);
if (remoteName) remotes[remoteName[1]] = [];
});

return true;
return remotes;
};

// Private
exports._populateRemotes = function(error, stdout, stderr) {
var remotes = stderr.split('\n');
// Given object whose keys represent remotes, get commands for each remote
// Returns promise that will resolve when all irsend invocations complete
exports._populateCommands = function (remotesObject) {
var commandPromises = [];
var remoteNames = Object.keys(remotesObject);

exports.remotes = {};
remoteNames.forEach(function (remote) {
commandPromises.push(exports.irsend.list(remote, '')
.then(function (irsendResult) {
return { [remote]: exports._parseCommands(irsendResult) }
})
);
})

remotes.forEach(function(element, index, array) {
var remoteName = element.match(/\s(.*)$/);
if (remoteName) exports.remotes[remoteName[1]] = [];
});
return Promise.all(commandPromises)
.then(exports._joinRemoteCommands);
};

exports._populateCommands = function() {
for (var remote in exports.remotes) {
(function(remote) {
exports.irsend.list(remote, '', function(error, stdout, stderr) {
exports._populateRemoteCommands(remote, error, stdout, stderr);
});
})(remote);
}
// Merges an array of remoteCommands into a single object
exports._joinRemoteCommands = function(remoteCommands) {
var remotes = {};

remoteCommands.forEach(function(remote) {
remotes = Object.assign(remotes, remote);
});

return remotes;
};

exports._populateRemoteCommands = function(remote, error, stdout, stderr) {
var commands = stderr.split('\n');
// Parses the results of irsend for a specifif remote
exports._parseCommands = function (irsendResult) {
var commands = [];

commands.forEach(function(element, index, array) {
var commandName = element.match(/\s.*\s(.*)$/);
if (commandName && commandName[1]) exports.remotes[remote].push(commandName[1]);
irsendResult[1].split('\n').forEach(function (command) {
var commandName = command.match(/\s.*\s(.*)$/);
if (commandName && commandName[1]) commands.push(commandName[1]);
});

return commands;
};
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lirc_node",
"version": "0.0.4",
"version": "1.0.0",
"description": "Control LIRC from Node",
"main": "lib/lirc_node.js",
"scripts": {
Expand All @@ -13,14 +13,20 @@
"keywords": [
"lirc"
],
"dependencies": {},
"dependencies": {
"bluebird": "3.2.1"
},
"devDependencies": {
"mocha": "2.3.3",
"q": "1.4.1",
"should": "7.1.0",
"sinon": "1.17.1"
"sinon": "1.17.1",
"sinon-as-promised": "4.0.0"
},
"author": "Alex Bain <alex@alexba.in>",
"engines" : {
"node" : ">=4.2"
},
"contributors": [
{
"name": "Mark Stickley",
Expand Down
Loading