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