The Vera Community forums have moved!

General => Remote Control => SQ Remote / Square Connect (iOS) => Topic started by: mikee123 on January 03, 2014, 11:25:26 am

Title: Roku 3 control question
Post by: mikee123 on January 03, 2014, 11:25:26 am
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
Title: Re: Roku 3 control question
Post by: Ds514 on January 26, 2014, 12:51:44 pm
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: http://sdkdocs.roku.com/display/sdkdoc/External+Control+Guide

"Back" is specifically included as an available command (http://<ROKUIP>:8060/keypress/Back). I do not see the channel list as an option using this method (see section 3.3 of the latter URL).
Title: Re: Roku 3 control question
Post by: mikee123 on January 26, 2014, 02:11:27 pm
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://<ROKUIP>: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...
Title: Re: Roku 3 control question
Post by: Ds514 on January 26, 2014, 03:05:05 pm
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: [Select]
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")

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.
Title: Re: Roku 3 control question
Post by: mikee123 on January 26, 2014, 05:41:07 pm
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 ?)
Title: Re: Roku 3 control question
Post by: Ds514 on January 26, 2014, 06:11:50 pm
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.
Title: Re: Roku 3 control question
Post by: mikee123 on January 27, 2014, 04:05:18 am
Thank you i will give it a try tonight, i'll leave everything as you suggested
Title: Re: Roku 3 control question
Post by: RichardTSchaefer on January 27, 2014, 07:46:22 am
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!
Title: Re: Roku 3 control question
Post by: mikee123 on January 27, 2014, 03:30:41 pm
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

Title: Re: Roku 3 control question
Post by: ih8gates on January 27, 2014, 06:11:45 pm
I'm pretty sure the string that the http.request() call gets should hold the full URL:

Code: [Select]
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.
Title: Re: Roku 3 control question
Post by: RichardTSchaefer on January 27, 2014, 06:31:21 pm
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 ?
Title: Re: Roku 3 control question
Post by: Ds514 on January 27, 2014, 07:08:46 pm
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".

Title: Re: Roku 3 control question
Post by: Ds514 on January 27, 2014, 07:53:42 pm
This is probably total overkill but I confirmed it works (derived from here: http://stackoverflow.com/questions/17372330/lua-socket-post):

Code: [Select]
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)

    }

I kinda hacked the timeout into there based on Richard's example. Not sure if the syntax is correct, but no error is generated.
Title: Re: Roku 3 control question
Post by: mikee123 on January 28, 2014, 04:18:19 am
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...
Title: Re: Roku 3 control question
Post by: mikee123 on January 28, 2014, 03:04:18 pm
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...
Title: Re: Roku 3 control question
Post by: Ds514 on January 30, 2014, 09:29:35 am
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: [Select]
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)

    }

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.
Title: Re: Roku 3 control question
Post by: blakem on December 31, 2015, 09:15:13 pm
Another possibly simpler method would be...
Code: [Select]
os.execute("curl -d '' http://192.168.0.235:8060/keypress/Back")