Electronics · raspberry pi

Tying it all together! Wand > LIRC > Socket > Forever > Outlet

Magic book

Image source: http://weknowyourdreams.com/single/magic/magic-03

By now we’ve figured out lots of fun chunks of code.  All inspired by the idea of a wand controlling your home.  When I say by now, I’m referring to the previous articles:

Listening to remote (the wand)

Keeping the listener alive.. forever

Talking to an tplink outlet or talking to a wemo outlet

The last thing to do is glue it all together!  This article handles connecting the IR remote to your long running process.  We’re going to use local file system handles as our socket for this.

Our long running or forever process is a separate program started by a separate program from the one started by LIRC.  When LIRC recognizes an IR command from one of your trained remotes, it runs the command held in the config entry.  For our purposes, we’re going to have that config entry set to call a NodeJS program every time the button is clicked.  Like this (the contents of my /etc/lirc/lircrc file):

begin
  prog = irexec
  button = KEY_EJECTCD
  config = /usr/bin/node /home/pi/kidpi/lirc/remotekeypressed.js "KEY_EJECTED"
end

Note that my lirc config is going to call my NodeJS program when it receives the remote command I’ve mapped to KEY_EJECTCD.

Which is great!  Now, that program: remotekeypressed.js, when run, needs to pass that key press to the forever process.  So… we need a way to communicate to the “forever” process!  Being Unix there TONS of ways of getting that done.  I chose local file sockets.

Opening a File Socket Server

The first thing we need to do is make sure that forever process we created is ready and listening on a file handle.  NodeJS makes that easy to do like this:

var net = require('net');

// This server listens on a Unix socket at /var/run/lirc/lircrun
var unixServer = net.createServer(function(client) {
  console.log("Received connection!");
});
unixServer.listen('/var/run/lirc/lircrun');

Notice how there is a file path held in that code?  /var/run/lirc/lircrun

In Linux, file descriptors can be treated just like sockets.  They a handle that the OS knows to watch for connections.  When a client connects the OS efficiently transfers data from the client process to the server process (IPC or Inter-Process Communication).

Restart your forever process, with that little gem in it.  When its running there will be a new file here:

/var/run/lirc/

That’s your listening process at work!

We need to connect a client to that handle… so take a look at the lircrc file from before:

config = /usr/bin/node /home/pi/kidpi/lirc/remotekeypressed.js "KEY_EJECTED"

That config tells LIRC to run remotekeypressed.js with a parameter of KEY_EJECTED.

Lets take a look at that program:

var net = require('net');

var client = net.createConnection("/var/run/lirc/lircrun");
client.on("connect", function() {
 console.log("Button pressed in JS:" + process.argv[2]);
 client.write(process.argv[2]);
 client.end();
});

This immediately opens a client socket using /var/run/lirc/lircrun which happens to be where our server is listening, then writes which key it saw into the socket!

Voila!  The LIRC or IR Remote, is now sending a quick message over to our NodeJS forever process which can start doing magic as a result!

Socket Connected – Time for control!

So putting it together with the tp-link control example from before we have:

var child_process = require('child_process');
var net = require('net');
var Hs100Api = require('hs100-api');

console.log("#################################### I started!");

// Make sure we report in on the watchdog...
setInterval(function() {
 var command = "/bin/systemd-notify --pid="+process.pid+" WATCHDOG=1";
 console.log("Calling in! USecs:" + process.env.WATCHDOG_USEC + " PID: " + process.env.WATCHDOG_PID);
 console.log(command);
 var args = [
 '--pid=' + process.pid,
 'WATCHDOG=1'
 ]
 child_process.execFile('/bin/systemd-notify', args);
 //child_process.execFile(command);
},10000);


// Something to hold our last outlet state.
var last = true;

// This server listens on a Unix socket at /var/run/lirc/lircrun
var unixServer = net.createServer(function(client) {
 console.log("Received connection!");

 var client = new Hs100Api.Client();
 var lightplug = client.getPlug({host: '192.168.1.107'});

 last = !last;
 lightplug.setPowerState(last);
});

unixServer.listen('/var/run/lirc/lircrun');

Everytime I get an IR command from my wand or remote, my lights toggle on and off.

So awesome!  My boys had a blast trying to do Morse code with the lamps. 😉

Other Resources

This fellow was recently featured on hacker news – and it looks like its another good tutorial on getting LIRC up on a pie:

http://wsmlab.blogspot.com/2017/04/ir-volume-control-for-sonos-connect-amp.html

2 thoughts on “Tying it all together! Wand > LIRC > Socket > Forever > Outlet

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.