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/09/03 11:46:38 UTC

[plc4x] branch feature/socketcan updated (879d627 -> b4c7fdd)

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 879d627  More tests of canopen payload.
 discard 6010a89  Fix socketcan mspec errors.
 discard bf44c4c  Update service list for canopen.
 discard 8c87768  Sketch of support for SDO operations.
 discard 831e3e1  Fix socketcan transport.
 discard 60cea99  More work on socketcan transport.
 discard 2b64d00  Focus on payloads and not frames.
 discard aa12cd4  Split different flavours of CAN formats.
 discard 2e1d4cd  More definitions of various frame formats.
 discard 60ba233  Step back to virtual fields in can transport.
 discard a43830b  Tests for socketcan frames + manual parsing based on ReadBuffer api.
 discard eef85dc  Scratch of socketcan transport and can frame definitions.
     add b93eb85  - Removed the description of serial transport on the Modbus page (for now) - Fixed some wrong documentation on the config arguments of the Modbus driver.
     new e34c37a  Scratch of socketcan transport and can frame definitions.
     new c9429da  Tests for socketcan frames + manual parsing based on ReadBuffer api.
     new 12df555  Step back to virtual fields in can transport.
     new 85bbfd0  More definitions of various frame formats.
     new d244ede  Split different flavours of CAN formats.
     new 8a96a19  Focus on payloads and not frames.
     new 144a360  More work on socketcan transport.
     new 07df725  Fix socketcan transport.
     new 6085f62  Sketch of support for SDO operations.
     new 8299feb  Update service list for canopen.
     new 9f66ffa  Fix socketcan mspec errors.
     new d2799e9  More tests of canopen payload.
     new 951ea4f  Fix socketcan mspec.
     new b4c7fdd  CANopen adjustments.

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   (879d627)
            \
             N -- N -- N   refs/heads/feature/socketcan (b4c7fdd)

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 14 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:
 .../src/main/resources/protocols/can/canopen.mspec | 144 ++++++++++++++-------
 .../main/resources/protocols/can/socketcan.mspec   |   6 +-
 sandbox/test-java-can-driver/pom.xml               |   5 +
 .../java/can/protocol/CANOpenProtocolLogic.java    |  12 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          |  71 ++++++----
 src/site/asciidoc/users/protocols/modbus.adoc      |  20 ++-
 src/site/site.xml                                  |   2 +-
 7 files changed, 164 insertions(+), 96 deletions(-)


[plc4x] 06/14: Focus on payloads and not frames.

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 8a96a194a403f8bb5e9be821b885a827e7876dd6
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Fri Aug 28 00:14:16 2020 +0200

    Focus on payloads and not frames.
---
 .../src/main/resources/protocols/can/canopen.mspec |  41 +++++----
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    | 102 +++++++++++++++++++++
 .../java/can/protocol/CANOpenProtocolLogic.java    |  62 +++++++++++++
 .../{CANOpenTest.java => CANOpenPayloadTest.java}  |   6 +-
 ...enTestSuite.xml => CANOpenPayloadTestSuite.xml} |  11 ++-
 5 files changed, 198 insertions(+), 24 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 553d12a..54337b4 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,28 +17,35 @@
  * under the License.
  */
 
