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.neohub.internal;
15 import static java.nio.charset.StandardCharsets.US_ASCII;
17 import java.io.IOException;
18 import java.io.InputStreamReader;
19 import java.io.OutputStreamWriter;
20 import java.net.InetSocketAddress;
21 import java.net.Socket;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * NeoHubConnector handles the ASCII based communication via TCP between openHAB
31 * @author Sebastian Prehn - Initial contribution
32 * @author Andrew Fiddian-Green - Refactoring for openHAB v2.x
36 public class NeoHubSocket {
38 private final Logger logger = LoggerFactory.getLogger(NeoHubSocket.class);
41 * Name of host or IP to connect to.
43 private final String hostname;
46 * The port to connect to
48 private final int port;
51 * The socket connect resp. read timeout value
53 private final int timeout;
55 public NeoHubSocket(final String hostname, final int portNumber, final int timeoutSeconds) {
56 this.hostname = hostname;
57 this.port = portNumber;
58 this.timeout = timeoutSeconds * 1000;
62 * sends the message over the network to the NeoHub and returns its response
64 * @param requestJson the message to be sent to the NeoHub
65 * @return responseJson received from NeoHub
66 * @throws NeoHubException, IOException
69 public String sendMessage(final String requestJson) throws IOException, NeoHubException {
70 IOException caughtException = null;
71 StringBuilder builder = new StringBuilder();
73 try (Socket socket = new Socket()) {
74 socket.connect(new InetSocketAddress(hostname, port), timeout);
75 socket.setSoTimeout(timeout);
77 try (InputStreamReader reader = new InputStreamReader(socket.getInputStream(), US_ASCII);
78 OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream(), US_ASCII)) {
79 if (logger.isDebugEnabled()) {
80 logger.debug("sending {} characters..", requestJson.length());
81 logger.debug(">> {}", requestJson);
84 writer.write(requestJson);
85 writer.write(0); // NULL terminate the command string
87 socket.shutdownOutput();
89 if (logger.isTraceEnabled()) {
90 logger.trace("sent {} characters..", requestJson.length());
95 // read until end of stream
96 while ((inChar = reader.read()) != -1) {
97 // a JSON block is terminated by a newline or NULL
98 if (!(done |= (inChar == '\n') || (inChar == 0))) {
99 builder.append((char) inChar);
103 } catch (IOException e) {
104 // catch IOExceptions here, and save them to be re-thrown later
108 String responseJson = builder.toString();
110 if (logger.isTraceEnabled()) {
111 logger.trace("received {} characters..", responseJson.length());
112 logger.trace("<< {}", responseJson);
115 if (logger.isDebugEnabled()) {
116 logger.debug("received {} characters (set log level to TRACE to see full string)..", responseJson.length());
117 logger.debug("<< {} ...", responseJson.substring(0, Math.min(responseJson.length(), 30)));
120 // if any type of Exception was caught above, re-throw it again to the caller
121 if (caughtException != null) {
122 throw caughtException;
125 if (responseJson.isEmpty()) {
126 throw new NeoHubException("empty response string");