]> git.basschouten.com Git - openhab-addons.git/blob
3326e087beba788f057eb3ecf2f61bd489ee6639
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.nikobus.internal.protocol;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.util.TooManyListenersException;
19 import java.util.function.Consumer;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.core.io.transport.serial.PortInUseException;
24 import org.openhab.core.io.transport.serial.SerialPort;
25 import org.openhab.core.io.transport.serial.SerialPortEvent;
26 import org.openhab.core.io.transport.serial.SerialPortEventListener;
27 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
28 import org.openhab.core.io.transport.serial.SerialPortManager;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * The {@link NikobusConnection } is responsible for creating connections to clients.
34  *
35  * @author Boris Krivonog - Initial contribution
36  */
37 @NonNullByDefault
38 public class NikobusConnection implements SerialPortEventListener {
39     private final Logger logger = LoggerFactory.getLogger(NikobusConnection.class);
40     private final SerialPortManager serialPortManager;
41     private final String portName;
42     private final Consumer<Byte> processData;
43     private @Nullable SerialPort serialPort;
44
45     public NikobusConnection(SerialPortManager serialPortManager, String portName, Consumer<Byte> processData) {
46         this.serialPortManager = serialPortManager;
47         this.portName = portName;
48         this.processData = processData;
49     }
50
51     /**
52      * Return true if this manager is connected.
53      *
54      * @return
55      */
56     public boolean isConnected() {
57         return serialPort != null;
58     }
59
60     /**
61      * Connect to the receiver.
62      *
63      **/
64     public void connect() throws IOException {
65         if (isConnected()) {
66             return;
67         }
68
69         SerialPortIdentifier portId = serialPortManager.getIdentifier(portName);
70         if (portId == null) {
71             throw new IOException(String.format("Port '%s' is not known!", portName));
72         }
73
74         logger.info("Connecting to {}", portName);
75
76         try {
77             SerialPort serialPort = portId.open("org.openhab.binding.nikobus.pc-link", 2000);
78             serialPort.addEventListener(this);
79             serialPort.notifyOnDataAvailable(true);
80             this.serialPort = serialPort;
81             logger.info("Connected to {}", portName);
82         } catch (PortInUseException e) {
83             throw new IOException(String.format("Port '%s' is in use!", portName), e);
84         } catch (TooManyListenersException e) {
85             throw new IOException(String.format("Cannot attach listener to port '%s'!", portName), e);
86         }
87     }
88
89     /**
90      * Closes the connection.
91      **/
92     public void close() {
93         SerialPort serialPort = this.serialPort;
94         this.serialPort = null;
95
96         if (serialPort != null) {
97             try {
98                 serialPort.removeEventListener();
99                 OutputStream outputStream = serialPort.getOutputStream();
100                 if (outputStream != null) {
101                     outputStream.close();
102                 }
103                 InputStream inputStream = serialPort.getInputStream();
104                 if (inputStream != null) {
105                     inputStream.close();
106                 }
107             } catch (IOException e) {
108                 logger.debug("Error closing serial port.", e);
109             } finally {
110                 serialPort.close();
111                 logger.debug("Closed serial port.");
112             }
113         }
114     }
115
116     /**
117      * Returns an output stream for this connection.
118      */
119     public @Nullable OutputStream getOutputStream() throws IOException {
120         SerialPort serialPort = this.serialPort;
121         if (serialPort == null) {
122             return null;
123         }
124         return serialPort.getOutputStream();
125     }
126
127     @Override
128     public void serialEvent(SerialPortEvent event) {
129         if (event.getEventType() != SerialPortEvent.DATA_AVAILABLE) {
130             return;
131         }
132         SerialPort serialPort = this.serialPort;
133         if (serialPort == null) {
134             return;
135         }
136         try {
137             InputStream inputStream = serialPort.getInputStream();
138             if (inputStream == null) {
139                 return;
140             }
141             byte[] readBuffer = new byte[64];
142             while (inputStream.available() > 0) {
143                 int length = inputStream.read(readBuffer);
144                 for (int i = 0; i < length; ++i) {
145                     processData.accept(readBuffer[i]);
146                 }
147             }
148         } catch (IOException e) {
149             logger.debug("Error reading from serial port: {}", e.getMessage(), e);
150         }
151     }
152 }