You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ld...@apache.org on 2020/10/22 11:55:10 UTC

[plc4x] 01/22: Scratch of socketcan transport and can frame definitions.

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

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 6464454c1d365128c2709bb8ddbccb8154eaf827
Author: Ɓukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Aug 18 00:40:25 2020 +0200

    Scratch of socketcan transport and can frame definitions.
---
 plc4j/transports/pom.xml                           |   1 +
 plc4j/transports/socketcan/pom.xml                 |  81 +++++++
 .../socketcan/CANTransportConfiguration.java       |  25 ++
 .../socketcan/SocketCANChannelFactory.java         |  70 ++++++
 .../transport/socketcan/SocketCANTransport.java    |  46 ++++
 .../socketcan/netty/SocketCANChannel.java          | 267 +++++++++++++++++++++
 .../socketcan/netty/SocketCANChannelConfig.java    |  31 +++
 .../socketcan/netty/address/SocketCANAddress.java  |  40 +++
 .../org.apache.plc4x.java.spi.transport.Transport  |  20 ++
 protocols/can/pom.xml                              |  43 ++++
 .../org/apache/plc4x/protocol/can/CANProtocol.java |  46 ++++
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  19 ++
 .../can/src/main/resources/protocols/can/can.mspec |  77 ++++++
 protocols/pom.xml                                  |   1 +
 sandbox/pom.xml                                    |   1 +
 sandbox/test-java-can-driver/pom.xml               | 133 ++++++++++
 .../org/apache/plc4x/java/can/CANPlcDriver.java    | 102 ++++++++
 .../java/can/configuration/CANConfiguration.java   |  26 ++
 .../plc4x/java/can/context/CANDriverContext.java   |  24 ++
 .../plc4x/java/can/field/CANFieldHandler.java      |  33 +++
 .../plc4x/java/can/protocol/CANProtocolLogic.java  |  51 ++++
 .../services/org.apache.plc4x.java.api.PlcDriver   |  19 ++
 .../test/java/org/apache/plc4x/java/can/Main.java  |  36 +++
 23 files changed, 1192 insertions(+)

diff --git a/plc4j/transports/pom.xml b/plc4j/transports/pom.xml
index 644bf4d..a07d9a3 100644
--- a/plc4j/transports/pom.xml
+++ b/plc4j/transports/pom.xml
@@ -37,6 +37,7 @@
     <module>pcap-replay</module>
     <module>pcap-shared</module>
     <module>raw-socket</module>
+    <module>socketcan</module>
     <module>serial</module>
     <module>tcp</module>
     <module>udp</module>
