Skip to content

Commit 1e08846

Browse files
committed
CANopen driver fixes.
Signed-off-by: Łukasz Dywicki <[email protected]>
1 parent be513fb commit 1e08846

File tree

10 files changed

+114
-97
lines changed

10 files changed

+114
-97
lines changed

plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/transport/GenericCANFrameDataHandler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
import org.apache.plc4x.java.transport.can.CANTransport;
2525
import org.apache.plc4x.java.transport.can.FrameData;
2626

27+
/**
28+
* Generic CAN frame handler turn a wire level message @{@link FrameData} into a wrapper which
29+
* does not have any specific other than node id and data.
30+
*
31+
* Because it is used by generic purpose driver it can not assume any semantics on message role.
32+
*/
2733
public class GenericCANFrameDataHandler implements CANTransport.FrameHandler<Message, GenericFrame> {
2834

2935
private final Supplier<CANFrameBuilder<Message>> frameBuilder;

plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/transport/GenericFrame.java

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
*/
1919
package org.apache.plc4x.java.can.generic.transport;
2020

21-
import org.apache.plc4x.java.spi.generation.Message;
22-
import org.apache.plc4x.java.spi.generation.SerializationException;
23-
import org.apache.plc4x.java.spi.generation.WriteBuffer;
24-
25-
public class GenericFrame implements Message {
21+
/**
22+
* Wrapper for wire level data.
23+
*/
24+
public class GenericFrame {
2625

2726
private final int nodeId;
2827
private final byte[] data;
@@ -40,27 +39,4 @@ public byte[] getData() {
4039
return data;
4140
}
4241

43-
@Override
44-
public void serialize(WriteBuffer writeBuffer) throws SerializationException {
45-
// TODO: Is this correct?
46-
writeBuffer.writeUnsignedShort("length", 8, (short) data.length);
47-
writeBuffer.writeUnsignedInt("nodeId", 32, nodeId);
48-
writeBuffer.writeByteArray("data", data);
49-
}
50-
51-
@Override
52-
public int getLengthInBytes() {
53-
return 0;
54-
}
55-
56-
@Override
57-
public int getLengthInBits() {
58-
return 0;
59-
}
60-
61-
/*@Override
62-
public MessageIO<? extends Message, ? extends Message> getMessageIO() {
63-
return null;
64-
}*/
65-
6642
}

plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/GenericCANDriverTest.java

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,40 @@
1818
*/
1919
package org.apache.plc4x.java.can.generic;
2020

21+
import io.netty.buffer.ByteBuf;
22+
import io.netty.buffer.ByteBufAllocator;
23+
import io.netty.buffer.ByteBufUtil;
24+
import io.netty.buffer.Unpooled;
25+
import io.netty.buffer.UnpooledDirectByteBuf;
26+
import io.netty.channel.Channel;
27+
import io.netty.channel.ChannelHandlerAdapter;
28+
import io.netty.channel.ChannelHandlerContext;
29+
import io.netty.channel.ChannelInboundHandlerAdapter;
30+
import io.netty.channel.ChannelOutboundHandlerAdapter;
31+
import io.netty.channel.ChannelPromise;
32+
import io.netty.channel.embedded.EmbeddedChannel;
33+
import io.netty.channel.embedded.Plc4xEmbeddedChannel;
34+
import java.util.Optional;
2135
import java.util.concurrent.CountDownLatch;
2236
import java.util.concurrent.atomic.AtomicReference;
2337

2438
import org.apache.plc4x.java.DefaultPlcDriverManager;
2539
import org.apache.plc4x.java.api.PlcConnection;
2640
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
2741
import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
42+
import org.apache.plc4x.java.spi.connection.ChannelExposingConnection;
2843
import org.junit.jupiter.api.Disabled;
2944
import org.junit.jupiter.api.Test;
3045

3146
import static org.junit.jupiter.api.Assertions.*;
3247

48+
/**
49+
* Test of generic can driver with virtual can transport.
50+
*
51+
* This test have additional role of confirming end to end behavior of driver and transport layer.
52+
* The virtual can transport rely on netty channel/pipeline infrastructure, hence it does not have
53+
* any backend such as memory queue. It simply converts message to a stream and expect it to be read.
54+
*/
3355
public class GenericCANDriverTest {
3456

3557
@Test
@@ -44,20 +66,26 @@ void testConnection() throws PlcConnectionException {
4466
}
4567

4668
@Test
47-
@Disabled("This test requires working virtual CAN transport to be truly platform independent")
4869
void testSubscribeAndWrite() throws Exception {
49-
// PlcConnection connection1 = new PlcDriverManager().getConnection("genericcan:socketcan://vcan0");
50-
// PlcConnection connection2 = new PlcDriverManager().getConnection("genericcan:socketcan://vcan0");
51-
PlcConnection connection1 = new DefaultPlcDriverManager().getConnection("genericcan:virtualcan://");
52-
PlcConnection connection2 = connection1;
70+
PlcConnection connection = new DefaultPlcDriverManager().getConnection("genericcan:virtualcan://");
71+
72+
Plc4xEmbeddedChannel subscribeChannel = null;
73+
Plc4xEmbeddedChannel writeChannel = null;
74+
if (connection instanceof ChannelExposingConnection) {
75+
Channel channel = ((ChannelExposingConnection) connection).getChannel();
76+
if (channel instanceof Plc4xEmbeddedChannel) {
77+
subscribeChannel = (Plc4xEmbeddedChannel) channel;
78+
writeChannel = (Plc4xEmbeddedChannel) channel;
79+
}
80+
}
5381

5482
CountDownLatch latch = new CountDownLatch(1);
55-
Byte tag1 = 0x55;
83+
short tag1 = 0x55;
5684
short tag2 = 10;
5785
short tag3 = 50;
5886

5987
final AtomicReference<PlcSubscriptionEvent> plcEvent = new AtomicReference<>();
60-
connection1.subscriptionRequestBuilder()
88+
connection.subscriptionRequestBuilder()
6189
.addEventTagAddress("tag1", "200:BYTE")
6290
.addEventTagAddress("tag2", "200:UNSIGNED8")
6391
.addEventTagAddress("tag3", "200:UNSIGNED8")
@@ -73,7 +101,7 @@ void testSubscribeAndWrite() throws Exception {
73101
});
74102
});
75103

76-
connection2.writeRequestBuilder()
104+
connection.writeRequestBuilder()
77105
.addTagAddress("f1", "200:BYTE", tag1)
78106
.addTagAddress("f2", "200:UNSIGNED8", tag2)
79107
.addTagAddress("f3", "200:UNSIGNED8", tag3)
@@ -83,10 +111,16 @@ void testSubscribeAndWrite() throws Exception {
83111
}
84112
}).get();
85113

