2 * Copyright (c) 2010-2020 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.openwebnet.handler;
15 import static org.openhab.binding.openwebnet.OpenWebNetBindingConstants.*;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
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;
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
47 * @author Massimo Valla - Initial contribution
50 public abstract class OpenWebNetThingHandler extends BaseThingHandler {
52 private final Logger logger = LoggerFactory.getLogger(OpenWebNetThingHandler.class);
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
58 protected @Nullable ScheduledFuture<?> refreshTimeout;
60 public OpenWebNetThingHandler(Thing thing) {
65 public void initialize() {
66 Bridge bridge = getBridge();
68 OpenWebNetBridgeHandler brH = (OpenWebNetBridgeHandler) bridge.getHandler();
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");
76 String deviceWhereStr = (String) getConfig().get(CONFIG_PROPERTY_WHERE);
79 if (brH.isBusGateway()) {
80 w = new WhereLightAutom(deviceWhereStr);
82 w = new WhereZigBee(deviceWhereStr);
84 } catch (IllegalArgumentException ia) {
85 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
86 "WHERE parameter in configuration is invalid");
90 final String oid = brH.ownIdFromDeviceWhere(w, this);
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...");
101 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
102 "No bridge associated, please assign a bridge in thing configuration.");
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());
116 if (deviceWhere == null) {
117 logger.info("Cannot handle {} command for {}: 'where' parameter is not configured or is invalid",
118 command, getThing().getUID());
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)");
129 }, THING_STATE_REQ_TIMEOUT_SEC, TimeUnit.SECONDS);
131 handleChannelCommand(channel, command);
134 logger.debug("Thing {} is not associated to any gateway, skipping command", getThing().getUID());
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
142 * @param channel specific ChannleUID
143 * @param command the Command to be executed
145 protected abstract void handleChannelCommand(ChannelUID channel, Command command);
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.
151 * @param msg the message to handle
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);
161 * Helper method to send OWN messages from ThingsHandlers
163 protected @Nullable Response send(OpenMessage msg) throws OWNException {
164 OpenWebNetBridgeHandler handler = bridgeHandler;
165 if (handler != null) {
166 OpenGateway gw = handler.gateway;
175 * Helper method to send with high priority OWN messages from ThingsHandlers
177 protected @Nullable Response sendHighPriority(OpenMessage msg) throws OWNException {
178 OpenWebNetBridgeHandler handler = bridgeHandler;
179 if (handler != null) {
180 OpenGateway gw = handler.gateway;
182 return gw.sendHighPriority(msg);
189 * Request to gateway state for thing channel. It must be implemented by each specific device handler.
191 * @param channel the channel to request the state for
193 protected abstract void requestChannelState(ChannelUID channel);
196 public void dispose() {
197 OpenWebNetBridgeHandler bh = bridgeHandler;
199 if (bh != null && oid != null) {
200 bh.unregisterDevice(oid);
202 ScheduledFuture<?> sc = refreshTimeout;
210 * Returns a prefix String for ownId specific for each handler. To be implemented by sub-classes.
214 protected abstract String ownIdPrefix();