]> git.basschouten.com Git - openhab-addons.git/blob
200248f9bba168b74187848134ca5c1762670e1c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.lgwebos.internal.handler;
14
15 import java.io.IOException;
16 import java.net.URI;
17 import java.util.Optional;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jetty.websocket.api.Session;
22 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
23 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
24 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
25 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
26 import org.eclipse.jetty.websocket.api.annotations.WebSocket;
27 import org.eclipse.jetty.websocket.client.WebSocketClient;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * WebSocket implementation to connect to WebOSTV mouse api.
33  *
34  * @author Sebastian Prehn - Initial contribution
35  *
36  */
37 @WebSocket()
38 @NonNullByDefault
39 public class LGWebOSTVMouseSocket {
40     private final Logger logger = LoggerFactory.getLogger(LGWebOSTVMouseSocket.class);
41
42     public enum State {
43         DISCONNECTED,
44         CONNECTING,
45         CONNECTED,
46         DISCONNECTING
47     }
48
49     public enum ButtonType {
50         HOME,
51         ENTER,
52         BACK,
53         EXIT,
54         UP,
55         DOWN,
56         LEFT,
57         RIGHT,
58     }
59
60     private State state = State.DISCONNECTED;
61     private final WebSocketClient client;
62     private @Nullable Session session;
63     private @Nullable WebOSTVMouseSocketListener listener;
64
65     public LGWebOSTVMouseSocket(WebSocketClient client) {
66         this.client = client;
67     }
68
69     public State getState() {
70         return state;
71     }
72
73     private void setState(State state) {
74         State oldState = this.state;
75         this.state = state;
76         Optional.ofNullable(this.listener).ifPresent(l -> l.onStateChanged(oldState, this.state));
77     }
78
79     public interface WebOSTVMouseSocketListener {
80
81         public void onStateChanged(State oldState, State newState);
82
83         public void onError(String errorMessage);
84     }
85
86     public void setListener(@Nullable WebOSTVMouseSocketListener listener) {
87         this.listener = listener;
88     }
89
90     public void connect(URI destUri) {
91         synchronized (this) {
92             if (state != State.DISCONNECTED) {
93                 logger.debug("Already connecting; not trying to connect again: {}", state);
94                 return;
95             }
96             setState(State.CONNECTING);
97         }
98
99         try {
100             this.client.connect(this, destUri);
101             logger.debug("Connecting to: {}", destUri);
102         } catch (IOException e) {
103             logger.warn("Unable to connect.", e);
104             setState(State.DISCONNECTED);
105         }
106     }
107
108     public void disconnect() {
109         setState(State.DISCONNECTING);
110         try {
111             Optional.ofNullable(this.session).ifPresent(s -> s.close());
112         } catch (Exception e) {
113             logger.debug("Error connecting to device.", e);
114         }
115         setState(State.DISCONNECTED);
116     }
117
118     @OnWebSocketClose
119     public void onClose(int statusCode, String reason) {
120         setState(State.DISCONNECTED);
121         logger.debug("WebSocket Closed - Code: {}, Reason: {}", statusCode, reason);
122         this.session = null;
123     }
124
125     @OnWebSocketConnect
126     public void onConnect(Session session) {
127         logger.debug("WebSocket Connected to: {}", session.getRemoteAddress().getAddress());
128         this.session = session;
129         setState(State.CONNECTED);
130     }
131
132     @OnWebSocketMessage
133     public void onMessage(String message) {
134         logger.debug("Message [in]: {}", message);
135     }
136
137     @OnWebSocketError
138     public void onError(Throwable cause) {
139         String message = cause.getMessage();
140         Optional.ofNullable(this.listener).ifPresent(l -> l.onError(message != null ? message : ""));
141         logger.debug("Connection Error.", cause);
142     }
143
144     private void sendMessage(String msg) {
145         Session s = this.session;
146         try {
147             if (s != null) {
148                 logger.debug("Message [out]: {}", msg);
149                 s.getRemote().sendString(msg);
150             } else {
151                 logger.warn("No Connection to TV, skipping [out]: {}", msg);
152             }
153
154         } catch (IOException e) {
155             logger.error("Unable to send message.", e);
156         }
157     }
158
159     public void click() {
160         sendMessage("type:click\n" + "\n");
161     }
162
163     public void button(ButtonType type) {
164         String keyName;
165         switch (type) {
166             case HOME:
167                 keyName = "HOME";
168                 break;
169             case ENTER:
170                 keyName = "ENTER";
171                 break;
172             case BACK:
173                 keyName = "BACK";
174                 break;
175             case EXIT:
176                 keyName = "EXIT";
177                 break;
178             case UP:
179                 keyName = "UP";
180                 break;
181             case DOWN:
182                 keyName = "DOWN";
183                 break;
184             case LEFT:
185                 keyName = "LEFT";
186                 break;
187             case RIGHT:
188                 keyName = "RIGHT";
189                 break;
190
191             default:
192                 keyName = "NONE";
193                 break;
194         }
195
196         button(keyName);
197     }
198
199     public void button(String keyName) {
200         sendMessage("type:button\n" + "name:" + keyName + "\n" + "\n");
201     }
202
203     public void move(double dx, double dy) {
204         sendMessage("type:move\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "down:0\n" + "\n");
205     }
206
207     public void move(double dx, double dy, boolean drag) {
208         sendMessage("type:move\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "down:" + (drag ? 1 : 0) + "\n" + "\n");
209     }
210
211     public void scroll(double dx, double dy) {
212         sendMessage("type:scroll\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "\n");
213     }
214 }