]> git.basschouten.com Git - openhab-addons.git/blob
d69da78f07eba6d818dda4050bdca8a2819bd1c1
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.openwebnet.handler;
14
15 import static org.openhab.binding.openwebnet.OpenWebNetBindingConstants.*;
16
17 import java.util.Map;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.core.thing.Bridge;
24 import org.openhab.core.thing.ChannelUID;
25 import org.openhab.core.thing.Thing;
26 import org.openhab.core.thing.ThingStatus;
27 import org.openhab.core.thing.ThingStatusDetail;
28 import org.openhab.core.thing.binding.BaseThingHandler;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.RefreshType;
31 import org.openwebnet4j.OpenGateway;
32 import org.openwebnet4j.communication.OWNException;
33 import org.openwebnet4j.communication.Response;
34 import org.openwebnet4j.message.BaseOpenMessage;
35 import org.openwebnet4j.message.OpenMessage;
36 import org.openwebnet4j.message.Where;
37 import org.openwebnet4j.message.WhereLightAutom;
38 import org.openwebnet4j.message.WhereZigBee;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link OpenWebNetThingHandler} is responsible for handling commands for a OpenWebNet device.
44  * It's the abstract class for all OpenWebNet things. It should be extended by each specific OpenWebNet category of
45  * device (WHO).
46  *
47  * @author Massimo Valla - Initial contribution
48  */
49 @NonNullByDefault
50 public abstract class OpenWebNetThingHandler extends BaseThingHandler {
51
52     private final Logger logger = LoggerFactory.getLogger(OpenWebNetThingHandler.class);
53
54     protected @Nullable OpenWebNetBridgeHandler bridgeHandler;
55     protected @Nullable String ownId; // OpenWebNet identifier for this device: WHO.WHERE
56     protected @Nullable Where deviceWhere; // this device Where address
57
58     protected @Nullable ScheduledFuture<?> refreshTimeout;
59
60     public OpenWebNetThingHandler(Thing thing) {
61         super(thing);
62     }
63
64     @Override
65     public void initialize() {
66         Bridge bridge = getBridge();
67         if (bridge != null) {
68             OpenWebNetBridgeHandler brH = (OpenWebNetBridgeHandler) bridge.getHandler();
69             if (brH != null) {
70                 bridgeHandler = brH;
71                 Object deviceWhereConfig = getConfig().get(CONFIG_PROPERTY_WHERE);
72                 if (!(deviceWhereConfig instanceof String)) {
73                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
74                             "WHERE parameter in configuration is null or invalid");
75                 } else {
76                     String deviceWhereStr = (String) getConfig().get(CONFIG_PROPERTY_WHERE);
77                     Where w;
78                     try {
79                         if (brH.isBusGateway()) {
80                             w = new WhereLightAutom(deviceWhereStr);
81                         } else {
82                             w = new WhereZigBee(deviceWhereStr);
83                         }
84                     } catch (IllegalArgumentException ia) {
85                         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
86                                 "WHERE parameter in configuration is invalid");
87                         return;
88                     }
89                     deviceWhere = w;
90                     final String oid = brH.ownIdFromDeviceWhere(w, this);
91                     ownId = oid;
92                     Map<String, String> properties = editProperties();
93                     properties.put(PROPERTY_OWNID, oid);
94                     updateProperties(properties);
95                     brH.registerDevice(oid, this);
96                     logger.debug("associated thing to bridge with ownId={}", ownId);
97                     updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "waiting state update...");
98                 }
99             }
100         } else {
101             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
102                     "No bridge associated, please assign a bridge in thing configuration.");
103         }
104     }
105
106     @Override
107     public void handleCommand(ChannelUID channel, Command command) {
108         logger.debug("handleCommand() (command={} - channel={})", command, channel);
109         OpenWebNetBridgeHandler handler = bridgeHandler;
110         if (handler != null) {
111             OpenGateway gw = handler.gateway;
112             if (gw != null && !gw.isConnected()) {
113                 logger.info("Cannot handle {} command for {}: gateway is not connected", command, getThing().getUID());
114                 return;
115             }
116             if (deviceWhere == null) {
117                 logger.info("Cannot handle {} command for {}: 'where' parameter is not configured or is invalid",
118                         command, getThing().getUID());
119                 return;
120             }
121             if (command instanceof RefreshType) {
122                 requestChannelState(channel);
123                 // set a schedule to put device OFFLINE if no answer is received after THING_STATE_REQ_TIMEOUT_SEC
124                 refreshTimeout = scheduler.schedule(() -> {
125                     if (thing.getStatus().equals(ThingStatus.UNKNOWN)) {
126                         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
127                                 "Could not get channel state (timer expired)");
128                     }
129                 }, THING_STATE_REQ_TIMEOUT_SEC, TimeUnit.SECONDS);
130             } else {
131                 handleChannelCommand(channel, command);
132             }
133         } else {
134             logger.debug("Thing {} is not associated to any gateway, skipping command", getThing().getUID());
135         }
136     }
137
138     /**
139      * Handles a command for the specific channel for this thing.
140      * It must be implemented by each specific OpenWebNet category of device (WHO), based on channel
141      *
142      * @param channel specific ChannleUID
143      * @param command the Command to be executed
144      */
145     protected abstract void handleChannelCommand(ChannelUID channel, Command command);
146
147     /**
148      * Handle incoming message from OWN network via bridge Thing, directed to this device. It should be further
149      * implemented by each specific device handler.
150      *
151      * @param msg the message to handle
152      */
153     protected void handleMessage(BaseOpenMessage msg) {
154         ThingStatus ts = getThing().getStatus();
155         if (ThingStatus.ONLINE != ts && ThingStatus.REMOVING != ts && ThingStatus.REMOVED != ts) {
156             updateStatus(ThingStatus.ONLINE);
157         }
158     }
159
160     /**
161      * Helper method to send OWN messages from ThingsHandlers
162      */
163     protected @Nullable Response send(OpenMessage msg) throws OWNException {
164         OpenWebNetBridgeHandler handler = bridgeHandler;
165         if (handler != null) {
166             OpenGateway gw = handler.gateway;
167             if (gw != null) {
168                 return gw.send(msg);
169             }
170         }
171         return null;
172     }
173
174     /**
175      * Helper method to send with high priority OWN messages from ThingsHandlers
176      */
177     protected @Nullable Response sendHighPriority(OpenMessage msg) throws OWNException {
178         OpenWebNetBridgeHandler handler = bridgeHandler;
179         if (handler != null) {
180             OpenGateway gw = handler.gateway;
181             if (gw != null) {
182                 return gw.sendHighPriority(msg);
183             }
184         }
185         return null;
186     }
187
188     /**
189      * Request to gateway state for thing channel. It must be implemented by each specific device handler.
190      *
191      * @param channel the channel to request the state for
192      */
193     protected abstract void requestChannelState(ChannelUID channel);
194
195     @Override
196     public void dispose() {
197         OpenWebNetBridgeHandler bh = bridgeHandler;
198         String oid = ownId;
199         if (bh != null && oid != null) {
200             bh.unregisterDevice(oid);
201         }
202         ScheduledFuture<?> sc = refreshTimeout;
203         if (sc != null) {
204             sc.cancel(true);
205         }
206         super.dispose();
207     }
208
209     /**
210      * Returns a prefix String for ownId specific for each handler. To be implemented by sub-classes.
211      *
212      * @return
213      */
214     protected abstract String ownIdPrefix();
215 }