]> git.basschouten.com Git - openhab-addons.git/blob
1b5970c058ef0af28be29ccee16d94251b01b1ea
[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.russound.internal.rio;
14
15 import org.openhab.binding.russound.internal.net.SocketSession;
16 import org.openhab.binding.russound.internal.net.SocketSessionListener;
17 import org.openhab.core.thing.Bridge;
18 import org.openhab.core.thing.ChannelUID;
19 import org.openhab.core.thing.Thing;
20 import org.openhab.core.thing.ThingStatus;
21 import org.openhab.core.thing.ThingStatusInfo;
22 import org.openhab.core.thing.binding.BaseThingHandler;
23
24 /**
25  * Represents the abstract base to a {@link BaseThingHandler} for common functionality to all Things. This abstract
26  * base provides management of the {@link AbstractRioProtocol}, parent {@link #bridgeStatusChanged(ThingStatusInfo)}
27  * event processing and the ability to get the current {@link SocketSession}.
28  * {@link #sendCommand(String)} and responses will be received on any {@link SocketSessionListener}
29  *
30  * @author Tim Roberts - Initial contribution
31  */
32 public abstract class AbstractThingHandler<E extends AbstractRioProtocol> extends BaseThingHandler
33         implements RioCallbackHandler {
34     /**
35      * The protocol handler for this base
36      */
37     private E protocolHandler;
38
39     /**
40      * Creates the handler from the given {@link Thing}
41      *
42      * @param thing a non-null {@link Thing}
43      */
44     protected AbstractThingHandler(Thing thing) {
45         super(thing);
46     }
47
48     /**
49      * Sets a new {@link AbstractRioProtocol} as the current protocol handler. If one already exists, it will be
50      * disposed of first.
51      *
52      * @param newProtocolHandler a, possibly null, {@link AbstractRioProtocol}
53      */
54     protected void setProtocolHandler(E newProtocolHandler) {
55         if (protocolHandler != null) {
56             protocolHandler.dispose();
57         }
58         protocolHandler = newProtocolHandler;
59     }
60
61     /**
62      * Get's the {@link AbstractRioProtocol} handler. May be null if none currently exists
63      *
64      * @return an {@link AbstractRioProtocol} handler or null if none exists
65      */
66     protected E getProtocolHandler() {
67         return protocolHandler;
68     }
69
70     /**
71      * Overridden to simply get the protocol handler's {@link RioHandlerCallback}
72      *
73      * @return the {@link RioHandlerCallback} or null if not found
74      */
75     @Override
76     public RioHandlerCallback getRioHandlerCallback() {
77         final E protocolHandler = getProtocolHandler();
78         return protocolHandler == null ? null : protocolHandler.getCallback();
79     }
80
81     /**
82      * Returns the {@link SocketSession} for this {@link Bridge}. The default implementation is to look in the parent
83      * {@link #getBridge()} for the {@link SocketSession}
84      *
85      * @return a {@link SocketSession} or null if none exists
86      */
87     @SuppressWarnings("rawtypes")
88     protected SocketSession getSocketSession() {
89         final Bridge bridge = getBridge();
90         if (bridge != null && bridge.getHandler() instanceof AbstractBridgeHandler) {
91             return ((AbstractBridgeHandler) bridge.getHandler()).getSocketSession();
92         }
93         return null;
94     }
95
96     /**
97      * Overrides the base to initialize or dispose the handler based on the parent bridge status changing. If offline,
98      * {@link #dispose()} will be called instead. We then try to reinitialize ourselves when the bridge goes back online
99      * via the {@link #retryBridge()} method.
100      */
101     @Override
102     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
103         if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
104             reconnect();
105         } else {
106             disconnect();
107         }
108         super.bridgeStatusChanged(bridgeStatusInfo);
109     }
110
111     /**
112      * Overrides the base method to remove any state linked to the {@lin ChannelUID} from the
113      * {@link StatefulHandlerCallback}
114      */
115     @Override
116     public void channelUnlinked(ChannelUID channelUID) {
117         // Remove any state when unlinking (that way if it is relinked - we get it)
118         final RioHandlerCallback callback = getProtocolHandler().getCallback();
119         if (callback instanceof StatefulHandlerCallback) {
120             ((StatefulHandlerCallback) callback).removeState(channelUID.getId());
121         }
122         super.channelUnlinked(channelUID);
123     }
124
125     /**
126      * Base method to reconnect the handler. The base implementation will simply {@link #disconnect()} then
127      * {@link #initialize()} the handler.
128      */
129     protected void reconnect() {
130         disconnect();
131         initialize();
132     }
133
134     /**
135      * Base method to disconnect the handler. This implementation will simply call
136      * {@link #setProtocolHandler(AbstractRioProtocol)} to null.
137      */
138     protected void disconnect() {
139         setProtocolHandler(null);
140     }
141
142     /**
143      * Overrides the dispose to call the {@link #disconnect()} method to disconnect the handler
144      */
145     @Override
146     public void dispose() {
147         disconnect();
148         super.dispose();
149     }
150 }