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/08/26 21:50:23 UTC

[plc4x] branch feature/socketcan updated (e14afe0 -> 91f1618)

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

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


 discard e14afe0  Tests for socketcan frames + manual parsing based on ReadBuffer api.
 discard 3a15c56  Scratch of socketcan transport and can frame definitions.
     add cda916d  - Fixed a tiny bug in the handling of string fields.
     add ced15b1  - Updated the hostname of the new PLC4X VM
     add ca7cae8  - Fixed a typo
     add a49eefc  - Allowed providing a bit-offset for STRING types - Added checks that result in exceptions if a bit-offset other than 0 is used for any type except BOOL
     add be90f0d  Added Pietrorimoldi to adopters. Thanks go to Stefano Bossi.
     add 9033ff8  Fixed alphabetical ordering of companies.
     new 4a2ac09  Scratch of socketcan transport and can frame definitions.
     new 1e900f3  Tests for socketcan frames + manual parsing based on ReadBuffer api.
     new f84f2fb  Step back to virtual fields in can transport.
     new 91f1618  More definitions of various frame formats.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (e14afe0)
            \
             N -- N -- N   refs/heads/feature/socketcan (91f1618)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../plc4x/java/s7/readwrite/field/S7Field.java     |  31 ++++++++-
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |   2 +-
 .../can/src/main/resources/protocols/can/can.mspec |  76 +++++++++++++++++----
 .../apache/plc4x/java/can/helper/HeaderParser.java |   4 +-
 .../apache/plc4x/java/can/ManualParserTest.java    |   3 +
 .../{SocketCANTest.java => SocketCAN20ATest.java}  |   6 +-
 ...tCANTestSuite.xml => SocketCAN20ATestSuite.xml} |  45 ++++++++----
 ...tCANTestSuite.xml => SocketCAN20BTestSuite.xml} |  26 ++-----
 .../resources/testsuite/SocketCANTestSuite.xml     |  42 ++++++++----
 .../asciidoc/developers/infrastructure/vm.adoc     |   6 +-
 .../asciidoc/developers/infrastructure/vpn.adoc    |   4 +-
 src/site/asciidoc/users/adopters.adoc              |  10 +--
 .../images/users/companies/logo-pietrorimoldi.jpg  | Bin 0 -> 584330 bytes
 13 files changed, 175 insertions(+), 80 deletions(-)
 copy sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/{SocketCANTest.java => SocketCAN20ATest.java} (85%)
 copy sandbox/test-java-can-driver/src/test/resources/testsuite/{SocketCANTestSuite.xml => SocketCAN20ATestSuite.xml} (53%)
 copy sandbox/test-java-can-driver/src/test/resources/testsuite/{SocketCANTestSuite.xml => SocketCAN20BTestSuite.xml} (63%)
 create mode 100644 src/site/resources/images/users/companies/logo-pietrorimoldi.jpg


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

Posted by ld...@apache.org.
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 4a2ac0931fa9c9fe05cdaf6baeb76759d07b3b99
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 1b438bf..7278668 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");
+
+    }
+
+}


[plc4x] 02/04: Tests for socketcan frames + manual parsing based on ReadBuffer api.

Posted by ld...@apache.org.
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 1e900f3aad43e39bd9a437b028b6b774cbc9d312
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Aug 20 21:46:34 2020 +0200

    Tests for socketcan frames + manual parsing based on ReadBuffer api.
