[oceanic] Remove dependency on RXTX for serial communication (#15044)
Signed-off-by: Karel Goderis <karel.goderis@me.com>
This commit is contained in:
parent
3c1cbaa769
commit
93b888ad31
@ -14,8 +14,4 @@
|
|||||||
|
|
||||||
<name>openHAB Add-ons :: Bundles :: Oceanic Binding</name>
|
<name>openHAB Add-ons :: Bundles :: Oceanic Binding</name>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<bnd.importpackage>gnu.io;version="[3.12,6)"</bnd.importpackage>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -21,12 +21,15 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
import org.openhab.binding.oceanic.internal.handler.NetworkOceanicThingHandler;
|
import org.openhab.binding.oceanic.internal.handler.NetworkOceanicThingHandler;
|
||||||
import org.openhab.binding.oceanic.internal.handler.SerialOceanicThingHandler;
|
import org.openhab.binding.oceanic.internal.handler.SerialOceanicThingHandler;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link OceanicHandlerFactory} is responsible for creating things and
|
* The {@link OceanicHandlerFactory} is responsible for creating things and
|
||||||
@ -40,6 +43,13 @@ public class OceanicHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||||
.unmodifiableSet(Stream.of(THING_TYPE_SERIAL, THING_TYPE_NETWORK).collect(Collectors.toSet()));
|
.unmodifiableSet(Stream.of(THING_TYPE_SERIAL, THING_TYPE_NETWORK).collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
private final SerialPortManager serialPortManager;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public OceanicHandlerFactory(final @Reference SerialPortManager serialPortManager) {
|
||||||
|
this.serialPortManager = serialPortManager;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||||
@ -50,7 +60,7 @@ public class OceanicHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
if (thingTypeUID.equals(THING_TYPE_SERIAL)) {
|
if (thingTypeUID.equals(THING_TYPE_SERIAL)) {
|
||||||
return new SerialOceanicThingHandler(thing);
|
return new SerialOceanicThingHandler(thing, serialPortManager);
|
||||||
}
|
}
|
||||||
if (thingTypeUID.equals(THING_TYPE_NETWORK)) {
|
if (thingTypeUID.equals(THING_TYPE_NETWORK)) {
|
||||||
return new NetworkOceanicThingHandler(thing);
|
return new NetworkOceanicThingHandler(thing);
|
||||||
|
|||||||
@ -63,10 +63,12 @@ public class NetworkOceanicThingHandler extends OceanicThingHandler {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
socket = new Socket(config.ipAddress, config.portNumber);
|
socket = new Socket(config.ipAddress, config.portNumber);
|
||||||
|
if (socket != null) {
|
||||||
socket.setSoTimeout(REQUEST_TIMEOUT);
|
socket.setSoTimeout(REQUEST_TIMEOUT);
|
||||||
outputStream = socket.getOutputStream();
|
outputStream = socket.getOutputStream();
|
||||||
inputStream = socket.getInputStream();
|
inputStream = socket.getInputStream();
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
}
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
logger.error("An exception occurred while resolving host {}:{} : '{}'", config.ipAddress, config.portNumber,
|
logger.error("An exception occurred while resolving host {}:{} : '{}'", config.ipAddress, config.portNumber,
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
|
|||||||
@ -17,45 +17,47 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Enumeration;
|
import java.util.TooManyListenersException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openhab.binding.oceanic.internal.SerialOceanicBindingConfiguration;
|
import org.openhab.binding.oceanic.internal.SerialOceanicBindingConfiguration;
|
||||||
import org.openhab.binding.oceanic.internal.Throttler;
|
import org.openhab.binding.oceanic.internal.Throttler;
|
||||||
|
import org.openhab.core.io.transport.serial.PortInUseException;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPort;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortEvent;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortEventListener;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
|
||||||
|
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||||
|
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingStatus;
|
import org.openhab.core.thing.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import gnu.io.CommPortIdentifier;
|
|
||||||
import gnu.io.NoSuchPortException;
|
|
||||||
import gnu.io.PortInUseException;
|
|
||||||
import gnu.io.RXTXCommDriver;
|
|
||||||
import gnu.io.SerialPort;
|
|
||||||
import gnu.io.UnsupportedCommOperationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SerialOceanicThingHandler} implements {@link OceanicThingHandler} for an Oceanic water softener that is
|
* The {@link SerialOceanicThingHandler} implements {@link OceanicThingHandler} for an Oceanic water softener that is
|
||||||
* directly connected to a serial port of the openHAB host
|
* directly connected to a serial port of the openHAB host
|
||||||
*
|
*
|
||||||
* @author Karel Goderis - Initial contribution
|
* @author Karel Goderis - Initial contribution
|
||||||
*/
|
*/
|
||||||
public class SerialOceanicThingHandler extends OceanicThingHandler {
|
public class SerialOceanicThingHandler extends OceanicThingHandler implements SerialPortEventListener {
|
||||||
|
|
||||||
private static final long REQUEST_TIMEOUT = 10000;
|
private static final long REQUEST_TIMEOUT = 10000;
|
||||||
private static final int BAUD = 19200;
|
private static final int BAUD = 19200;
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(SerialOceanicThingHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(SerialOceanicThingHandler.class);
|
||||||
|
|
||||||
|
private final SerialPortManager serialPortManager;
|
||||||
private SerialPort serialPort;
|
private SerialPort serialPort;
|
||||||
private CommPortIdentifier portId;
|
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
private OutputStream outputStream;
|
private OutputStream outputStream;
|
||||||
private SerialPortReader readerThread;
|
private SerialPortReader readerThread;
|
||||||
|
|
||||||
public SerialOceanicThingHandler(Thing thing) {
|
public SerialOceanicThingHandler(Thing thing, SerialPortManager serialPortManager) {
|
||||||
super(thing);
|
super(thing);
|
||||||
|
this.serialPortManager = serialPortManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,73 +67,46 @@ public class SerialOceanicThingHandler extends OceanicThingHandler {
|
|||||||
SerialOceanicBindingConfiguration config = getConfigAs(SerialOceanicBindingConfiguration.class);
|
SerialOceanicBindingConfiguration config = getConfigAs(SerialOceanicBindingConfiguration.class);
|
||||||
|
|
||||||
if (serialPort == null && config.port != null) {
|
if (serialPort == null && config.port != null) {
|
||||||
if (portId == null) {
|
|
||||||
try {
|
|
||||||
RXTXCommDriver rxtxCommDriver = new RXTXCommDriver();
|
|
||||||
rxtxCommDriver.initialize();
|
|
||||||
CommPortIdentifier.addPortName(config.port, CommPortIdentifier.PORT_RAW, rxtxCommDriver);
|
|
||||||
portId = CommPortIdentifier.getPortIdentifier(config.port);
|
|
||||||
} catch (NoSuchPortException e) {
|
|
||||||
logger.error("An exception occurred while setting up serial port '{}' : '{}'", config.port,
|
|
||||||
e.getMessage(), e);
|
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
|
||||||
"Could not setup serial port " + serialPort + ": " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (portId != null) {
|
SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(config.port);
|
||||||
try {
|
|
||||||
serialPort = portId.open(this.getThing().getUID().getBindingId(), 2000);
|
if (portIdentifier == null) {
|
||||||
} catch (PortInUseException e) {
|
String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName())
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
.collect(Collectors.joining(System.lineSeparator()));
|
||||||
"Could not open serial port " + serialPort + ": " + e.getMessage());
|
String description = String.format("Serial port '%s' could not be found. Available ports are:%n%s",
|
||||||
|
config.port, availablePorts);
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inputStream = serialPort.getInputStream();
|
logger.info("Connecting to the Oceanic water softener using {}.", config.port);
|
||||||
} catch (IOException e) {
|
serialPort = portIdentifier.open(this.getThing().getUID().getBindingId(), 2000);
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
|
||||||
"Could not open serial port " + serialPort + ": " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
serialPort.notifyOnDataAvailable(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
|
serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
|
||||||
SerialPort.PARITY_NONE);
|
SerialPort.PARITY_NONE);
|
||||||
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
|
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
|
||||||
} catch (UnsupportedCommOperationException e) {
|
serialPort.enableReceiveThreshold(1);
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
serialPort.disableReceiveTimeout();
|
||||||
"Could not configure serial port " + serialPort + ": " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
inputStream = serialPort.getInputStream();
|
||||||
outputStream = serialPort.getOutputStream();
|
outputStream = serialPort.getOutputStream();
|
||||||
updateStatus(ThingStatus.ONLINE);
|
|
||||||
} catch (IOException e) {
|
serialPort.addEventListener(this);
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
serialPort.notifyOnDataAvailable(true);
|
||||||
"Could not communicate with the serial port " + serialPort + ": " + e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
readerThread = new SerialPortReader(inputStream);
|
readerThread = new SerialPortReader(inputStream);
|
||||||
readerThread.start();
|
readerThread.start();
|
||||||
} else {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
updateStatus(ThingStatus.ONLINE);
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
|
} catch (PortInUseException portInUseException) {
|
||||||
while (portList.hasMoreElements()) {
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port in use: " + config.port);
|
||||||
CommPortIdentifier id = (CommPortIdentifier) portList.nextElement();
|
} catch (UnsupportedCommOperationException | IOException e) {
|
||||||
if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) {
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication error");
|
||||||
sb.append(id.getName() + "\n");
|
} catch (TooManyListenersException e) {
|
||||||
}
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
}
|
"Too many listeners to serial port.");
|
||||||
logger.error("Serial port '{}' could not be found. Available ports are:\n {}", config.port, sb);
|
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,6 +192,13 @@ public class SerialOceanicThingHandler extends OceanicThingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialEvent(SerialPortEvent serialPortEvent) {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Received a serial port event : {}", serialPortEvent.getEventType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class SerialPortReader extends Thread {
|
public class SerialPortReader extends Thread {
|
||||||
|
|
||||||
private boolean interrupted = false;
|
private boolean interrupted = false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user