-[type 'CANOpenFrame'
-    [enum CANOpenService 'function']
-    [simple int 11 'identifier']
-    [reserved int 9 '0x0'] // filling gap used by extended frame, and extended marker which should always be 0
-    [simple bit 'remote']
-    [simple bit 'error']
-    [reserved int 5 '0x0']  // filling gap used by extended frame
-    [implicit uint 8 'size' 'COUNT(payload)']
-    [reserved uint 8 '0x0'] // in case of fd frame these are flags
-    [reserved uint 8 '0x0'] // padding 1
-    [reserved uint 8 '0x0'] // padding 2
-    [simple CANOpenPayload 'payload' ['function', 'size']]
+[enum uint 4 'CANOpenService'
+    ['0x00' BROADCAST]
+    ['0x07' NMT]
 ]
 
-[enum uint 4 'CANOpenService'
-    ['0b1110' NMT]
+[enum uint 8 'NMTStateRequest'
+    ['0x01' OPERATIONAL]
+    ['0x02' STOP]
+    ['0x80' PRE_OPERATIONAL]
+    ['0x81' RESET_NODE]
+    ['0x82' RESET_COMMUNICATION]
 ]
 
-[discriminatedType 'CANOpenPayload' [CANOpenService 'function', uint 8 'size']
+[enum uint 8 'NMTState'
+    ['0x00' BOOTED_UP]
+    ['0x04' STOPPED]
+    ['0x05' OPERATIONAL]
+    ['0x7f' PRE_OPERATIONAL]
+]
+
+[discriminatedType 'CANOpenPayload' [CANOpenService 'function']
     [typeSwitch 'function'
-        ['CANOpenService.NMT' CANOpenNetworkPayload [uint 8 'size']
-            [array int 8 'data' COUNT 'size']
+        ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
+            [enum NMTStateRequest 'request']
+            [reserved uint 1 '0x0']
+            [simple uint 7 'node']
+        ]
+        ['CANOpenService.NMT' CANOpenNetworkPayload
+            [enum NMTState 'state']
         ]
     ]
 ]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
new file mode 100644
index 0000000..b1c6fe6
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.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.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.CANOpenProtocolLogic;
+import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.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 java.util.function.Consumer;
+import java.util.function.ToIntFunction;
+
+/**
+ */
+public class CANOpenPlcDriver 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(CANOpenProtocolLogic.class)
+            .withDriverContext(CANDriverContext.class)
+            .withPacketSizeEstimator(CANEstimator.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);
+
+                CanFrame frame = CanFrame.create(byteBuf.nioBuffer());
+                System.out.println(frame);
+
+                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/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
new file mode 100644
index 0000000..e6f18ca
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -0,0 +1,62 @@
+/*
+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.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+
+    private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.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);
+
+        int identifier = msg.getIdentifier();
+        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
+        if (service != null) {
+            ReadBuffer buffer = new ReadBuffer(msg.getData());
+            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+        }
+    }
+
+    @Override
+    public void close(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+    @Override
+    public void onDisconnect(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
similarity index 84%
rename from sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
rename to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
index a97a1eb..8af4f2b 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
@@ -21,10 +21,10 @@ package org.apache.plc4x.java.can;
 
 import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
 
-public class CANOpenTest extends ParserSerializerTestsuiteRunner {
+public class CANOpenPayloadTest extends ParserSerializerTestsuiteRunner {
 
-    public CANOpenTest() {
-        super("/testsuite/CANOpenTestSuite.xml");
+    public CANOpenPayloadTest() {
+        super("/testsuite/CANOpenPayloadTestSuite.xml");
     }
 
 }
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
similarity index 85%
rename from sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
rename to sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index b99128d..b5676d9 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -22,11 +22,14 @@
   <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Network heartbeat frame: 728#05</name>
-    <raw>280700000100000005</raw>
-    <root-type>CANOpenFrame</root-type>
+    <name>Network heartbeat payload: 0000</name>
+    <raw>0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenPayload">
         <function>15</function>
         <identifier>5</identifier>
         <extended>false</extended>


[plc4x] 04/14: 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 85bbfd06c6fc853d250ae89f5c196ade583435f5
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>
 


[plc4x] 12/14: More tests of canopen payload.

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 d2799e96577cb123140538a88f112ff4bb888751
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 18:13:32 2020 +0200

    More tests of canopen payload.
---
 .../src/main/resources/protocols/can/canopen.mspec | 67 +++++++++++++++++-----
 .../testsuite/CANOpenPayloadTestSuite.xml          | 41 +++++++++++++
 2 files changed, 94 insertions(+), 14 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 0c4f175..c929ae4 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,20 +17,21 @@
  * under the License.
  */
 
-[enum uint 4 'CANOpenService'
-    ['0b0000' BROADCAST   ]
-    ['0b0001' SYNC        ]
-    ['0b1110' NMT         ]
-    ['0b1100' SDO_REQUEST ]
-    ['0b1011' SDO_RESPONSE]
-    ['0b0011' TPDO_1]
-    ['0b0100' RPDO_1]
-    ['0b0101' TPDO_2]
-    ['0b0110' RPDO_2]
-    ['0b0111' TPDO_3]
-    ['0b1000' RPDO_3]
-    ['0b1001' TPDO_4]
-    ['0b1010' RPDO_4]
+[enum uint 4 'CANOpenService' [bit 'sdo', bit 'pdo', bit 'transmit', bit 'receive']
+    ['0b0000' BROADCAST    ['false', 'false', 'false', 'false'] ]
+    ['0b0001' SYNC         ['false', 'false', 'false', 'false'] ]
+    ['0b0010' TIME         ['false', 'false', 'false', 'false'] ]
+    ['0b1110' NMT          ['false', 'false', 'false', 'false'] ]
+    ['0b1100' SDO_REQUEST  ['true',  'false', 'false', 'true' ] ]
+    ['0b1011' SDO_RESPONSE ['true',  'false', 'true',  'false'] ]
+    ['0b0011' TPDO_1       ['false', 'true',  'true',  'false'] ]
+    ['0b0100' RPDO_1       ['false', 'true',  'false', 'true' ] ]
+    ['0b0101' TPDO_2       ['false', 'true',  'true',  'false'] ]
+    ['0b0110' RPDO_2       ['false', 'true',  'false', 'true' ] ]
+    ['0b0111' TPDO_3       ['false', 'true',  'true',  'false'] ]
+    ['0b1000' RPDO_3       ['false', 'true',  'false', 'true' ] ]
+    ['0b1001' TPDO_4       ['false', 'true',  'true',  'false'] ]
+    ['0b1010' RPDO_4       ['false', 'true',  'false', 'true' ] ]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -55,6 +56,9 @@
             [reserved uint 1 '0x00']
             [simple uint 7 'node']
         ]
+        ['CANOpenService.TIME' CANOpenTimeSynchronization
+            [simple TimeOfDay 'timeOfDay']
+        ]
         ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTState 'state']
         ]
@@ -78,6 +82,30 @@
             [simple uint 8 'subindex']
             [array uint 8 'data' COUNT 'size']
         ]
+        ['CANOpenService.RPDO_1' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['1', 'true']]
+        ]
+        ['CANOpenService.TPDO_1' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_2' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['2', 'true']]
+        ]
+        ['CANOpenService.TPDO_2' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_3' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['3', 'true']]
+        ]
+        ['CANOpenService.TPDO_3' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_4' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['4', 'true']]
+        ]
+        ['CANOpenService.TPDO_4' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
     ]
 ]
 
@@ -90,3 +118,14 @@
     ['0x05' BLOCK_UPLOAD]
     ['0x06' BLOCK_DOWNLOAD]
 ]
+
+[type 'CANOpenPDO' [uint 2 'index', bit 'receive']
+
+]
+
+[type 'TimeOfDay'
+    // CiA 301 - section 7.1.6.5
+    [simple uint 28 'millis']
+    [reserved int 4 '0x00']
+    [simple uint 16 'days']
+]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index ecf224b..3188005 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -21,6 +21,47 @@
 
   <name>Tests of CANopen frames payload.</name>
 
+
+  <testcase>
+    <name>Time synchronization, payload: A017BD805034</name>
+    <!--
+    Initial test payload was A017BD835034, however it does not align with CANOpen spec or mapping on our side is wrong
+    -->
+    <raw>A017BD805034</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TIME</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+          <millis>-663027446</millis>
+          <days>13392</days>
+        </timeOfDay>
+      </CANOpenTimeSynchronization>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Time synchronization, payload: 7019BE805034</name>
+    <!--
+    Initial test payload was 7019BE835034, however it does not align with CANOpen spec or mapping on our side is wrong
+    -->
+    <raw>7019BE805034</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TIME</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+          <millis>-392494841</millis>
+          <days>13392</days>
+        </timeOfDay>
+      </CANOpenTimeSynchronization>
+    </xml>
+  </testcase>
+
   <testcase>
     <name>Network heartbeat, payload: 00</name>
     <raw>00</raw>


[plc4x] 03/14: 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 12df5559ba7c3cd9d35936d58cfa4a351809030c
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] 08/14: Fix socketcan 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 07df72545c54c8ec0d22a287e40a0d7b2f50f15d
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Sat Aug 29 10:08:17 2020 +0200

    Fix socketcan transport.
---
 .../plc4x/java/transport/socketcan/netty/SocketCANChannel.java   | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

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
index 305d452..b302a7d 100644
--- 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
@@ -114,10 +114,10 @@ public class SocketCANChannel extends OioByteStreamChannel {
             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);