---
 .../can/src/main/resources/protocols/can/can.mspec | 71 ++++++++++-------
 .../org/apache/plc4x/java/can/CANPlcDriver.java    | 10 +--
 .../apache/plc4x/java/can/helper/HeaderParser.java | 44 +++++++++++
 .../apache/plc4x/java/can/ManualParserTest.java    | 92 ++++++++++++++++++++++
 .../org/apache/plc4x/java/can/SocketCANTest.java   | 30 +++++++
 .../resources/testsuite/SocketCANTestSuite.xml     | 54 +++++++++++++
 6 files changed, 267 insertions(+), 34 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index bbee418..113e304 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -18,22 +18,19 @@
  */
 
 [type 'CANFrame'
+    [simple CANHeader 'header']
     [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']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+]
+
+[type 'CANHeader'
+    [simple uint 11 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+
 ]
 
 /* These are structures defined in linux kernel, provided here just for information purposes
@@ -55,23 +52,39 @@ struct canfd_frame {
 };
 */
 
+[type 'OtherSocketCANFrame'
+    [simple int 32 'rawId']
+    [virtual bit 'extended'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+    ]
+    [virtual bit 'remote'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+    ]
+    [virtual bit 'error'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
+    ]
+//    [typeSwitch 'extended'
+//        ['true' ExtendedOtherSocketCanFrame
+//            [simple uint 8 'flags']
+//        ]
+//        ['false' ExtendedOtherSocketCanFrame
+            [reserved uint 8 '0x0']
+//        ]
+//    ]
+    [reserved uint 8 '0x0']
+    [reserved uint 8 '0x0']
+    [implicit uint 8 'size' 'COUNT(data)']
+    [array int 8 'data' COUNT 'size']
+]
+
 [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']
-        ]
-    ]
+    [simple uint 29 'identifier']
+    [implicit uint 8 'length' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // flags
+    [reserved uint 8 '0x0'] // padding
+    [reserved uint 8 '0x0'] // padding
     [array int 8 'data' COUNT 'length']
 ]
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
index 4b7eb16..e1a55ed 100644
--- 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
@@ -20,22 +20,17 @@ 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;
@@ -83,9 +78,14 @@ public class CANPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
         @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);
+
+                CanFrame frame = CanFrame.create(byteBuf.nioBuffer());
+                System.out.println(frame);
+
                 return len + 8 /* overhead */;
             }
             return -1; //discard
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
new file mode 100644
index 0000000..3ce7f0f
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -0,0 +1,44 @@
+package org.apache.plc4x.java.can.helper;
+
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+public class HeaderParser {
+
+    public static final int EXTENDED_FRAME_FORMAT_FLAG = 0x80000000;
+
+    public static final int REMOTE_TRANSMISSION_FLAG = 0x40000000;
+
+    public static final int ERROR_FRAME_FLAG = 0x20000000;
+
+    public static final int STANDARD_FORMAT_IDENTIFIER_MASK = 0x7ff;
+
+    public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0x1fffffff;
+
+    public static int readIdentifier(ReadBuffer buffer) throws ParseException {
+        int identifier = buffer.readInt(32);
+        if ((identifier & EXTENDED_FORMAT_IDENTIFIER_MASK) == 0) {
+            return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
+        }
+        return identifier & EXTENDED_FORMAT_IDENTIFIER_MASK;
+    }
+
+    public static void writeIdentifier(WriteBuffer buffer, SocketCANFrame frame) throws ParseException {
+
+    }
+
+    public static boolean isExtended(int identifier) {
+        return (identifier & EXTENDED_FRAME_FORMAT_FLAG) != 0;
+    }
+
+    public static boolean isRemote(int identifier) {
+        return (identifier & REMOTE_TRANSMISSION_FLAG) != 0;
+    }
+
+    public static boolean isError(int identifier) {
+        return (identifier & ERROR_FRAME_FLAG) != 0;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
new file mode 100644
index 0000000..11c6ca6
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
@@ -0,0 +1,92 @@
+package org.apache.plc4x.java.can;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ManualParserTest {
+
+    public static final int EXTENDED_FRAME_FORMAT_FLAG = 0b10000000_00000000_00000000_00000000;
+    public static final int REMOTE_TRANSMISSION_FLAG = 0b01000000_00000000_00000000_00000000;
+    public static final int ERROR_FRAME_FLAG = 0b00100000_00000000_00000000_00000000;
+
+    public static final int STANDARD_FORMAT_IDENTIFIER_MASK = 0b00000000_00000000_00000111_11111111;
+    public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0b00011111_11111111_11111111_11111111;
+
+    // cansend 5A1#11.2233.44556677.88
+    String STANDARD = "a1050000080000001122334455667788";
+
+    // cansend 1E6EC676#05.05.1F.26.C3
+    String EXTENDED = "76c66e9e0500000005051f26c3000000";
+
+    @Test
+    public void readBufferTest() throws Exception {
+        ReadBuffer buffer = new ReadBuffer(new byte[]{(byte) 0xA1, 0x05, 0x00, 0x00}, true);
+        int value = buffer.readInt(32);
+
+        assertEquals(value, 0x5A1);
+    }
+
+    @Test
+    public void standardFrameParser() throws Exception {
+        SocketCanFrameStub frame = parse(STANDARD);
+        //System.out.println(frame);
+
+        assertEquals(frame.id, 0x5A1);
+        assertEquals(frame.extended, false);
+        assertEquals(frame.remote, false);
+        assertEquals(frame.error, false);
+        assertEquals(frame.data.length, 8);
+    }
+
+    @Test
+    public void extendedFrameParser() throws Exception {
+        SocketCanFrameStub frame = parse(EXTENDED);
+        //System.out.println(frame);
+
+        assertEquals(frame.id, 0x1e6ec676);
+        assertEquals(frame.extended, true);
+        assertEquals(frame.remote, false);
+        assertEquals(frame.error, false);
+        assertEquals(frame.data.length, 5);
+    }
+
+    public final static SocketCanFrameStub parse(String hex) throws Exception {
+        byte[] input = Hex.decodeHex(hex.toCharArray());
+
+        ReadBuffer readBuffer = new ReadBuffer(input, true);
+        int rawId = readBuffer.readInt(32);
+        boolean extended = (rawId & EXTENDED_FRAME_FORMAT_FLAG) != 0;
+        boolean remote = (rawId & REMOTE_TRANSMISSION_FLAG) != 0;
+        boolean error = (rawId & ERROR_FRAME_FLAG) != 0;
+        int id = extended ? (rawId & EXTENDED_FORMAT_IDENTIFIER_MASK) : (rawId & STANDARD_FORMAT_IDENTIFIER_MASK);
+        int length = readBuffer.readByte(8);
+        byte[] data = readBuffer.getBytes(8, 8 + length);
+
+        return new SocketCanFrameStub(
+            id, extended, remote, error, data
+        );
+    }
+
+    static class SocketCanFrameStub {
+        public int id;
+        public boolean extended;
+        public boolean remote;
+        public boolean error;
+        public byte[] data;
+
+        public SocketCanFrameStub(int id, boolean extended, boolean remote, boolean error, byte[] data) {
+            this.id = id;
+            this.extended = extended;
+            this.remote = remote;
+            this.error = error;
+            this.data = data;
+        }
+
+        public String toString() {
+            return "CAN Frame ID=" + Integer.toHexString(id) + ", extended=" + extended + ", remote=" + remote + ", error=" + error + ", data=" + Hex.encodeHexString(data);
+        }
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java
new file mode 100644
index 0000000..270b45a
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java
@@ -0,0 +1,30 @@
+/*
+  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.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class SocketCANTest extends ParserSerializerTestsuiteRunner {
+
+    public SocketCANTest() {
+        super("/testsuite/SocketCANTestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
new file mode 100644
index 0000000..774563b
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -0,0 +1,54 @@
+<?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.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
+
+  <name>CAN Standard Format Frame</name>
+
+  <testcase>
+    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
+    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <identifier>510576246</identifier>
+        <extended>true</extended>
+        <remote>false</remote>
+        <error>true</error>
+        <data></data>
+      </SocketCANFDFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Standard frame 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>false</remote>
+        <error>false</error>
+        <data></data>
+      </ScoketCANSFFrame>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file


[plc4x] 03/04: Step back to virtual fields in can transport.

Posted by ld...@apache.org.
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 f84f2fb97ac909beb2586324182e4902adb982f6
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Mon Aug 24 17:57:02 2020 +0200

    Step back to virtual fields in can transport.
---
 protocols/can/src/main/resources/protocols/can/can.mspec | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index 113e304..16408fd 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -52,7 +52,7 @@ struct canfd_frame {
 };
 */
 
-[type 'OtherSocketCANFrame'
+[type 'SocketCANFrame'
     [simple int 32 'rawId']
     [virtual bit 'extended'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
@@ -63,6 +63,7 @@ struct canfd_frame {
     [virtual bit 'error'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
     ]
+    [implicit uint 8 'size' 'COUNT(data)']
 //    [typeSwitch 'extended'
 //        ['true' ExtendedOtherSocketCanFrame
 //            [simple uint 8 'flags']
@@ -71,13 +72,13 @@ struct canfd_frame {
             [reserved uint 8 '0x0']
 //        ]
 //    ]
-    [reserved uint 8 '0x0']
-    [reserved uint 8 '0x0']
-    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] //flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
 ]
 
-[type 'SocketCANFrame'
+[type 'SimplifiedSocketCANFrame'
     [simple bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']


[plc4x] 04/04: More definitions of various frame formats.

Posted by ld...@apache.org.
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 91f1618c2039079eb8bb4c912d38e9334fc261c0
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Wed Aug 26 23:49:33 2020 +0200

    More definitions of various frame formats.
---
 .../can/src/main/resources/protocols/can/can.mspec | 67 ++++++++++++++++++----
 .../apache/plc4x/java/can/helper/HeaderParser.java |  4 +-
 .../apache/plc4x/java/can/ManualParserTest.java    |  3 +
 .../apache/plc4x/java/can/SocketCAN20ATest.java    | 30 ++++++++++
 ...tCANTestSuite.xml => SocketCAN20ATestSuite.xml} | 45 ++++++++++-----
 ...tCANTestSuite.xml => SocketCAN20BTestSuite.xml} | 26 ++-------
 .../resources/testsuite/SocketCANTestSuite.xml     | 42 ++++++++++----
 7 files changed, 156 insertions(+), 61 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index 16408fd..147492b 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -52,10 +52,35 @@ struct canfd_frame {
 };
 */
 
+[type 'BrokenSocketCANFrame'
+    [discriminator bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [simple bit 'extended']
+    [typeSwitch 'extended'
+        ['true' ExtendedSocketCANFrame
+            [simple uint 29 'identifier']
+        ]
+
+        ['false' StandardSocketCANFrame
+            [const  uint 18 '0x0']
+            [simple uint 11 'identifier']
+        ]
+    ]
+    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // padding
+    [reserved uint 8 '0x0'] // reserved / padding
+    [reserved uint 8 '0x0'] // reserved / padding
+    [array int 8 'data' COUNT 'size']
+]
+
 [type 'SocketCANFrame'
     [simple int 32 'rawId']
+    [virtual int 32 'identifier'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.readIdentifier", rawId)'
+    ]
     [virtual bit 'extended'
-        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isExtended", rawId)'
     ]
     [virtual bit 'remote'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
@@ -64,28 +89,48 @@ struct canfd_frame {
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
     ]
     [implicit uint 8 'size' 'COUNT(data)']
-//    [typeSwitch 'extended'
-//        ['true' ExtendedOtherSocketCanFrame
-//            [simple uint 8 'flags']
-//        ]
-//        ['false' ExtendedOtherSocketCanFrame
-            [reserved uint 8 '0x0']
-//        ]
-//    ]
     [reserved uint 8 '0x0'] //flags
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
 ]
 
+[type 'SocketCAN20AFrame'
+    [simple int 16 'identifier']
+    [reserved int 8 '0x0'] // filling gap used by extended frame
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [reserved int 5 '0x0']  // filling gap used by extended frame
+    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // in case of fd frame these are flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
+    [array int 8 'data' COUNT 'size']
+]
+
 [type 'SimplifiedSocketCANFrame'
     [simple bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']
     [simple uint 29 'identifier']
-    [implicit uint 8 'length' 'COUNT(data)']
+    //implicit uint 8 'size' 'COUNT(data)'
     [reserved uint 8 '0x0'] // flags
     [reserved uint 8 '0x0'] // padding
     [reserved uint 8 '0x0'] // padding
-    [array int 8 'data' COUNT 'length']
+    //array int 8 'data' COUNT 'size'
+]
+
+[enum 'CanOpenNMTCommand'
+    ['0x01', START_DEVICE]
+    ['0x02', STOP_DEVICE]
+    ['0x80', PRE_START]
+    ['0x81', RESET_DEVICE]
+    ['0x82', RESET_COMMUNICATION]
 ]
+
+[dataIo 'CANOpenFrame' [uint 4 'function', uint 7 nodeId, int 8 'data']
+    [discriminator uint 4 'afunction']
+    [typeSwitch 'afunction'
+    ]
+]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
index 3ce7f0f..c0363f6 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -2,7 +2,6 @@ package org.apache.plc4x.java.can.helper;
 
 import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 public class HeaderParser {
@@ -17,8 +16,7 @@ public class HeaderParser {
 
     public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0x1fffffff;
 
-    public static int readIdentifier(ReadBuffer buffer) throws ParseException {
-        int identifier = buffer.readInt(32);
+    public static int readIdentifier(int identifier) {
         if ((identifier & EXTENDED_FORMAT_IDENTIFIER_MASK) == 0) {
             return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
         }
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
index 11c6ca6..c055513 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
@@ -18,6 +18,9 @@ public class ManualParserTest {
     // cansend 5A1#11.2233.44556677.88
     String STANDARD = "a1050000080000001122334455667788";
 
+    // cansend 5A1#R
+    String STANDARD_REPLY = "a1050040000000000000000000000000";
+
     // cansend 1E6EC676#05.05.1F.26.C3
     String EXTENDED = "76c66e9e0500000005051f26c3000000";
 
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java
new file mode 100644
index 0000000..8d86d97
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java
@@ -0,0 +1,30 @@
+/*
+  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.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class SocketCAN20ATest extends ParserSerializerTestsuiteRunner {
+
+    public SocketCAN20ATest() {
+        super("/testsuite/SocketCAN20ATestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
similarity index 53%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
index 774563b..60140de 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
@@ -19,35 +19,50 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>CAN Standard Format Frame</name>
+  <name>Tests of socketcan/CAN 2.0A frames</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Standard frame with 5 byte payload: 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
+    <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
+        <error>false</error>
+        <data>ESIzRFVmd4g=</data>
+      </SocketCAN20AFrame>
     </xml>
   </testcase>
 
   <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Standard frame with no payload: 5A1#</name>
+    <raw>a105000000000000</raw>
+    <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
         <data></data>
-      </ScoketCANSFFrame>
+      </SocketCAN20AFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Remote transmission request: 5A1#R</name>
+    <raw>a105004000000000</raw>
+    <root-type>SocketCAN20AFrame</root-type>
+    <xml>
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>true</remote>
+        <error>false</error>
+        <data></data>
+      </SocketCAN20AFrame>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
similarity index 63%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
index 774563b..e8f08f4 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
@@ -19,35 +19,21 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>CAN Standard Format Frame</name>
+  <name>Tests of socketcan/CAN 2.0B frames</name>
 
   <testcase>
     <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <raw>76c66e9e0500000005051f26c3</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>-1636907402</rawId>
+        <data>BQUfJsM=</data>
         <identifier>510576246</identifier>
         <extended>true</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
-    <root-type>SocketCANFrame</root-type>
-    <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
-        <identifier>1441</identifier>
-        <extended>false</extended>
-        <remote>false</remote>
         <error>false</error>
-        <data></data>
-      </ScoketCANSFFrame>
+      </SocketCANFrame>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
index 774563b..f2518c0 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -22,32 +22,50 @@
   <name>CAN Standard Format Frame</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <name>Standard frame with 5 byte payload: 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1441</rawId>
+        <data>ESIzRFVmd4g=</data>
+        <identifier>1441</identifier>
+        <extended>false</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
+        <error>false</error>
+      </SocketCANFrame>
     </xml>
   </testcase>
 
   <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
+    <name>Standard frame with no payload: 5A1#</name>
+    <raw>a105000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1441</rawId>
+        <data></data>
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
+      </SocketCANFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Remote transmission request: 5A1#R</name>
+    <raw>a105004000000000</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1073743265</rawId>
         <data></data>
-      </ScoketCANSFFrame>
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>true</remote>
+        <error>false</error>
+      </SocketCANFrame>
     </xml>
   </testcase>