]> git.basschouten.com Git - openhab-addons.git/blob
ad0f714c8442cf8f10856d5a99cd1a4ec20bb175
[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.hdanywhere.internal.handler;
14
15 import static org.apache.commons.lang.StringUtils.isNotBlank;
16
17 import java.io.IOException;
18 import java.math.BigDecimal;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import org.openhab.binding.hdanywhere.internal.HDanywhereBindingConstants.Port;
25 import org.openhab.core.io.net.http.HttpUtil;
26 import org.openhab.core.library.types.DecimalType;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.binding.BaseThingHandler;
31 import org.openhab.core.types.Command;
32 import org.openhab.core.types.RefreshType;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * The {@link MultiroomPlusHandler} is responsible for handling commands, which are
38  * sent to one of the channels. It supports the Multiroom+ V1/2/3 matrix (Note: this matrix is not longer supported by
39  * HDanywhere)
40  *
41  * @author Karel Goderis - Initial contribution
42  */
43 public class MultiroomPlusHandler extends BaseThingHandler {
44
45     // List of Configurations constants
46     public static final String IP_ADDRESS = "ipAddress";
47     public static final String PORTS = "ports";
48     public static final String POLLING_INTERVAL = "interval";
49
50     private final Logger logger = LoggerFactory.getLogger(MultiroomPlusHandler.class);
51
52     private ScheduledFuture<?> pollingJob;
53
54     /**
55      * the timeout to use for connecting to a given host (defaults to 5000
56      * milliseconds)
57      */
58     private static int timeout = 5000;
59
60     public MultiroomPlusHandler(Thing thing) {
61         super(thing);
62     }
63
64     private Runnable pollingRunnable = () -> {
65         try {
66             String host = (String) getConfig().get(IP_ADDRESS);
67             int numberOfPorts = ((BigDecimal) getConfig().get(PORTS)).intValue();
68
69             String httpMethod = "GET";
70             String url = "http://" + host + "/status_show.shtml";
71
72             if (isNotBlank(httpMethod) && isNotBlank(url)) {
73                 String response = HttpUtil.executeUrl(httpMethod, url, null, null, null, timeout);
74
75                 if (response != null) {
76                     updateStatus(ThingStatus.ONLINE);
77
78                     for (int i = 1; i <= numberOfPorts; i++) {
79                         Pattern p = Pattern.compile("var out" + i + "var = (.*);");
80                         Matcher m = p.matcher(response);
81
82                         while (m.find()) {
83                             DecimalType decimalType = new DecimalType(m.group(1));
84                             updateState(new ChannelUID(getThing().getUID(), Port.get(i).channelID()), decimalType);
85                         }
86                     }
87                 } else {
88                     updateStatus(ThingStatus.OFFLINE);
89                 }
90             }
91         } catch (Exception e) {
92             logger.warn("An exception occurred while polling the HDanwywhere matrix: '{}'", e.getMessage());
93         }
94     };
95
96     @Override
97     public void handleCommand(ChannelUID channelUID, Command command) {
98         if (command instanceof RefreshType) {
99             // Simply schedule a single run of the polling runnable to refresh all channels
100             scheduler.schedule(pollingRunnable, 0, TimeUnit.SECONDS);
101         } else {
102             String channelID = channelUID.getId();
103
104             String host = (String) getConfig().get(IP_ADDRESS);
105             int numberOfPorts = ((BigDecimal) getConfig().get(PORTS)).intValue();
106             int sourcePort = Integer.valueOf(command.toString());
107             int outputPort = Port.get(channelID).toNumber();
108
109             if (sourcePort > numberOfPorts) {
110                 // nice try - we can switch to a port that does not physically exist
111                 logger.warn("Source port {} goes beyond the physical number of {} ports available on the matrix {}",
112                         new Object[] { sourcePort, numberOfPorts, host });
113             } else if (outputPort > numberOfPorts) {
114                 // nice try - we can switch to a port that does not physically exist
115                 logger.warn("Output port {} goes beyond the physical number of {} ports available on the matrix {}",
116                         new Object[] { outputPort, numberOfPorts, host });
117             } else {
118                 String httpMethod = "GET";
119                 String url = "http://" + host + "/switch.cgi?command=3&data0=";
120
121                 url = url + String.valueOf(outputPort) + "&data1=";
122                 url = url + command.toString() + "&checksum=";
123
124                 int checksum = 3 + outputPort + sourcePort;
125                 url = url + String.valueOf(checksum);
126
127                 try {
128                     HttpUtil.executeUrl(httpMethod, url, null, null, null, timeout);
129                 } catch (IOException e) {
130                     logger.error("Communication with device failed", e);
131                 }
132             }
133         }
134     }
135
136     @Override
137     public void dispose() {
138         logger.debug("Disposing HDanywhere matrix handler.");
139         if (pollingJob != null && !pollingJob.isCancelled()) {
140             pollingJob.cancel(true);
141             pollingJob = null;
142         }
143     }
144
145     @Override
146     public void initialize() {
147         logger.debug("Initializing HDanywhere Multiroom+ matrix handler.");
148         onUpdate();
149
150         updateStatus(ThingStatus.UNKNOWN);
151     }
152
153     private synchronized void onUpdate() {
154         if (pollingJob == null || pollingJob.isCancelled()) {
155             int pollingInterval = ((BigDecimal) getConfig().get(POLLING_INTERVAL)).intValue();
156             pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 1, pollingInterval, TimeUnit.SECONDS);
157         }
158     }
159 }