diff --git a/plc4j/transports/socketcan/pom.xml b/plc4j/transports/socketcan/pom.xml
new file mode 100644
index 0000000..0e28c7b
--- /dev/null
+++ b/plc4j/transports/socketcan/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4j-transports</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4j-transport-socketcan</artifactId>
+  <name>PLC4J: Transports: SocketCAN</name>
+  <description>Base classes needed to implement plc4x drivers based on SocketCAN connections.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-spi</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>tel.schich</groupId>
+      <artifactId>javacan</artifactId>
+      <version>2.1.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!--
+       Generate an OSGI compatible MANIFEST file.
+     -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+            <Bundle-Activator>org.apache.plc4x.java.osgi.TransportActivator</Bundle-Activator>
+            <Export-Service>org.apache.plc4x.java.spi.transport.Transport,org.apache.plc4x.java.transport.socketcan.SocketCANTransport</Export-Service>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java
new file mode 100644
index 0000000..791b465
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java
@@ -0,0 +1,25 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import org.apache.plc4x.java.spi.transport.TransportConfiguration;
+
+public interface CANTransportConfiguration extends TransportConfiguration {
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java
new file mode 100644
index 0000000..f4c7cc7
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java
@@ -0,0 +1,70 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.ThreadPerChannelEventLoop;
+import io.netty.channel.oio.OioEventLoopGroup;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.connection.NettyChannelFactory;
+import org.apache.plc4x.java.transport.socketcan.netty.SocketCANChannel;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SocketCANChannelFactory extends NettyChannelFactory implements HasConfiguration<CANTransportConfiguration> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SocketCANChannelFactory.class);
+
+    private CANTransportConfiguration configuration;
+
+    public SocketCANChannelFactory(SocketCANAddress address) {
+        super(address);
+    }
+
+    @Override
+    public void setConfiguration(CANTransportConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public Class<? extends Channel> getChannel() {
+        return SocketCANChannel.class;
+    }
+
+    @Override
+    public boolean isPassive() {
+        return true;
+    }
+
+    @Override
+    public EventLoopGroup getEventLoopGroup() {
+        return new ThreadPerChannelEventLoop(new OioEventLoopGroup());
+    }
+
+    @Override
+    public void configureBootstrap(Bootstrap bootstrap) {
+        if(configuration != null) {
+            logger.info("Configuring Bootstrap with {}", configuration);
+        }
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java
new file mode 100644
index 0000000..95279c1
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java
@@ -0,0 +1,46 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import org.apache.plc4x.java.spi.connection.ChannelFactory;
+import org.apache.plc4x.java.spi.transport.Transport;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+
+/**
+ * CAN specific transport which rely on JavaCAN library.
+ */
+public class SocketCANTransport implements Transport {
+
+    @Override
+    public String getTransportCode() {
+        return "javacan";
+    }
+
+    @Override
+    public String getTransportName() {
+        return "JavaCAN Transport";
+    }
+
+    @Override
+    public ChannelFactory createChannelFactory(String transportConfig) {
+        SocketCANAddress address = new SocketCANAddress(transportConfig);
+        return new SocketCANChannelFactory(address);
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
new file mode 100644
index 0000000..764d1f5
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.transport.socketcan.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelPromise;
+import io.netty.channel.oio.OioByteStreamChannel;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import tel.schich.javacan.CanChannels;
+import tel.schich.javacan.CanFrame;
+import tel.schich.javacan.NetworkDevice;
+import tel.schich.javacan.RawCanChannel;
+import tel.schich.javacan.linux.LinuxNetworkDevice;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+
+/**
+ * A naive copy of pcap channel implementation which allows to pass over data to PLC4X as well as drop it back to JavaCAN.
+ * Sadly all this involves double parsing.
+ */
+public class SocketCANChannel extends OioByteStreamChannel {
+
+    private static final Logger logger = LoggerFactory.getLogger(SocketCANChannel.class);
+
+    private final SocketCANChannelConfig config;
+
+    private SocketCANAddress remoteRawSocketAddress;
+    private SocketAddress localAddress;
+    private RawCanChannel handle;
+    private Thread loopThread;
+
+    public SocketCANChannel() {
+        super(null);
+        config = new SocketCANChannelConfig(this);
+    }
+
+    @Override
+    protected boolean isInputShutdown() {
+        return false;
+    }
+
+    @Override
+    protected ChannelFuture shutdownInput() {
+        throw new UnsupportedOperationException("");
+    }
+
+    @Override
+    protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
+        if (!(remoteAddress instanceof SocketCANAddress)) {
+            logger.error("Expecting remote address of type SocketCANAddress");
+            pipeline().fireExceptionCaught(new IllegalArgumentException("Expecting remote address of type SocketCANAddress"));
+            return;
+        }
+        this.localAddress = localAddress;
+        remoteRawSocketAddress = (SocketCANAddress) remoteAddress;
+
+        // Try to get the device name of the network interface that we want to open.
+        String interfaceName = getInterfaceName(remoteRawSocketAddress);
+        if(interfaceName == null) {
+            logger.error("Interface name is not specified and couldn't detect it automatically");
+            pipeline().fireExceptionCaught(new IllegalArgumentException("Interface name is not specified and couldn't detect it automatically"));
+            return;
+        }
+
+        NetworkDevice device = LinuxNetworkDevice.lookup(interfaceName);
+        // Get a handle to the network-device and open it.
+        handle = CanChannels.newRawChannel(device);
+
+        if(logger.isDebugEnabled()) {
+            logger.debug(String.format("Listening on device %s", interfaceName));
+        }
+
+        // TODO If the address allows fine tuning which packets to process, set a filter to reduce the load.
+//        String filter =
+//        if(filter.length() > 0) {
+//            handle.setFilter(filter, BpfProgram.BpfCompileMode.OPTIMIZE);
+//        }
+
+        // Create a buffer where the raw socket worker can send data to.
+        ByteBuf buffer = Unpooled.buffer();
+
+        // Start a thread that processes the callbacks from the raw socket and simply
+        // forwards the bytes read to the buffer.
+        loopThread = new Thread(() -> {
+            try {
+                while (!isInputShutdown()) {
+                    CanFrame frame = handle.read();
+                    ByteBuf frameBytes = ByteBufAllocator.DEFAULT.buffer();
+                    frameBytes.writeBytes(frame.getBuffer());
+                    String dump = ByteBufUtil.prettyHexDump(frameBytes);
+                    System.out.println(frame + "\n" + dump);
+                    buffer.writeBytes(frame.getBuffer());
+                }
+            } catch (IOException e) {
+                logger.warn("Could not read data", e);
+                pipeline().fireExceptionCaught(e);
+            }
+        });
+        loopThread.start();
+
+        activate(new CANInputStream(buffer), new CANOutputStream(handle));
+    }
+
+    @Override
+    protected SocketAddress localAddress0() {
+        return localAddress;
+    }
+
+    @Override
+    protected SocketAddress remoteAddress0() {
+        return remoteRawSocketAddress;
+    }
+
+    @Override
+    protected void doBind(SocketAddress localAddress) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    protected void doDisconnect() {
+        this.loopThread.interrupt();
+        if (this.handle != null) {
+            try {
+                this.handle.close();
+            } catch (IOException e) {
+                logger.error("Failed to close CAN socket!");
+            }
+        }
+    }
+
+    @Override
+    protected int doReadBytes(ByteBuf buf) throws Exception {
+        if (handle == null || !handle.isOpen()) {
+            return -1;
+        }
+        try {
+            return super.doReadBytes(buf);
+        } catch (SocketTimeoutException ignored) {
+            return 0;
+        }
+    }
+
+    @Override
+    public ChannelConfig config() {
+        return this.config;
+    }
+
+    @Override
+    public boolean isOpen() {
+        return true;
+    }
+
+    @Override
+    protected AbstractUnsafe newUnsafe() {
+        return new RawSocketUnsafe();
+    }
+
+    private String getInterfaceName(SocketCANAddress address) {
+        // If the device name is provided, simply use this.
+        if(address.getInterfaceName() != null) {
+            return address.getInterfaceName();
+        }
+
+        // TODO: Implement this ...
+        return null;
+    }
+
+    /**
+     * InputStream that fulfills the contract of Netty for read operations to timeout.
+     * Without this the InputStream would simply block indefinitely which would block
+     * the entire IO module.
+     */
+    private static class CANInputStream extends InputStream {
+        final ByteBuf buf;
+
+        private CANInputStream(ByteBuf buf) {
+            this.buf = buf;
+        }
+
+        @Override
+        public int available() {
+            return buf.readableBytes();
+        }
+
+        @Override
+        public int read() throws IOException {
+            // Timeout 10 ms
+            final long timeout = System.nanoTime() + 10_000;
+            // Yes, this could make the thread go nuts in case of no data,
+            // but the Netty guys are doing it the same way and there probably
+            // is a reason for it ;-)
+            while (System.nanoTime() < timeout) {
+                if (buf.readableBytes() > 0) {
+                    return buf.readByte() & 0xFF;
+                }
+            }
+            throw new SocketTimeoutException();
+        }
+    }
+
+
+    private static class CANOutputStream extends OutputStream {
+
+        private final RawCanChannel rawCanChannel;
+
+        public CANOutputStream(RawCanChannel rawCanChannel) {
+            this.rawCanChannel = rawCanChannel;
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            throw new IOException("Appending single bytes is not permitted. Use write(byte[], int, int)");
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
+            CanFrame frame = CanFrame.create(buffer);
+            rawCanChannel.write(frame);
+        }
+    }
+
+    /**
+     * Internal helper to wrap access to unsafe operations (Only used internally by netty)
+     */
+    private class RawSocketUnsafe extends AbstractUnsafe {
+        @Override
+        public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
+            try {
+                doConnect(remoteAddress, localAddress);
+                pipeline().fireChannelActive();
+                promise.setSuccess();
+            } catch (Exception e) {
+                promise.setFailure(e);
+            }
+        }
+    }
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java
new file mode 100644
index 0000000..42f604a
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java
@@ -0,0 +1,31 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan.netty;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.DefaultChannelConfig;
+
+public class SocketCANChannelConfig extends DefaultChannelConfig implements ChannelConfig {
+
+    public SocketCANChannelConfig(Channel channel) {
+        super(channel);
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java
new file mode 100644
index 0000000..e11ff17
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan.netty.address;
+
+import java.net.SocketAddress;
+
+/**
+ * Simple address implementation which covers only interface name.
+ */
+public class SocketCANAddress extends SocketAddress {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String interfaceName;
+
+    public SocketCANAddress(String interfaceName) {
+        this.interfaceName = interfaceName;
+    }
+
+    public String getInterfaceName() {
+        return interfaceName;
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport b/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport
new file mode 100644
index 0000000..31b1a03
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+org.apache.plc4x.java.transport.socketcan.SocketCANTransport
\ No newline at end of file
diff --git a/protocols/can/pom.xml b/protocols/can/pom.xml
new file mode 100644
index 0000000..be98554
--- /dev/null
+++ b/protocols/can/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4x-protocols</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4x-protocols-can</artifactId>
+
+  <name>Protocols: CAN</name>
+  <description>CAN stands for Controller Area Network.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-protocol-base-mspec</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
new file mode 100644
index 0000000..853fb50
--- /dev/null
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
@@ -0,0 +1,46 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.protocol.can;
+
+import org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+import java.io.InputStream;
+import java.util.Map;
+
+public class CANProtocol implements Protocol {
+
+    @Override
+    public String getName() {
+        return "can";
+    }
+
+    @Override
+    public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
+        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        if(schemaInputStream == null) {
+            throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
+        }
+        return new MessageFormatParser().parse(schemaInputStream);
+    }
+
+}
diff --git a/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000..d422eca
--- /dev/null
+++ b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.plc4x.protocol.can.CANProtocol
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
new file mode 100644
index 0000000..bbee418
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+[type 'CANFrame'
+    [simple uint 11 'identifier']
+    [simple bit 'remoteTransmissionRequest']
+    [discriminator bit 'extended']
+    [typeSwitch 'extended'
+        ['false' CANDataFrame
+            [reserved uint 1 '0x0']
+        ]
+        ['true' ExtendedCANFrame
+            [simple uint 18 'extensionId']
+            [simple bit 'extensionRemoteTransmissionRequest']
+            [reserved uint 2 '0x0']
+        ]
+    ]
+    [simple uint 4 'length']
+    [array uint 8 'data' count 'length']
+    [simple uint 15 'crc']
+]
+
+/* These are structures defined in linux kernel, provided here just for information purposes
+struct can_frame {
+  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
+  __u8    can_dlc; // frame payload length in byte (0 .. 8)
+  __u8    __pad;   // padding
+  __u8    __res0;  // reserved / padding
+  __u8    __res1;  // reserved / padding
+  __u8    data[8] __attribute__((aligned(8)));
+};
+struct canfd_frame {
+  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
+  __u8    len;     // frame payload length in byte (0 .. 64)
+  __u8    flags;   // additional flags for CAN FD
+  __u8    __res0;  // reserved / padding
+  __u8    __res1;  // reserved / padding
+  __u8    data[64] __attribute__((aligned(8)));
+};
+*/
+
+[type 'SocketCANFrame'
+    [simple uint 29 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [implicit uint 8 'length' 'ARRAY_SIZE_IN_BYTES(data)']
+    [typeSwitch 'extended', 'identifier'
+        ['true' SocketCANFDFrame
+            [simple uint 8 'flags']
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+        ]
+        ['false' ScoketCANFrame
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+        ]
+    ]
+    [array int 8 'data' COUNT 'length']
+]
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 1459800..2191ba9 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -43,6 +43,7 @@
     <module>knxnetip</module>
     <module>modbus</module>
     <module>s7</module>
+    <module>can</module>
   </modules>
 
   <build>
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index 27e3b8d..26c5f83 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -42,6 +42,7 @@
 
     <module>test-java-bacnetip-driver</module>
     <module>test-java-df1-driver</module>
+    <module>test-java-can-driver</module>
 
     <module>test-streampipes-plc4x-adapters</module>
     <module>test-streampipes-plc4x-processors</module>
diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml
new file mode 100644
index 0000000..86bfddf
--- /dev/null
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x.sandbox</groupId>
+    <artifactId>plc4x-sandbox</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>test-java-can-driver</artifactId>
+
+  <name>Sandbox: Test Generated CAN Driver</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.plc4x.plugins</groupId>
+        <artifactId>plc4x-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>test</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>generate-driver</goal>
+            </goals>
+            <configuration>
+              <protocolName>can</protocolName>
+              <languageName>java</languageName>
+              <outputFlavor>read-write</outputFlavor>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-api</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-transport-socketcan</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>osgi.cmpn</artifactId>
+      <version>6.0.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-language-java</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- Logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+      <version>1.7.25</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-protocols-can</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-test-utils</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
new file mode 100644
index 0000000..4b7eb16
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
@@ -0,0 +1,102 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.plc4x.java.can;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.can.context.CANDriverContext;
+import org.apache.plc4x.java.can.field.CANFieldHandler;
+import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
+import org.apache.plc4x.java.can.readwrite.CANFrame;
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.can.readwrite.io.CANFrameIO;
+import org.apache.plc4x.java.can.readwrite.io.SocketCANFrameIO;
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
+import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+import tel.schich.javacan.CanFrame;
+import tel.schich.javacan.CanId;
+
+import java.util.function.Consumer;
+import java.util.function.ToIntFunction;
+
+/**
+ */
+public class CANPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
+
+    @Override
+    public String getProtocolCode() {
+        return "can";
+    }
+
+    @Override
+    public String getProtocolName() {
+        return "Controller Area Network";
+    }
+
+    @Override
+    protected Class<? extends Configuration> getConfigurationType() {
+        return CANConfiguration.class;
+    }
+
+    @Override
+    protected String getDefaultTransport() {
+        return "javacan";
+    }
+
+    @Override
+    protected CANFieldHandler getFieldHandler() {
+        return new CANFieldHandler();
+    }
+
+    @Override
+    protected ProtocolStackConfigurer<SocketCANFrame> getStackConfigurer() {
+        return SingleProtocolStackConfigurer.builder(SocketCANFrame.class, SocketCANFrameIO.class)
+            .withProtocol(CANProtocolLogic.class)
+            .withDriverContext(CANDriverContext.class)
+            .withPacketSizeEstimator(CANEstimator.class)
+            //.withCorruptPacketRemover(CANCleaner.class)
+            .build();
+    }
+
+    public static class CANEstimator implements ToIntFunction<ByteBuf> {
+        @Override
+        public int applyAsInt(ByteBuf byteBuf) {
+            if (byteBuf.readableBytes() >= 5) {
+                System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
+                byte len = byteBuf.getByte(4);
+                System.out.println("Length " + (int) len);
+                return len + 8 /* overhead */;
+            }
+            return -1; //discard
+        }
+    }
+
+    public class CANCleaner implements Consumer<ByteBuf> {
+        @Override
+        public void accept(ByteBuf byteBuf) {
+            System.out.println("Discard");
+            byteBuf.readByte();
+        }
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
new file mode 100644
index 0000000..1a86e45
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
@@ -0,0 +1,26 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.configuration;
+
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.transport.socketcan.CANTransportConfiguration;
+
+public class CANConfiguration implements Configuration, CANTransportConfiguration {
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java
new file mode 100644
index 0000000..4f0d553
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java
@@ -0,0 +1,24 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.context;
+
+import org.apache.plc4x.java.spi.context.DriverContext;
+
+public class CANDriverContext implements DriverContext {
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java
new file mode 100644
index 0000000..2f2c3f8
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java
@@ -0,0 +1,33 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.spi.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+
+public class CANFieldHandler extends DefaultPlcFieldHandler implements PlcFieldHandler {
+
+    @Override
+    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+        return null;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
new file mode 100644
index 0000000..57dd683
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
@@ -0,0 +1,51 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.protocol;
+
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CANProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+
+    private Logger logger = LoggerFactory.getLogger(CANProtocolLogic.class);
+
+    @Override
+    public void onConnect(ConversationContext<SocketCANFrame> context) {
+        context.fireConnected();
+    }
+
+    @Override
+    protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
+        logger.info("Decode CAN message {}", msg);
+    }
+
+    @Override
+    public void close(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+    @Override
+    public void onDisconnect(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
new file mode 100644
index 0000000..cb3d2ec
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.plc4x.java.can.CANPlcDriver
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
new file mode 100644
index 0000000..622f602
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
@@ -0,0 +1,36 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can;
+
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+
+/**
+ * Here we begin .. ;-)
+ */
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+        PlcDriverManager driverManager = new PlcDriverManager();
+
+        PlcConnection connection = driverManager.getConnection("can:javacan://vcan0");
+
+    }
+
+}