# Roku Binding

This binding connects Roku streaming media players and Roku TVs to openHAB.
The Roku device must support the Roku ECP protocol REST API.

In order for the binding to control the Roku, the following setting:
**Settings-> System-> Advanced system settings-> Control by mobile apps**
must be configured as `Enabled` or `Permissive`.

## Supported Things

There are two supported Thing types, which represent either a standalone Roku device or a Roku TV.
A supported Roku streaming media player or streaming stick uses the `roku_player` id and a supported Roku TV uses the `roku_tv` id.
The Roku TV type adds additional channels and button commands to the button channel dropdown for TV specific functionality.
Multiple Things can be added if more than one Roku device is to be controlled.

## Discovery

Auto-discovery is supported if the Roku device can be located on the local network using UPnP.
Otherwise the Thing must be manually added.

## Binding Configuration

The binding has no configuration options, all configuration is done at Thing level.

## Thing Configuration

The Thing has a few configuration parameters:

| Parameter | Description                                                                                                              |
|-----------|--------------------------------------------------------------------------------------------------------------------------|
| hostName  | The host name or IP address of the Roku device. Mandatory.                                                               |
| port      | The port on the Roku device that listens for http connections. Default 8060.                                             |
| refresh   | Overrides the refresh interval for player status updates. Optional, the default is 10 seconds and minimum is 1 second.   |

## Channels

The following channels are available:

| Channel ID         | Item Type            | Description                                                                                                                                                     |
|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| activeApp          | String               | A dropdown containing a list of all apps installed on the Roku. The app currently running is automatically selected. The list updates every 10 minutes.         |
| activeAppName      | String               | The name of the current app (Read-only).                                                                                                                        |
| button             | String               | Sends a remote control command the Roku. See list of available commands below. (Write-only)                                                                     |
| control            | Player               | Control Playback e.g. play/pause/next/previous                                                                                                                  |
| playMode           | String               | The current playback mode e.g. stop, play, pause (Read-only).                                                                                                   |
| timeElapsed        | Number:Time          | The total number of seconds of playback time elapsed for the current playing title (Read-only).                                                                 |
| timeTotal          | Number:Time          | The total length of the current playing title in seconds (Read-only). This data is not provided by all streaming apps.                                          |
| endTime            | DateTime             | The date/time when the currently playing media will end (Read-only). N/A if timeTotal is not provided by the current streaming app.                             |
| progress           | Dimmer               | The current progress [0-100%] of playing media (Read-only). N/A if timeTotal is not provided by the current streaming app.                                      |
| power              | Switch               | Controls the power for a Roku TV Thing only.                                                                                                                    |
| powerState         | String               | The current power state for the Roku TV Thing. (Read-only - e.g. PowerOn, DisplayOff, Ready, Offline)                                                           |
| activeChannel      | String               | A dropdown containing a list of available TV channels on the Roku TV. The channel currently tuned is automatically selected. The list updates every 10 minutes. |
| signalMode         | String               | The signal type of the current TV channel, e.g. 1080i (Read-only).                                                                                              |
| signalQuality      | Number:Dimensionless | The signal quality of the current TV channel, 0-100% (Read-only).                                                                                               |
| channelName        | String               | The name of the channel currently selected (Read-only).                                                                                                         |
| programTitle       | String               | The name of the current TV program (Read-only).                                                                                                                 |
| programDescription | String               | The description of the current TV program (Read-only).                                                                                                          |
| programRating      | String               | The TV parental guideline rating of the current TV program (Read-only).                                                                                         |

Some Notes:

- The values for `activeApp`, `activeAppName`, `playMode`, `timeElapsed`, `timeTotal`, `activeChannel`, `signalMode`, `signalQuality`, `channelName`, `programTitle`, `programDescription`, `programRating`, `power` & `powerState` refresh automatically per the configured `refresh` interval.
- The `endTime` and `progress` channels may not be accurate for some streaming apps especially 'live' streams where the `timeTotal` value constantly increases.
- After being switched off for 10 minutes, a Roku TV will shut down its network interface causing the Thing to go OFFLINE.
- If the following setting: **Settings-> System-> Power-> Fast TV Start** is set to `On`, then the Roku TV Thing will always stay ONLINE even when the TV is switched off.

**List of available button commands for Roku streaming devices:**

- Home
- Rev
- Fwd
- Play
- Select
- Left
- Right
- Up
- Down
- Back
- InstantReplay
- Info
- Backspace
- Search
- Enter
- FindRemote