+//                    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) {
@@ -245,6 +245,7 @@ public class SocketCANChannel extends OioByteStreamChannel {
         public void write(byte[] b, int off, int len) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocateDirect(len - off);
             buffer.put(b, off, len);
+            buffer.flip();
             CanFrame frame = CanFrame.create(buffer);
             rawCanChannel.write(frame);
         }


[plc4x] 09/14: Sketch of support for SDO operations.

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 6085f62b8de6d14281ce6a3026eab4eab31aae16
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Sat Aug 29 10:09:57 2020 +0200

    Sketch of support for SDO operations.
---
 .../src/main/resources/protocols/can/canopen.mspec |  40 ++++++-
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  17 +--
 .../java/can/configuration/CANConfiguration.java   |  12 +++
 .../java/can/protocol/CANOpenProtocolLogic.java    |  58 ++++++-----
 .../test/java/org/apache/plc4x/java/can/Main.java  |   2 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          | 115 ++++++++++++++++++++-
 6 files changed, 196 insertions(+), 48 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 54337b4..d5160c6 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -18,8 +18,10 @@
  */
 
 [enum uint 4 'CANOpenService'
-    ['0x00' BROADCAST]
-    ['0x07' NMT]
+    ['0b0000' BROADCAST   ]
+    ['0b1110' NMT         ]
+    ['0b1100' SDO_REQUEST ]
+    ['0b1011' SDO_RESPONSE]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -41,11 +43,41 @@
     [typeSwitch 'function'
         ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
             [enum NMTStateRequest 'request']
-            [reserved uint 1 '0x0']
+            [reserved uint 1 '0x00']
             [simple uint 7 'node']
         ]
         ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTState 'state']
         ]
+        ['CANOpenService.SDO_REQUEST' CANOpenSDORequest
+            [enum SDOCommand 'command']
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'COUNT(data)']
+            [simple bit 'expedited'] // segmented
+            [simple bit 'placement']
+            [simple uint 16 'index']
+            [simple uint 8 'subindex']
+            [array uint 8 'data' COUNT 'size']
+        ]
+        ['CANOpenService.SDO_RESPONSE' CANOpenSDOResponse
+            [enum SDOCommand 'command']
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'COUNT(data)']
+            [simple bit 'expedited'] // segmented
+            [simple bit 'placement']
+            [simple uint 16 'index']
+            [simple uint 8 'subindex']
+            [array uint 8 'data' COUNT 'size']
+        ]
     ]
-]
\ No newline at end of file
+]
+
+[enum uint 3 'SDOCommand'
+    ['0x00' SEGMENT_DOWNLOAD]
+    ['0x01' INITIALIZE_DOWNLOAD]
+    ['0x02' INITIALIZE_UPLOAD]
+    ['0x03' SEGMENT_UPLOAD]
+    ['0x04' ABORT]
+    ['0x05' BLOCK_UPLOAD]
+    ['0x06' BLOCK_DOWNLOAD]
+]
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index 4255ff2..6acff67 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -78,25 +78,10 @@ public class CANOpenPlcDriver 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 16; // socketcan transport always returns 16 bytes padded with zeros;
             }
             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
index 925ca15..214794d 100644
--- 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
@@ -27,6 +27,9 @@ public class CANConfiguration implements Configuration, CANTransportConfiguratio
     @ConfigurationParameter
     private int nodeId;
 
+    @ConfigurationParameter
+    private boolean hearbeat;
+
     public int getNodeId() {
         return nodeId;
     }
@@ -34,4 +37,13 @@ public class CANConfiguration implements Configuration, CANTransportConfiguratio
     public void setNodeId(int nodeId) {
         this.nodeId = nodeId;
     }
+
+    public boolean isHeartbeat() {
+        return hearbeat;
+    }
+
+    public void setHearbeat(boolean hearbeat) {
+        this.hearbeat = hearbeat;
+    }
+
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 555ef92..9cc2fdb 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -45,6 +45,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     private CANConfiguration configuration;
     private RequestTransactionManager tm;
+    private Timer heartbeat;
 
     @Override
     public void setConfiguration(CANConfiguration configuration) {
@@ -55,39 +56,46 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     @Override
     public void onConnect(ConversationContext<SocketCANFrame> context) {
-        CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.BOOTED_UP);
-        WriteBuffer buffer = new WriteBuffer(1);
         try {
-            CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
-            context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
-            context.fireConnected();
-
-            Timer heartbeat = new Timer();
-            heartbeat.scheduleAtFixedRate(new TimerTask() {
-                @Override
-                public void run() {
-                    CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.OPERATIONAL);
-                    WriteBuffer buffer = new WriteBuffer(1);
-                    context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
-                }
-            }, 5000, 5000);
+            if (configuration.isHeartbeat()) {
+                context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.BOOTED_UP)));
+                context.fireConnected();
+
+                this.heartbeat = new Timer();
+                this.heartbeat.scheduleAtFixedRate(new TimerTask() {
+                    @Override
+                    public void run() {
+                        try {
+                            context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.OPERATIONAL)));
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }, 5000, 5000);
+            }
         } catch (ParseException e) {
             e.printStackTrace();
         }
     }
 
+    private SocketCANFrame createFrame(CANOpenNetworkPayload state) throws ParseException {
+        WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes());
+        CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
+        return new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData());
+    }
+
     @Override
     protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
         logger.info("Decode CAN message {}", msg);
 
-        int identifier = msg.getIdentifier();
-        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
-        if (service != null) {
-            ReadBuffer buffer = new ReadBuffer(msg.getData());
-            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
-
-
-        }
+//        int identifier = msg.getIdentifier();
+//        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
+//        if (service != null) {
+//            ReadBuffer buffer = new ReadBuffer(msg.getData());
+//            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+//
+//
+//        }
     }
 
     @Override
