]> git.basschouten.com Git - openhab-addons.git/blob
f752d4ace3df5966408d4876080cf407d09e9249
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.insteon.internal.driver;
14
15 import java.io.EOFException;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19
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;
26
27 /**
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)
30  *
31  * @author Bernd Pfrommer - Initial contribution
32  * @author Daniel Pfrommer - openHAB 1 insteonplm binding
33  * @author Rob Nielsen - Port to openHAB 2 insteon binding
34  */
35 @NonNullByDefault
36 public abstract class IOStream {
37     private static final Logger logger = LoggerFactory.getLogger(IOStream.class);
38     protected @Nullable InputStream in = null;
39     protected @Nullable OutputStream out = null;
40     private volatile boolean stopped = false;
41
42     public void start() {
43         stopped = false;
44     }
45
46     public void stop() {
47         stopped = true;
48     }
49
50     /**
51      * read data from iostream
52      *
53      * @param b byte array (output)
54      * @param offset offset for placement into byte array
55      * @param readSize size to read
56      * @return number of bytes read
57      */
58     public int read(byte[] b, int offset, int readSize) throws InterruptedException, IOException {
59         int len = 0;
60         while (!stopped && len < 1) {
61             InputStream in = this.in;
62             if (in != null) {
63                 len = in.read(b, offset, readSize);
64             } else {
65                 throw new IOException("in is null");
66             }
67             if (len == -1) {
68                 throw new EOFException();
69             }
70
71             if (Thread.interrupted()) {
72                 throw new InterruptedException();
73             }
74         }
75         return (len);
76     }
77
78     /**
79      * Write data to iostream
80      *
81      * @param b byte array to write
82      */
83     public void write(byte @Nullable [] b) throws IOException {
84         OutputStream out = this.out;
85         if (out != null) {
86             out.write(b);
87         } else {
88             throw new IOException("out is null");
89         }
90     }
91
92     /**
93      * Opens the IOStream
94      *
95      * @return true if open was successful, false if not
96      */
97     public abstract boolean open();
98
99     /**
100      * Closes the IOStream
101      */
102     public abstract void close();
103
104     /**
105      * Creates an IOStream from an allowed config string:
106      *
107      * /dev/ttyXYZ (serial port like e.g. usb: /dev/ttyUSB0 or alias /dev/insteon)
108      *
109      * /hub2/user:password@myinsteonhub.mydomain.com:25105,poll_time=1000 (insteon hub2 (2014))
110      *
111      * /hub/myinsteonhub.mydomain.com:9761
112      *
113      * /tcp/serialportserver.mydomain.com:port (serial port exposed via tcp, eg. ser2net)
114      *
115      * @param config
116      * @return reference to IOStream
117      */
118
119     public static IOStream create(@Nullable SerialPortManager serialPortManager, String config) {
120         if (config.startsWith("/hub2/")) {
121             return makeHub2014Stream(config);
122         } else if (config.startsWith("/hub/") || config.startsWith("/tcp/")) {
123             return makeTCPStream(config);
124         } else {
125             return new SerialIOStream(serialPortManager, config);
126         }
127     }
128
129     private static HubIOStream makeHub2014Stream(String config) {
130         @Nullable
131         String user = null;
132         @Nullable
133         String pass = null;
134         int pollTime = 1000; // poll time in milliseconds
135
136         // Get rid of the /hub2/ part and split off options at the end
137         String[] parts = config.substring(6).split(",");
138
139         // Parse the first part, the address
140         String[] adr = parts[0].split("@");
141         String[] hostPort;
142         if (adr.length > 1) {
143             String[] userPass = adr[0].split(":");
144             user = userPass[0];
145             pass = userPass[1];
146             hostPort = adr[1].split(":");
147         } else {
148             hostPort = parts[0].split(":");
149         }
150         HostPort hp = new HostPort(hostPort, 25105);
151         // check if additional options are given
152         if (parts.length > 1) {
153             if (parts[1].trim().startsWith("poll_time")) {
154                 pollTime = Integer.parseInt(parts[1].split("=")[1].trim());
155             }
156         }
157         return new HubIOStream(hp.host, hp.port, pollTime, user, pass);
158     }
159
160     private static TcpIOStream makeTCPStream(String config) {
161         // Get rid of the /hub/ part and split off options at the end, if any
162         String[] parts = config.substring(5).split(",");
163         String[] hostPort = parts[0].split(":");
164         HostPort hp = new HostPort(hostPort, 9761);
165         return new TcpIOStream(hp.host, hp.port);
166     }
167
168     private static class HostPort {
169         public String host = "localhost";
170         public int port = -1;
171
172         HostPort(String[] hostPort, int defaultPort) {
173             port = defaultPort;
174             host = hostPort[0];
175             try {
176                 if (hostPort.length > 1) {
177                     port = Integer.parseInt(hostPort[1]);
178                 }
179             } catch (NumberFormatException e) {
180                 logger.warn("bad format for port {} ", hostPort[1], e);
181             }
182         }
183     }
184 }