Skip to content

Commit f6efa87

Browse files
authored
[roku] Add End Time and Media Progress channels (openhab#18059)
Signed-off-by: Michael Lobstein <[email protected]>
1 parent 98ff656 commit f6efa87

File tree

6 files changed

+105
-33
lines changed

6 files changed

+105
-33
lines changed

bundles/org.openhab.binding.roku/README.md

+32-23
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ The following channels are available:
4646
| playMode | String | The current playback mode ie: stop, play, pause (ReadOnly). |
4747
| timeElapsed | Number:Time | The total number of seconds of playback time elapsed for the current playing title (ReadOnly). |
4848
| timeTotal | Number:Time | The total length of the current playing title in seconds (ReadOnly). This data is not provided by all streaming apps. |
49+
| endTime | DateTime | The date/time when the currently playing media will end (ReadOnly). N/A if timeTotal is not provided by the current streaming app. |
50+
| progress | Dimmer | The current progress [0-100%] of playing media (ReadOnly). N/A if timeTotal is not provided by the current streaming app. |
4951
| 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. |
5052
| signalMode | String | The signal type of the current TV channel, ie: 1080i (ReadOnly). |
5153
| signalQuality | Number:Dimensionless | The signal quality of the current TV channel, 0-100% (ReadOnly). |
@@ -59,6 +61,7 @@ The following channels are available:
5961
Some Notes:
6062

6163
- The values for `activeApp`, `activeAppName`, `playMode`, `timeElapsed`, `timeTotal`, `activeChannel`, `signalMode`, `signalQuality`, `channelName`, `programTitle`, `programDescription`, `programRating`, `power` & `powerState` refresh automatically per the configured `refresh` interval.
64+
- The `endTime` and `progress` channels may not be accurate for some streaming apps especially 'live' streams where the `timeTotal` value constantly increases.
6265

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

@@ -113,32 +116,36 @@ roku:roku_tv:mytv1 "My Roku TV" [ hostName="192.168.10.1", refresh=10 ]
113116
```java
114117
// Roku streaming media player items:
115118

116-
String Player_ActiveApp "Current App: [%s]" { channel="roku:roku_player:myplayer1:activeApp" }
117-
String Player_ActiveAppName "Current App Name: [%s]" { channel="roku:roku_player:myplayer1:activeAppName" }
118-
String Player_Button "Send Command to Roku" { channel="roku:roku_player:myplayer1:button" }
119-
Player Player_Control "Control" { channel="roku:roku_player:myplayer1:control" }
120-
String Player_PlayMode "Status: [%s]" { channel="roku:roku_player:myplayer1:playMode" }
121-
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeElapsed" }
122-
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeTotal" }
119+
String Player_ActiveApp "Current App: [%s]" { channel="roku:roku_player:myplayer1:activeApp" }
120+
String Player_ActiveAppName "Current App Name: [%s]" { channel="roku:roku_player:myplayer1:activeAppName" }
121+
String Player_Button "Send Command to Roku" { channel="roku:roku_player:myplayer1:button" }
122+
Player Player_Control "Control" { channel="roku:roku_player:myplayer1:control" }
123+
String Player_PlayMode "Status: [%s]" { channel="roku:roku_player:myplayer1:playMode" }
124+
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeElapsed" }
125+
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeTotal" }
126+
DateTime Player_EndTime "End Time: [%1$tl:%1$tM %1$tp]" { channel="roku:roku_player:myplayer1:endTime" }
127+
Dimmer Player_Progress "Progress [%.0f%%]" { channel="roku:roku_player:myplayer1:progress" }
123128

124129
// Roku TV items:
125130

126-
Switch Player_Power "Power: [%s]" { channel="roku:roku_tv:mytv1:power" }
127-
String Player_PowerState "Power State: [%s] { channel="roku:roku_tv:mytv1:powerState" }
128-
String Player_ActiveApp "Current App: [%s]" { channel="roku:roku_tv:mytv1:activeApp" }
129-
String Player_ActiveAppName "Current App Name: [%s]" { channel="roku:roku_tv:mytv1:activeAppName" }
130-
String Player_Button "Send Command to Roku" { channel="roku:roku_tv:mytv1:button" }
131-
Player Player_Control "Control" { channel="roku:roku_tv:mytv1:control" }
132-
String Player_PlayMode "Status: [%s]" { channel="roku:roku_tv:mytv1:playMode" }
133-
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeElapsed" }
134-
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeTotal" }
135-
String Player_ActiveChannel "Current Channel: [%s]" { channel="roku:roku_tv:mytv1:activeChannel" }
136-
String Player_SignalMode "Signal Mode: [%s]" { channel="roku:roku_tv:mytv1:signalMode" }
137-
Number Player_SignalQuality "Signal Quality: [%d %%]" { channel="roku:roku_tv:mytv1:signalQuality" }
138-
String Player_ChannelName "Channel Name: [%s]" { channel="roku:roku_tv:mytv1:channelName" }
139-
String Player_ProgramTitle "Program Title: [%s]" { channel="roku:roku_tv:mytv1:programTitle" }
140-
String Player_ProgramDescription "Program Description: [%s]" { channel="roku:roku_tv:mytv1:programDescription" }
141-
String Player_ProgramRating "Program Rating: [%s]" { channel="roku:roku_tv:mytv1:programRating" }
131+
Switch Player_Power "Power: [%s]" { channel="roku:roku_tv:mytv1:power" }
132+
String Player_PowerState "Power State: [%s] { channel="roku:roku_tv:mytv1:powerState" }
133+
String Player_ActiveApp "Current App: [%s]" { channel="roku:roku_tv:mytv1:activeApp" }
134+
String Player_ActiveAppName "Current App Name: [%s]" { channel="roku:roku_tv:mytv1:activeAppName" }
135+
String Player_Button "Send Command to Roku" { channel="roku:roku_tv:mytv1:button" }
136+
Player Player_Control "Control" { channel="roku:roku_tv:mytv1:control" }
137+
String Player_PlayMode "Status: [%s]" { channel="roku:roku_tv:mytv1:playMode" }
138+
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeElapsed" }
139+
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeTotal" }
140+
DateTime Player_EndTime "End Time: [%1$tl:%1$tM %1$tp]" { channel="roku:roku_tv:mytv1:endTime" }
141+
Dimmer Player_Progress "Progress [%.0f%%]" { channel="roku:roku_tv:mytv1:progress" }
142+
String Player_ActiveChannel "Current Channel: [%s]" { channel="roku:roku_tv:mytv1:activeChannel" }
143+
String Player_SignalMode "Signal Mode: [%s]" { channel="roku:roku_tv:mytv1:signalMode" }
144+
Number Player_SignalQuality "Signal Quality: [%d %%]" { channel="roku:roku_tv:mytv1:signalQuality" }
145+
String Player_ChannelName "Channel Name: [%s]" { channel="roku:roku_tv:mytv1:channelName" }
146+
String Player_ProgramTitle "Program Title: [%s]" { channel="roku:roku_tv:mytv1:programTitle" }
147+
String Player_ProgramDescription "Program Description: [%s]" { channel="roku:roku_tv:mytv1:programDescription" }
148+
String Player_ProgramRating "Program Rating: [%s]" { channel="roku:roku_tv:mytv1:programRating" }
142149
```
143150
144151
### `roku.sitemap` Example
@@ -154,6 +161,8 @@ sitemap roku label="Roku" {
154161
Text item=Player_PlayMode
155162
Text item=Player_TimeElapsed icon="time"
156163
Text item=Player_TimeTotal icon="time"
164+
Text item=Player_EndTime icon="time"
165+
Slider item=Player_Progress icon="time"
157166
// The following items apply to Roku TVs only
158167
Switch item=Player_Power
159168
Text item=Player_PowerState

bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/RokuBindingConstants.java

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class RokuBindingConstants {
5555
public static final String PLAY_MODE = "playMode";
5656
public static final String TIME_ELAPSED = "timeElapsed";
5757
public static final String TIME_TOTAL = "timeTotal";
58+
public static final String END_TIME = "endTime";
59+
public static final String PROGRESS = "progress";
5860
public static final String ACTIVE_CHANNEL = "activeChannel";
5961
public static final String SIGNAL_MODE = "signalMode";
6062
public static final String SIGNAL_QUALITY = "signalQuality";

bundles/org.openhab.binding.roku/src/main/java/org/openhab/binding/roku/internal/handler/RokuHandler.java

+25-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import static org.openhab.binding.roku.internal.RokuBindingConstants.*;
1616

17+
import java.math.BigDecimal;
18+
import java.time.Instant;
1719
import java.util.ArrayList;
1820
import java.util.HashMap;
1921
import java.util.List;
@@ -34,8 +36,10 @@
3436
import org.openhab.binding.roku.internal.dto.Player;
3537
import org.openhab.binding.roku.internal.dto.TvChannel;
3638
import org.openhab.binding.roku.internal.dto.TvChannels.Channel;
39+
import org.openhab.core.library.types.DateTimeType;
3740
import org.openhab.core.library.types.NextPreviousType;
3841
import org.openhab.core.library.types.OnOffType;
42+
import org.openhab.core.library.types.PercentType;
3943
import org.openhab.core.library.types.PlayPauseType;
4044
import org.openhab.core.library.types.QuantityType;
4145
import org.openhab.core.library.types.StringType;
@@ -195,21 +199,32 @@ private void refreshPlayerState() {
195199
PLAY.equalsIgnoreCase(playerInfo.getState()) ? PlayPauseType.PLAY : PlayPauseType.PAUSE);
196200

197201
// Remove non-numeric from string, ie: ' ms'
198-
String position = playerInfo.getPosition().replaceAll(NON_DIGIT_PATTERN, EMPTY);
199-
if (!EMPTY.equals(position)) {
200-
updateState(TIME_ELAPSED,
201-
new QuantityType<>(Integer.parseInt(position) / 1000, API_SECONDS_UNIT));
202+
final String positionStr = playerInfo.getPosition().replaceAll(NON_DIGIT_PATTERN, EMPTY);
203+
int position = -1;
204+
if (!EMPTY.equals(positionStr)) {
205+
position = Integer.parseInt(positionStr) / 1000;
206+
updateState(TIME_ELAPSED, new QuantityType<>(position, API_SECONDS_UNIT));
202207
} else {
203208
updateState(TIME_ELAPSED, UnDefType.UNDEF);
204209
}
205210

206-
String duration = playerInfo.getDuration().replaceAll(NON_DIGIT_PATTERN, EMPTY);
207-
if (!EMPTY.equals(duration)) {
208-
updateState(TIME_TOTAL,
209-
new QuantityType<>(Integer.parseInt(duration) / 1000, API_SECONDS_UNIT));
211+
final String durationStr = playerInfo.getDuration().replaceAll(NON_DIGIT_PATTERN, EMPTY);
212+
int duration = -1;
213+
if (!EMPTY.equals(durationStr)) {
214+
duration = Integer.parseInt(durationStr) / 1000;
215+
updateState(TIME_TOTAL, new QuantityType<>(duration, API_SECONDS_UNIT));
210216
} else {
211217
updateState(TIME_TOTAL, UnDefType.UNDEF);
212218
}
219+
220+
if (position >= 0 && duration > 0) {
221+
updateState(END_TIME, new DateTimeType(Instant.now().plusSeconds(duration - position)));
222+
updateState(PROGRESS,
223+
new PercentType(BigDecimal.valueOf(Math.round(position / (double) duration * 100.0))));
224+
} else {
225+
updateState(END_TIME, UnDefType.UNDEF);
226+
updateState(PROGRESS, UnDefType.UNDEF);
227+
}
213228
} catch (NumberFormatException e) {
214229
logger.debug("Unable to parse playerInfo integer value. Exception: {}", e.getMessage());
215230
} catch (RokuLimitedModeException e) {
@@ -224,6 +239,8 @@ private void refreshPlayerState() {
224239
updateState(PLAY_MODE, UnDefType.UNDEF);
225240
updateState(TIME_ELAPSED, UnDefType.UNDEF);
226241
updateState(TIME_TOTAL, UnDefType.UNDEF);
242+
updateState(END_TIME, UnDefType.UNDEF);
243+
updateState(PROGRESS, UnDefType.UNDEF);
227244
}
228245

229246
if (thingTypeUID.equals(THING_TYPE_ROKU_TV) && tvActive) {

bundles/org.openhab.binding.roku/src/main/resources/OH-INF/i18n/roku.properties

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ channel-type.roku.channelName.label = Channel Name
8080
channel-type.roku.channelName.description = The Name of the Channel Currently Selected
8181
channel-type.roku.control.label = Control
8282
channel-type.roku.control.description = Control playback e.g. Play/Pause/Next/Previous
83+
channel-type.roku.endTime.label = End Time
84+
channel-type.roku.endTime.description = The date/time when the currently playing media will end
8385
channel-type.roku.playMode.label = Play Mode
8486
channel-type.roku.playMode.description = The Current Playback Mode
8587
channel-type.roku.powerState.label = Power State
@@ -93,6 +95,8 @@ channel-type.roku.programRating.label = Program Rating
9395
channel-type.roku.programRating.description = The TV Parental Guideline Rating of the Current TV Program
9496
channel-type.roku.programTitle.label = Program Title
9597
channel-type.roku.programTitle.description = The Name of the Current TV Program
98+
channel-type.roku.progress.label = Media Progress
99+
channel-type.roku.progress.description = The current progress of playing media
96100
channel-type.roku.signalMode.label = Signal Mode
97101
channel-type.roku.signalMode.description = The Signal Type of the Current TV Channel, ie: 1080i
98102
channel-type.roku.signalQuality.label = Signal Quality

bundles/org.openhab.binding.roku/src/main/resources/OH-INF/thing/roku.xml

+24-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
<channel id="playMode" typeId="playMode"/>
2020
<channel id="timeElapsed" typeId="timeElapsed"/>
2121
<channel id="timeTotal" typeId="timeTotal"/>
22+
<channel id="endTime" typeId="endTime"/>
23+
<channel id="progress" typeId="progress"/>
2224
</channels>
2325

2426
<properties>
@@ -28,7 +30,7 @@
2830
<property name="Serial Number">unknown</property>
2931
<property name="Device Id">unknown</property>
3032
<property name="Software Version">unknown</property>
31-
<property name="thingTypeVersion">1</property>
33+
<property name="thingTypeVersion">2</property>
3234
</properties>
3335

3436
<representation-property>uuid</representation-property>
@@ -52,6 +54,8 @@
5254
<channel id="playMode" typeId="playMode"/>
5355
<channel id="timeElapsed" typeId="timeElapsed"/>
5456
<channel id="timeTotal" typeId="timeTotal"/>
57+
<channel id="endTime" typeId="endTime"/>
58+
<channel id="progress" typeId="progress"/>
5559
<channel id="activeChannel" typeId="activeChannel"/>
5660
<channel id="signalMode" typeId="signalMode"/>
5761
<channel id="signalQuality" typeId="signalQuality"/>
@@ -69,7 +73,7 @@
6973
<property name="Serial Number">unknown</property>
7074
<property name="Device Id">unknown</property>
7175
<property name="Software Version">unknown</property>
72-
<property name="thingTypeVersion">1</property>
76+
<property name="thingTypeVersion">2</property>
7377
</properties>
7478

7579
<representation-property>uuid</representation-property>
@@ -185,6 +189,24 @@
185189
<state readOnly="true" pattern="%d %unit%"/>
186190
</channel-type>
187191

192+
<channel-type id="endTime">
193+
<item-type>DateTime</item-type>
194+
<label>End Time</label>
195+
<description>The date/time when the currently playing media will end</description>
196+
<category>Time</category>
197+
<tags>
198+
<tag>Status</tag>
199+
<tag>Timestamp</tag>
200+
</tags>
201+
<state readOnly="true"/>
202+
</channel-type>
203+
204+
<channel-type id="progress">
205+
<item-type>Dimmer</item-type>
206+
<label>Media Progress</label>
207+
<description>The current progress of playing media</description>
208+
</channel-type>
209+
188210
<channel-type id="activeChannel">
189211
<item-type>String</item-type>
190212
<label>Active Channel</label>

bundles/org.openhab.binding.roku/src/main/resources/OH-INF/update/update.xml

+18
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
<type>roku:control</type>
1313
</add-channel>
1414
</instruction-set>
15+
16+
<instruction-set targetVersion="2">
17+
<add-channel id="endTime">
18+
<type>roku:endTime</type>
19+
</add-channel>
20+
<add-channel id="progress">
21+
<type>roku:progress</type>
22+
</add-channel>
23+
</instruction-set>
1524
</thing-type>
1625

1726
<thing-type uid="roku:roku_tv">
@@ -29,6 +38,15 @@
2938
<type>roku:control</type>
3039
</add-channel>
3140
</instruction-set>
41+
42+
<instruction-set targetVersion="2">
43+
<add-channel id="endTime">
44+
<type>roku:endTime</type>
45+
</add-channel>
46+
<add-channel id="progress">
47+
<type>roku:progress</type>
48+
</add-channel>
49+
</instruction-set>
3250
</thing-type>
3351

3452
</update:update-descriptions>

0 commit comments

Comments
 (0)