2 * Copyright (c) 2010-2021 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.hdanywhere.internal.handler;
15 import static org.apache.commons.lang.StringUtils.isNotBlank;
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;
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;
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
41 * @author Karel Goderis - Initial contribution
43 public class MultiroomPlusHandler extends BaseThingHandler {
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";
50 private final Logger logger = LoggerFactory.getLogger(MultiroomPlusHandler.class);
52 private ScheduledFuture<?> pollingJob;
55 * the timeout to use for connecting to a given host (defaults to 5000
58 private static int timeout = 5000;
60 public MultiroomPlusHandler(Thing thing) {
64 private Runnable pollingRunnable = () -> {
66 String host = (String) getConfig().get(IP_ADDRESS);
67 int numberOfPorts = ((BigDecimal) getConfig().get(PORTS)).intValue();
69 String httpMethod = "GET";
70 String url = "http://" + host + "/status_show.shtml";
72 if (isNotBlank(httpMethod) && isNotBlank(url)) {
73 String response = HttpUtil.executeUrl(httpMethod, url, null, null, null, timeout);
75 if (response != null) {
76 updateStatus(ThingStatus.ONLINE);
78 for (int i = 1; i <= numberOfPorts; i++) {
79 Pattern p = Pattern.compile("var out" + i + "var = (.*);");
80 Matcher m = p.matcher(response);
83 DecimalType decimalType = new DecimalType(m.group(1));
84 updateState(new ChannelUID(getThing().getUID(), Port.get(i).channelID()), decimalType);
88 updateStatus(ThingStatus.OFFLINE);
91 } catch (Exception e) {
92 logger.warn("An exception occurred while polling the HDanwywhere matrix: '{}'", e.getMessage());
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);
102 String channelID = channelUID.getId();
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();
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 });
118 String httpMethod = "GET";
119 String url = "http://" + host + "/switch.cgi?command=3&data0=";
121 url = url + String.valueOf(outputPort) + "&data1=";
122 url = url + command.toString() + "&checksum=";
124 int checksum = 3 + outputPort + sourcePort;
125 url = url + String.valueOf(checksum);
128 HttpUtil.executeUrl(httpMethod, url, null, null, null, timeout);
129 } catch (IOException e) {
130 logger.error("Communication with device failed", e);
137 public void dispose() {
138 logger.debug("Disposing HDanywhere matrix handler.");
139 if (pollingJob != null && !pollingJob.isCancelled()) {
140 pollingJob.cancel(true);
146 public void initialize() {
147 logger.debug("Initializing HDanywhere Multiroom+ matrix handler.");
150 updateStatus(ThingStatus.UNKNOWN);
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);