**List of additional button commands for Roku TVs:**

- ChannelUp
- ChannelDown
- VolumeUp
- VolumeDown
- VolumeMute
- InputTuner
- InputHDMI1
- InputHDMI2
- InputHDMI3
- InputHDMI4
- InputAV1
- PowerOff
- POWERON _(NOTE: POWERON needs to be completely capitalized due to a bug with older Roku devices)_

**Sending characters via button commands:**

- Printable ASCII characters that are URL-safe can be transmitted without encoding using the "Lit_" prefix (e.g., "Lit_R" for the letter R).
- Characters that are not URL-safe (including spaces, reserved URL characters, and non-ASCII characters) should be URL-encoded (e.g., "Lit_%20" for a space and "Lit_%E2%82%AC" for the euro symbol).

## Full Example

### `roku.things` Example

```java
// Roku streaming media player
roku:roku_player:myplayer1 "My Roku" [ hostName="192.168.10.1", refresh=10 ]

// Roku TV
roku:roku_tv:mytv1 "My Roku TV" [ hostName="192.168.10.1", refresh=10 ]

```

### `roku.items` Example

```java
// Roku streaming media player items:

String Player_ActiveApp        "Current App [%s]"              { channel="roku:roku_player:myplayer1:activeApp" }
String Player_ActiveAppName    "Current App Name [%s]"         { channel="roku:roku_player:myplayer1:activeAppName" }
String Player_Button           "Send Command to Roku"          { channel="roku:roku_player:myplayer1:button" }
Player Player_Control          "Control"                       { channel="roku:roku_player:myplayer1:control" }
String Player_PlayMode         "Status [%s]"                   { channel="roku:roku_player:myplayer1:playMode" }
Number:Time Player_TimeElapsed "Elapsed Time [%s]"             { channel="roku:roku_player:myplayer1:timeElapsed" }
Number:Time Player_TimeTotal   "Total Time [%s]"               { channel="roku:roku_player:myplayer1:timeTotal" }
DateTime Player_EndTime        "End Time [%s]"                 { channel="roku:roku_player:myplayer1:endTime" }
Dimmer Player_Progress         "Progress [%.0f%%]"             { channel="roku:roku_player:myplayer1:progress" }

// Roku TV items:

Switch Tv_Power                "Power [%s]"                    { channel="roku:roku_tv:mytv1:power" }
String Tv_PowerState           "Power State [%s]"              { channel="roku:roku_tv:mytv1:powerState" }
String Player_ActiveApp        "Current App [%s]"              { channel="roku:roku_tv:mytv1:activeApp" }
String Player_ActiveAppName    "Current App Name [%s]"         { channel="roku:roku_tv:mytv1:activeAppName" }
String Player_Button           "Send Command to Roku"          { channel="roku:roku_tv:mytv1:button" }
Player Player_Control          "Control"                       { channel="roku:roku_tv:mytv1:control" }
String Player_PlayMode         "Status [%s]"                   { channel="roku:roku_tv:mytv1:playMode" }
Number:Time Player_TimeElapsed "Elapsed Time [%s]"             { channel="roku:roku_tv:mytv1:timeElapsed" }
Number:Time Player_TimeTotal   "Total Time [%s]"               { channel="roku:roku_tv:mytv1:timeTotal" }
DateTime Player_EndTime        "End Time [%s]"                 { channel="roku:roku_tv:mytv1:endTime" }
Dimmer Player_Progress         "Progress [%.0f%%]"             { channel="roku:roku_tv:mytv1:progress" }
String Tv_ActiveChannel        "Current Channel [%s]"          { channel="roku:roku_tv:mytv1:activeChannel" }
String Tv_SignalMode           "Signal Mode [%s]"              { channel="roku:roku_tv:mytv1:signalMode" }
Number Tv_SignalQuality        "Signal Quality [%d %%]"        { channel="roku:roku_tv:mytv1:signalQuality" }
String Tv_ChannelName          "Channel Name [%s]"             { channel="roku:roku_tv:mytv1:channelName" }
String Tv_ProgramTitle         "Program Title [%s]"            { channel="roku:roku_tv:mytv1:programTitle" }
String Tv_ProgramDescription   "Program Description [%s]"      { channel="roku:roku_tv:mytv1:programDescription" }
String Tv_ProgramRating        "Program Rating [%s]"           { channel="roku:roku_tv:mytv1:programRating" }

// A virtual switch used to trigger a rule to start a given app
Switch Player_StartYouTube     "Start YouTube"
```

