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