Skip to content

Commit

Permalink
Fix RFC2217 for Zigbee (#661)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Schall <github.com@mon-clan.de>
  • Loading branch information
dschall authored Oct 2, 2021
1 parent 0d9206e commit 436d4a9
Showing 1 changed file with 63 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.TooManyListenersException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import org.openhab.core.io.transport.serial.PortInUseException;
Expand Down Expand Up @@ -103,8 +103,6 @@ public class ZigBeeSerialPort implements ZigBeePort, SerialPortEventListener {
*/
private final Object bufferSynchronisationObject = new Object();

private Set<String> portOpenRuntimeExcepionMessages = ConcurrentHashMap.newKeySet();

/**
* Constructor setting port name and baud rate.
*
Expand Down Expand Up @@ -136,24 +134,40 @@ public boolean open(int baudRate, FlowControl flowControl) {
logger.debug("Connecting to serial port [{}] at {} baud, flow control {}.", portName, baudRate,
flowControl);

// in some rare cases we have to check whether a port really exists, because if it doesn't the call to
// CommPortIdentifier#open will kill the whole JVM
Stream<SerialPortIdentifier> serialPortIdentifiers = serialPortManager.getIdentifiers();
if (!serialPortIdentifiers.findAny().isPresent()) {
logger.debug("No communication ports found, cannot connect to [{}]", portName);
return false;
// In some rare cases we have to check whether a port really exists, because if it doesn't the call to
// CommPortIdentifier#open will kill the whole JVM.
// Virtual ports (like RFC2217) do not have a discovery logic, so we have to skip this check.
// TODO: Remove this check once nrjavaserial does no longer crash on non-existent ports.
if(!portName.toLowerCase().startsWith("rfc2217")) {
Stream<SerialPortIdentifier> serialPortIdentifiers = serialPortManager.getIdentifiers();
if (!serialPortIdentifiers.findAny().isPresent()) {
logger.debug("No communication ports found, cannot connect to [{}]", portName);
return false;
}
}

SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(portName);
if (portIdentifier == null) {
logger.error("Serial Error: Port {} does not exist.", portName);
logger.error("Serial Error: Port [{}] does not exist.", portName);
return false;
}

SerialPort localSerialPort;

try {
localSerialPort = portIdentifier.open("org.openhab.binding.zigbee", 100);
} catch (PortInUseException e) {
logger.error("Serial Error: Port [{}] is in use.", portName);
return false;
}

try {
localSerialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
logger.error("Failed to set serial port parameters on [{}]", portName);
return false;
}

try {
SerialPort localSerialPort = portIdentifier.open("org.openhab.binding.zigbee", 100);
localSerialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
switch (flowControl) {
case FLOWCONTROL_OUT_NONE:
localSerialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
Expand All @@ -167,41 +181,49 @@ public boolean open(int baudRate, FlowControl flowControl) {
default:
break;
}
} catch (UnsupportedCommOperationException e) {
logger.debug("Flow Control Mode {} is unsupported on [{}].", flowControl, portName);
}

try {
localSerialPort.enableReceiveTimeout(100);
localSerialPort.addEventListener(this);
localSerialPort.notifyOnDataAvailable(true);

logger.debug("Serial port [{}] is initialized.", portName);
serialPort = localSerialPort;
portOpenRuntimeExcepionMessages.clear();
} catch (PortInUseException e) {
logger.error("Serial Error: Port {} in use.", portName);
return false;
} catch (UnsupportedCommOperationException e) {
logger.error("Serial Error: Unsupported comm operation on Port {}.", portName);
return false;
} catch (TooManyListenersException e) {
logger.error("Serial Error: Too many listeners on Port {}.", portName);
return false;
} catch (RuntimeException e) {
if (!portOpenRuntimeExcepionMessages.contains(e.getMessage())) {
portOpenRuntimeExcepionMessages.add(e.getMessage());
logger.error("Serial Error: Device cannot be opened on Port {}. Caused by {}", portName,
e.getMessage());
}
logger.debug("Enabling receive timeout is unsupported on [{}]", portName);
}

try {
inputStream = localSerialPort.getInputStream();
} catch (IOException e) {
logger.debug("Failed to get input stream on [{}].", portName);
return false;
}

try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
outputStream = localSerialPort.getOutputStream();
} catch (IOException e) {
logger.debug("Failed to get output stream on [{}].", portName);
return false;
}

try {
localSerialPort.addEventListener(this);
} catch (TooManyListenersException e) {
logger.error("Serial Error: Too many listeners on [{}].", portName);
return false;
}

localSerialPort.notifyOnDataAvailable(true);

logger.debug("Serial port [{}] is initialized.", portName);

serialPort = localSerialPort;
return true;
} catch (Exception e) {
logger.error("Unable to open serial port: ", e);
} catch (RuntimeException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.close();
logger.error("Serial Error: Device cannot be opened on [{}]. Caused by {}, call stack: {}", portName, e.getMessage(), sw.toString());
return false;
}
}
Expand Down Expand Up @@ -241,6 +263,7 @@ public void write(int value) {
}
try {
outputStream.write(value);
outputStream.flush();
} catch (IOException e) {
}
}
Expand All @@ -257,6 +280,7 @@ public void write(int[] outArray) {
}
try {
outputStream.write(bytes);
outputStream.flush();
} catch (IOException e) {
}
}
Expand Down

0 comments on commit 436d4a9

Please sign in to comment.