]> git.basschouten.com Git - openhab-addons.git/blob
68a257816be17d542f4636626df85373e7a38184
[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.heos.internal.api;
14
15 import static org.openhab.binding.heos.internal.resources.HeosConstants.*;
16
17 import java.io.IOException;
18 import java.net.URL;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.heos.internal.json.dto.HeosResponseObject;
27 import org.openhab.binding.heos.internal.json.payload.BrowseResult;
28 import org.openhab.binding.heos.internal.json.payload.Group;
29 import org.openhab.binding.heos.internal.json.payload.Media;
30 import org.openhab.binding.heos.internal.json.payload.Player;
31 import org.openhab.binding.heos.internal.resources.HeosCommands;
32 import org.openhab.binding.heos.internal.resources.HeosConstants;
33 import org.openhab.binding.heos.internal.resources.HeosEventListener;
34 import org.openhab.binding.heos.internal.resources.Telnet.ReadException;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.gson.JsonElement;
39
40 /**
41  * The {@link HeosFacade} is the interface for handling commands, which are
42  * sent to the HEOS system.
43  *
44  * @author Johannes Einig - Initial contribution
45  */
46 @NonNullByDefault
47 public class HeosFacade {
48     private static final int MAX_QUEUE_PAGES = 25;
49     private final Logger logger = LoggerFactory.getLogger(HeosFacade.class);
50
51     private final HeosSystem heosSystem;
52     private final HeosEventController eventController;
53
54     public HeosFacade(HeosSystem heosSystem, HeosEventController eventController) {
55         this.heosSystem = heosSystem;
56         this.eventController = eventController;
57     }
58
59     public synchronized List<BrowseResult> getFavorites() throws IOException, ReadException {
60         return getBrowseResults(FAVORITE_SID);
61     }
62
63     public List<BrowseResult> getInputs() throws IOException, ReadException {
64         return getBrowseResults(String.valueOf(INPUT_SID));
65     }
66
67     public List<BrowseResult> getPlaylists() throws IOException, ReadException {
68         return getBrowseResults(PLAYLISTS_SID);
69     }
70
71     private List<BrowseResult> getBrowseResults(String sourceIdentifier) throws IOException, ReadException {
72         HeosResponseObject<BrowseResult[]> response = browseSource(sourceIdentifier);
73         logger.debug("Response: {}", response);
74
75         if (response.payload == null) {
76             return Collections.emptyList();
77         }
78         logger.debug("Received results: {}", Arrays.asList(response.payload));
79
80         return Arrays.asList(response.payload);
81     }
82
83     public List<Media> getQueue(String pid) throws IOException, ReadException {
84         List<Media> media = new ArrayList<>();
85         for (int page = 0; page < MAX_QUEUE_PAGES; page++) {
86             HeosResponseObject<Media[]> response = fetchQueue(pid, page);
87             if (!response.result || response.payload == null) {
88                 break;
89             }
90
91             media.addAll(Arrays.asList(response.payload));
92
93             if (response.payload.length < 100) {
94                 break;
95             }
96
97             if (page == MAX_QUEUE_PAGES - 1) {
98                 logger.info("Currently only a maximum of {} pages is fetched for every queue", MAX_QUEUE_PAGES);
99             }
100         }
101
102         return media;
103     }
104
105     HeosResponseObject<Media[]> fetchQueue(String pid, int page) throws IOException, ReadException {
106         return heosSystem.send(HeosCommands.getQueue(pid, page * 100, (page + 1) * 100), Media[].class);
107     }
108
109     public HeosResponseObject<Player> getPlayerInfo(String pid) throws IOException, ReadException {
110         return heosSystem.send(HeosCommands.getPlayerInfo(pid), Player.class);
111     }
112
113     public HeosResponseObject<Group> getGroupInfo(String gid) throws IOException, ReadException {
114         return heosSystem.send(HeosCommands.getGroupInfo(gid), Group.class);
115     }
116
117     /**
118      * Pauses the HEOS player
119      *
120      * @param pid The PID of the dedicated player
121      */
122     public void pause(String pid) throws IOException, ReadException {
123         heosSystem.send(HeosCommands.setPlayStatePause(pid));
124     }
125
126     /**
127      * Starts the HEOS player
128      *
129      * @param pid The PID of the dedicated player
130      */
131     public void play(String pid) throws IOException, ReadException {
132         heosSystem.send(HeosCommands.setPlayStatePlay(pid));
133     }
134
135     /**
136      * Stops the HEOS player
137      *
138      * @param pid The PID of the dedicated player
139      */
140     public void stop(String pid) throws IOException, ReadException {
141         heosSystem.send(HeosCommands.setPlayStateStop(pid));
142     }
143
144     /**
145      * Jumps to the next song on the HEOS player
146      *
147      * @param pid The PID of the dedicated player
148      */
149     public void next(String pid) throws IOException, ReadException {
150         heosSystem.send(HeosCommands.playNext(pid));
151     }
152
153     /**
154      * Jumps to the previous song on the HEOS player
155      *
156      * @param pid The PID of the dedicated player
157      */
158     public void previous(String pid) throws IOException, ReadException {
159         heosSystem.send(HeosCommands.playPrevious(pid));
160     }
161
162     /**
163      * Toggles the mute state the HEOS player
164      *
165      * @param pid The PID of the dedicated player
166      */
167     public void mute(String pid) throws IOException, ReadException {
168         heosSystem.send(HeosCommands.setMuteToggle(pid));
169     }
170
171     /**
172      * Mutes the HEOS player
173      *
174      * @param pid The PID of the dedicated player
175      */
176     public void muteON(String pid) throws IOException, ReadException {
177         heosSystem.send(HeosCommands.setMuteOn(pid));
178     }
179
180     /**
181      * Un-mutes the HEOS player
182      *
183      * @param pid The PID of the dedicated player
184      */
185     public void muteOFF(String pid) throws IOException, ReadException {
186         heosSystem.send(HeosCommands.setMuteOff(pid));
187     }
188
189     /**
190      * Set the play mode of the player or group
191      *
192      * @param pid The PID of the dedicated player or group
193      * @param mode The shuffle mode: Allowed commands: on; off
194      */
195     public void setShuffleMode(String pid, String mode) throws IOException, ReadException {
196         heosSystem.send(HeosCommands.setShuffleMode(pid, mode));
197     }
198
199     /**
200      * Sets the repeat mode of the player or group
201      *
202      * @param pid The ID of the dedicated player or group
203      * @param mode The repeat mode. Allowed commands: on_all; on_one; off
204      */
205     public void setRepeatMode(String pid, String mode) throws IOException, ReadException {
206         heosSystem.send(HeosCommands.setRepeatMode(pid, mode));
207     }
208
209     /**
210      * Set the HEOS player to a dedicated volume
211      *
212      * @param vol The volume the player shall be set to (value between 0 -100)
213      * @param pid The ID of the dedicated player or group
214      */
215     public void setVolume(String vol, String pid) throws IOException, ReadException {
216         heosSystem.send(HeosCommands.setVolume(vol, pid));
217     }
218
219     /**
220      * Increases the HEOS player volume 1 Step
221      *
222      * @param pid The ID of the dedicated player or group
223      */
224     public void increaseVolume(String pid) throws IOException, ReadException {
225         heosSystem.send(HeosCommands.volumeUp(pid));
226     }
227
228     /**
229      * Decreases the HEOS player volume 1 Step
230      *
231      * @param pid The ID of the dedicated player or group
232      */
233     public void decreaseVolume(String pid) throws IOException, ReadException {
234         heosSystem.send(HeosCommands.volumeDown(pid));
235     }
236
237     /**
238      * Toggles mute state of the HEOS group
239      *
240      * @param gid The GID of the group
241      */
242     public void muteGroup(String gid) throws IOException, ReadException {
243         heosSystem.send(HeosCommands.setMuteToggle(gid));
244     }
245
246     /**
247      * Mutes the HEOS group
248      *
249      * @param gid The GID of the group
250      */
251     public void muteGroupON(String gid) throws IOException, ReadException {
252         heosSystem.send(HeosCommands.setGroupMuteOn(gid));
253     }
254
255     /**
256      * Un-mutes the HEOS group
257      *
258      * @param gid The GID of the group
259      */
260     public void muteGroupOFF(String gid) throws IOException, ReadException {
261         heosSystem.send(HeosCommands.setGroupMuteOff(gid));
262     }
263
264     /**
265      * Set the volume of the group to a specific level
266      *
267      * @param vol The volume the group shall be set to (value between 0-100)
268      * @param gid The GID of the group
269      */
270     public void volumeGroup(String vol, String gid) throws IOException, ReadException {
271         heosSystem.send(HeosCommands.setGroupVolume(vol, gid));
272     }
273
274     /**
275      * Increases the HEOS group volume 1 Step
276      *
277      * @param gid The ID of the dedicated player or group
278      */
279     public void increaseGroupVolume(String gid) throws IOException, ReadException {
280         heosSystem.send(HeosCommands.setGroupVolumeUp(gid));
281     }
282
283     /**
284      * Decreases the HEOS group volume 1 Step
285      *
286      * @param gid The ID of the dedicated player or group
287      */
288     public void decreaseGroupVolume(String gid) throws IOException, ReadException {
289         heosSystem.send(HeosCommands.setGroupVolumeDown(gid));
290     }
291
292     /**
293      * Un-Group the HEOS group to single player
294      *
295      * @param gid The GID of the group
296      */
297     public void ungroupGroup(String gid) throws IOException, ReadException {
298         String[] pid = new String[] { gid };
299         heosSystem.send(HeosCommands.setGroup(pid));
300     }
301
302     /**
303      * Builds a group from single players
304      *
305      * @param pids The single player IDs of the player which shall be grouped
306      * @return
307      */
308     public boolean groupPlayer(String[] pids) throws IOException, ReadException {
309         return heosSystem.send(HeosCommands.setGroup(pids)).result;
310     }
311
312     /**
313      * Browses through a HEOS source. Currently no response
314      *
315      * @param sid The source sid which shall be browsed
316      * @return
317      */
318     public HeosResponseObject<BrowseResult[]> browseSource(String sid) throws IOException, ReadException {
319         return heosSystem.send(HeosCommands.browseSource(sid), BrowseResult[].class);
320     }
321
322     /**
323      * Adds a media container to the queue and plays the media directly
324      * Information of the sid and cid has to be obtained via the browse function
325      *
326      * @param pid The player ID where the media object shall be played
327      * @param sid The source ID where the media is located
328      * @param cid The container ID of the media
329      */
330     public void addContainerToQueuePlayNow(String pid, String sid, String cid) throws IOException, ReadException {
331         heosSystem.send(HeosCommands.addContainerToQueuePlayNow(pid, sid, cid));
332     }
333
334     /**
335      * Reboot the bridge to which the connection is established
336      */
337     public void reboot() throws IOException, ReadException {
338         heosSystem.send(HeosCommands.rebootSystem());
339     }
340
341     /**
342      * Login in via the bridge to the HEOS account
343      *
344      * @param name The username
345      * @param password The password of the user
346      * @return
347      */
348     public HeosResponseObject<Void> logIn(String name, String password) throws IOException, ReadException {
349         return heosSystem.send(HeosCommands.signIn(name, password));
350     }
351
352     /**
353      * Get all the players known by HEOS
354      *
355      * @return
356      */
357     public HeosResponseObject<Player[]> getPlayers() throws IOException, ReadException {
358         return heosSystem.send(HeosCommands.getPlayers(), Player[].class);
359     }
360
361     /**
362      * Get all the groups known by HEOS
363      *
364      * @return
365      */
366     public HeosResponseObject<Group[]> getGroups() throws IOException, ReadException {
367         return heosSystem.send(HeosCommands.getGroups(), Group[].class);
368     }
369
370     /**
371      * Plays a specific station on the HEOS player
372      *
373      * @param pid The player ID
374      * @param sid The source ID where the media is located
375      * @param cid The container ID of the media
376      * @param mid The media ID of the media
377      * @param name Station name returned by 'browse' command.
378      */
379     public void playStream(@Nullable String pid, @Nullable String sid, @Nullable String cid, @Nullable String mid,
380             @Nullable String name) throws IOException, ReadException {
381         heosSystem.send(HeosCommands.playStream(pid, sid, cid, mid, name));
382     }
383
384     /**
385      * Plays a specific station on the HEOS player
386      *
387      * @param pid The player ID
388      * @param sid The source ID where the media is located
389      * @param mid The media ID of the media
390      */
391     public void playStream(String pid, String sid, String mid) throws IOException, ReadException {
392         heosSystem.send(HeosCommands.playStream(pid, sid, mid));
393     }
394
395     /**
396      * Plays a specified local input source on the player.
397      * Input name as per specified in HEOS CLI Protocol
398      *
399      * @param pid
400      * @param input
401      */
402     public void playInputSource(String pid, String input) throws IOException, ReadException {
403         heosSystem.send(HeosCommands.playInputSource(pid, pid, input));
404     }
405
406     /**
407      * Plays a specified input source from another player on the selected player.
408      * Input name as per specified in HEOS CLI Protocol
409      *
410      * @param destinationPid the PID where the source shall be played
411      * @param sourcePid the PID where the source is located.
412      * @param input the input name
413      */
414     public void playInputSource(String destinationPid, String sourcePid, String input)
415             throws IOException, ReadException {
416         heosSystem.send(HeosCommands.playInputSource(destinationPid, sourcePid, input));
417     }
418
419     /**
420      * Plays a file from a URL
421      *
422      * @param pid the PID where the file shall be played
423      * @param url the complete URL the file is located
424      */
425     public void playURL(String pid, URL url) throws IOException, ReadException {
426         heosSystem.send(HeosCommands.playURL(pid, url.toString()));
427     }
428
429     /**
430      * clear the queue
431      *
432      * @param pid The player ID the media is playing on
433      */
434     public void clearQueue(String pid) throws IOException, ReadException {
435         heosSystem.send(HeosCommands.clearQueue(pid));
436     }
437
438     /**
439      * Deletes a media from the queue
440      *
441      * @param pid The player ID the media is playing on
442      * @param qid The queue ID of the media. (starts by 1)
443      */
444     public void deleteMediaFromQueue(String pid, String qid) throws IOException, ReadException {
445         heosSystem.send(HeosCommands.deleteQueueItem(pid, qid));
446     }
447
448     /**
449      * Plays a specific media file from the queue
450      *
451      * @param pid The player ID the media shall be played on
452      * @param qid The queue ID of the media. (starts by 1)
453      */
454     public void playMediaFromQueue(String pid, String qid) throws IOException, ReadException {
455         heosSystem.send(HeosCommands.playQueueItem(pid, qid));
456     }
457
458     /**
459      * Asks for the actual state of the player. The result has
460      * to be handled by the event controller. The system returns {@link HeosConstants#PLAY},
461      * {@link HeosConstants#PAUSE} or {@link HeosConstants#STOP}.
462      *
463      * @param id The player ID the state shall get for
464      * @return
465      */
466     public HeosResponseObject<Void> getPlayState(String id) throws IOException, ReadException {
467         return heosSystem.send(HeosCommands.getPlayState(id));
468     }
469
470     /**
471      * Ask for the actual mute state of the player. The result has
472      * to be handled by the event controller. The HEOS system returns {@link HeosConstants#ON}
473      * or {@link HeosConstants#OFF}.
474      *
475      * @param id The player id the mute state shall get for
476      * @return
477      */
478     public HeosResponseObject<Void> getPlayerMuteState(String id) throws IOException, ReadException {
479         return heosSystem.send(HeosCommands.getMute(id));
480     }
481
482     /**
483      * Ask for the actual volume the player. The result has
484      * to be handled by the event controller. The HEOS system returns
485      * a value between 0 and 100
486      *
487      * @param id The player id the volume shall get for
488      * @return
489      */
490     public HeosResponseObject<Void> getPlayerVolume(String id) throws IOException, ReadException {
491         return heosSystem.send(HeosCommands.getVolume(id));
492     }
493
494     /**
495      * Ask for the actual shuffle mode of the player. The result has
496      * to be handled by the event controller. The HEOS system returns {@link HeosConstants#ON},
497      * {@link HeosConstants#HEOS_REPEAT_ALL} or {@link HeosConstants#HEOS_REPEAT_ONE}
498      *
499      * @param id The player id the shuffle mode shall get for
500      * @return
501      */
502     public HeosResponseObject<Void> getPlayMode(String id) throws IOException, ReadException {
503         return heosSystem.send(HeosCommands.getPlayMode(id));
504     }
505
506     public HeosResponseObject<Void> getGroupMuteState(String id) throws IOException, ReadException {
507         return heosSystem.send(HeosCommands.getGroupMute(id));
508     }
509
510     public HeosResponseObject<Void> getGroupVolume(String id) throws IOException, ReadException {
511         return heosSystem.send(HeosCommands.getGroupVolume(id));
512     }
513
514     public HeosResponseObject<Media> getNowPlayingMedia(String id) throws IOException, ReadException {
515         return heosSystem.send(HeosCommands.getNowPlayingMedia(id), Media.class);
516     }
517
518     /**
519      * Sends a RAW command to the HEOS bridge. The command has to be
520      * in accordance with the HEOS CLI specification
521      *
522      * @param command to send
523      * @return
524      */
525     public HeosResponseObject<JsonElement> sendRawCommand(String command) throws IOException, ReadException {
526         return heosSystem.send(command, JsonElement.class);
527     }
528
529     /**
530      * Register an {@link HeosEventListener} to get notification of system events
531      *
532      * @param listener The HeosEventListener
533      */
534     public void registerForChangeEvents(HeosEventListener listener) {
535         eventController.addListener(listener);
536     }
537
538     /**
539      * Unregister an {@link HeosEventListener} to get notification of system events
540      *
541      * @param listener The HeosEventListener
542      */
543     public void unregisterForChangeEvents(HeosEventListener listener) {
544         eventController.removeListener(listener);
545     }
546
547     public boolean isConnected() {
548         return heosSystem.isConnected();
549     }
550
551     public void closeConnection() {
552         heosSystem.closeConnection();
553     }
554 }