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 <[email protected]> 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"); + + } + +}
