]> git.basschouten.com Git - openhab-addons.git/blob
6d089732c9e4b41484b03fdc8ada6bd3479a7f31
[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.unifi.internal.handler;
14
15 import static org.openhab.core.thing.ThingStatus.OFFLINE;
16 import static org.openhab.core.thing.ThingStatus.ONLINE;
17 import static org.openhab.core.types.RefreshType.REFRESH;
18
19 import java.lang.reflect.ParameterizedType;
20 import java.util.Optional;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.unifi.internal.api.UniFiController;
25 import org.openhab.binding.unifi.internal.api.UniFiException;
26 import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
27 import org.openhab.core.thing.Bridge;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.thing.binding.BaseThingHandler;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.State;
34 import org.openhab.core.types.UnDefType;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * @author Matthew Bowman - Initial contribution
40  *
41  * @param <E> entity - the UniFi entity class used by this thing handler
42  * @param <C> config - the UniFi config class used by this thing handler
43  */
44 @NonNullByDefault
45 public abstract class UniFiBaseThingHandler<E, C> extends BaseThingHandler {
46
47     private final Logger logger = LoggerFactory.getLogger(UniFiBaseThingHandler.class);
48
49     public UniFiBaseThingHandler(final Thing thing) {
50         super(thing);
51     }
52
53     @Override
54     @SuppressWarnings("unchecked")
55     public final void initialize() {
56         final Bridge bridge = getBridge();
57         if (bridge == null || bridge.getHandler() == null
58                 || !(bridge.getHandler() instanceof UniFiControllerThingHandler)) {
59             updateStatus(OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
60                     "@text/error.thing.offline.configuration_error");
61             return;
62         }
63         // mgb: derive the config class from the generic type
64         @SuppressWarnings("null")
65         final Class<?> clazz = (Class<?>) (((ParameterizedType) getClass().getGenericSuperclass())
66                 .getActualTypeArguments()[1]);
67         final C config = (C) getConfigAs(clazz);
68         if (initialize(config)) {
69             if (bridge.getStatus() == OFFLINE) {
70                 updateStatus(OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "@text/error.thing.offline.bridge_offline");
71                 return;
72             } else {
73                 updateStatus(ONLINE);
74             }
75         }
76     }
77
78     /**
79      * Utility method to access the {@link UniFiController} instance associated with this thing.
80      *
81      * @return
82      */
83     @SuppressWarnings("null")
84     private final @Nullable UniFiController getController() {
85         final Bridge bridge = getBridge();
86         if (bridge != null && bridge.getHandler() != null
87                 && (bridge.getHandler() instanceof UniFiControllerThingHandler)) {
88             return ((UniFiControllerThingHandler) bridge.getHandler()).getController();
89         }
90         return null;
91     }
92
93     private @Nullable E getEntity() {
94         final UniFiController controller = getController();
95         return controller == null ? null : getEntity(controller.getCache());
96     }
97
98     @Override
99     public final void handleCommand(final ChannelUID channelUID, final Command command) {
100         logger.debug("Handling command = {} for channel = {}", command, channelUID);
101         // mgb: only handle commands if we're ONLINE
102         if (getThing().getStatus() == ONLINE) {
103             final @Nullable E entity = getEntity();
104             final UniFiController controller = getController();
105
106             if (command == REFRESH) {
107                 updateState(entity, channelUID);
108             } else {
109                 if (entity != null && controller != null) {
110                     try {
111                         if (!handleCommand(controller, entity, channelUID, command)) {
112                             logger.info("Ignoring unsupported command = {} for channel = {}", command, channelUID);
113                         }
114                     } catch (final UniFiException e) {
115                         logger.info("Unexpected error handling command = {} for channel = {} : {}", command, channelUID,
116                                 e.getMessage());
117                     }
118                 } else {
119                     logger.info(
120                             "Could not handle command {} for channel = {} because no entity/controller data available.",
121                             command, channelUID);
122                 }
123             }
124         } else {
125             logger.info("Could not handle command {} for channel = {} because thing not online.", command, channelUID);
126         }
127     }
128
129     protected final void refresh() {
130         // mgb: only refresh if we're ONLINE
131         if (getThing().getStatus() == ONLINE) {
132             final @Nullable E entity = getEntity();
133
134             getThing().getChannels().forEach(channel -> updateState(entity, channel.getUID()));
135         }
136     }
137
138     private void updateState(final @Nullable E entity, final ChannelUID channelUID) {
139         final String channelId = channelUID.getId();
140         final State state = Optional.ofNullable(entity).map(e -> getChannelState(e, channelId))
141                 .orElseGet(() -> getDefaultState(channelId));
142
143         if (state != UnDefType.NULL) {
144             updateState(channelUID, state);
145         }
146     }
147
148     /**
149      * Additional sub class specific initialization.
150      * If initialization is unsuccessful it should set the thing status and return false.
151      * if it was successful it should return true
152      *
153      * @param config thing configuration
154      * @return true if initialization was successful
155      */
156     protected abstract boolean initialize(C config);
157
158     /**
159      * Returns the default state if no data available. Default implementation return {@link UnDefType#UNDEF}.
160      *
161      * @param channelId channel to update
162      * @return default state
163      */
164     protected State getDefaultState(final String channelId) {
165         return UnDefType.UNDEF;
166     }
167
168     /**
169      * Returns the cached UniFi entity object related to this thing.
170      *
171      * @param cache cache to get the cached entity from
172      * @return cached entry or null if not exists
173      */
174     protected abstract @Nullable E getEntity(UniFiControllerCache cache);
175
176     /**
177      * Returns the state to set for the given channel. If {@link UnDefType#NULL} is returned it means the channel should
178      * not be updated.
179      *
180      * @param entity UniFi entity object to get the state information from
181      * @param channelId Channel to update
182      * @return state to set or {@link UnDefType#NULL} if channel state should not be updated.
183      */
184     protected abstract State getChannelState(E entity, String channelId);
185
186     /**
187      * Send the given command to the UniFi controller.
188      *
189      * @param controller controller object to use to send the command to the UniFi controller
190      * @param entity data object of the thing to send command to
191      * @param channelUID channel the command is from
192      * @param command command to send
193      * @return true if command was send
194      * @throws UniFiException
195      */
196     protected abstract boolean handleCommand(UniFiController controller, E entity, ChannelUID channelUID,
197             Command command) throws UniFiException;
198 }