]> git.basschouten.com Git - openhab-addons.git/blob
6904d8b21c1a556d929764319d43a950c8a7ad73
[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.androidtv.internal;
14
15 import static org.openhab.binding.androidtv.internal.AndroidTVBindingConstants.*;
16
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.concurrent.ScheduledExecutorService;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.androidtv.internal.protocol.googletv.GoogleTVConfiguration;
27 import org.openhab.binding.androidtv.internal.protocol.googletv.GoogleTVConnectionManager;
28 import org.openhab.binding.androidtv.internal.protocol.shieldtv.ShieldTVConfiguration;
29 import org.openhab.binding.androidtv.internal.protocol.shieldtv.ShieldTVConnectionManager;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.binding.BaseThingHandler;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.CommandOption;
39 import org.openhab.core.types.State;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * The {@link AndroidTVHandler} is responsible for handling commands, which are
45  * sent to one of the channels.
46  *
47  * Significant portions reused from Lutron binding with permission from Bob A.
48  *
49  * @author Ben Rosenblum - Initial contribution
50  */
51 @NonNullByDefault
52 public class AndroidTVHandler extends BaseThingHandler {
53
54     private final Logger logger = LoggerFactory.getLogger(AndroidTVHandler.class);
55
56     private @Nullable ShieldTVConnectionManager shieldtvConnectionManager;
57     private @Nullable GoogleTVConnectionManager googletvConnectionManager;
58
59     private @Nullable ScheduledFuture<?> monitorThingStatusJob;
60     private final Object monitorThingStatusJobLock = new Object();
61     private static final int THING_STATUS_FREQUENCY = 250;
62
63     private final AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider;
64     private final AndroidTVTranslationProvider translationProvider;
65     private final ThingTypeUID thingTypeUID;
66     private final String thingID;
67
68     public AndroidTVHandler(Thing thing, AndroidTVDynamicCommandDescriptionProvider commandDescriptionProvider,
69             AndroidTVTranslationProvider translationProvider, ThingTypeUID thingTypeUID) {
70         super(thing);
71         this.commandDescriptionProvider = commandDescriptionProvider;
72         this.translationProvider = translationProvider;
73         this.thingTypeUID = thingTypeUID;
74         this.thingID = this.getThing().getUID().getId();
75     }
76
77     public void setThingProperty(String property, String value) {
78         thing.setProperty(property, value);
79     }
80
81     public AndroidTVTranslationProvider getTranslationProvider() {
82         return translationProvider;
83     }
84
85     public String getThingID() {
86         return this.thingID;
87     }
88
89     public void updateChannelState(String channel, State state) {
90         updateState(channel, state);
91     }
92
93     public ScheduledExecutorService getScheduler() {
94         return scheduler;
95     }
96
97     public void updateCDP(String channelName, Map<String, String> cdpMap) {
98         logger.trace("{} - Updating CDP for {}", this.thingID, channelName);
99         List<CommandOption> commandOptions = new ArrayList<CommandOption>();
100         cdpMap.forEach((key, value) -> commandOptions.add(new CommandOption(key, value)));
101         logger.trace("{} - CDP List: {}", this.thingID, commandOptions);
102         commandDescriptionProvider.setCommandOptions(new ChannelUID(getThing().getUID(), channelName), commandOptions);
103     }
104
105     private void monitorThingStatus() {
106         synchronized (monitorThingStatusJobLock) {
107             checkThingStatus();
108             monitorThingStatusJob = scheduler.schedule(this::monitorThingStatus, THING_STATUS_FREQUENCY,
109                     TimeUnit.MILLISECONDS);
110         }
111     }
112
113     public void checkThingStatus() {
114         String statusMessage = "";
115         boolean failed = false;
116
117         GoogleTVConnectionManager googletvConnectionManager = this.googletvConnectionManager;
118         ShieldTVConnectionManager shieldtvConnectionManager = this.shieldtvConnectionManager;
119
120         if (googletvConnectionManager != null) {
121             if (!googletvConnectionManager.getLoggedIn()) {
122                 failed = true;
123             }
124             statusMessage = "GoogleTV: " + googletvConnectionManager.getStatusMessage();
125         }
126
127         if (THING_TYPE_SHIELDTV.equals(thingTypeUID)) {
128             if (shieldtvConnectionManager != null) {
129                 if (!shieldtvConnectionManager.getLoggedIn()) {
130                     failed = true;
131                 }
132                 statusMessage = statusMessage + " | ShieldTV: " + shieldtvConnectionManager.getStatusMessage();
133             }
134         }
135
136         if (failed) {
137             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, statusMessage);
138         } else {
139             updateStatus(ThingStatus.ONLINE);
140         }
141     }
142
143     @Override
144     public void initialize() {
145         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "@text/offline.protocols-starting");
146
147         GoogleTVConfiguration googletvConfig = getConfigAs(GoogleTVConfiguration.class);
148         String ipAddress = googletvConfig.ipAddress;
149
150         if (ipAddress.isBlank()) {
151             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
152                     "@text/offline.googletv-address-not-specified");
153             return;
154         }
155
156         googletvConnectionManager = new GoogleTVConnectionManager(this, googletvConfig);
157
158         if (THING_TYPE_SHIELDTV.equals(thingTypeUID)) {
159             ShieldTVConfiguration shieldtvConfig = getConfigAs(ShieldTVConfiguration.class);
160             ipAddress = shieldtvConfig.ipAddress;
161
162             if (ipAddress.isBlank()) {
163                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
164                         "@text/offline.shieldtv-address-not-specified");
165                 return;
166             }
167
168             shieldtvConnectionManager = new ShieldTVConnectionManager(this, shieldtvConfig);
169         }
170
171         monitorThingStatusJob = scheduler.schedule(this::monitorThingStatus, THING_STATUS_FREQUENCY,
172                 TimeUnit.MILLISECONDS);
173     }
174
175     @Override
176     public void handleCommand(ChannelUID channelUID, Command command) {
177         logger.trace("{} - Command received at handler: {} {}", this.thingID, channelUID.getId(), command);
178
179         if (command.toString().equals("REFRESH")) {
180             // REFRESH causes issues on some channels. Block for now until implemented.
181             return;
182         }
183
184         GoogleTVConnectionManager googletvConnectionManager = this.googletvConnectionManager;
185         ShieldTVConnectionManager shieldtvConnectionManager = this.shieldtvConnectionManager;
186
187         if (CHANNEL_DEBUG.equals(channelUID.getId())) {
188             if (command instanceof StringType) {
189                 if (command.toString().equals("GOOGLETV_HALT") && (googletvConnectionManager != null)) {
190                     googletvConnectionManager.dispose();
191                     googletvConnectionManager = null;
192                 } else if (command.toString().equals("GOOGLETV_START")) {
193                     GoogleTVConfiguration googletvConfig = getConfigAs(GoogleTVConfiguration.class);
194                     googletvConnectionManager = new GoogleTVConnectionManager(this, googletvConfig);
195                 } else if (command.toString().equals("GOOGLETV_SHIM") && (googletvConnectionManager == null)) {
196                     GoogleTVConfiguration googletvConfig = getConfigAs(GoogleTVConfiguration.class);
197                     googletvConfig.shim = true;
198                     googletvConnectionManager = new GoogleTVConnectionManager(this, googletvConfig);
199                 } else if (command.toString().equals("SHIELDTV_HALT") && (shieldtvConnectionManager != null)) {
200                     shieldtvConnectionManager.dispose();
201                     shieldtvConnectionManager = null;
202                 } else if (command.toString().equals("SHIELDTV_START")) {
203                     ShieldTVConfiguration shieldtvConfig = getConfigAs(ShieldTVConfiguration.class);
204                     shieldtvConnectionManager = new ShieldTVConnectionManager(this, shieldtvConfig);
205                 } else if (command.toString().equals("SHIELDTV_SHIM") && (shieldtvConnectionManager == null)) {
206                     ShieldTVConfiguration shieldtvConfig = getConfigAs(ShieldTVConfiguration.class);
207                     shieldtvConfig.shim = true;
208                     shieldtvConnectionManager = new ShieldTVConnectionManager(this, shieldtvConfig);
209                 } else if (command.toString().startsWith("GOOGLETV") && (googletvConnectionManager != null)) {
210                     googletvConnectionManager.handleCommand(channelUID, command);
211                 } else if (command.toString().startsWith("SHIELDTV") && (shieldtvConnectionManager != null)) {
212                     shieldtvConnectionManager.handleCommand(channelUID, command);
213                 }
214             }
215             return;
216         }
217
218         if (THING_TYPE_SHIELDTV.equals(thingTypeUID) && (shieldtvConnectionManager != null)) {
219             if (CHANNEL_PINCODE.equals(channelUID.getId())) {
220                 if (command instanceof StringType) {
221                     if (!shieldtvConnectionManager.getLoggedIn()) {
222                         shieldtvConnectionManager.handleCommand(channelUID, command);
223                         return;
224                     }
225                 }
226             } else if (CHANNEL_APP.equals(channelUID.getId())) {
227                 if (command instanceof StringType) {
228                     shieldtvConnectionManager.handleCommand(channelUID, command);
229                     return;
230                 }
231             }
232         }
233
234         if (googletvConnectionManager != null) {
235             googletvConnectionManager.handleCommand(channelUID, command);
236             return;
237         }
238
239         logger.warn("{} - Commands All Failed.  Please report this as a bug. {} {}", thingID, channelUID.getId(),
240                 command);
241     }
242
243     @Override
244     public void dispose() {
245         synchronized (monitorThingStatusJobLock) {
246             ScheduledFuture<?> monitorThingStatusJob = this.monitorThingStatusJob;
247             if (monitorThingStatusJob != null) {
248                 monitorThingStatusJob.cancel(true);
249             }
250         }
251
252         GoogleTVConnectionManager googletvConnectionManager = this.googletvConnectionManager;
253         ShieldTVConnectionManager shieldtvConnectionManager = this.shieldtvConnectionManager;
254
255         if (shieldtvConnectionManager != null) {
256             shieldtvConnectionManager.dispose();
257         }
258
259         if (googletvConnectionManager != null) {
260             googletvConnectionManager.dispose();
261         }
262     }
263 }