Labor Day Hacking With Node.js

I’ve been reading up on node.js recently, and have been pretty intrigued with what I found. The long weekend seemed like a good opportunity for some extended hacking. After setting up a nice little development enviroment, and reading up on some other node.js projects, I set myself the following goal for the weekend. Build a web app with a node.js backend that would let me remotely control my media center box.

Now we aren’t talking fully on VNC here, just basically a way to turn my laptop into a remote keyboard and mouse for the other computer. That way I could open and browse hulu without having to get up.

Luckily, I’m happy to say the project was a complete success. If you need proof check out the video below.

Right now it’s real basic. Because of some quirks with jQuery, chrome and the keypress vs. keydown events, all letters are capitals. Also key combinations like Ctrl+C and Ctrl+V don’t work, but it’s passable for most tasks I need it for and gives me a fun base to play around with.

The Secret Sauce

So how does this work? Well basically my media PC is running a simple node.js  webserver that serves up pages and maintains a single websocket connection using the socket.io library. On the client side, there’s some javascript that broadcasts messages across the socket whenever there’s a key up, key down, click, or mouse movement. On the server, some node.js goodness forwards these messages along to the XServer to control the display on the media center.

It’s actually not much more than 200 lines of code, not including the libraries. The most complicated part is the communication between my server and the XServer. I started out trying to use Andrey Sidorov’s node-x11 library, which is a pretty neat little project. Basically, it uses the net library in node.js to connect to the Unix X11 Socket and stream requests to the socket over TCP/IP. Unfortunately it’s pretty new, so there really aren’t any methods for sending mouse or keyboard events across the socket yet. I used his framework to write out a new WarpPointer method, which moves the mouse around, but quickly found that sending click or keypress events was going to be waaaaay more complicated.

So for those areas specifically I took a fallback strategy, and resorted to a quick little hack. Instead  of talking with the XServer directly, I had node.js kick off a child process and run the command line tool “xdotool.” xdotool is basically a simple command line window management tool that lets you fake XEvents with a fairly simple syntax. Way simpler than building a request for scratch. Of course it’s an ugly hack, but adding the pieces to Sidorov’s framework to send the events to the XServer over the weekend wasn’t going to happen. As the library get’s fleshed out, I’ll strip that hack out.

I had to resort to a similar hack to get the size of the users current resolution, basically parsing the results of an “xwinfo”  call. Again, something that I’ll have to eventually refactor out, but good enough for right now.

If you want to see the detailed code, I’ve got it up here on github.

https://github.com/AndrewSwerlick/node-remote

What’s Next?

I don’t plan to shelve this hack by any means. In fact I’d love to expand it to a more full featured remote control type app. Right now I’ve got a short list of 4 goals.

1. Improve interaction with X so it’s not calling out to the command line to do the manipulation

2. Improve mobile support. Right now, since moving the browser window around in a mobile doesn’t fire a mousemove() event, you can’t use the remote on a phone.

3. Figure out how to handle key combinations. Right now the app doesn’t recognize key combinations. Similarly, all letters come across as capitals. Both of these issues are tied to challenges around recognizing which key has been pressed in javascript, and making sure that we prevent the browser from acting on keystrokes like backspace

4. Build out some short cuts/quick links functionality. For example, a hulu browser, that will let you search hulu and start shows with a few keystrokes. Or a short cut tab that will let you quick start often used programs.

Conclusions

So what did I learn about node.js from this first little foray? Well I’m certainly impressed at how easy it was to get something basic up and running. Especially considering that I’d never worked with websockets before, socket.io made it dead simple. The async nature of node.js was also especially interesting to work with, but not too unfamiliar with because of my work with Silverlight.

Of course, I probably could have done the same thing with ruby, or mvc.net, etc, but I don’t think it would be as quick. One of the things I liked about node.js was how easy it was to jump between scripting type stuff, like running console apps and parsing the output, and more traditional server type tasks. It was also great to pass JSON objects across the wire through sockets, and then be able to immediately consume those objects in server side code without having to jump through any hoops to parse those objects into server side variables.

I’ve also always liked the loose and fast nature of javascript, that allows for lots of flexibility in terms of object construction. Even in this small project, I could see how this flexibility would be really fun to work with. I’m definitely excited to see where the framework goes, and definitely plan to keep playing with it.

Advertisements

2 thoughts on “Labor Day Hacking With Node.js

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s