Android and Linux

Monday, July 4, 2011

Control Roku from command line

I got a Roku to play Netflix Instant on my TV (as well as other channels available through Roku). It connects to your wifi or ethernet and streams video through a wire to your TV and is controlled with a remote control. The Roku has two output ports, one for RCA cables and one for HDMI cables. I have the HDMI going to the TV in the living room and RCA cables going to my bedroom TV so I can also watch the Roku in there. But, of course, the remote control doesn't work from my bedroom.

Luckily, the Roku can also be controlled over your home network. There is a Roku remote control app available for Android called RoMote which works great, except you have to tell it to connect and it loses the connection when you close the app. If you only need to push one button, like Pause, it's a bit of a hassle because you have to open the app, click connect, then tap Pause and close the app.

There is an SDK available that allows developers to create their own apps, which is obviously how the RoMote developer made his. This is an example of what the SDK uses for the general format for keypresses. This example uses the Home button and assumes the Roku IP is

echo -e 'POST /keypress/Home/1.1\r\n\r\n' | ncat 8060

Yuck. Luckily again, we can make that a little nicer looking by using cURL or wget to post data.

curl -d "" ""

wget --post-data "" ""

The Roku only seems to work with the HTTP POST method. The -d option tells cURL to post http data and obviously the "--post-data" option does the same for wget. The data is supposed to be between the first quotation marks and as you see, mine are empty, so it's posting, but it's posting nothing. The important part is the url that it posts to, in this case /keypress/Home. When the Roku detects a post to that url, it acts as if the Home key on the remote control has been pressed.

Here is a list of the available controls:


Lit_ is special, you enter a letter with Lit_x. For example, to search for movies containing "foo", you'd hit the following 5 urls in order:


The /query/apps URL will give you a list of the apps installed on the Roku. Apps are basically channels. There is a Netflix app, WeatherChannel app, etc. The data comes back in xml format.
# curl                              
<app id="5127" version="1.0.10">Roku Spotlight</app>
<app id="11" version="2.1.22">Roku Channel Store</app>
<app id="12" version="2.3.20">Netflix</app>
<app id="2016" version="2.0.37">Movies on Demand</app>
<app id="2285" version="1.9.1">Hulu Plus</app>
<app id="28" version="1.0.24">Pandora</app>
<app id="1688" version="1.5.10">Roku Newscaster</app>
<app id="1756" version="1.5.5">Funny Videos and Pics by Break</app>
<app id="2115" version="1.4.1">SHOUTcast Internet Radio</app>
<app id="27" version="1.1.110207">Mediafly</app>
<app id="2898" version="0.0.0">Weather Underground</app>
<app id="2963" version="1.0.0">My Damn Channel</app>
<app id="4070" version="1.5.1306292789">TEDTalks</app>
<app id="45" version="1.5.0">Revision3</app>
<app id="4687" version="1.0.0">Inmoo </app>
<app id="6493" version="1.0.1">Sunlight Foundation White House Video Stream</app>
<app id="1980" version="1.1.100907">Vimeo</app>
<app id="2091" version="1.2.1">Warriors of War</app>

If you want to watch a channel, just hit this url containing the numerical ID. For example, if you want to check the weather:


And using the numerical ID, you can view that channel's icon using this url: /query/icon/2898.

That's pretty much all there is to imitating the Roku remote control. I'll probably be putting this all into a script and posting it later when I have more time. Being able to control it this way allows you to script your player. For example, Netflix has entire seasons of TV shows available but doesn't have a "play all" option, so you could use this to watch one, wait 23 minutes, watch another etc then you could have Weather Undergroud start playing at the time you wake up.

This can also be controlled through your Android phone. cURL isn't available on Android, but see wget is, and see my earlier post about using Tasker to post HTTP data.