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.rfxcom.internal.connector;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.util.TooManyListenersException;
19 import org.openhab.binding.rfxcom.internal.config.RFXComBridgeConfiguration;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
21 import org.openhab.core.io.transport.serial.PortInUseException;
22 import org.openhab.core.io.transport.serial.SerialPort;
23 import org.openhab.core.io.transport.serial.SerialPortEvent;
24 import org.openhab.core.io.transport.serial.SerialPortEventListener;
25 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
26 import org.openhab.core.io.transport.serial.SerialPortManager;
27 import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
28 import org.openhab.core.util.HexUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * RFXCOM connector for serial port communication.
35 * @author Pauli Anttila - Initial contribution
37 public class RFXComSerialConnector extends RFXComBaseConnector implements SerialPortEventListener {
38 private final Logger logger = LoggerFactory.getLogger(RFXComSerialConnector.class);
40 private OutputStream out;
41 private SerialPort serialPort;
42 private final SerialPortManager serialPortManager;
44 private final String readerThreadName;
45 private Thread readerThread;
47 public RFXComSerialConnector(SerialPortManager serialPortManager, String readerThreadName) {
49 this.serialPortManager = serialPortManager;
50 this.readerThreadName = readerThreadName;
54 public void connect(RFXComBridgeConfiguration device)
55 throws RFXComException, PortInUseException, UnsupportedCommOperationException, IOException {
56 SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(device.serialPort);
57 if (portIdentifier == null) {
58 logger.debug("No serial port {}", device.serialPort);
59 throw new RFXComException("No serial port " + device.serialPort);
62 SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
64 serialPort = commPort;
65 serialPort.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
66 serialPort.enableReceiveThreshold(1);
67 serialPort.enableReceiveTimeout(100); // In ms. Small values mean faster shutdown but more cpu usage.
69 in = serialPort.getInputStream();
70 out = serialPort.getOutputStream();
73 if (in.markSupported()) {
77 // RXTX serial port library causes high CPU load
78 // Start event listener, which will just sleep and slow down event loop
80 serialPort.addEventListener(this);
81 serialPort.notifyOnDataAvailable(true);
82 logger.debug("Serial port event listener started");
83 } catch (TooManyListenersException e) {
86 readerThread = new RFXComStreamReader(this, readerThreadName);
91 public void disconnect() {
92 logger.debug("Disconnecting");
94 if (serialPort != null) {
95 serialPort.removeEventListener();
96 logger.debug("Serial port event listener stopped");
99 if (readerThread != null) {
100 logger.debug("Interrupt serial listener");
101 readerThread.interrupt();
104 } catch (InterruptedException e) {
109 logger.debug("Close serial out stream");
112 } catch (IOException e) {
113 logger.debug("Error while closing the out stream: {}", e.getMessage());
117 logger.debug("Close serial in stream");
120 } catch (IOException e) {
121 logger.debug("Error while closing the in stream: {}", e.getMessage());
125 if (serialPort != null) {
126 logger.debug("Close serial port");
135 logger.debug("Closed");
139 public void sendMessage(byte[] data) throws IOException {
141 throw new IOException("Not connected sending messages is not possible");
144 if (logger.isTraceEnabled()) {
145 logger.trace("Send data (len={}): {}", data.length, HexUtils.bytesToHex(data));
153 public void serialEvent(SerialPortEvent arg0) {
156 * See more details from
157 * https://github.com/NeuronRobotics/nrjavaserial/issues/22
159 logger.trace("RXTX library CPU load workaround, sleep forever");
160 Thread.sleep(Long.MAX_VALUE);
161 } catch (InterruptedException ignore) {