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.plex.internal.handler;
15 import static org.openhab.binding.plex.internal.PlexBindingConstants.*;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.plex.internal.config.PlexPlayerConfiguration;
19 import org.openhab.binding.plex.internal.dto.MediaContainer.MediaType;
20 import org.openhab.binding.plex.internal.dto.PlexPlayerState;
21 import org.openhab.binding.plex.internal.dto.PlexSession;
22 import org.openhab.core.library.types.PlayPauseType;
23 import org.openhab.core.library.types.StringType;
24 import org.openhab.core.thing.Bridge;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.thing.binding.BaseThingHandler;
30 import org.openhab.core.types.Command;
31 import org.openhab.core.types.RefreshType;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * Handler for Plex Player.
38 * @author Brian Homeyer - Initial contribution
39 * @author Aron Beurskens - Binding development
42 public class PlexPlayerHandler extends BaseThingHandler {
43 private @NonNullByDefault({}) String playerID;
45 private PlexSession currentSessionData;
46 private boolean foundInSession;
48 private final Logger logger = LoggerFactory.getLogger(PlexPlayerHandler.class);
50 public PlexPlayerHandler(Thing thing) {
52 currentSessionData = new PlexSession();
56 * Initialize the player thing, check the bridge status and hang out waiting
57 * for the session data to get polled.
60 public void initialize() {
61 PlexPlayerConfiguration config = getConfigAs(PlexPlayerConfiguration.class);
62 foundInSession = false;
63 playerID = config.playerID;
64 logger.debug("Initializing PLEX player : {}", playerID);
65 updateStatus(ThingStatus.UNKNOWN);
69 * Currently only the 'player' channel accepts commands, all others are read-only
72 public void handleCommand(ChannelUID channelUID, Command command) {
73 if (command instanceof RefreshType) {
74 logger.debug("REFRESH not implemented");
78 Bridge bridge = getBridge();
79 PlexServerHandler bridgeHandler = bridge == null ? null : (PlexServerHandler) bridge.getHandler();
81 if (bridgeHandler == null) {
82 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_MISSING_ERROR, "No bridge associated");
84 switch (channelUID.getId()) {
85 case CHANNEL_PLAYER_CONTROL:
86 bridgeHandler.getPlexAPIConnector().controlPlayer(command, playerID);
89 logger.debug("Channel {} not implemented/supported to control player {}", channelUID.getId(),
96 * This is really just to set these all back to false so when we refresh the data it's
97 * updated for Power On/Off. This is only called from the Server Bridge.
99 * @param foundInSession Will always be false, so this can probably be changed.
101 public void setFoundInSession(boolean foundInSession) {
102 this.foundInSession = foundInSession;
106 * Returns the session key from the current player
110 public String getSessionKey() {
111 return currentSessionData.getSessionKey();
115 * Called when this thing gets its configuration changed.
118 public void thingUpdated(Thing thing) {
125 * Refreshes all the data from the session XML call. This is called from the bridge
127 * @param sessionData The Video section of the XML(which is what pertains to the player)
129 public void refreshSessionData(MediaType sessionData) {
130 currentSessionData.setState(PlexPlayerState.of(sessionData.getPlayer().getState()));
131 currentSessionData.setDuration(sessionData.getMedia().getDuration());
132 currentSessionData.setMachineIdentifier(sessionData.getPlayer().getMachineIdentifier());
133 currentSessionData.setViewOffset(sessionData.getViewOffset());
134 currentSessionData.setTitle(sessionData.getTitle());
135 currentSessionData.setType(sessionData.getType());
136 currentSessionData.setThumb(sessionData.getThumb());
137 currentSessionData.setArt(sessionData.getArt());
138 currentSessionData.setLocal(sessionData.getPlayer().getLocal());
139 currentSessionData.setSessionKey(sessionData.getSessionKey());
140 currentSessionData.setUserId(sessionData.getUser().getId());
141 currentSessionData.setUserTitle(sessionData.getUser().getTitle());
143 foundInSession = true;
144 updateStatus(ThingStatus.ONLINE);
148 * Update just the state, this status comes from the websocket.
150 * @param state - The state to update it to.
152 public synchronized void updateStateChannel(String state) {
153 currentSessionData.setState(PlexPlayerState.of(state));
154 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_STATE),
155 new StringType(String.valueOf(foundInSession ? currentSessionData.getState() : "Stopped")));
159 * Updates the channel states to match reality.
161 public synchronized void updateChannels() {
162 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_STATE),
163 new StringType(String.valueOf(foundInSession ? currentSessionData.getState() : "Stopped")));
164 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_POWER),
165 new StringType(String.valueOf(foundInSession ? "ON" : "OFF")));
166 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_TITLE),
167 new StringType(String.valueOf(foundInSession ? currentSessionData.getTitle() : "")));
168 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_TYPE),
169 new StringType(String.valueOf(foundInSession ? currentSessionData.getType() : "")));
170 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_ART),
171 new StringType(String.valueOf(foundInSession ? currentSessionData.getArt() : "")));
172 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_THUMB),
173 new StringType(String.valueOf(foundInSession ? currentSessionData.getThumb() : "")));
174 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_PROGRESS),
175 new StringType(String.valueOf(foundInSession ? currentSessionData.getProgress() : "0")));
176 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_ENDTIME),
177 new StringType(String.valueOf(foundInSession ? currentSessionData.getEndTime() : "")));
178 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_ENDTIME),
179 new StringType(String.valueOf(foundInSession ? currentSessionData.getEndTime() : "")));
180 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_USER),
181 new StringType(String.valueOf(foundInSession ? currentSessionData.getUserTitle() : "")));
183 // Make sure player control is in sync with the play state
184 if (currentSessionData.getState() == PlexPlayerState.PLAYING) {
185 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_CONTROL), PlayPauseType.PLAY);
187 if (currentSessionData.getState() == PlexPlayerState.PAUSED) {
188 updateState(new ChannelUID(getThing().getUID(), CHANNEL_PLAYER_CONTROL), PlayPauseType.PAUSE);