You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2019/08/11 14:32:06 UTC

[plc4x] branch netty-serial-nio updated: Some improvements.

This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch netty-serial-nio
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/netty-serial-nio by this push:
     new acfbbf4  Some improvements.
acfbbf4 is described below

commit acfbbf411032ef5880533bd0f2d1b4ad2542e1d6
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Sun Aug 11 16:31:59 2019 +0200

    Some improvements.
---
 .../plc4x/java/base/connection/SerialChannel.java  | 41 +++++++++++++++-------
 .../java/base/connection/SerialChannelFactory.java | 25 +++++++++----
 .../java/base/connection/SerialChannelHandler.java | 17 +++++++--
 .../java/base/connection/SerialSocketAddress.java  | 28 +++++++++++++++
 .../base/connection/SerialChannelFactoryTest.java  | 33 ++++++++++++++++-
 5 files changed, 120 insertions(+), 24 deletions(-)

diff --git a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannel.java b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannel.java
index 9c48cf8..aa7a32f 100644
--- a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannel.java
+++ b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannel.java
@@ -19,9 +19,7 @@
 
 package org.apache.plc4x.java.base.connection;
 
-import com.fazecast.jSerialComm.SerialPort;
-import com.fazecast.jSerialComm.SerialPortDataListener;
-import com.fazecast.jSerialComm.SerialPortEvent;
+import com.sun.org.apache.xml.internal.serializer.utils.SerializerMessages_ca;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.channel.AbstractChannel;
@@ -37,7 +35,6 @@ import io.netty.channel.EventLoop;
 import io.netty.channel.FileRegion;
 import io.netty.channel.RecvByteBufAllocator;
 import io.netty.channel.VoidChannelPromise;
-import io.netty.channel.jsc.JSerialCommDeviceAddress;
 import io.netty.channel.nio.AbstractNioByteChannel;
 import io.netty.channel.nio.AbstractNioChannel;
 import io.netty.channel.nio.NioEventLoop;
@@ -163,14 +160,18 @@ public class SerialChannel extends AbstractNioByteChannel implements DuplexChann
     @Override
     protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
         this.remoteAddress = remoteAddress;