### `roku.sitemap` Example

```perl
sitemap roku label="Roku" {
    Frame label="My Roku" {
        Selection item=Player_ActiveApp icon="screen"
        Text item=Player_ActiveAppName
        // This Selection is deprecated in favor of the Buttongrid element below
        Selection item=Player_Button icon="screen"
        Default item=Player_Control
        Text item=Player_PlayMode
        Text item=Player_TimeElapsed icon="time"
        Text item=Player_TimeTotal icon="time"
        Text item=Player_EndTime icon="time"
        Slider item=Player_Progress icon="time"
        // The following items apply to Roku TVs only
        Switch item=Tv_Power
        Text item=Tv_PowerState
        Selection item=Tv_ActiveChannel icon="screen"
        Text item=Tv_SignalMode
        Text item=Tv_SignalQuality
        Text item=Tv_ChannelName
        Text item=Tv_ProgramTitle
        Text item=Tv_ProgramDescription
        Text item=Tv_ProgramRating

        // Virtual switch/button to trigger a rule to start a given app
        // The ON value displays as the button label
        Switch item=Player_StartYouTube mappings=[ON="YouTube"]

        // Buttongrid for Roku player
        Buttongrid label="Remote Control" staticIcon=material:tv_remote item=Player_Button buttons=[1:1:Back="Back", 1:2:Home="Home"=f7:house, 1:3:Search="Search", 2:2:Up="Up"=f7:arrowtriangle_up, 4:2:Down="Down"=f7:arrowtriangle_down, 3:1:Left="Left"=f7:arrowtriangle_left, 3:3:Right="Right"=f7:arrowtriangle_right, 3:2:Select="Select", 5:1:InstantReplay="Instant Replay", 5:2:Info="Info*", 6:1:Rev="Reverse"=f7:backward, 6:2:Play="Play/Pause"=f7:playpause, 6:3:Fwd="Forward"=f7:forward, 7:1:Enter="Enter", 7:2:Backspace="Backspace", 7:3:FindRemote="Find Remote"]

        // Buttongrid for Roku TV
        Buttongrid label="Remote Control" staticIcon=material:tv_remote item=Player_Button buttons=[1:1:POWERON="Power On"=switch-on, 1:2:PowerOff="Power Off"=switch-off, 1:3:InputTuner="Tuner", 1:4:InputAV1="AV 1", 2:1:InputHDMI1="HDMI 1", 2:2:InputHDMI2="HDMI 2", 2:3:InputHDMI3="HDMI 3", 2:4:InputHDMI4="HDMI 4", 3:1:Back="Back", 3:2:Home="Home"=f7:house, 3:3:Search="Search", 4:2:Up="Up"=f7:arrowtriangle_up, 6:2:Down="Down"=f7:arrowtriangle_down, 5:1:Left="Left"=f7:arrowtriangle_left, 5:3:Right="Right"=f7:arrowtriangle_right, 5:2:Select="Select", 7:1:InstantReplay="Instant Replay", 7:2:Info="Info*", 8:1:Rev="Reverse"=f7:backward, 8:2:Play="Play/Pause"=f7:playpause, 8:3:Fwd="Forward"=f7:forward, 9:1:Enter="Enter", 9:2:Backspace="Backspace", 9:3:FindRemote="Find Remote", 4:4:ChannelUp="Channel +", 5:4:ChannelDown="Channel -", 7:4:VolumeUp="Volume +", 8:4:VolumeMute="Mute"=soundvolume_mute, 9:4:VolumeDown="Volume -"]
    }
}
```

### `roku.rules` Example

```java
rule "Start the YouTube app on Roku"
when
  Item Player_StartYouTube received command
then
  // Find the list of all installed apps and their IDs at http://$ROKU_IP:8060/query/apps
  Player_ActiveApp.sendCommand("837")

  // It is also possible to launch specific content within an app via deep-linking.
  // See here for more details:
  // https://virtu.is/frozen-buttons-launching-disney-movies-on-roku-with-automator/

  // Command to start 'Frozen' on Disney+:
  // Player_ActiveApp.sendCommand("291097?MediaType=movie&ContentID=8e06a8b7-d667-4e31-939d-f40a6dd78a88")

  // Command to start 'Me at the zoo' on YouTube:
  // Player_ActiveApp.sendCommand("837?contentId=jNQXAC9IVRw")
end
```
