Roku 3 control question

I have a Roku 3 which i can control via the ipad app. There is one (actually 2, but that is the most important one) button i cannot get, the back button. None of the controls in the database work, and as the remote is wifi only i cannot learn that command. There is another one in the iphone/ipad roku app, which brings up the channel list. So, ir learning does not work (and this forum wouldnt probably be the righgt place to ask).
But - i could use Vera to send a wifi command for the 2 commands which i cannot send via ir.
The question is, has anybody attempted this ? Theoretically it should be possible i think

You can invoke an http POST comand to the ROKU according to the following instructions:

On the Vera: http://wiki.micasaverde.com/index.php/Luup_Scenes_Events#Access_the_web

To the Roku: Roku

“Back” is specifically included as an available command (http://:8060/keypress/Back). I do not see the channel list as an option using this method (see section 3.3 of the latter URL).

Hi, thank you that sounds as if it will do what i want. Now i have never attempted to invoke http post commands, so my questions might be stupid…

So basically i create a scene, and in luup, i add the http://:8060/keypress/Back ? Where i replace ROKUIP with my Rokus ip. I looked at the micaseverde link you provided, but i do not understand it at all…

I think you have it right. I have not actually incorporated this into a Vera scene as yet.

In the Vera scene’s LUUP tab, as you suspect, I would add the following (with the assumption that my Roku is at …235):

[code]local http = require(“socket.http”)

– 5 Second timeout
http.TIMEOUT = 5

– The return parameters are in a different order from luup.inet.wget(…)
result, status = http.request(“http://192.168.0.235:8060/keypress/Back”, “run=run”)
[/code]

A little heads up, when testing this elsewhere, I found that not all of the commands that were supposed to work actually worked. “Back” was correctly responsive, however. Where I originally found this approach, the OP advised on setting the Roku into Developer mode first. I did not see any reason that would be necessary and did not do this myself, but it could explain why I did not get all commands responding correctly. Also, if you just try the above URL in a browser window, it won’t work; it must be by invoking http POST.

Ok now that makes it clearer for me. Just one question remaining (for now)

http.TIMEOUT = 5

do i have to set a value for that or is that being set somewhere already (as 5 seconds above that statement ?)

I see this elsewhere in all REST API commands and suspect that it is mandatory. I would not omit it as I expect it is required and is not being set elsewhere. Just its absence may be enough to throw an error. Hopefully one of the qualified developers will chime in on this.

Thank you i will give it a try tonight, i’ll leave everything as you suggested

It’s not mandatory from a LUA perspective.

It is mandatory from a Vera perspective. The default timeout might be more like 20s.
Things that take that long can cause Vera tor restart!

I am doing something wrong. I created a scene, and put the lua code in, with the ip of my Roku. But when i run the scene nothing happens

I’m pretty sure the string that the http.request() call gets should hold the full URL:

local  body, code, headers, status = http.request("http://192.168.0.21:8060/keypress/Back/?run=run")

You’ll find it’s easier (much faster) to test code using Apps>>Develop Apps>>Test Luup Code. There, you can enter your code, click OK and see if it works (or errors) without saving and waiting for Vera to reload.

The request you are making is a GET request.
If this device has a REST api … you must use a POST request to command the device.

You would need to do the following:
local body = “run=run”;
local url = “http://192.168.0.21:8060/keypress/Back
local rbody, code, headers, status = http.request(url, body);

Basically the body contains everything you would have placed after the ?

According to the Roku’s SDK documents (linked in my earlier post), these external commands are based on a RESTful service over port 8060. The only thing not covered in the Vera wiki that may be relevant is that the POST command is “C Escaped” and possibly that it is “URL encoded”. Here is how the REST command appears in another device in which this does work:

POST /keypress/Back HTTP/1.1
Host: 192.168.0.235:8060
Connection: Close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

The LUUP code that may need to convey “C Escaped” and “URL Encoded”.

This is probably total overkill but I confirmed it works (derived from here: http - lua socket POST - Stack Overflow):

[code]local http = require “socket.http”
local ltn12 = require “ltn12”
local util = require “util”
local timeout = 5
local body, code, headers, status = http.request {
method = “POST”,
url = “http://192.168.0.235:8060/keypress/Back”,
source = ltn12.source.string(reqbody),
headers =
{
[“Connection”] = “Close”,
[“Content-Type”] = “application/x-www-form-urlencoded”,
a },
sink = ltn12.sink.table(respbody)

}

[/code]

I kinda hacked the timeout into there based on Richard’s example. Not sure if the syntax is correct, but no error is generated.

Thanks for the help guys, i will have a play tonight… i must admit i do not understand the explanations, so for me its copy and paste see if it works… it will take me a while to understand what it actually does…

I cannot say i understood what i did… but copied and pasted your code, replaced the ip with my Roku’s ip, and it works ! So overkill or not, the important bit is it works. Now, when i have some spare time, i will have a close look and try to understand the code…

This code also works and the timeout syntax is more consistent with the example from the wiki (getting that part right may be a good idea based on Richard’s comment):

[code]local http = require “socket.http”
local ltn12 = require “ltn12”
local util = require “util”
http.timeout = 5
local body, code, headers, status = http.request {
method = “POST”,
url = “http://192.168.0.235:8060/keypress/Back”,
source = ltn12.source.string(reqbody),
headers =
{
[“Connection”] = “Close”,
[“Content-Type”] = “application/x-www-form-urlencoded”,
a },
sink = ltn12.sink.table(respbody)

}[/code]

There are lines in there that are almost certainly unneeded. Some may argue that it is worthwhile to whittle away the excess until you have code that does what you need without doing anything else.

Another possibly simpler method would be…

os.execute("curl -d '' http://192.168.0.235:8060/keypress/Back")