@@ -101,7 +109,9 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     }
 
     private int cobId(CANOpenService service) {
-        return service.getValue() & configuration.getNodeId();
+        // form 32 bit socketcan identifier
+        return (configuration.getNodeId() << 24) & 0xff000000 |
+            (service.getValue() << 16 ) & 0x00ff0000;
     }
 
 }
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
index e8279b6..8212bea 100644
--- 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
@@ -29,7 +29,7 @@ public class Main {
     public static void main(String[] args) throws Exception {
         PlcDriverManager driverManager = new PlcDriverManager();
 
-        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=15");
+        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=11");
 
     }
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index 773f608..d7c1a33 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -19,10 +19,10 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>Tests of socketcan/CANopen frames.</name>
+  <name>Tests of CANopen frames payload.</name>
 
   <testcase>
-    <name>Network heartbeat payload: 00</name>
+    <name>Network heartbeat, payload: 00</name>
     <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
@@ -36,7 +36,7 @@
   </testcase>
 
   <testcase>
-    <name>Network heartbeat payload: 7F</name>
+    <name>Network heartbeat, payload: 7F</name>
     <raw>7F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
@@ -49,4 +49,113 @@
     </xml>
   </testcase>
 
+  <testcase>
+    <name>SDO request, payload: 4317100000000000</name>
+    <raw>4317100000000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIALIZE_UPLOAD</command>
+        <expedited>true</expedited>
+        <placement>true</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO request, payload: 00171000A00F0000</name>
+    <raw>00171000A00F0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_DOWNLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO write request, payload: 2B171000D00F</name>
+    <raw>2B171000D00F</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIALIZE_DOWNLOAD</command>
+        <expedited>true</expedited>
+        <placement>true</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data>
+          <data>208</data>
+          <data>15</data>
+        </data>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO write result, payload: 60171000D0F00000</name>
+    <raw>00171000A00F0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_DOWNLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <!-- samples -->
+  <testcase>
+    <name>SDO response, payload: 6000200000</name>
+    <raw>6000200000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_RESPONSE</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>PDO, payload: 78563412</name>
+    <raw>78563412</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_RESPONSE</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+
+  </testcase>
+
 </test:testsuite>
\ No newline at end of file


[plc4x] 11/14: Fix socketcan mspec errors.

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 9f66ffa54729f1f11790ea1f9a59b397f0028501
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 17:58:00 2020 +0200

    Fix socketcan mspec errors.
---
 protocols/can/src/main/resources/protocols/can/socketcan.mspec | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index e657a9d..201c0d6 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -28,7 +28,7 @@
         ]
 
         ['false' StandardSocketCANFrame
-            [const  uint 18 '0x0']
+            [const  uint 18 'spacing' '0x0']
             [simple uint 11 'identifier']
         ]
     ]
