]> git.basschouten.com Git - openhab-addons.git/blob
1c9eeb541d3c71891e0dc71ddae9b10fac1b6f3c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.roku.internal.communication;
14
15 import java.io.StringReader;
16 import java.util.List;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeoutException;
19
20 import javax.xml.bind.JAXBContext;
21 import javax.xml.bind.JAXBException;
22 import javax.xml.bind.Unmarshaller;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jetty.client.HttpClient;
26 import org.eclipse.jetty.http.HttpMethod;
27 import org.openhab.binding.roku.internal.RokuHttpException;
28 import org.openhab.binding.roku.internal.dto.ActiveApp;
29 import org.openhab.binding.roku.internal.dto.Apps;
30 import org.openhab.binding.roku.internal.dto.Apps.App;
31 import org.openhab.binding.roku.internal.dto.DeviceInfo;
32 import org.openhab.binding.roku.internal.dto.Player;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Methods for accessing the HTTP interface of the Roku
38  *
39  * @author Michael Lobstein - Initial contribution
40  */
41 @NonNullByDefault
42 public class RokuCommunicator {
43     private final Logger logger = LoggerFactory.getLogger(RokuCommunicator.class);
44     private final HttpClient httpClient;
45
46     private final String urlKeyPress;
47     private final String urlLaunchApp;
48     private final String urlQryDevice;
49     private final String urlQryActiveApp;
50     private final String urlQryApps;
51     private final String urlQryPlayer;
52
53     public RokuCommunicator(HttpClient httpClient, String host, int port) {
54         this.httpClient = httpClient;
55
56         final String baseUrl = "http://" + host + ":" + port;
57         urlKeyPress = baseUrl + "/keypress/";
58         urlLaunchApp = baseUrl + "/launch/";
59         urlQryDevice = baseUrl + "/query/device-info";
60         urlQryActiveApp = baseUrl + "/query/active-app";
61         urlQryApps = baseUrl + "/query/apps";
62         urlQryPlayer = baseUrl + "/query/media-player";
63     }
64
65     /**
66      * Send a keypress command to the Roku
67      *
68      * @param key The key code to send
69      *
70      */
71     public void keyPress(String key) throws RokuHttpException {
72         postCommand(urlKeyPress + key);
73     }
74
75     /**
76      * Send a launch app command to the Roku
77      *
78      * @param appId The appId of the app to launch
79      *
80      */
81     public void launchApp(String appId) throws RokuHttpException {
82         postCommand(urlLaunchApp + appId);
83     }
84
85     /**
86      * Send a command to get device-info from the Roku and return a DeviceInfo object
87      *
88      * @return A DeviceInfo object populated with information about the connected Roku
89      * @throws RokuHttpException
90      */
91     public DeviceInfo getDeviceInfo() throws RokuHttpException {
92         try {
93             JAXBContext ctx = JAXBUtils.JAXBCONTEXT_DEVICE_INFO;
94             if (ctx != null) {
95                 Unmarshaller unmarshaller = ctx.createUnmarshaller();
96                 if (unmarshaller != null) {
97                     DeviceInfo device = (DeviceInfo) unmarshaller.unmarshal(new StringReader(getCommand(urlQryDevice)));
98                     if (device != null) {
99                         return device;
100                     }
101                 }
102             }
103             throw new RokuHttpException("No DeviceInfo model in response");
104         } catch (JAXBException e) {
105             throw new RokuHttpException("Exception creating DeviceInfo Unmarshaller: " + e.getLocalizedMessage());
106         }
107     }
108
109     /**
110      * Send a command to get active-app from the Roku and return an ActiveApp object
111      *
112      * @return An ActiveApp object populated with information about the current running app on the Roku
113      * @throws RokuHttpException
114      */
115     public ActiveApp getActiveApp() throws RokuHttpException {
116         try {
117             JAXBContext ctx = JAXBUtils.JAXBCONTEXT_ACTIVE_APP;
118             if (ctx != null) {
119                 Unmarshaller unmarshaller = ctx.createUnmarshaller();
120                 if (unmarshaller != null) {
121                     ActiveApp activeApp = (ActiveApp) unmarshaller
122                             .unmarshal(new StringReader(getCommand(urlQryActiveApp)));
123                     if (activeApp != null) {
124                         return activeApp;
125                     }
126                 }
127             }
128             throw new RokuHttpException("No ActiveApp model in response");
129         } catch (JAXBException e) {
130             throw new RokuHttpException("Exception creating ActiveApp Unmarshaller: " + e.getLocalizedMessage());
131         }
132     }
133
134     /**
135      * Send a command to get the installed app list from the Roku and return a List of App objects
136      *
137      * @return A List of App objects for all apps currently installed on the Roku
138      * @throws RokuHttpException
139      */
140     public List<App> getAppList() throws RokuHttpException {
141         try {
142             JAXBContext ctx = JAXBUtils.JAXBCONTEXT_APPS;
143             if (ctx != null) {
144                 Unmarshaller unmarshaller = ctx.createUnmarshaller();
145                 if (unmarshaller != null) {
146                     Apps appList = (Apps) unmarshaller.unmarshal(new StringReader(getCommand(urlQryApps)));
147                     if (appList != null) {
148                         return appList.getApp();
149                     }
150                 }
151             }
152             throw new RokuHttpException("No AppList model in response");
153         } catch (JAXBException e) {
154             throw new RokuHttpException("Exception creating AppList Unmarshaller: " + e.getLocalizedMessage());
155         }
156     }
157
158     /**
159      * Send a command to get media-player from the Roku and return a Player object
160      *
161      * @return A Player object populated with information about the current stream playing on the Roku
162      * @throws RokuHttpException
163      */
164     public Player getPlayerInfo() throws RokuHttpException {
165         try {
166             JAXBContext ctx = JAXBUtils.JAXBCONTEXT_PLAYER;
167             if (ctx != null) {
168                 Unmarshaller unmarshaller = ctx.createUnmarshaller();
169                 if (unmarshaller != null) {
170                     Player playerInfo = (Player) unmarshaller.unmarshal(new StringReader(getCommand(urlQryPlayer)));
171                     if (playerInfo != null) {
172                         return playerInfo;
173                     }
174                 }
175             }
176             throw new RokuHttpException("No Player info model in response");
177         } catch (JAXBException e) {
178             throw new RokuHttpException("Exception creating Player info Unmarshaller: " + e.getLocalizedMessage());
179         }
180     }
181
182     /**
183      * Sends a GET command to the Roku
184      *
185      * @param url The url to send with the command embedded in the URI
186      * @return The response content of the http request
187      */
188     private String getCommand(String url) {
189         try {
190             return httpClient.GET(url).getContentAsString();
191         } catch (InterruptedException | TimeoutException | ExecutionException e) {
192             logger.debug("Error executing player GET command, URL: {}, {} ", url, e.getMessage());
193             return "";
194         }
195     }
196
197     /**
198      * Sends a POST command to the Roku
199      *
200      * @param url The url to send with the command embedded in the URI
201      * @throws RokuHttpException
202      */
203     private void postCommand(String url) throws RokuHttpException {
204         try {
205             httpClient.POST(url).method(HttpMethod.POST).send();
206         } catch (InterruptedException | TimeoutException | ExecutionException e) {
207             throw new RokuHttpException("Error executing player POST command, URL: " + url + e.getMessage());
208         }
209     }
210 }