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