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.insteon.internal.driver;
15 import java.io.EOFException;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.insteon.internal.driver.hub.HubIOStream;
23 import org.openhab.core.io.transport.serial.SerialPortManager;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Abstract class for implementation for I/O stream with anything that looks
29 * like a PLM (e.g. the insteon hubs, serial/usb connection etc)
31 * @author Bernd Pfrommer - Initial contribution
32 * @author Daniel Pfrommer - openHAB 1 insteonplm binding
33 * @author Rob Nielsen - Port to openHAB 2 insteon binding
36 @SuppressWarnings("null")
37 public abstract class IOStream {
38 private static final Logger logger = LoggerFactory.getLogger(IOStream.class);
39 protected @Nullable InputStream in = null;
40 protected @Nullable OutputStream out = null;
41 private volatile boolean stopped = false;
52 * read data from iostream
54 * @param b byte array (output)
55 * @param offset offset for placement into byte array
56 * @param readSize size to read
57 * @return number of bytes read
59 public int read(byte[] b, int offset, int readSize) throws InterruptedException, IOException {
61 while (!stopped && len < 1) {
62 len = in.read(b, offset, readSize);
64 throw new EOFException();
67 if (Thread.interrupted()) {
68 throw new InterruptedException();
75 * Write data to iostream
77 * @param b byte array to write
79 public void write(byte @Nullable [] b) throws IOException {
86 * @return true if open was successful, false if not
88 public abstract boolean open();
93 public abstract void close();
96 * Creates an IOStream from an allowed config string:
98 * /dev/ttyXYZ (serial port like e.g. usb: /dev/ttyUSB0 or alias /dev/insteon)
100 * /hub2/user:password@myinsteonhub.mydomain.com:25105,poll_time=1000 (insteon hub2 (2014))
102 * /hub/myinsteonhub.mydomain.com:9761
104 * /tcp/serialportserver.mydomain.com:port (serial port exposed via tcp, eg. ser2net)
107 * @return reference to IOStream
110 public static IOStream create(@Nullable SerialPortManager serialPortManager, String config) {
111 if (config.startsWith("/hub2/")) {
112 return makeHub2014Stream(config);
113 } else if (config.startsWith("/hub/") || config.startsWith("/tcp/")) {
114 return makeTCPStream(config);
116 return new SerialIOStream(serialPortManager, config);
120 private static HubIOStream makeHub2014Stream(String config) {
125 int pollTime = 1000; // poll time in milliseconds
127 // Get rid of the /hub2/ part and split off options at the end
128 String[] parts = config.substring(6).split(",");
130 // Parse the first part, the address
131 String[] adr = parts[0].split("@");
133 if (adr.length > 1) {
134 String[] userPass = adr[0].split(":");
137 hostPort = adr[1].split(":");
139 hostPort = parts[0].split(":");
141 HostPort hp = new HostPort(hostPort, 25105);
142 // check if additional options are given
143 if (parts.length > 1) {
144 if (parts[1].trim().startsWith("poll_time")) {
145 pollTime = Integer.parseInt(parts[1].split("=")[1].trim());
148 return new HubIOStream(hp.host, hp.port, pollTime, user, pass);
151 private static TcpIOStream makeTCPStream(String config) {
152 // Get rid of the /hub/ part and split off options at the end, if any
153 String[] parts = config.substring(5).split(",");
154 String[] hostPort = parts[0].split(":");
155 HostPort hp = new HostPort(hostPort, 9761);
156 return new TcpIOStream(hp.host, hp.port);
160 private static class HostPort {
161 public String host = "localhost";
162 public int port = -1;
164 HostPort(String[] hostPort, int defaultPort) {
168 if (hostPort.length > 1) {
169 port = Integer.parseInt(hostPort[1]);
171 } catch (NumberFormatException e) {
172 logger.warn("bad format for port {} ", hostPort[1], e);