114+
// copy outbound message to inbound queue to confirm that transport API works and subscription
115+
// is properly matched against incoming message
116+
ByteBuf outgoing = writeChannel.flushOutbound().readOutbound();
117+
subscribeChannel.writeInbound(Unpooled.wrappedBuffer(outgoing));
118+
subscribeChannel.flushInbound();
119+
86120
latch.await();
87121

88122
PlcSubscriptionEvent event = plcEvent.get();
89-
assertEquals(tag1, event.getByte("tag1"));
123+
assertEquals(tag1, (short) event.getByte("tag1"));
90124
assertEquals(tag2, event.getShort("tag2"));
91125
assertEquals(tag3, event.getShort("tag3"));
92126

plc4j/drivers/canopen/src/main/generated/org/apache/plc4x/java/canopen/readwrite/CANOpenDataType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ public enum CANOpenDataType {
4545
INTEGER64((long) 16L, (String) "LINT", (short) 64),
4646
REAL32((long) 17L, (String) "REAL", (short) 32),
4747
REAL64((long) 18L, (String) "LREAL", (short) 64),
48-
RECORD((long) 19L, (String) "BYTE", (short) 8),
49-
OCTET_STRING((long) 20L, (String) "BYTE", (short) 8),
48+
RECORD((long) 19L, (String) "RAW_BYTE_ARRAY", (short) 8),
49+
OCTET_STRING((long) 20L, (String) "RAW_BYTE_ARRAY", (short) 8),
5050
VISIBLE_STRING((long) 21L, (String) "CHAR", (short) 8),
5151
UNICODE_STRING((long) 22L, (String) "WCHAR", (short) 16),
5252
TIME_OF_DAY((long) 23L, (String) "TIME_OF_DAY", (short) 48),

plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcRawByteArray.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ public PlcValueType getPlcValueType() {
4343
}
4444

4545
@Override
46-
public String toString() {
47-
return Hex.encodeHexString(value);
46+
public byte[] getRaw() {
47+
return value;
4848
}
4949

50-
public byte[] getBytes() {
51-
return value;
50+
@Override
51+
public String toString() {
52+
return Hex.encodeHexString(value);
5253
}
5354

5455
@Override

plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration;
2727
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
2828
import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
29+
import org.apache.plc4x.java.spi.configuration.PlcTransportConfiguration;
2930
import org.apache.plc4x.java.spi.connection.ChannelFactory;
3031
import org.apache.plc4x.java.spi.generation.*;
3132
import org.apache.plc4x.java.transport.can.CANFrameBuilder;
@@ -59,6 +60,14 @@ public ToIntFunction<ByteBuf> getEstimator() {
5960
return (buff) -> 16;
6061
}
6162

63+
public static class EmptyConfiguration implements PlcTransportConfiguration {}
64+
65+
@Override
66+
public Class<? extends PlcTransportConfiguration> getTransportConfigType() {
67+
return EmptyConfiguration.class;
68+
}
69+
70+
6271
@Override
6372
public MessageInput<SocketCANFrame> getMessageInput(PlcConnectionConfiguration cfg) {
6473
return SocketCANFrame::staticParse;

plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANFrame.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,36 @@
1818
*/
1919
package org.apache.plc4x.java.transport.virtualcan;
2020

21+
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
22+
import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
23+
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
24+
2125
import org.apache.commons.codec.binary.Hex;
26+
import org.apache.plc4x.java.spi.codegen.WithOption;
27+
import org.apache.plc4x.java.spi.generation.ByteOrder;
2228
import org.apache.plc4x.java.spi.generation.Message;
29+
import org.apache.plc4x.java.spi.generation.MessageInput;
30+
import org.apache.plc4x.java.spi.generation.ParseException;
31+
import org.apache.plc4x.java.spi.generation.ReadBuffer;
2332
import org.apache.plc4x.java.spi.generation.SerializationException;
2433
import org.apache.plc4x.java.spi.generation.WriteBuffer;
2534

2635
public class VirtualCANFrame implements Message {
36+
37+
public final static MessageInput<VirtualCANFrame> PARSER = new MessageInput<VirtualCANFrame>() {
38+
39+
@Override
40+
public VirtualCANFrame parse(ReadBuffer io, Object... args) throws ParseException {
41+
WithOption withOption = WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN);
42+
43+
short length = io.readUnsignedShort("length", 8, withOption);
44+
int nodeId = io.readInt("nodeId", 32, withOption);
45+
byte[] data = io.readByteArray("data", length, withOption);
46+
47+
return new VirtualCANFrame(nodeId, data);
48+
}
49+
};
50+
2751
private final int nodeId;
2852
private final byte[] data;
2953

@@ -42,19 +66,22 @@ public byte[] getData() {
4266

4367
@Override
4468
public void serialize(WriteBuffer writeBuffer) throws SerializationException {
45-
writeBuffer.writeUnsignedShort("length", 8, (short) data.length);
46-
writeBuffer.writeUnsignedInt("nodeId", 32, nodeId);
47-
writeBuffer.writeByteArray("data", data);
69+
WithOption withOption = WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN);
70+
71+
writeSimpleField("length", (short) data.length, writeUnsignedShort(writeBuffer, 8), withOption);
72+
writeSimpleField("nodeId", nodeId, writeSignedInt(writeBuffer, 32), withOption);
73+
writeByteArrayField("data", data, writeByteArray(writeBuffer, 8), withOption);
4874
}
4975

76+
5077
@Override
5178
public int getLengthInBytes() {
52-
return 0;
79+
return 1 + 4 + data.length;
5380
}
5481

5582
@Override
5683
public int getLengthInBits() {
57-
return 0;
84+
return getLengthInBytes() * 8;
5885
}
5986

6087
public String toString() {

plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANTransport.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
import io.netty.buffer.ByteBuf;
2222
import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration;
2323
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
24+
import org.apache.plc4x.java.spi.configuration.PlcTransportConfiguration;
2425
import org.apache.plc4x.java.spi.generation.*;
2526
import org.apache.plc4x.java.transport.can.CANFrameBuilder;
2627
import org.apache.plc4x.java.transport.can.CANTransport;
2728
import org.apache.plc4x.java.transport.can.FrameData;
2829
import org.apache.plc4x.java.transport.test.TestTransport;
29-
import org.apache.plc4x.java.transport.virtualcan.io.VirtualCANFrameIO;
3030

3131
import java.util.function.Function;
3232
import java.util.function.ToIntFunction;
@@ -45,14 +45,21 @@ public String getTransportName() {
4545

4646
@Override
4747
public ToIntFunction<ByteBuf> getEstimator() {
48-
return value -> value.getShort(value.readerIndex());
48+
return ByteBuf::readableBytes;
4949
}
5050

5151
@Override
5252
public Class<VirtualCANFrame> getMessageType() {
5353
return VirtualCANFrame.class;
5454
}
5555

56+
public static class EmptyConfiguration implements PlcTransportConfiguration {}
57+
58+
@Override
59+
public Class<? extends PlcTransportConfiguration> getTransportConfigType() {
60+
return EmptyConfiguration.class;
61+
}
62+
5663
@Override
5764
public CANFrameBuilder<VirtualCANFrame> getTransportFrameBuilder() {
5865
return new CANFrameBuilder<>() {
@@ -110,7 +117,7 @@ public byte[] getData() {
110117

111118
@Override
112119
public MessageInput<VirtualCANFrame> getMessageInput(PlcConnectionConfiguration configuration) {
113-
return new VirtualCANFrameIO();
120+
return VirtualCANFrame.PARSER;
114121
}
115122

116123
}

plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/io/VirtualCANFrameIO.java

Lines changed: 0 additions & 43 deletions
This file was deleted.

protocols/canopen/src/main/resources/protocols/can/canopen.mspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,8 @@
262262
[REAL64 ['64', '"LREAL"' ] ]
263263

264264
// compound/complex types
265-
[RECORD [ '8', '"BYTE"' ] ]
266-
[OCTET_STRING [ '8', '"BYTE"' ] ]
265+
[RECORD [ '8', '"RAW_BYTE_ARRAY"' ] ]
266+
[OCTET_STRING [ '8', '"RAW_BYTE_ARRAY"' ] ]
267267
[VISIBLE_STRING [ '8', '"CHAR"' ] ]
268268
[UNICODE_STRING ['16', '"WCHAR"' ] ]
269269
[TIME_OF_DAY ['48', '"TIME_OF_DAY"'] ]
@@ -330,7 +330,7 @@
330330
[simple float 64 value]
331331
]
332332
['RECORD' List(int 32 size)
333-
[array byte value length 'size']
333+
[array byte value count 'size']
334334
]
335335
['OCTET_STRING' STRING
336336
[simple vstring 'size' value]

0 commit comments

Comments
 (0)