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.hdanywhere.internal.handler;
15 import static org.apache.commons.lang.StringUtils.isNotBlank;
17 import java.io.ByteArrayInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.math.BigDecimal;
21 import java.nio.charset.StandardCharsets;
23 import java.util.Properties;
24 import java.util.concurrent.ScheduledFuture;
25 import java.util.concurrent.TimeUnit;
27 import org.openhab.binding.hdanywhere.internal.HDanywhereBindingConstants.Port;
28 import org.openhab.core.io.net.http.HttpUtil;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.binding.BaseThingHandler;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.RefreshType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.gson.Gson;
40 import com.google.gson.reflect.TypeToken;
43 * The {@link Mhub4K431Handler} is responsible for handling commands, which are
44 * sent to one of the channels. It supports the MHUB 4K (4×3+1) matrix
46 * @author Karel Goderis - Initial contribution
48 public class Mhub4K431Handler extends BaseThingHandler {
50 // List of Configurations constants
51 public static final String IP_ADDRESS = "ipAddress";
52 // public static final String PORTS = "ports";
53 public static final String POLLING_INTERVAL = "interval";
55 private final Logger logger = LoggerFactory.getLogger(Mhub4K431Handler.class);
57 private ScheduledFuture<?> pollingJob;
58 protected final Gson gson = new Gson();
60 private final int timeout = 5000;
61 private final int numberOfPorts = 4;
63 public Mhub4K431Handler(Thing thing) {
68 public void initialize() {
69 logger.debug("Initializing HDanywhere MHUB 4K (4×3+1) matrix handler.");
71 if (pollingJob == null || pollingJob.isCancelled()) {
72 int pollingInterval = ((BigDecimal) getConfig().get(POLLING_INTERVAL)).intValue();
73 pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 1, pollingInterval, TimeUnit.SECONDS);
75 updateStatus(ThingStatus.UNKNOWN);
79 public void dispose() {
80 logger.debug("Disposing HDanywhere matrix handler.");
81 if (pollingJob != null && !pollingJob.isCancelled()) {
82 pollingJob.cancel(true);
87 private Runnable pollingRunnable = () -> {
89 String host = (String) getConfig().get(IP_ADDRESS);
91 String httpMethod = "POST";
92 String url = "http://" + host + "/cgi-bin/MUH44TP_getsetparams.cgi";
93 String content = "{tag:ptn}";
94 InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
96 if (isNotBlank(httpMethod) && isNotBlank(url)) {
97 String response = HttpUtil.executeUrl(httpMethod, url, null, stream, null, timeout);
98 response = response.trim();
99 response = response.substring(1, response.length() - 1);
101 if (response != null) {
102 updateStatus(ThingStatus.ONLINE);
104 java.lang.reflect.Type type = new TypeToken<Map<String, String>>() {
106 Map<String, String> map = gson.fromJson(response, type);
108 String inputChannel = map.get("Inputchannel");
110 for (int i = 0; i < numberOfPorts; i++) {
111 DecimalType decimalType = new DecimalType(String.valueOf(inputChannel.charAt(i)));
112 updateState(new ChannelUID(getThing().getUID(), Port.get(i + 1).channelID()), decimalType);
115 updateStatus(ThingStatus.OFFLINE);
118 } catch (Exception e) {
119 logger.debug("An exception occurred while polling the HDanwywhere matrix: '{}'", e.getMessage());
120 updateStatus(ThingStatus.OFFLINE);
125 public void handleCommand(ChannelUID channelUID, Command command) {
126 if (command instanceof RefreshType) {
127 // Simply schedule a single run of the polling runnable to refresh all channels
128 scheduler.schedule(pollingRunnable, 0, TimeUnit.SECONDS);
130 String channelID = channelUID.getId();
132 String host = (String) getConfig().get(IP_ADDRESS);
133 int sourcePort = Integer.valueOf(command.toString());
134 int outputPort = Port.get(channelID).toNumber();
136 if (sourcePort > numberOfPorts) {
137 // nice try - we can switch to a port that does not physically exist
138 logger.warn("Source port {} goes beyond the physical number of {} ports available on the matrix {}",
139 new Object[] { sourcePort, numberOfPorts, host });
140 } else if (outputPort > numberOfPorts) {
141 // nice try - we can switch to a port that does not physically exist
142 logger.warn("Output port {} goes beyond the physical number of {} ports available on the matrix {}",
143 new Object[] { outputPort, numberOfPorts, host });
145 String httpMethod = "POST";
146 String url = "http://" + host + "/cgi-bin/MMX32_Keyvalue.cgi";
148 String content = "{CMD=";
149 content = content + command.toString() + "B";
150 content = content + String.valueOf(outputPort) + ".";
152 InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
154 Properties httpHeaders = new Properties();
155 httpHeaders.setProperty("Cookie", "logintype-88=01");
158 String response = HttpUtil.executeUrl(httpMethod, url, httpHeaders, stream,
159 "application/x-www-form-urlencoded; charset=UTF-8", timeout);
160 } catch (IOException e) {
161 logger.debug("Communication with device failed", e);
162 updateStatus(ThingStatus.OFFLINE);