@@ -58,7 +58,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
-    [padding  uint 8 'pad' '0x00' '8 - (COUNT(data))']
+    [padding  uint 8 '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'


[plc4x] 13/14: Fix socketcan mspec.

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 951ea4fac287302c522f80fd8ffe9add4f1e7ae2
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Sep 3 13:40:38 2020 +0200

    Fix socketcan mspec.
---
 protocols/can/src/main/resources/protocols/can/socketcan.mspec | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index 201c0d6..9440365 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -18,15 +18,13 @@
  */
 
 [type 'BrokenSocketCANFrame'
-    [discriminator bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']
-    [simple bit 'extended']
+    [discriminator bit 'extended']
     [typeSwitch 'extended'
         ['true' ExtendedSocketCANFrame
             [simple uint 29 'identifier']
         ]
-
         ['false' StandardSocketCANFrame
             [const  uint 18 'spacing' '0x0']
             [simple uint 11 'identifier']
@@ -58,7 +56,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
-    [padding  uint 8 '0x00' '8 - (COUNT(data))']
+    [padding uint 8 'alignment' '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'


[plc4x] 10/14: Update service list for canopen.

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 8299febb0a077fea9df47927a209f3aa205a4166
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 11:42:00 2020 +0200

    Update service list for canopen.
---
 .../can/src/main/resources/protocols/can/canopen.mspec     |  9 +++++++++
 .../plc4x/java/can/protocol/CANOpenProtocolLogic.java      |  4 ++++
 .../test/resources/testsuite/CANOpenPayloadTestSuite.xml   | 14 ++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index d5160c6..0c4f175 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -19,9 +19,18 @@
 
 [enum uint 4 'CANOpenService'
     ['0b0000' BROADCAST   ]
+    ['0b0001' SYNC        ]
     ['0b1110' NMT         ]
     ['0b1100' SDO_REQUEST ]
     ['0b1011' SDO_RESPONSE]
+    ['0b0011' TPDO_1]
+    ['0b0100' RPDO_1]
+    ['0b0101' TPDO_2]
+    ['0b0110' RPDO_2]
+    ['0b0111' TPDO_3]
+    ['0b1000' RPDO_3]
+    ['0b1001' TPDO_4]
+    ['0b1010' RPDO_4]
 ]
 
 [enum uint 8 'NMTStateRequest'
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 9cc2fdb..0090e0e 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -114,4 +114,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
             (service.getValue() << 16 ) & 0x00ff0000;
     }
 
+    private CANOpenService serviceId(int nodeId) {
+        // form 32 bit socketcan identifier
+        return CANOpenService.valueOf((byte) (nodeId >> 7));
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index d7c1a33..ecf224b 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -50,6 +50,20 @@
   </testcase>
 
   <testcase>
+    <name>Network heartbeat, payload: 05</name>
+    <raw>05</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
     <name>SDO request, payload: 4317100000000000</name>
     <raw>4317100000000000</raw>
     <root-type>CANOpenPayload</root-type>


[plc4x] 07/14: More work on socketcan 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 144a360d38f0541e639a44f59006891cbb7736c7
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Fri Aug 28 12:05:30 2020 +0200

    More work on socketcan transport.
---
 .../socketcan/netty/SocketCANChannel.java          |  3 +-
 .../main/resources/protocols/can/socketcan.mspec   |  1 +
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  4 +-
 .../java/can/configuration/CANConfiguration.java   | 11 +++++
 .../java/can/protocol/CANOpenProtocolLogic.java    | 49 +++++++++++++++++++++-
 .../services/org.apache.plc4x.java.api.PlcDriver   |  1 +
 .../test/java/org/apache/plc4x/java/can/Main.java  |  2 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          | 29 ++++++++-----
 .../resources/testsuite/SocketCANTestSuite.xml     |  4 +-
 9 files changed, 86 insertions(+), 18 deletions(-)

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
index 764d1f5..305d452 100644
--- 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
@@ -243,7 +243,8 @@ public class SocketCANChannel extends OioByteStreamChannel {
 
         @Override
         public void write(byte[] b, int off, int len) throws IOException {
-            ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
+            ByteBuffer buffer = ByteBuffer.allocateDirect(len - off);
+            buffer.put(b, off, len);
             CanFrame frame = CanFrame.create(buffer);
             rawCanChannel.write(frame);
         }
diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index e2e9e3b..e657a9d 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -58,6 +58,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
+    [padding  uint 8 'pad' '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index b1c6fe6..4255ff2 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -42,12 +42,12 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
 
     @Override
     public String getProtocolCode() {
-        return "can";
+        return "canopen";
     }
 
     @Override
     public String getProtocolName() {
-        return "Controller Area Network";
+        return "CANopen";
     }
 
     @Override
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
index 1a86e45..925ca15 100644
--- 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
@@ -19,8 +19,19 @@ under the License.
 package org.apache.plc4x.java.can.configuration;
 
 import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.transport.socketcan.CANTransportConfiguration;
 
 public class CANConfiguration implements Configuration, CANTransportConfiguration {
 
+    @ConfigurationParameter
+    private int nodeId;
+
+    public int getNodeId() {
+        return nodeId;
+    }
+
+    public void setNodeId(int nodeId) {
+        this.nodeId = nodeId;
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index e6f18ca..555ef92 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -18,23 +18,62 @@ under the License.
 */
 package org.apache.plc4x.java.can.protocol;
 
+import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenNetworkPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.canopen.readwrite.types.NMTState;
 import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> implements HasConfiguration<CANConfiguration> {
 
     private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.class);
 
+    private CANConfiguration configuration;
+    private RequestTransactionManager tm;
+
+    @Override
+    public void setConfiguration(CANConfiguration configuration) {
+        this.configuration = configuration;
+        // Set the transaction manager to allow only one message at a time.
+        this.tm = new RequestTransactionManager(1);
+    }
+
     @Override
     public void onConnect(ConversationContext<SocketCANFrame> context) {
-        context.fireConnected();
+        CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.BOOTED_UP);
+        WriteBuffer buffer = new WriteBuffer(1);
+        try {
+            CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
+            context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
+            context.fireConnected();
+
+            Timer heartbeat = new Timer();
+            heartbeat.scheduleAtFixedRate(new TimerTask() {
+                @Override
+                public void run() {
+                    CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.OPERATIONAL);
+                    WriteBuffer buffer = new WriteBuffer(1);
+                    context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
+                }
+            }, 5000, 5000);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
     }
 
     @Override
@@ -46,6 +85,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
         if (service != null) {
             ReadBuffer buffer = new ReadBuffer(msg.getData());
             CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+
+
         }
     }
 
@@ -59,4 +100,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
 
     }
 
+    private int cobId(CANOpenService service) {
+        return service.getValue() & configuration.getNodeId();
+    }
+
 }
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
index cb3d2ec..3bbef56 100644
--- 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
@@ -17,3 +17,4 @@
 # under the License.
 #
 org.apache.plc4x.java.can.CANPlcDriver
+org.apache.plc4x.java.can.CANOpenPlcDriver
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
index 622f602..e8279b6 100644
--- 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
@@ -29,7 +29,7 @@ public class Main {
     public static void main(String[] args) throws Exception {
         PlcDriverManager driverManager = new PlcDriverManager();
 
-        PlcConnection connection = driverManager.getConnection("can:javacan://vcan0");
+        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=15");
 
     }
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index b5676d9..773f608 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -22,21 +22,30 @@
   <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Network heartbeat payload: 0000</name>
-    <raw>0000</raw>
+    <name>Network heartbeat payload: 00</name>
+    <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>NMT</arg1>
     </parser-arguments>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenPayload">
-        <function>15</function>
-        <identifier>5</identifier>
-        <extended>false</extended>
-        <remote>false</remote>
-        <error>false</error>
-        <data>ESIzRFVmd4g=</data>
-      </SocketCANFrame>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>BOOTED_UP</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Network heartbeat payload: 7F</name>
+    <raw>7F</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
     </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 03eaaf1..84fc15e 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
@@ -39,7 +39,7 @@
 
   <testcase>
     <name>Standard frame with no payload: 5A1#</name>
-    <raw>a105000000000000</raw>
+    <raw>a1050000000000000000000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
       <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
@@ -55,7 +55,7 @@
 
   <testcase>
     <name>Remote transmission request: 5A1#R</name>
-    <raw>a105004000000000</raw>
+    <raw>a1050040000000000000000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
       <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">


[plc4x] 05/14: Split different flavours of CAN 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 d244eded16148356bf5d217a152d9d242e347a07
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Aug 27 22:59:52 2020 +0200

    Split different flavours of CAN formats.
---
 .../can/{CANProtocol.java => CAN20AProtocol.java}  |  6 +--
 .../can/{CANProtocol.java => CANOpenProtocol.java} |  6 +--
 .../{CANProtocol.java => SocketCANProtocol.java}   |  6 +--
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  4 +-
 .../src/main/resources/protocols/can/can20a.mspec  | 25 +++++++++
 .../src/main/resources/protocols/can/canopen.mspec | 44 ++++++++++++++++
 .../protocols/can/{can.mspec => socketcan.mspec}   | 61 ----------------------
 sandbox/test-java-can-driver/pom.xml               | 16 +++++-
 .../org/apache/plc4x/java/can/CANPlcDriver.java    |  4 +-
 .../plc4x/java/can/helper/CANOpenHelper.java       | 18 +++++++
 .../apache/plc4x/java/can/helper/HeaderParser.java |  2 +-
 .../plc4x/java/can/protocol/CANProtocolLogic.java  |  2 +-
 .../org/apache/plc4x/java/can/CANOpenTest.java}    | 32 ++++--------
 ...ketCAN20BTestSuite.xml => CANOpenTestSuite.xml} | 18 +++----
 .../resources/testsuite/SocketCAN20ATestSuite.xml  |  6 +--
 .../resources/testsuite/SocketCAN20BTestSuite.xml  |  2 +-
 .../resources/testsuite/SocketCANTestSuite.xml     |  6 +--
 17 files changed, 144 insertions(+), 114 deletions(-)

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/CAN20AProtocol.java
similarity index 89%
copy from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
copy to protocols/can/src/main/java/org/apache/plc4x/protocol/can/CAN20AProtocol.java
index 853fb50..f93d868 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CAN20AProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class CAN20AProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "can20a";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = CAN20AProtocol.class.getResourceAsStream("/protocols/can/can20a.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
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/CANOpenProtocol.java
similarity index 89%
copy from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
copy to protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANOpenProtocol.java
index 853fb50..e6ddd5a 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANOpenProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class CANOpenProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "canopen";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = CANOpenProtocol.class.getResourceAsStream("/protocols/can/canopen.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
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/SocketCANProtocol.java
similarity index 88%
rename from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
rename to protocols/can/src/main/java/org/apache/plc4x/protocol/can/SocketCANProtocol.java
index 853fb50..dba9730 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/SocketCANProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class SocketCANProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "socketcan";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = SocketCANProtocol.class.getResourceAsStream("/protocols/can/socketcan.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
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
index d422eca..bf88883 100644
--- 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
@@ -16,4 +16,6 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-org.apache.plc4x.protocol.can.CANProtocol
\ No newline at end of file
+org.apache.plc4x.protocol.can.CAN20AProtocol
+org.apache.plc4x.protocol.can.SocketCANProtocol
+org.apache.plc4x.protocol.can.CANOpenProtocol
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/can20a.mspec b/protocols/can/src/main/resources/protocols/can/can20a.mspec
new file mode 100644
index 0000000..ffa733a
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/can20a.mspec
@@ -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.
+ */
+
+[type 'CANFrame'
+    [simple uint 11 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+]
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
new file mode 100644
index 0000000..553d12a
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -0,0 +1,44 @@
+/*
+ * 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 'CANOpenFrame'
+    [enum CANOpenService 'function']
+    [simple int 11 'identifier']
+    [reserved int 9 '0x0'] // filling gap used by extended frame, and extended marker which should always be 0
+    [simple bit 'remote']
+    [simple bit 'error']
+    [reserved int 5 '0x0']  // filling gap used by extended frame
+    [implicit uint 8 'size' 'COUNT(payload)']
+    [reserved uint 8 '0x0'] // in case of fd frame these are flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
+    [simple CANOpenPayload 'payload' ['function', 'size']]
+]
+
+[enum uint 4 'CANOpenService'
+    ['0b1110' NMT]
+]
+
+[discriminatedType 'CANOpenPayload' [CANOpenService 'function', uint 8 'size']
+    [typeSwitch 'function'
+        ['CANOpenService.NMT' CANOpenNetworkPayload [uint 8 'size']
+            [array int 8 'data' COUNT 'size']
+        ]
+    ]
+]
\ 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/socketcan.mspec
similarity index 61%
rename from protocols/can/src/main/resources/protocols/can/can.mspec
rename to protocols/can/src/main/resources/protocols/can/socketcan.mspec
index 147492b..e2e9e3b 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -17,41 +17,6 @@
  * under the License.
  */
 
-[type 'CANFrame'
-    [simple CANHeader 'header']
-    [simple uint 11 'identifier']
-    [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
-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 'BrokenSocketCANFrame'
     [discriminator bit 'extended']
     [simple bit 'remote']
@@ -107,30 +72,4 @@ struct canfd_frame {
     [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 'size' 'COUNT(data)'
-    [reserved uint 8 '0x0'] // flags
-    [reserved uint 8 '0x0'] // padding
-    [reserved uint 8 '0x0'] // padding
-    //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/pom.xml b/sandbox/test-java-can-driver/pom.xml
index 86bfddf..50e48e7 100644
--- a/sandbox/test-java-can-driver/pom.xml
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -37,13 +37,25 @@
         <artifactId>plc4x-maven-plugin</artifactId>
         <executions>
           <execution>
-            <id>test</id>
+            <id>socketcan</id>
             <phase>generate-sources</phase>
             <goals>
               <goal>generate-driver</goal>
             </goals>
             <configuration>
-              <protocolName>can</protocolName>
+              <protocolName>socketcan</protocolName>
+              <languageName>java</languageName>
+              <outputFlavor>read-write</outputFlavor>
+            </configuration>
+          </execution>
+          <execution>
+            <id>canopen</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>generate-driver</goal>
+            </goals>
+            <configuration>
+              <protocolName>canopen</protocolName>
               <languageName>java</languageName>
               <outputFlavor>read-write</outputFlavor>
             </configuration>
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 e1a55ed..c135280 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
@@ -24,8 +24,8 @@ 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.SocketCANFrame;
-import org.apache.plc4x.java.can.readwrite.io.SocketCANFrameIO;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.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;
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
new file mode 100644
index 0000000..5f6b4d3
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
@@ -0,0 +1,18 @@
+package org.apache.plc4x.java.can.helper;
+
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+public class CANOpenHelper {
+
+    public static CANOpenService readFunction(short identifier) {
+        return CANOpenService.valueOf((byte) (identifier >> 7));
+    }
+
+    public static void writeFunction(WriteBuffer io, short identifier) {
+        // NOOP - a placeholder to let mspec compile
+    }
+
+}
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 c0363f6..2ad7a1c 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
@@ -1,6 +1,6 @@
 package org.apache.plc4x.java.can.helper;
 
-import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
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
index 57dd683..b556a07 100644
--- 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
@@ -18,7 +18,7 @@ under the License.
 */
 package org.apache.plc4x.java.can.protocol;
 
-import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.slf4j.Logger;
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
similarity index 52%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
index e8f08f4..a97a1eb 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
@@ -1,5 +1,4 @@
-<?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
@@ -16,25 +15,16 @@
   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>Tests of socketcan/CAN 2.0B frames</name>
+package org.apache.plc4x.java.can;
 
-  <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3</raw>
-    <root-type>SocketCANFrame</root-type>
-    <xml>
-      <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>false</error>
-      </SocketCANFrame>
-    </xml>
-  </testcase>
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
 
-</test:testsuite>
\ No newline at end of file
+public class CANOpenTest extends ParserSerializerTestsuiteRunner {
+
+    public CANOpenTest() {
+        super("/testsuite/CANOpenTestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
similarity index 71%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
index e8f08f4..b99128d 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
@@ -19,20 +19,20 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>Tests of socketcan/CAN 2.0B frames</name>
+  <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Network heartbeat frame: 728#05</name>
+    <raw>280700000100000005</raw>
+    <root-type>CANOpenFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <rawId>-1636907402</rawId>
-        <data>BQUfJsM=</data>
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenFrame">
+        <function>15</function>
+        <identifier>5</identifier>
+        <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
+        <data>ESIzRFVmd4g=</data>
       </SocketCANFrame>
     </xml>
   </testcase>
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
index 60140de..3e647c5 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
@@ -26,7 +26,7 @@
     <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
@@ -41,7 +41,7 @@
     <raw>a105000000000000</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
@@ -56,7 +56,7 @@
     <raw>a105004000000000</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>true</remote>
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
index e8f08f4..0e9caf3 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
@@ -26,7 +26,7 @@
     <raw>76c66e9e0500000005051f26c3</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>-1636907402</rawId>
         <data>BQUfJsM=</data>
         <identifier>510576246</identifier>
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 f2518c0..03eaaf1 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
@@ -26,7 +26,7 @@
     <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1441</rawId>
         <data>ESIzRFVmd4g=</data>
         <identifier>1441</identifier>
@@ -42,7 +42,7 @@
     <raw>a105000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1441</rawId>
         <data></data>
         <identifier>1441</identifier>
@@ -58,7 +58,7 @@
     <raw>a105004000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1073743265</rawId>
         <data></data>
         <identifier>1441</identifier>


[plc4x] 14/14: CANopen adjustments.

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 b4c7fdda53fd4589fd6b037d9403ec35fea27e15
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Sep 3 13:46:10 2020 +0200

    CANopen adjustments.
---
 .../src/main/resources/protocols/can/canopen.mspec | 144 ++++++++++++++-------
 sandbox/test-java-can-driver/pom.xml               |   5 +
 .../java/can/protocol/CANOpenProtocolLogic.java    |  12 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          |  71 ++++++----
 4 files changed, 153 insertions(+), 79 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index c929ae4..bb825f3 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,21 +17,22 @@
  * under the License.
  */
 
-[enum uint 4 'CANOpenService' [bit 'sdo', bit 'pdo', bit 'transmit', bit 'receive']
-    ['0b0000' BROADCAST    ['false', 'false', 'false', 'false'] ]
-    ['0b0001' SYNC         ['false', 'false', 'false', 'false'] ]
-    ['0b0010' TIME         ['false', 'false', 'false', 'false'] ]
-    ['0b1110' NMT          ['false', 'false', 'false', 'false'] ]
-    ['0b1100' SDO_REQUEST  ['true',  'false', 'false', 'true' ] ]
-    ['0b1011' SDO_RESPONSE ['true',  'false', 'true',  'false'] ]
-    ['0b0011' TPDO_1       ['false', 'true',  'true',  'false'] ]
-    ['0b0100' RPDO_1       ['false', 'true',  'false', 'true' ] ]
-    ['0b0101' TPDO_2       ['false', 'true',  'true',  'false'] ]
-    ['0b0110' RPDO_2       ['false', 'true',  'false', 'true' ] ]
-    ['0b0111' TPDO_3       ['false', 'true',  'true',  'false'] ]
-    ['0b1000' RPDO_3       ['false', 'true',  'false', 'true' ] ]
-    ['0b1001' TPDO_4       ['false', 'true',  'true',  'false'] ]
-    ['0b1010' RPDO_4       ['false', 'true',  'false', 'true' ] ]
+[enum uint 4 'CANOpenService' [uint 8 'min', uint 8 'max', bit 'pdo']
+    ['0b0000' NMT             ['0',     '0'    , 'false' ] ]
+    ['0b0001' SYNC            ['0x80',  '0x80' , 'false' ] ]
+    ['0b0001' EMCY            ['0x81',  '0xFF' , 'false' ] ]
+    ['0b0010' TIME            ['0x100', '0x100', 'false' ] ]
+    ['0b0011' TRANSMIT_PDO_1  ['0x181', '0x1FF', 'true'  ] ]
+    ['0b0100' RECEIVE_PDO_1   ['0x201', '0x27F', 'true'  ] ]
+    ['0b0101' TRANSMIT_PDO_2  ['0x281', '0x2FF', 'true'  ] ]
+    ['0b0110' RECEIVE_PDO_2   ['0x301', '0x37F', 'true'  ] ]
+    ['0b0111' TRANSMIT_PDO_3  ['0x381', '0x3FF', 'true'  ] ]
+    ['0b1000' RECEIVE_PDO_3   ['0x401', '0x47F', 'true'  ] ]
+    ['0b1001' TRANSMIT_PDO_4  ['0x481', '0x4FF', 'true'  ] ]
+    ['0b1010' RECEIVE_PDO_4   ['0x501', '0x57F', 'true'  ] ]
+    ['0b1011' TRANSMIT_SDO    ['0x581', '0x5FF', 'false' ] ]
+    ['0b1100' RECEIVE_SDO     ['0x601', '0x67F', 'false' ] ]
+    ['0b1110' HEARTBEAT       ['0x701', '0x77F', 'false' ] ]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -51,7 +52,7 @@
 
 [discriminatedType 'CANOpenPayload' [CANOpenService 'function']
     [typeSwitch 'function'
-        ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
+        ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTStateRequest 'request']
             [reserved uint 1 '0x00']
             [simple uint 7 'node']
@@ -59,56 +60,103 @@
         ['CANOpenService.TIME' CANOpenTimeSynchronization
             [simple TimeOfDay 'timeOfDay']
         ]
-        ['CANOpenService.NMT' CANOpenNetworkPayload
-            [enum NMTState 'state']
-        ]
-        ['CANOpenService.SDO_REQUEST' CANOpenSDORequest
-            [enum SDOCommand 'command']
-            [reserved uint 1 '0x00']
-            [implicit uint 2 'size' 'COUNT(data)']
-            [simple bit 'expedited'] // segmented
-            [simple bit 'placement']
-            [simple uint 16 'index']
-            [simple uint 8 'subindex']
-            [array uint 8 'data' COUNT 'size']
-        ]
-        ['CANOpenService.SDO_RESPONSE' CANOpenSDOResponse
-            [enum SDOCommand 'command']
-            [reserved uint 1 '0x00']
-            [implicit uint 2 'size' 'COUNT(data)']
-            [simple bit 'expedited'] // segmented
-            [simple bit 'placement']
-            [simple uint 16 'index']
-            [simple uint 8 'subindex']
-            [array uint 8 'data' COUNT 'size']
-        ]
-        ['CANOpenService.RPDO_1' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_1' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'true']]
         ]
-        ['CANOpenService.TPDO_1' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_1' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_2' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_2' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['2', 'true']]
         ]
-        ['CANOpenService.TPDO_2' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_2' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_3' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_3' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['3', 'true']]
         ]
-        ['CANOpenService.TPDO_3' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_3' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_4' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_4' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['4', 'true']]
         ]
-        ['CANOpenService.TPDO_4' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_4' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
+        ['CANOpenService.TRANSMIT_SDO' CANOpenSDORequest
+            [enum SDOCommand 'command']
+            [simple SDORequest 'request' ['command']]
+        ]
+        ['CANOpenService.RECEIVE_SDO' CANOpenSDOResponse
+            [enum SDOCommand 'command']
+            [simple SDOResponse 'response' ['command']]
+        ]
+        ['CANOpenService.HEARTBEAT' CANOpenHeartbeatPayload
+            [enum NMTState 'state']
+        ]
+    ]
+]
+
+[type 'SDORequest' [SDOCommand 'command']
+    [typeSwitch 'command'
+        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadRequest
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
+            [simple bit 'expedited']
+            [simple bit 'indicated']
+            [simple Multiplexer 'address']
+            [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
+            [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
+        ]
+        ['SDOCommand.SEGMENT_DOWNLOAD' SDOSegmentDownloadRequest
+            [simple bit 'toggle']
+            [implicit uint 3 'size' '7 - COUNT(data)']
+            [simple bit 'last']
+            [array int 8 'data' COUNT '7 - data']
+            [padding uint 8 'alignment' '0x00' '7 - (COUNT(data))']
+        ]
+        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadRequest
+            [reserved uint 5 '0x00']
+            [simple Multiplexer 'address']
+            [reserved int 32 '0x00'] // padding
+        ]
+    ]
+]
+
+[type 'SDOResponse' [SDOCommand 'command']
+    [typeSwitch 'command'
+        ['SDOCommand.SEGMENT_UPLOAD' SDOSegmentUploadResponse
+            [reserved uint 5 '0x00']
+            [simple Multiplexer 'address']
+            [reserved int 32 '0x00'] // padding
+        ]
+        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadResponse
+            [simple bit 'toggle']
+            [reserved uint 4 '0x00']
+            [reserved int 32 '0x00'] // padding
+        ]
+        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadResponse
+            [simple SDOSegment 'segment']
+        ]
     ]
 ]
 
+[type 'SDOSegment'
+    [reserved uint 1 '0x00']
+    [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
+    [simple bit 'expedited']
+    [simple bit 'indicated']
+    [simple Multiplexer 'address']
+    [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
+    [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
+]
+
+[type 'Multiplexer'
+    [simple uint 16 'index']
+    [simple uint 8 'subindex']
+]
+
 [enum uint 3 'SDOCommand'
     ['0x00' SEGMENT_DOWNLOAD]
     ['0x01' INITIALIZE_DOWNLOAD]
@@ -120,7 +168,7 @@
 ]
 
 [type 'CANOpenPDO' [uint 2 'index', bit 'receive']
-
+    [array int 8 'data' COUNT '8']
 ]
 
 [type 'TimeOfDay'
diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml
index 50e48e7..e3e72c4 100644
--- a/sandbox/test-java-can-driver/pom.xml
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -73,6 +73,11 @@
     </dependency>
 
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-configuration2</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-transport-socketcan</artifactId>
       <version>0.8.0-SNAPSHOT</version>
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 0090e0e..c193ec3 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -19,8 +19,10 @@ under the License.
 package org.apache.plc4x.java.can.protocol;
 
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenHeartbeatPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenNetworkPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
@@ -58,7 +60,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     public void onConnect(ConversationContext<SocketCANFrame> context) {
         try {
             if (configuration.isHeartbeat()) {
-                context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.BOOTED_UP)));
+                context.sendToWire(createFrame(new CANOpenHeartbeatPayload(NMTState.BOOTED_UP)));
                 context.fireConnected();
 
                 this.heartbeat = new Timer();
@@ -66,7 +68,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
                     @Override
                     public void run() {
                         try {
-                            context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.OPERATIONAL)));
+                            context.sendToWire(createFrame(new CANOpenHeartbeatPayload(NMTState.OPERATIONAL)));
                         } catch (ParseException e) {
                             e.printStackTrace();
                         }
@@ -78,10 +80,10 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
         }
     }
 
-    private SocketCANFrame createFrame(CANOpenNetworkPayload state) throws ParseException {
+    private SocketCANFrame createFrame(CANOpenHeartbeatPayload state) throws ParseException {
         WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes());
-        CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
-        return new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData());
+        CANOpenHeartbeatPayloadIO.staticSerialize(buffer, state);
+        return new SocketCANFrame(cobId(CANOpenService.HEARTBEAT), buffer.getData());
     }
 
     @Override
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index 3188005..8537aee 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -67,12 +67,12 @@
     <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>BOOTED_UP</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
@@ -81,12 +81,12 @@
     <raw>7F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
@@ -95,21 +95,21 @@
     <raw>05</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 4317100000000000</name>
-    <raw>4317100000000000</raw>
+    <name>SDO request, payload: 43171000</name>
+    <raw>43171000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -124,11 +124,11 @@
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 00171000A00F0000</name>
-    <raw>00171000A00F0000</raw>
+    <name>SDO request, payload: 00171000<!--A00F0000--></name>
+    <raw>00171000<!--A00F0000--></raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -147,7 +147,7 @@
     <raw>2B171000D00F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -165,11 +165,11 @@
   </testcase>
 
   <testcase>
-    <name>SDO write result, payload: 60171000D0F00000</name>
-    <raw>00171000A00F0000</raw>
+    <name>SDO write result, payload: 60171000<!--A00F0000--></name>
+    <raw>00171000<!--A00F0000--></raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -185,16 +185,21 @@
 
   <!-- samples -->
   <testcase>
-    <name>SDO response, payload: 6000200000</name>
-    <raw>6000200000</raw>
+    <name>SDO response, payload: 60002000</name>
+    <raw>60002000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_RESPONSE</arg1>
+      <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
-        <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>SEGMENT_UPLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>8192</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDOResponse>
     </xml>
   </testcase>
 
@@ -203,14 +208,28 @@
     <raw>78563412</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_RESPONSE</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
         <state>PRE_OPERATIONAL</state>
       </CANOpenNetworkPayload>
     </xml>
+  </testcase>
+
 
+  <testcase>
+    <name>PDO, payload: F9013E014C015C01</name>
+    <raw>F9013E014C015C01</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_PDO_1</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
   </testcase>
 
 </test:testsuite>
\ No newline at end of file


[plc4x] 02/14: 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 c9429dada6a31bb105a541ec92a40e722b465e4b
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] 01/14: 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 e34c37a167f2a77316633dd3a751f9c52b9a1538
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");
+
+    }
+
+}