-        if (!(remoteAddress instanceof JSerialCommDeviceAddress)) {
-            throw new IllegalArgumentException("Socket Address has to be of type " + JSerialCommDeviceAddress.class);
+        if (!(remoteAddress instanceof SerialSocketAddress)) {
+            throw new IllegalArgumentException("Socket Address has to be of type " + SerialSocketAddress.class);
         }
-        logger.debug("Connecting to Socket Address '{}'", ((JSerialCommDeviceAddress) remoteAddress).value());
+        logger.debug("Connecting to Socket Address '{}'", ((SerialSocketAddress) remoteAddress).getIdentifier());
 
         try {
-            // TODO this should take port from remote Adress
-            comPort = SerialChannelHandler.DummyHandler.INSTANCE;
+            // A bit hacky but to make a Test Connection start the String with TEST
+            if (((SerialSocketAddress) remoteAddress).getIdentifier().startsWith("TEST")) {
+                comPort = SerialChannelHandler.DummyHandler.INSTANCE;
+            } else {
+                comPort = new SerialChannelHandler.SerialPortHandler(remoteAddress);
+            }
             logger.debug("Using Com Port {}, trying to open port", comPort.getIdentifier());
             if (comPort.open()) {
                 logger.debug("Opened port successful to {}", comPort.getIdentifier());
@@ -189,6 +190,12 @@ public class SerialChannel extends AbstractNioByteChannel implements DuplexChann
         }
     }
 
+    @Override protected void doClose() throws Exception {
+        if (this.comPort != null) {
+            this.comPort.close();
+        }
+    }
+
     @Override
     protected void doFinishConnect() throws Exception {
         throw new NotImplementedException("");
@@ -383,6 +390,7 @@ public class SerialChannel extends AbstractNioByteChannel implements DuplexChann
 
         @Override
         public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
+            SerialChannel.this.remoteAddress = remoteAddress;
             eventLoop().execute(() -> {
                 try {
                     final boolean sucess = doConnect(remoteAddress, localAddress);
@@ -392,7 +400,7 @@ public class SerialChannel extends AbstractNioByteChannel implements DuplexChann
                         // Finally, close the promise
                         promise.setSuccess();
                     } else {
-                        promise.setFailure(new RuntimeException("Unable to open the com port " + remoteAddress.toString()));
+                        promise.setFailure(new RuntimeException("Unable to open the com port '" + ((SerialSocketAddress) remoteAddress).getIdentifier() + "'"));
                     }
                 } catch (Exception e) {
                     promise.setFailure(e);
@@ -407,9 +415,16 @@ public class SerialChannel extends AbstractNioByteChannel implements DuplexChann
 
         @Override
         public void close(ChannelPromise promise) {
-            logger.debug("Closing the Serial Port '{}'", this.remoteAddress());
-            // TODO this should close the Serial Port
-            throw new NotImplementedException("");
+            logger.debug("Closing the Serial Port '{}'", ((SerialSocketAddress) SerialChannel.this.remoteAddress).getIdentifier());
+            eventLoop().execute(() -> {
+                try {
+                    doClose();
+                    promise.setSuccess();
+                } catch (Exception e) {
+                    logger.warn("Unable to close the connection", e);
+                    promise.setFailure(e);
+                }
+            });
         }
 
         @Override
diff --git a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelFactory.java b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelFactory.java
index 27b84c3..2e0e422 100644
--- a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelFactory.java
+++ b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelFactory.java
@@ -22,13 +22,12 @@ import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelOption;
-import io.netty.channel.jsc.JSerialCommChannel;
-import io.netty.channel.jsc.JSerialCommDeviceAddress;
 import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.oio.OioEventLoopGroup;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 
+import java.net.SocketAddress;
 import java.util.concurrent.Executor;
 
 public class SerialChannelFactory implements ChannelFactory {
@@ -42,15 +41,27 @@ public class SerialChannelFactory implements ChannelFactory {
     @Override
     public Channel createChannel(ChannelHandler channelHandler)
         throws PlcConnectionException {
-        JSerialCommDeviceAddress address = new JSerialCommDeviceAddress(serialPort);
+        SocketAddress address = new SerialSocketAddress(serialPort);
 
         try {
             Bootstrap bootstrap = new Bootstrap();
-            bootstrap.group(new NioEventLoopGroup(0, (Executor)null, new SerialSelectorProvider()));
+            final NioEventLoopGroup eventLoop = new NioEventLoopGroup(0, (Executor) null, new SerialSelectorProvider());
+            bootstrap.group(eventLoop);
             bootstrap.channel(SerialChannel.class);
             bootstrap.handler(channelHandler);
             // Start the client.
-            ChannelFuture f = bootstrap.connect(address).sync();
+            ChannelFuture f = bootstrap.connect(address);
+            f.addListener(new GenericFutureListener<Future<? super Void>>() {
+                    @Override public void operationComplete(Future<? super Void> future) throws Exception {
+                        if (future.isSuccess()) {
+                            System.out.println("Connection sucesfull!");
+                        } else {
+                            System.out.println("Connection not sucessfull: " + future.cause().getMessage());
+                            eventLoop.shutdownGracefully();
+                        }
+                    }
+                });
+            f.sync();
             f.awaitUninterruptibly();
             // Wait till the session is finished initializing.
             return f.channel();
diff --git a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelHandler.java b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelHandler.java
index e001458..6773602 100644
--- a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelHandler.java
+++ b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialChannelHandler.java
@@ -6,6 +6,7 @@ import com.fazecast.jSerialComm.SerialPortEvent;
 import io.netty.channel.jsc.JSerialCommDeviceAddress;
 
 import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
 
 /**
  * This is a wrapper mostly for testing {@link SerialChannel}, @{@link SerialPollingSelector},
@@ -30,6 +31,8 @@ public abstract class SerialChannelHandler {
      */
     abstract void registerSelectionKey(SerialSelectionKey selectionKey);
 
+    public abstract void close();
+
     public static class DummyHandler extends SerialChannelHandler {
 
         public static final DummyHandler INSTANCE = new DummyHandler(null);
@@ -52,6 +55,10 @@ public abstract class SerialChannelHandler {
             this.selectionKey = selectionKey;
         }
 
+        @Override public void close() {
+            // NOOP
+        }
+
         public void fireEvent(int readyOp) {
             ((SerialPollingSelector) this.selectionKey.selector())
                 .addEvent(new SerialPollingSelector.SelectorEvent(this.selectionKey, readyOp));
@@ -65,7 +72,7 @@ public abstract class SerialChannelHandler {
 
         public SerialPortHandler(SocketAddress address) {
             super(address);
-            comPort = SerialPort.getCommPort(((JSerialCommDeviceAddress) address).value());
+            comPort = SerialPort.getCommPort(((SerialSocketAddress) address).getIdentifier());
         }
 
         @Override public boolean open() {
@@ -85,10 +92,14 @@ public abstract class SerialChannelHandler {
 
                 @Override
                 public void serialEvent(SerialPortEvent event) {
-                    // TODO notify the selector that something happens
-                    selectionKey.selector().wakeup();
+                    ((SerialPollingSelector) selectionKey.selector())
+                        .addEvent(new SerialPollingSelector.SelectorEvent(selectionKey, SelectionKey.OP_READ));
                 }
             });
         }
+
+        @Override public void close() {
+            this.comPort.closePort();
+        }
     }
 }
diff --git a/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialSocketAddress.java b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialSocketAddress.java
new file mode 100644
index 0000000..fc8fdea
--- /dev/null
+++ b/plc4j/protocols/driver-bases/serial/src/main/java/org/apache/plc4x/java/base/connection/SerialSocketAddress.java
@@ -0,0 +1,28 @@
+package org.apache.plc4x.java.base.connection;
+
+import java.net.SocketAddress;
+import java.util.Objects;
+
+public class SerialSocketAddress extends SocketAddress {
+
+    private final String identifier;
+
+    public SerialSocketAddress(String identifier) {
+        this.identifier = identifier;
+    }
+
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    @Override public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SerialSocketAddress that = (SerialSocketAddress) o;
+        return Objects.equals(identifier, that.identifier);
+    }
+
+    @Override public int hashCode() {
+        return Objects.hash(identifier);
+    }
+}
diff --git a/plc4j/protocols/driver-bases/serial/src/test/java/org/apache/plc4x/java/base/connection/SerialChannelFactoryTest.java b/plc4j/protocols/driver-bases/serial/src/test/java/org/apache/plc4x/java/base/connection/SerialChannelFactoryTest.java
index b333cda..3bea440 100644
--- a/plc4j/protocols/driver-bases/serial/src/test/java/org/apache/plc4x/java/base/connection/SerialChannelFactoryTest.java
+++ b/plc4j/protocols/driver-bases/serial/src/test/java/org/apache/plc4x/java/base/connection/SerialChannelFactoryTest.java
@@ -19,11 +19,13 @@
 
 package org.apache.plc4x.java.base.connection;
 
+import com.fazecast.jSerialComm.SerialPort;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFactory;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInitializer;
+import io.netty.channel.jsc.JSerialCommDeviceAddress;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.handler.codec.ByteToMessageCodec;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
@@ -46,8 +48,18 @@ public class SerialChannelFactoryTest {
     private static final Logger logger = LoggerFactory.getLogger(SerialChannelFactoryTest.class);
 
     @Test
+    public void showAllPorts() {
+        System.out.println("-------------------------------------");
+        System.out.println(" Starting to Display all Serial Ports");
+        System.out.println("-------------------------------------");
+        for (SerialPort commPort : SerialPort.getCommPorts()) {
+            System.out.println(commPort.getDescriptivePortName());
+        }
+    }
+
+    @Test
     public void createChannel() throws PlcConnectionException, InterruptedException, UnknownHostException {
-        SerialChannelFactory asdf = new SerialChannelFactory("asdf");
+        SerialChannelFactory asdf = new SerialChannelFactory("TEST-port1");
         final TcpSocketChannelFactory factory = new TcpSocketChannelFactory(InetAddress.getLocalHost(), 5432);
         final Channel channel = asdf.createChannel(new ChannelInitializer<SerialChannel>() {
             @Override protected void initChannel(SerialChannel ch) throws Exception {
@@ -63,6 +75,25 @@ public class SerialChannelFactoryTest {
         channel.close().sync();
     }
 
+    @Test
+    public void createChannelToSBL() throws PlcConnectionException, InterruptedException, UnknownHostException {
+        SerialChannelFactory asdf = new SerialChannelFactory("JBLFlip3-SPPDev");
+        Channel channel = null;
+        try {
+            channel = asdf.createChannel(new ChannelInitializer<SerialChannel>() {
+                @Override protected void initChannel(SerialChannel ch) throws Exception {
+                    ch.pipeline().addLast(new DemoCodec());
+                }
+            });
+        } catch (Exception e) {
+            // do nothing
+        }
+        Thread.sleep(5_000);
+        if (channel != null) {
+            channel.close().sync();
+        }
+    }
+
     private static class DemoCodec extends ByteToMessageCodec<Object> {
         @Override protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception {
             // do nothing here