2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.spotify.internal.handler;
15 import static org.openhab.binding.spotify.internal.SpotifyBindingConstants.*;
17 import java.util.Collections;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.spotify.internal.api.SpotifyApi;
22 import org.openhab.binding.spotify.internal.api.model.Device;
23 import org.openhab.binding.spotify.internal.api.model.Playlist;
24 import org.openhab.core.library.types.DecimalType;
25 import org.openhab.core.library.types.NextPreviousType;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.PercentType;
28 import org.openhab.core.library.types.PlayPauseType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.types.Command;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * Class to handle {@link Command} actions and call the Spotify Web Api.
38 * @author Andreas Stenlund - Initial contribution
39 * @author Hilbrand Bouwkamp - Moved to separate class, general refactoring and bug fixes
42 class SpotifyHandleCommands {
44 private final Logger logger = LoggerFactory.getLogger(SpotifyHandleCommands.class);
46 private final SpotifyApi spotifyApi;
48 private List<Device> devices = Collections.emptyList();
49 private List<Playlist> playlists = Collections.emptyList();
52 * Constructor. For the bridge the deviceId is empty.
54 * @param spotifyApi The api class to use to call the spotify api
56 public SpotifyHandleCommands(SpotifyApi spotifyApi) {
57 this.spotifyApi = spotifyApi;
60 public void setDevices(final List<Device> devices) {
61 this.devices = devices;
64 public void setPlaylists(final List<Playlist> playlists) {
65 this.playlists = playlists;
69 * Handles commands from the given Channel and calls Spotify Web Api with the given command.
71 * @param channelUID Channel the command is from
72 * @param command command to run
73 * @param active true if current known device is the active device
74 * @param deviceId Current known active Spotify device id
75 * @return true if the command was done or else if no channel or command matched
77 public boolean handleCommand(ChannelUID channelUID, Command command, boolean active, String deviceId) {
78 logger.debug("Received channel: {}, command: {}", channelUID, command);
79 boolean commandRun = false;
80 final String channel = channelUID.getId();
83 case CHANNEL_DEVICENAME:
84 if (command instanceof StringType) {
85 final String newName = command.toString();
87 devices.stream().filter(d -> d.getName().equals(newName)).findFirst()
88 .ifPresent(d -> playDeviceId(d.getId(), active, deviceId));
92 case CHANNEL_DEVICEID:
94 if (command instanceof StringType) {
95 playDeviceId(command.toString(), active, deviceId);
99 case CHANNEL_DEVICEPLAYER:
100 case CHANNEL_TRACKPLAYER:
101 commandRun = handleDevicePlay(command, active, deviceId);
103 case CHANNEL_DEVICESHUFFLE:
104 if (command instanceof OnOffType onOffCommand) {
105 spotifyApi.setShuffleState(deviceId, onOffCommand);
109 case CHANNEL_TRACKREPEAT:
110 if (command instanceof StringType) {
111 spotifyApi.setRepeatState(deviceId, command.toString());
114 case CHANNEL_DEVICEVOLUME:
115 if (command instanceof DecimalType decimalCommand) {
116 final PercentType volume = command instanceof PercentType percentType ? percentType
117 : new PercentType(decimalCommand.intValue());
119 spotifyApi.setVolume(deviceId, volume.intValue());
123 case CHANNEL_TRACKPLAY:
124 case CHANNEL_PLAYLISTS:
125 if (command instanceof StringType) {
126 spotifyApi.playTrack(deviceId, command.toString(), 0, 0);
130 case CHANNEL_PLAYLISTNAME:
131 if (command instanceof StringType) {
132 final String newName = command.toString();
134 playlists.stream().filter(pl -> pl.getName().equals(newName)).findFirst()
135 .ifPresent(pl -> spotifyApi.playTrack(deviceId, pl.getUri(), 0, 0));
143 private void playDeviceId(String newDeviceId, boolean active, String currentDeviceId) {
144 if (currentDeviceId.equals(newDeviceId) && active) {
145 spotifyApi.play(newDeviceId);
147 spotifyApi.transferPlay(newDeviceId, true);
152 * Helper method to handle device play status.
154 * @param command command to run
155 * @param active true if the device this command is send to is the active device
156 * @param deviceId Spotify device id the command is intended for
157 * @return true if the command was done or else if no channel or command matched
159 private boolean handleDevicePlay(Command command, boolean active, String deviceId) {
160 if (command instanceof PlayPauseType) {
161 final boolean play = command == PlayPauseType.PLAY;
163 if (active || deviceId.isEmpty()) {
165 spotifyApi.play(deviceId);
167 spotifyApi.pause(deviceId);
170 spotifyApi.transferPlay(deviceId, play);
173 } else if (command instanceof NextPreviousType) {
174 if (command == NextPreviousType.NEXT) {
175 spotifyApi.next(deviceId);
177 spotifyApi.previous(deviceId);