]> git.basschouten.com Git - openhab-addons.git/blob
14773c87e1fed8efb0cbbfb668c31d84dfdc5866
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.deconz.internal.netutils;
14
15 import java.net.URI;
16 import java.util.Map;
17 import java.util.concurrent.ConcurrentHashMap;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jetty.websocket.api.Session;
21 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
22 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
23 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
24 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
25 import org.eclipse.jetty.websocket.api.annotations.WebSocket;
26 import org.eclipse.jetty.websocket.client.WebSocketClient;
27 import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage;
28 import org.openhab.binding.deconz.internal.dto.LightMessage;
29 import org.openhab.binding.deconz.internal.dto.SensorMessage;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.gson.Gson;
34
35 /**
36  * Establishes and keeps a websocket connection to the deCONZ software.
37  *
38  * The connection is closed by deCONZ now and then and needs to be re-established.
39  *
40  * @author David Graeff - Initial contribution
41  */
42 @WebSocket
43 @NonNullByDefault
44 public class WebSocketConnection {
45     private final Logger logger = LoggerFactory.getLogger(WebSocketConnection.class);
46
47     private final WebSocketClient client;
48     private final WebSocketConnectionListener connectionListener;
49     private final Map<String, WebSocketMessageListener> sensorListener = new ConcurrentHashMap<>();
50     private final Map<String, WebSocketMessageListener> lightListener = new ConcurrentHashMap<>();
51     private final Gson gson;
52     private boolean connected = false;
53
54     public WebSocketConnection(WebSocketConnectionListener listener, WebSocketClient client, Gson gson) {
55         this.connectionListener = listener;
56         this.client = client;
57         this.client.setMaxIdleTimeout(0);
58         this.gson = gson;
59     }
60
61     public void start(String ip) {
62         if (connected) {
63             return;
64         }
65         try {
66             URI destUri = URI.create("ws://" + ip);
67
68             client.start();
69
70             logger.debug("Connecting to: {}", destUri);
71             client.connect(this, destUri).get();
72         } catch (Exception e) {
73             connectionListener.connectionError(e);
74         }
75     }
76
77     public void close() {
78         try {
79             connected = false;
80             client.stop();
81         } catch (Exception e) {
82             logger.debug("Error while closing connection", e);
83         }
84         client.destroy();
85     }
86
87     public void registerSensorListener(String sensorID, WebSocketMessageListener listener) {
88         sensorListener.put(sensorID, listener);
89     }
90
91     public void unregisterSensorListener(String sensorID) {
92         sensorListener.remove(sensorID);
93     }
94
95     public void registerLightListener(String lightID, WebSocketMessageListener listener) {
96         lightListener.put(lightID, listener);
97     }
98
99     public void unregisterLightListener(String lightID) {
100         sensorListener.remove(lightID);
101     }
102
103     @OnWebSocketConnect
104     public void onConnect(Session session) {
105         connected = true;
106         logger.debug("Connect: {}", session.getRemoteAddress().getAddress());
107         connectionListener.connectionEstablished();
108     }
109
110     @SuppressWarnings("null")
111     @OnWebSocketMessage
112     public void onMessage(String message) {
113         logger.trace("Raw data received by websocket: {}", message);
114         DeconzBaseMessage changedMessage = gson.fromJson(message, DeconzBaseMessage.class);
115         switch (changedMessage.r) {
116             case "sensors":
117                 WebSocketMessageListener listener = sensorListener.get(changedMessage.id);
118                 if (listener != null) {
119                     listener.messageReceived(changedMessage.id, gson.fromJson(message, SensorMessage.class));
120                 } else {
121                     logger.trace("Couldn't find sensor listener for id {}", changedMessage.id);
122                 }
123                 break;
124             case "lights":
125                 listener = lightListener.get(changedMessage.id);
126                 if (listener != null) {
127                     listener.messageReceived(changedMessage.id, gson.fromJson(message, LightMessage.class));
128                 } else {
129                     logger.trace("Couldn't find light listener for id {}", changedMessage.id);
130                 }
131                 break;
132             default:
133                 logger.debug("Unknown message type: {}", changedMessage.r);
134         }
135     }
136
137     @OnWebSocketError
138     public void onError(Throwable cause) {
139         connected = false;
140         connectionListener.connectionError(cause);
141     }
142
143     @OnWebSocketClose
144     public void onClose(int statusCode, String reason) {
145         connected = false;
146         connectionListener.connectionLost(reason);
147     }
148
149     public boolean isConnected() {
150         return connected;
151     }
152 }