Clearly I need a REST
Jeff Lockyear
Junior Member
As an Accidental Programmer I sometimes run across a problem that requires knowledge, rather than brute force, and I think this is one of those times.
I have one of the little Roku media streamers, which has external control support (found here):
http://sdkdocs.roku.com/display/sdkdoc/External+Control+Guide
I can establish a connection with my master on the correct port, but I just can't get my commands acted upon. I've tried various iterations of what's in the examples, but it seems (for example) a Home button emulation should be sent as (after a successful connection) POST /keypress/Home
At least I think so. If anyone can offer an educated opinion as to how the string needs to actually be formatted I'd appreciate it. All the online help examples involve various.cryptic.libraries that I don't have the depth to understand.
I have one of the little Roku media streamers, which has external control support (found here):
http://sdkdocs.roku.com/display/sdkdoc/External+Control+Guide
I can establish a connection with my master on the correct port, but I just can't get my commands acted upon. I've tried various iterations of what's in the examples, but it seems (for example) a Home button emulation should be sent as (after a successful connection) POST /keypress/Home
At least I think so. If anyone can offer an educated opinion as to how the string needs to actually be formatted I'd appreciate it. All the online help examples involve various.cryptic.libraries that I don't have the depth to understand.
Comments
-
Jeff,
Can you post the code with your string build too? Might help.
E -
Sure! Through the course of testing and head beating I've ended up reducing it to the super simple:
DEFINE_DEVICE dvRoku = 0:3:0 vdvRoku = 33001:1:0 DEFINE_EVENT DATA_EVENT [dvRoku] { ONLINE: SEND_STRING dvRoku, 'POST /keypress/Home' // 'POST /keypress/Home HTTP/1.1' } CHANNEL_EVENT [vdvRoku,1] { ON: IP_CLIENT_OPEN (dvRoku.Port,'192.168.1.20',8060,1) }
Thanks! I have the Roku up on the TV and I'm not on the Home screen, so I would know if this command worked. -
Here's a snippet of how an HTTP header should be formed. This particular example is from my BoxeeBox control module which uses the same RESTful scheme (though different commands)
DEFINE_FUNCTION AddHTTPGet(CHAR cShortURI[]) { //---Add an HTTP GET request to BBox.Comm.cQue //---To be instantiated by SendQue above STACK_VAR CHAR cURLString[512] STACK_VAR CHAR cHeader[512] cURLString = "'/',cShortURI" DebugString(4,"'Add to Que: HTTP://',BBox.Comm.cIPAddress,cURLString") cHeader = "'GET ',cURLString,' HTTP/1.1',$0D,$0A" cHeader = "cHeader,'Host: ',BBox.Comm.cIPAddress,$0D,$0A" cHeader = "cHeader,'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64,rv:13.0) Gecko/20100101 Firefox/13.0.1',$0D,$0A" cHeader = "cHeader,'Accept: text/html,application/xhtml+xml,application/xml;q=0.9*/*;q=0.8',$0D,$0A" cHeader = "cHeader,'Accept-Language: en-us;q=0.5',$0D,$0A" cHeader = "cHeader,'Accept-Encoding: gzip,deflate',$0D,$0A" cHeader = "cHeader,'Connection: keep-alive',$0D,$0A,$0D,$0A" BBox.Comm.cQue = "BBox.Comm.cQue,cHeader,$0B,$0B" DebugString(3,"'AddHTTPGet : ',cShortURI") }
You can find the entire module here: https://github.com/nickmil/BoxeeBox
As you can see, there is a lot of information required of an HTTP header. A tool that will come in quite handy as you play more with RESTful APIs is the POSTman REST client. It's a Chrome app that breaks down everything that happens in a REST request and response. -
Yup, that looks quite different to what I have.
-
The equivalent here would be your '/keypress/home' string.
-
nickm,
I replaced your GET with POST in the function and gave it a try with my Home command and it worked, thanks. I guess the Roku document assumes a level of http/REST knowledge that I don't have.
Cheers! -
If you want a quick and painless intro to REST there's a great 15 minute talk on the Google Developers channel.
-
Ah, cool, I'll check that out. Thanks!
-
You don't necessarily need all that header information ... especially the "CONNECTION: keep_alive field." In fact, that one might even be hurting you by forcing the connection to stay open after it's finished. I was stunned how much more responsive a weather module worked when I replaced that with "CONNECTION: close." What I do on all my HTTP mods is to start with a full-blown header, then take stuff out one at a time until it breaks. Then I know I have it reduced to what is really needed to make it work.
-
DHawthorne wrote: »You don't necessarily need all that header information ...
Agreed. There is a lot of header information that typically isn't needed in the scope of devices/services we are communicating with. -
Here's an example of what I would observe in WireShark between my PC and a particular device:
SEND_STRING dvJSON,"'POST /jsonrpc.js HTTP/1.1',STR_CRLF"; SEND_STRING dvJSON,"'Host: ',sJSON.sPlayer.cIP,':',itoa(sJSON.sPlayer.nPort),STR_CRLF"; SEND_STRING dvJSON,"'User-Agent: Netlinx',STR_CRLF"; //SEND_STRING dvJSON,"'User-Agent: User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0',STR_CRLF"; SEND_STRING dvJSON,"'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',STR_CRLF"; SEND_STRING dvJSON,"'Accept-Language: en-us',STR_CRLF"; SEND_STRING dvJSON,"'Accept-Encoding: gzip, deflate',STR_CRLF"; SEND_STRING dvJSON,"'X-Requested-With: XMLHttpRequest',STR_CRLF"; SEND_STRING dvJSON,"'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',STR_CRLF"; SEND_STRING dvJSON,"'Referer: http://',sJSON.sPlayer.cIP,':',itoa(sJSON.sPlayer.nPort),'/',STR_CRLF"; SEND_STRING dvJSON,"'Content-Length: ',itoa(length_string(sJSON.sPlayer.cFullCmd)),STR_CRLF"; SEND_STRING dvJSON,"'Cookie: Squeezebox-player=',fnEncodeURL(sJSON.sPlayer.cStrMAC),'; Squeezebox-expandPlayerControl=false; ', 'Squeezebox-expanded-MY_MUSIC=1; Squeezebox-expanded-RADIO=0; Squeezebox-expanded-PLUGIN_MY_APPS_MODULE_NAME=1; ', 'Squeezebox-expanded-FAVORITES=0; Squeezebox-expanded-PLUGINS=0; Squeezebox-playersettings=null; ', 'Squeezebox-advancedsettings=settings/server/debugging.html%3F; Squeezebox-expanded-updatePlugins=1; ', 'Squeezebox-expanded-activePlugins=1; Squeezebox-expanded-inactivePlugins=1; Squeezebox-expanded-otherPlugins0=1; ', 'Squeezebox-expanded-otherPlugins1=1; __utma=124789194.27251913.1391382619.1391382619.1391382619.1; ', '__utmz=124789194.1391382619.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)',STR_CRLF"; SEND_STRING dvJSON,"'Connection: keep-alive',STR_CRLF"; SEND_STRING dvJSON,"'Pragma: no-cache',STR_CRLF"; SEND_STRING dvJSON,"'Cache-Control: no-cache',STR_CRLF"; SEND_STRING dvJSON,"STR_CRLF"; SEND_STRING dvJSON,"sJSON.sPlayer.cFullCmd,STR_CRLF";
and then as Dave mentioned I would get it working using everything that I observed being used and then comment out a line or more at a time and test. In the end all I ended up needing was:SEND_STRING dvJSON,"'POST /jsonrpc.js HTTP/1.1',STR_CRLF"; SEND_STRING dvJSON,"'Host: ',sJSON.sPlayer.cIP,':',itoa(sJSON.sPlayer.nPort),STR_CRLF"; SEND_STRING dvJSON,"'Referer: http://',sJSON.sPlayer.cIP,':',itoa(sJSON.sPlayer.nPort),'/',STR_CRLF"; SEND_STRING dvJSON,"'Content-Length: ',itoa(length_string(sJSON.sPlayer.cFullCmd)),STR_CRLF"; SEND_STRING dvJSON,"STR_CRLF"; SEND_STRING dvJSON,"sJSON.sPlayer.cFullCmd,STR_CRLF";
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums
