]> git.basschouten.com Git - openhab-addons.git/commitdiff
[oceanic] Remove dependency on RXTX for serial communication (#15044)
authorKarel Goderis <karel.goderis@me.com>
Fri, 2 Jun 2023 19:57:32 +0000 (21:57 +0200)
committerGitHub <noreply@github.com>
Fri, 2 Jun 2023 19:57:32 +0000 (21:57 +0200)
Signed-off-by: Karel Goderis <karel.goderis@me.com>
bundles/org.openhab.binding.oceanic/pom.xml
bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicHandlerFactory.java
bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java
bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java

index da59973c9a305cf3db013f1b465d9a894d2613e8..de8af3662dd11020f72000c563c40cce99878195 100644 (file)
@@ -14,8 +14,4 @@
 
   <name>openHAB Add-ons :: Bundles :: Oceanic Binding</name>
 
-  <properties>
-    <bnd.importpackage>gnu.io;version="[3.12,6)"</bnd.importpackage>
-  </properties>
-
 </project>
index 6e4dfee7faa9b2b56231def47971f1a0454e2430..7496b00bc2076799483f478b72990994887a433c 100644 (file)
@@ -21,12 +21,15 @@ import java.util.stream.Stream;
 
 import org.openhab.binding.oceanic.internal.handler.NetworkOceanicThingHandler;
 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.ThingTypeUID;
 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
 import org.openhab.core.thing.binding.ThingHandler;
 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.Reference;
 
 /**
  * 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
             .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
     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
         return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
@@ -50,7 +60,7 @@ public class OceanicHandlerFactory extends BaseThingHandlerFactory {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (thingTypeUID.equals(THING_TYPE_SERIAL)) {
-            return new SerialOceanicThingHandler(thing);
+            return new SerialOceanicThingHandler(thing, serialPortManager);
         }
         if (thingTypeUID.equals(THING_TYPE_NETWORK)) {
             return new NetworkOceanicThingHandler(thing);
index 1722a082fd70adc71638d9d33ff6e6fff96e3424..a2def1158e5713ffeb13959d9b8b164ef23db8e1 100644 (file)
@@ -63,10 +63,12 @@ public class NetworkOceanicThingHandler extends OceanicThingHandler {
 
         try {
             socket = new Socket(config.ipAddress, config.portNumber);
-            socket.setSoTimeout(REQUEST_TIMEOUT);
-            outputStream = socket.getOutputStream();
-            inputStream = socket.getInputStream();
-            updateStatus(ThingStatus.ONLINE);
+            if (socket != null) {
+                socket.setSoTimeout(REQUEST_TIMEOUT);
+                outputStream = socket.getOutputStream();
+                inputStream = socket.getInputStream();
+                updateStatus(ThingStatus.ONLINE);
+            }
         } catch (UnknownHostException e) {
             logger.error("An exception occurred while resolving host {}:{} : '{}'", config.ipAddress, config.portNumber,
                     e.getMessage());
index b2444bcbcba02af78b59579c74ec505c6c28d06f..125747e2bb356c8ff40d95f4d72113d0508b140a 100644 (file)
@@ -17,45 +17,47 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.text.SimpleDateFormat;
 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.openhab.binding.oceanic.internal.SerialOceanicBindingConfiguration;
 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.ThingStatus;
 import org.openhab.core.thing.ThingStatusDetail;
 import org.slf4j.Logger;
 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
  * directly connected to a serial port of the openHAB host
  *
  * @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 int BAUD = 19200;
 
     private final Logger logger = LoggerFactory.getLogger(SerialOceanicThingHandler.class);
 
+    private final SerialPortManager serialPortManager;
     private SerialPort serialPort;
-    private CommPortIdentifier portId;
     private InputStream inputStream;
     private OutputStream outputStream;
     private SerialPortReader readerThread;
 
-    public SerialOceanicThingHandler(Thing thing) {
+    public SerialOceanicThingHandler(Thing thing, SerialPortManager serialPortManager) {
         super(thing);
+        this.serialPortManager = serialPortManager;
     }
 
     @Override
@@ -65,73 +67,46 @@ public class SerialOceanicThingHandler extends OceanicThingHandler {
         SerialOceanicBindingConfiguration config = getConfigAs(SerialOceanicBindingConfiguration.class);
 
         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) {
-                try {
-                    serialPort = portId.open(this.getThing().getUID().getBindingId(), 2000);
-                } catch (PortInUseException e) {
-                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                            "Could not open serial port " + serialPort + ": " + e.getMessage());
-                    return;
-                }
+            SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(config.port);
 
-                try {
-                    inputStream = serialPort.getInputStream();
-                } catch (IOException e) {
-                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                            "Could not open serial port " + serialPort + ": " + e.getMessage());
-                    return;
-                }
+            if (portIdentifier == null) {
+                String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName())
+                        .collect(Collectors.joining(System.lineSeparator()));
+                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;
+            }
 
-                serialPort.notifyOnDataAvailable(true);
+            try {
+                logger.info("Connecting to the Oceanic water softener using {}.", config.port);
+                serialPort = portIdentifier.open(this.getThing().getUID().getBindingId(), 2000);
 
-                try {
-                    serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
-                            SerialPort.PARITY_NONE);
-                    serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
-                } catch (UnsupportedCommOperationException e) {
-                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                            "Could not configure serial port " + serialPort + ": " + e.getMessage());
-                    return;
-                }
+                serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
+                        SerialPort.PARITY_NONE);
+                serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
+                serialPort.enableReceiveThreshold(1);
+                serialPort.disableReceiveTimeout();
 
-                try {
-                    outputStream = serialPort.getOutputStream();
-                    updateStatus(ThingStatus.ONLINE);
-                } catch (IOException e) {
-                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
-                            "Could not communicate with the serial port " + serialPort + ": " + e.getMessage());
-                    return;
-                }
+                inputStream = serialPort.getInputStream();
+                outputStream = serialPort.getOutputStream();
+
+                serialPort.addEventListener(this);
+                serialPort.notifyOnDataAvailable(true);
 
                 readerThread = new SerialPortReader(inputStream);
                 readerThread.start();
-            } else {
-                StringBuilder sb = new StringBuilder();
-                @SuppressWarnings("rawtypes")
-                Enumeration portList = CommPortIdentifier.getPortIdentifiers();
-                while (portList.hasMoreElements()) {
-                    CommPortIdentifier id = (CommPortIdentifier) portList.nextElement();
-                    if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) {
-                        sb.append(id.getName() + "\n");
-                    }
-                }
-                logger.error("Serial port '{}' could not be found. Available ports are:\n {}", config.port, sb);
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
+
+                updateStatus(ThingStatus.ONLINE);
+
+            } catch (PortInUseException portInUseException) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port in use: " + config.port);
+            } catch (UnsupportedCommOperationException | IOException e) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication error");
+            } catch (TooManyListenersException e) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "Too many listeners to serial port.");
             }
         }
     }
@@ -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 {
 
         private boolean interrupted = false;