I am interested in this binding. I have 2 TCL Roku tv’s and 2 Roku streaming sticks.
I’d test it, if someone could post a jar file.
I am interested in this binding. I have 2 TCL Roku tv’s and 2 Roku streaming sticks.
I’d test it, if someone could post a jar file.
Same here. Where do I start?
I gave up on this binding and now I use EXEC and CURL for each command. The Roku external control API is very easy to follow. https://sdkdocs.roku.com/display/sdkdoc/External+Control+API#ExternalControlAPI-query/apps
I know this is not the best solution, but it is simple and works very well for me.
Here is sample of my Bedroom Roku .items list (note I use static IP’s for all my devices).
/*Master Bedroom */
Switch RokuMBHome "Roku MB Home" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/home]"}
Switch RokuMBUp "Roku MB UP" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/up]"}
Switch RokuMBDown "Roku MB DOWN" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/down]"}
Switch RokuMBLeft "Roku MB Left" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/left]"}
Switch RokuMBRight "Roku MB Right" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/right]"}
Switch RokuMBSelect "Roku MB Select" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/select]"}
Switch RokuMBReplay "Roku MB Replay" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/replay]"}
Switch RokuMBRewind "Roku MB Rewind" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/rewind]"}
Switch RokuMBFastFW "Roku MB FastFW" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/fastforward]"}
Switch RokuMBPlayPause "Roku MB PlayPause" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/play]"}
Switch RokuMBOptions "Roku MB Options" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/keypress/options]"}
Switch RokuMBNetflix "Roku MB Netflix" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/launch/12]"}
Switch RokuMBAmazon "Roku MB Amazon" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/launch/13]"}
Switch RokuMBVue "Roku MB PS Vue" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/launch/93374]"}
Switch RokuMBPlex "Roku MB Plex" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/launch/13535]"}
Switch RokuMBPandora "Roku MB Pandora" (gROKU_ALL,gROKU_MB) { exec=">[*:curl -d '' http://10.200.200.71:8060/launch/28]"}
I then have a widget created in Habpanel to simulate the remote and APP buttons.
For any automation, it can be done in the rules, here is an example of when the lights turn on, I pause the Roku
rule "MBLightPauseRokuON" when
Item MBLight changed from OFF to ON
then
executeCommandLine("curl -XPOST http://10.200.200.71:8060/keypress/play")
logInfo("Lights", "MB Light On, Roku paused")
end
Wow, that’s exactly what I’m looking for… however, I’ve added those lines to my .items file (edited to fit with my home setup and Roku IP address) and they show up as openHab items to link to in HabPanel, but when I press a button, nothing happens. I copied and pasted the curl statement for play/pause from the .things file into a terminal and the Roku responded. I just cannot get it to work from HabPanel on any of the other UIs. Do I need to install or configure any bindings or transforms? Any help gratefully received!
Thanks BK, I have that installed and still nothing happens… I’ve done a completely fresh install and still cannot get anything to happen when I press the switch associated to (e.g.) play. Will have to keep reading and searching.
Can you please share your habpanel widget?
It’s not pretty, and mostly hijacked from other people projects…I am sure someone on here can clean it up and make it better. I use as a widget or habpanel template
<style>
.glyphicon.glyphicon-chevron-left {
font-size: 40px;
}
.glyphicon.glyphicon-chevron-up {
font-size: 40px;
}
.glyphicon.glyphicon-chevron-right {
font-size: 40px;
}
.glyphicon.glyphicon-chevron-down {
font-size: 40px;
}
.glyphicon.glyphicon-chevron-left {
font-size: 40px;
}
.glyphicon.glyphicon-home {
font-size: 40px;
}
.glyphicon.glyphicon-ok {
font-size: 40px;
}
.glyphicon.glyphicon-certificate {
font-size: 40px;
}
.glyphicon.glyphicon-repeat {
font-size: 40px;
}
.glyphicon.glyphicon-backward {
font-size: 40px;
}
.glyphicon.glyphicon-play {
font-size: 40px;
}
.glyphicon.glyphicon-forward {
font-size: 40px;
}
.glyphicon.glyphicon-info-sign {
font-size: 40px;
}
left {
float: left;
width: auto;
padding: 10px;
}
center {
float: left;
width: auto;
padding: 10px;
}
right {
float: left;
width: auto;
padding: 10px;
}
rr {
float: left;
width: auto;
padding: 10px;
}
rrr {
float: left;
width: auto;
padding: 10px;
}
</style>
Living Room Roku
<section>
<left>
<div class="row" style="margin-top: 15px; margin-left: 0px; margin-right: 0px" ></div>
<div ng-if="itemValue('RokuMBRight').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBRight', 'ON')">
<span class="glyphicon glyphicon-info-sign"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBLeft').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBLeft', 'ON')">
<span class="glyphicon glyphicon-chevron-left"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBReplay').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBReplay', 'ON')">
<span class="glyphicon glyphicon-repeat"></span>
</button>
</div>
<br></br>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBRewind').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBRewind', 'ON')">
<span class="glyphicon glyphicon-backward"></span>
</button>
</div>
</left></section>
<section>
<center>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBUp').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBUp', 'ON')">
<span class="glyphicon glyphicon-chevron-up"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBSelect').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBSelect', 'ON')">
<span class="glyphicon glyphicon-ok"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBDown').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBDown', 'ON')">
<span class="glyphicon glyphicon-chevron-down"></span>
</button>
</div>
<br></br>
<div class="row" style="margin-top: 15px; margin-left: 0px; margin-right: 0px" ></div>
<div ng-if="itemValue('RokuMBPlay').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBPlay', 'ON')">
<span class="glyphicon glyphicon-play"></span>
</button>
</div>
</center></section>
<section>
<right>
<div class="row" style="margin-top: 15px; margin-left: 0px" ></div>
<div ng-if="itemValue('RokuMBHome').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBHome', 'ON')">
<span class="glyphicon glyphicon-home"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px; margin-right: 0px" ></div>
<div ng-if="itemValue('RokuMBRight').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBRight', 'ON')">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
</div>
<div class="row" style="margin-top: 15px; margin-left: 0px; margin-right: 0px" ></div>
<div ng-if="itemValue('RokuMBRight').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBRight', 'ON')">
<span class="glyphicon glyphicon-certificate"></span>
</button>
</div>
<br></br>
<div class="row" style="margin-top: 15px; margin-left: 0px; margin-right: 0px" ></div>
<div ng-if="itemValue('RokuMBFastFW').split(',')[2]!='0'">
<button class="btn btn-lg" style="background: purple; color: white"
ng-click="sendCmd('RokuMBFastFW', 'ON')">
<span class="glyphicon glyphicon-forward"></span>
</button>
</div>
</right></section>
For the other buttons I simply use a switch in habpanel and point the icon to Custom URL and grab it directly from Roku , for example Netflix is http://10.200.200.71:8060/query/icon/12
I am not sure what is wrong, it may help to set a rule when the switch is activated and add a log such as
rule "RokuMB Home"
when
Item RokuMBHome changed from ON to OFF or
Item RokuMBHome changed from OFF to ON
then
logInfo("Roku", "Roku Home pressed")
end
This will let you know that Openhab is seeing the command.
I also have the http binding installed, but not sure if that is required?
Thanks BK, but I’ve found that the only thing that works is to put very stripped-out items in the .items file
(e.g.)
Switch RokuPlayPause “Roku PlayPause”
then a corresponding rule in a .rules file
(e.g.)
rule “RokuPlay” when
Item RokuPlayPause changed
then
executeCommandLine(“curl -XPOST http://192.168.0.10:8060/keypress/play”)
end
and then it all seems to work OK.
Thanks also for posting your widget; just one thing, do you know how to make the “Play” button a toggle as once it sends “On” then Roku is paused and the actual button on the remote control is a toggle On/Off = Play/Pause??
Thanks again for your help; I only heard of openHAB on Monday so I’m on a very steep learning curve
I came across this post for a Roku binding. From the thread, it appears to be mostly done, maybe some final touches and testing needed. The author has opened it up for someone else to pick up. Maybe worth taking a look at?..
I’m definitely interested in a Roku binding. I just don’t do code…
@morph166955 I copied and pasted your code and it works great!
I had a little trouble getting the searchRokus.py script to run. First you have to make the file executable with
sudo chmod a + x /etc/openhab2/scripts/searchRokus.py
I still had trouble getting this to run, and discovered an EOL issue that I could fix in the edit menu of Notebook++. Once that was fixed, the script worked great.
I was able combine your example with the Habpanel in post #35 above by @bkyle.
Did you post the latest v3 code anywhere. I seem to be having trouble getting this to work. So far I had to update the roku.rules to point to where the python script was. (Yes Im testing all this out on a windows PC)
val String ssdp = executeCommandLine(“C:/openhab2/conf/scripts/searchRokus.py”, 20000)
However, I am still getting an error
19:53:00.002 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule ‘ROKU APPINFO’: 1
Any ideas?
Greetings all,
Using the OH3 Roku binding works for me. Is there an issue? What I wanted was a widget that would act as a remote. I created a crude one that works. Just wanted to know if anyone had something refined. I am using an image card to act as buttons, so I had to create various button icons. Does anyone have a nice clean widget? Or, would someone like to have a look at my widget? thanks!
Check these out for some examples:
Not sure if your still looking for one but im just about done a roku remote widget
Sorry on late reply. I have not Im willing to share what I have. That said it is not “serviceable” at the moment.
I have done a rough widget and rule that works with Telstra TV (roku).
Rule code:
configuration: {}
triggers:
- id: "1"
configuration:
itemName: rokuitem
type: core.ItemStateUpdateTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >-
//need below to log to openhab.log file
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
//below is if you are going to use the ececute command
var Exec = Java.type("org.openhab.core.model.script.actions.Exec");
//below is also needed for the execute command
var Duration = Java.type("java.time.Duration");
var HttpUtil = Java.type("org.openhab.core.io.net.http.HttpUtil");
var HttpGet = Java.type("org.openhab.core.model.script.actions.HTTP");
//below is the Telstra TV settings
var PORT = "8060"
var IP = "192.168.1.161"
var stateof = event.itemState.toString() ;
logger.info("results = " + stateof);
switch(stateof) {
case "KEY_POWER":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Home", 20000);
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/PowerOff", 20000);
logger.info('Play key pressed');
break;
case "KEY_PLAY":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Play", 20000);
logger.info('Play key pressed');
break;
case "KEY_PAUSE":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Play", 20000);
logger.info('Play key pressed');
break;
case "KEY_REWIND":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Rev", 20000);
logger.info('Play key pressed');
break;
case "KEY_FF":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Fwd", 20000);
logger.info('Play key pressed');
break;
case "KEY_UP":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Up", 20000);
logger.info('Play key pressed');
break;
case "KEY_LEFT":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Left", 20000);
logger.info('Play key pressed');
break;
case "KEY_ENTER":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Select", 20000);
logger.info('Play key pressed');
break;
case "KEY_RIGHT":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Right", 20000);
logger.info('Play key pressed');
break;
case "KEY_DOWN":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Down", 20000);
logger.info('Play key pressed');
break;
case "KEY_HOME":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Home", 20000);
logger.info('Play key pressed');
break;
case "KEY_RETURN":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/InstantReplay", 20000);
logger.info('Play key pressed');
break;
case "KEY_BACK":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/keypress/Back", 20000);
logger.info('Play key pressed');
break;
case "KEY_NETFLIX":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/launch/12", 20000);
logger.info('Play key pressed');
break;
case "KEY_AMAZON":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/launch/13", 20000);
logger.info('Play key pressed');
break;
case "KEY_SBS":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/launch/65507", 20000);
logger.info('SBS key pressed');
break;
case "KEY_IVIEW":
HttpUtil.executeUrl("POST","http://"+IP+":"+PORT+"/launch/73305", 20000);
logger.info('KEY_IVIEW key pressed');
break;
default:
logger.info('Nothing ran');
}
/*
curl "http://192.168.1.50:8060/query/apps"
<?xml version="1.0" encoding="UTF-8" ?>
<apps>
<app id="62034" type="appl" version="3.7.0">Telstra TV Box Office</app>
<app id="587447" type="appl" version="1.8.4">Binge Entertainment</app>
<app id="71361" type="appl" version="3.27.3321">Stan</app>
<app id="12" type="appl" version="4.2.98018037">Netflix</app>
<app id="262035" type="appl" version="1.17.134">Kayo Sports. Stream Live Sport</app>
<app id="13" type="appl" version="11.4.2020092816">Prime Video</app>
<app id="65509" type="appl" version="4.5.0">7plus</app>
<app id="65575" type="appl" version="3.8.116">9Now</app>
<app id="74349" type="appl" version="5.1.2">10 play</app>
<app id="73305" type="appl" version="5.0.3">ABC iview</app>
<app id="65507" type="appl" version="2.5.226">SBS On Demand</app>
<app id="837" type="appl" version="1.0.80000314">YouTube</app>
</apps>
*/
type: script.ScriptAction
Widget code:
uid: Remote roku
tags: []
props:
parameters:
- context: item
description: Select the remote you wish to use at an equipment item level
label: Select Equipment
name: item
required: true
type: TEXT
parameterGroups: []
timestamp: Jul 3, 2021, 4:54:59 PM
component: f7-block
config:
style:
box-shadow: 2px 3px rgb(150,150,150)
background-color: rgb(192, 192, 192)
--f7-card-margin-horizontal: 0px
border-radius: 30px
width: 15rem
height: 40rem
slots:
default:
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 65px
top: 20px
width: 110px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 28px
left: 108px
color: red
iconF7: power
iconSize: 25
action: command
actionCommand: KEY_POWER
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 90px
top: 110px
width: 60px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 116px
left: 95px
color: white
iconF7: play
iconSize: 25
action: command
actionCommand: KEY_PLAY
actionItem: =props.item
- component: oh-link
config:
style:
position: absolute
top: 116px
left: 117px
color: white
iconF7: pause
iconSize: 25
action: command
actionCommand: KEY_PAUSE
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 20px
top: 110px
width: 60px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 117px
left: 35px
color: white
iconF7: backward
iconSize: 25
action: command
actionCommand: KEY_REWIND
actionItem: =props.item
- component: oh-link
config:
style:
position: absolute
top: 117px
right: 35px
color: white
iconF7: forward
iconSize: 25
action: command
actionCommand: KEY_FF
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
right: 20px
top: 110px
width: 60px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 197px
left: 103px
color: white
z-index: 2
iconF7: arrowtriangle_up
iconSize: 35
action: command
actionCommand: KEY_UP
actionItem: =props.item
- component: oh-link
config:
style:
position: absolute
top: 263px
left: 35px
color: white
z-index: 2
iconF7: arrowtriangle_left
iconSize: 35
action: command
actionCommand: KEY_LEFT
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 80px
top: 242px
width: 80px
height: 80px
border-radius: 50%
border: gray solid 1px
z-index: 2
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 30px
top: 190px
width: 180px
height: 180px
border-radius: 50%
z-index: 1
- component: oh-link
config:
text: OK
style:
font-size: 25px
position: absolute
top: 261px
left: 103px
color: white
z-index: 3
iconSize: 75
action: command
actionCommand: KEY_ENTER
actionItem: =props.item
- component: oh-link
config:
style:
position: absolute
top: 263px
right: 35px
color: white
iconF7: arrowtriangle_right
iconSize: 35
action: command
actionCommand: KEY_RIGHT
actionItem: =props.item
- component: oh-link
config:
style:
position: absolute
top: 330px
left: 103px
color: white
iconF7: arrowtriangle_down
iconSize: 35
action: command
actionCommand: KEY_DOWN
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 80px
top: 385px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 392px
left: 108px
color: white
iconF7: house
iconSize: 25
action: command
actionCommand: KEY_HOME
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 20px
top: 440px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 446px
left: 45px
color: white
iconF7: arrow_left
iconSize: 25
action: command
actionCommand: KEY_BACK
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
right: 20px
top: 440px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 447px
right: 45px
color: white
iconF7: arrow_counterclockwise
iconSize: 25
action: command
actionCommand: KEY_RETURN
actionItem: =props.item
- component: f7-badge
config:
bgColor: black
style:
position: absolute
right: 20px
top: 495px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 505px
right: 35px
color: white
iconSize: 25
action: command
actionCommand: KEY_AMAZON
actionItem: =props.item
text: Amazon
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 20px
top: 495px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 505px
left: 35px
color: white
iconSize: 25
action: command
actionCommand: KEY_NETFLIX
actionItem: =props.item
text: Netflix
- component: f7-badge
config:
bgColor: black
style:
position: absolute
left: 20px
top: 545px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 555px
left: 35px
color: white
iconSize: 25
action: command
actionCommand: KEY_SBS
actionItem: =props.item
text: SBS
- component: f7-badge
config:
bgColor: black
style:
position: absolute
right: 20px
top: 545px
width: 80px
height: 40px
border-radius: 12px
- component: oh-link
config:
style:
position: absolute
top: 555px
right: 35px
color: white
iconSize: 25
action: command
actionCommand: KEY_IVIEW
actionItem: =props.item
text: iVeiw
- component: oh-link
config:
color: red
style:
font-size: 25px
position: absolute
left: 25px
top: 600px
width: 200px
height: 40px
display: flex
text: Telstra TV
It is a bit rough but works.
Just create a string item called rokuitem and it should work.
Also set your IP address as static so it stays the same as that is hard coded into the rule.
No warranty.