]> git.basschouten.com Git - openhab-addons.git/blob
9f74a053306f3ffa57e847534dd0180693f61de2
[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.volumio.internal;
14
15 import java.net.InetAddress;
16 import java.net.URI;
17 import java.net.URISyntaxException;
18 import java.net.UnknownHostException;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.json.JSONException;
22 import org.json.JSONObject;
23 import org.openhab.binding.volumio.internal.mapping.VolumioCommands;
24 import org.openhab.core.library.types.PercentType;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import io.socket.client.IO;
29 import io.socket.client.Socket;
30 import io.socket.emitter.Emitter;
31
32 /**
33  * @author Patrick Sernetz - Initial Contribution
34  * @author Chris Wohlbrecht - Adaption for openHAB 3
35  * @author Michael Loercher - Adaption for openHAB 3
36  */
37 @NonNullByDefault
38 public class VolumioService {
39
40     private final Logger logger = LoggerFactory.getLogger(VolumioService.class);
41
42     private final Socket socket;
43
44     private boolean connected;
45
46     public VolumioService(String protocol, String hostname, int port, int timeout)
47             throws URISyntaxException, UnknownHostException {
48         String uriString = String.format("%s://%s:%d", protocol, hostname, port);
49
50         URI destUri = new URI(uriString);
51
52         IO.Options opts = new IO.Options();
53         opts.reconnection = true;
54         opts.reconnectionDelay = 1000 * 30;
55         opts.reconnectionDelayMax = 1000 * 60;
56         opts.timeout = timeout;
57
58         // Connection to mdns endpoint is only available after fetching ip.
59         InetAddress ipaddress = InetAddress.getByName(hostname);
60         logger.debug("Resolving {} to IP {}", hostname, ipaddress.getHostAddress());
61
62         socket = IO.socket(destUri, opts);
63
64         bindDefaultEvents(hostname);
65     }
66
67     private void bindDefaultEvents(String hostname) {
68         socket.on(Socket.EVENT_CONNECTING, arg0 -> logger.debug("Trying to connect to Volumio on {}", hostname));
69
70         socket.on(Socket.EVENT_RECONNECTING, arg0 -> logger.debug("Trying to reconnect to Volumio on {}", hostname));
71
72         socket.on(Socket.EVENT_CONNECT_ERROR, arg0 -> logger.error("Could not connect to Volumio on {}", hostname));
73
74         socket.on(Socket.EVENT_CONNECT_TIMEOUT,
75                 arg0 -> logger.error("Timedout while conntecting to Volumio on {}", hostname));
76
77         socket.on(Socket.EVENT_CONNECT, arg0 -> {
78             logger.info("Connected to Volumio on {}", hostname);
79             setConnected(true);
80
81         }).on(Socket.EVENT_DISCONNECT, arg0 -> {
82             logger.warn("Disconnected from Volumio on {}", hostname);
83             setConnected(false);
84         });
85     }
86
87     public void connect() throws InterruptedException {
88         socket.connect();
89     }
90
91     public void disconnect() {
92         socket.disconnect();
93     }
94
95     public void close() {
96         socket.off();
97         socket.close();
98     }
99
100     public void on(String eventName, Emitter.Listener listener) {
101         socket.on(eventName, listener);
102     }
103
104     public void once(String eventName, Emitter.Listener listener) {
105         socket.once(eventName, listener);
106     }
107
108     public void getState() {
109         socket.emit(VolumioCommands.GET_STATE);
110     }
111
112     public void play() {
113         socket.emit(VolumioCommands.PLAY);
114     }
115
116     public void pause() {
117         socket.emit(VolumioCommands.PAUSE);
118     }
119
120     public void stop() {
121         socket.emit(VolumioCommands.STOP);
122     }
123
124     public void play(Integer index) {
125         socket.emit(VolumioCommands.PLAY, index);
126     }
127
128     public void next() {
129         socket.emit(VolumioCommands.NEXT);
130     }
131
132     public void previous() {
133         socket.emit(VolumioCommands.PREVIOUS);
134     }
135
136     public void setVolume(PercentType level) {
137         socket.emit(VolumioCommands.VOLUME, level.intValue());
138     }
139
140     public void shutdown() {
141         socket.emit(VolumioCommands.SHUTDOWN);
142     }
143
144     public void reboot() {
145         socket.emit(VolumioCommands.REBOOT);
146     }
147
148     public void playPlaylist(String playlistName) {
149         JSONObject item = new JSONObject();
150
151         try {
152             item.put("name", playlistName);
153
154             socket.emit(VolumioCommands.PLAY_PLAYLIST, item);
155         } catch (JSONException e) {
156             logger.error("The following error occurred {}", e.getMessage());
157         }
158     }
159
160     public void clearQueue() {
161         socket.emit(VolumioCommands.CLEAR_QUEUE);
162     }
163
164     public void setRandom(boolean val) {
165         JSONObject item = new JSONObject();
166
167         try {
168             item.put("value", val);
169
170             socket.emit(VolumioCommands.RANDOM, item);
171         } catch (JSONException e) {
172             logger.error("The following error occurred {}", e.getMessage());
173         }
174     }
175
176     public void setRepeat(boolean val) {
177         JSONObject item = new JSONObject();
178
179         try {
180             item.put("value", val);
181
182             socket.emit(VolumioCommands.REPEAT, item);
183         } catch (JSONException e) {
184             logger.error("The following error occurred {}", e.getMessage());
185         }
186     }
187
188     public void playFavorites(String favoriteName) {
189         JSONObject item = new JSONObject();
190
191         try {
192             item.put("name", favoriteName);
193
194             socket.emit(VolumioCommands.PLAY_FAVOURITES, item);
195         } catch (JSONException e) {
196             logger.error("The following error occurred {}", e.getMessage());
197         }
198     }
199
200     /**
201      * Play a radio station from volumio´s Radio Favourites identifed by
202      * its index.
203      */
204     public void playRadioFavourite(final Integer index) {
205         logger.debug("socket.emit({})", VolumioCommands.PLAY_RADIO_FAVOURITES);
206
207         socket.once("pushPlayRadioFavourites", arg -> play(index));
208
209         socket.emit(VolumioCommands.PLAY_RADIO_FAVOURITES);
210     }
211
212     public void playURI(String uri) {
213         JSONObject item = new JSONObject();
214         logger.debug("PlayURI: {}", uri);
215         try {
216             item.put("uri", uri);
217
218             socket.emit(VolumioCommands.PLAY, uri);
219         } catch (JSONException e) {
220             logger.error("The following error occurred {}", e.getMessage());
221         }
222     }
223
224     public void addPlay(String uri, String title, String serviceType) {
225         JSONObject item = new JSONObject();
226
227         try {
228             item.put("uri", uri);
229             item.put("title", title);
230             item.put("service", serviceType);
231
232             socket.emit(VolumioCommands.ADD_PLAY, item);
233         } catch (JSONException e) {
234             logger.error("The following error occurred {}", e.getMessage());
235         }
236     }
237
238     public void replacePlay(String uri, String title, String serviceType) {
239         JSONObject item = new JSONObject();
240
241         try {
242             item.put("uri", uri);
243             item.put("title", title);
244             item.put("service", serviceType);
245
246             socket.emit(VolumioCommands.REPLACE_AND_PLAY, item);
247         } catch (JSONException e) {
248             logger.error("The following error occurred {}", e.getMessage());
249         }
250     }
251
252     public boolean isConnected() {
253         return this.connected;
254     }
255
256     public void setConnected(boolean status) {
257         this.connected = status;
258     }
259
260     public void sendSystemCommand(String string) {
261         logger.warn("Jukebox Command: {}", string);
262         switch (string) {
263             case VolumioCommands.SHUTDOWN:
264                 shutdown();
265                 break;
266             case VolumioCommands.REBOOT:
267                 reboot();
268                 break;
269             default:
270                 break;
271         }
272     }
273 }