This is an automated email from the ASF dual-hosted git repository. ldywicki pushed a commit to branch feature/socketcan-0.8-preparations in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 30b42b7778aff2b53d3d68fe8da62ed9ec674386 Author: Ćukasz Dywicki <[email protected]> AuthorDate: Wed Oct 21 10:42:11 2020 +0200 Support for NMT and HEARTBEAT subscriptions. --- sandbox/test-java-can-driver/pom.xml | 13 + .../api/segmentation/accumulator/ByteStorage.java | 18 ++ .../apache/plc4x/java/can/field/CANOpenField.java | 4 + ...penNMTField.java => CANOpenHeartbeatField.java} | 18 +- .../plc4x/java/can/field/CANOpenNMTField.java | 10 +- .../plc4x/java/can/field/CANOpenPDOField.java | 8 +- .../java/can/field/CANOpenSubscriptionField.java | 11 + .../java/can/protocol/CANOpenProtocolLogic.java | 51 +++- ...nHandle.java => CANOpenSubscriptionHandle.java} | 13 +- .../plc4x/java/can/field/CANOpenNMTFieldTest.java | 9 +- .../plc4x/java/can/field/CANOpenSDOFieldTest.java | 26 ++ .../resources/testsuite/CANOpenDriverSDOIT.xml | 324 +++++++++++++++++++++ 12 files changed, 472 insertions(+), 33 deletions(-) diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml index 4ed0eaa..fcb4507 100644 --- a/sandbox/test-java-can-driver/pom.xml +++ b/sandbox/test-java-can-driver/pom.xml @@ -29,6 +29,7 @@ <artifactId>test-java-can-driver</artifactId> <name>Sandbox: Test Generated CAN Driver</name> + <packaging>bundle</packaging> <build> <plugins> @@ -62,6 +63,18 @@ </execution> </executions> </plugin> + <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.DriverActivator</Bundle-Activator> + <Export-Service>org.apache.plc4x.java.api.PlcDriver,org.apache.plc4x.java.can.CANOpenPlcDriver</Export-Service> + </instructions> + </configuration> + </plugin> </plugins> </build> diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java index 1f143f2..ae0a6b4 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java @@ -56,4 +56,22 @@ public class ByteStorage<T> implements Storage<T, byte[]> { } } + public static class SDODownloadStorage extends ByteStorage<SDORequest> { + public SDODownloadStorage() { + super((sdoRequest -> { + if (sdoRequest instanceof SDOSegmentDownloadRequest) { + return ((SDOSegmentDownloadRequest) sdoRequest).getData(); + } + if (sdoRequest instanceof SDOInitiateDownloadRequest) { + SDOInitiateDownloadRequest initiate = (SDOInitiateDownloadRequest) sdoRequest; + + if (initiate.getPayload() instanceof SDOInitiateExpeditedUploadResponse) { + return ((SDOInitiateExpeditedUploadResponse) initiate.getPayload()).getData(); + } + } + return new byte[0]; + })); + } + } + } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java index 6917351..ddd2a1a 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java @@ -46,6 +46,10 @@ public abstract class CANOpenField implements PlcField { return CANOpenSDOField.of(addressString); } else if (CANOpenPDOField.matches(addressString)) { return CANOpenPDOField.of(addressString); + } else if (CANOpenNMTField.matches(addressString)) { + return CANOpenNMTField.of(addressString); + } else if (CANOpenHeartbeatField.matches(addressString)) { + return CANOpenHeartbeatField.of(addressString); } throw new PlcInvalidFieldException("Unable to parse address: " + addressString); diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenHeartbeatField.java similarity index 73% copy from sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java copy to sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenHeartbeatField.java index 83bba15..ef6a4ad 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenHeartbeatField.java @@ -19,18 +19,24 @@ under the License. package org.apache.plc4x.java.can.field; import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class CANOpenNMTField extends CANOpenField { +public class CANOpenHeartbeatField extends CANOpenField implements CANOpenSubscriptionField { - public static final Pattern ADDRESS_PATTERN = Pattern.compile("NMT|NMT:" + CANOpenField.NODE_PATTERN); + public static final Pattern ADDRESS_PATTERN = Pattern.compile("HEARTBEAT|HEARTBEAT:" + CANOpenField.NODE_PATTERN); - public CANOpenNMTField(int node) { + public CANOpenHeartbeatField(int node) { super(node); } + @Override + public CANOpenService getService() { + return CANOpenService.HEARTBEAT; + } + public boolean isWildcard() { return getNodeId() == 0; } @@ -48,11 +54,11 @@ public class CANOpenNMTField extends CANOpenField { throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN); } - public static CANOpenNMTField of(String addressString) { + public static CANOpenHeartbeatField of(String addressString) { Matcher matcher = getMatcher(addressString); - int nodeId = Integer.parseInt(matcher.group("nodeId")); + int nodeId = matcher.group("nodeId") == null ? 0 : Integer.parseInt(matcher.group("nodeId")); - return new CANOpenNMTField(nodeId); + return new CANOpenHeartbeatField(nodeId); } } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java index 83bba15..74370b1 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java @@ -19,11 +19,12 @@ under the License. package org.apache.plc4x.java.can.field; import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class CANOpenNMTField extends CANOpenField { +public class CANOpenNMTField extends CANOpenField implements CANOpenSubscriptionField { public static final Pattern ADDRESS_PATTERN = Pattern.compile("NMT|NMT:" + CANOpenField.NODE_PATTERN); @@ -31,6 +32,11 @@ public class CANOpenNMTField extends CANOpenField { super(node); } + @Override + public CANOpenService getService() { + return CANOpenService.NMT; + } + public boolean isWildcard() { return getNodeId() == 0; } @@ -50,7 +56,7 @@ public class CANOpenNMTField extends CANOpenField { public static CANOpenNMTField of(String addressString) { Matcher matcher = getMatcher(addressString); - int nodeId = Integer.parseInt(matcher.group("nodeId")); + int nodeId = matcher.group("nodeId") == null ? 0 : Integer.parseInt(matcher.group("nodeId")); return new CANOpenNMTField(nodeId); } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java index 2761260..cfe050d 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java @@ -26,7 +26,7 @@ import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class CANOpenPDOField extends CANOpenField { +public class CANOpenPDOField extends CANOpenField implements CANOpenSubscriptionField { public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?<pdo>(?:RECEIVE|TRANSMIT)_PDO_[1-4]):" + CANOpenField.NODE_PATTERN + ":(?<canDataType>\\w+)(\\[(?<numberOfElements>\\d)])?"); private final CANOpenService service; @@ -74,4 +74,10 @@ public class CANOpenPDOField extends CANOpenField { public CANOpenService getService() { return service; } + + @Override + public boolean isWildcard() { + return false; + } + } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSubscriptionField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSubscriptionField.java new file mode 100644 index 0000000..78fafc0 --- /dev/null +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSubscriptionField.java @@ -0,0 +1,11 @@ +package org.apache.plc4x.java.can.field; + +import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; + +public interface CANOpenSubscriptionField { + CANOpenService getService(); + + boolean isWildcard(); + + int getNodeId(); +} diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java index 5285b16..a46b17d 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java @@ -38,16 +38,14 @@ import org.apache.plc4x.java.can.canopen.CANOpenFrameBuilderFactory; import org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrameBuilder; import org.apache.plc4x.java.can.configuration.CANConfiguration; import org.apache.plc4x.java.can.context.CANOpenDriverContext; -import org.apache.plc4x.java.can.field.CANOpenField; -import org.apache.plc4x.java.can.field.CANOpenNMTField; -import org.apache.plc4x.java.can.field.CANOpenPDOField; -import org.apache.plc4x.java.can.field.CANOpenSDOField; +import org.apache.plc4x.java.can.field.*; import org.apache.plc4x.java.can.socketcan.SocketCANConversation; import org.apache.plc4x.java.canopen.readwrite.*; import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO; import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO; import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; import org.apache.plc4x.java.canopen.readwrite.types.NMTState; +import org.apache.plc4x.java.canopen.readwrite.types.NMTStateRequest; import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.configuration.HasConfiguration; @@ -251,11 +249,15 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.UNSUPPORTED, null)); } else if ((subscription.getPlcField() instanceof CANOpenPDOField)) { answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.OK, - new CANOpenPDOSubscriptionHandle(this, entry.getKey(), (CANOpenPDOField) subscription.getPlcField()) + new CANOpenSubscriptionHandle(this, entry.getKey(), (CANOpenPDOField) subscription.getPlcField()) )); } else if ((subscription.getPlcField() instanceof CANOpenNMTField)) { answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.OK, - new CANOpenNMTSubscriptionHandle(this, entry.getKey(), (CANOpenNMTField) subscription.getPlcField()) + new CANOpenSubscriptionHandle(this, entry.getKey(), (CANOpenNMTField) subscription.getPlcField()) + )); + } else if ((subscription.getPlcField() instanceof CANOpenHeartbeatField)) { + answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.OK, + new CANOpenSubscriptionHandle(this, entry.getKey(), (CANOpenHeartbeatField) subscription.getPlcField()) )); } else { answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.INVALID_ADDRESS, null)); @@ -294,11 +296,11 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem CANOpenService service = msg.getService(); CANOpenPayload payload = msg.getPayload(); - if (service != null) { + if (service != null && nodeId != this.configuration.getNodeId()) { if (service.getPdo() && payload instanceof CANOpenPDOPayload) { - publishEvent(service, nodeId, (CANOpenPDOPayload) payload); - } else if (service == CANOpenService.NMT && payload instanceof CANOpenNetworkPayload) { - publishEvent(service, nodeId, (CANOpenNetworkPayload) payload); + publishEvent(service, nodeId, payload); + } else if (service == CANOpenService.HEARTBEAT && payload instanceof CANOpenHeartbeatPayload) { + publishEvent(service, nodeId, payload); } else { String hex = ""; if (logger.isInfoEnabled()) { @@ -331,14 +333,14 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem Consumer<PlcSubscriptionEvent> consumer = entry.getValue(); for (InternalPlcSubscriptionHandle handler : registration.getAssociatedHandles()) { - if (handler instanceof CANOpenPDOSubscriptionHandle && payload instanceof CANOpenPDOPayload) { - CANOpenPDOSubscriptionHandle handle = (CANOpenPDOSubscriptionHandle) handler; + CANOpenSubscriptionHandle handle = (CANOpenSubscriptionHandle) handler; + if (payload instanceof CANOpenPDOPayload) { if (handle.matches(service, nodeId)) { logger.trace("Dispatching notification {} for node {} to {}", service, nodeId, handle); dispatchedHandle = handle; - CANOpenPDOField field = handle.getField(); + CANOpenPDOField field = (CANOpenPDOField) handle.getField(); byte[] data = ((CANOpenPDOPayload) payload).getPdo().getData(); try { PlcValue value = DataItemIO.staticParse(new ReadBuffer(data, true), field.getCanOpenDataType(), data.length); @@ -362,9 +364,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem consumer.accept(event); } } - } else if (handler instanceof CANOpenPDOSubscriptionHandle && payload instanceof CANOpenHeartbeatPayload) { - CANOpenNMTSubscriptionHandle handle = (CANOpenNMTSubscriptionHandle) handler; - + } else if (payload instanceof CANOpenHeartbeatPayload) { if (handle.matches(service, nodeId)) { logger.trace("Dispatching notification {} for node {} to {}", service, nodeId, handle); dispatchedHandle = handle; @@ -383,6 +383,25 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem ); consumer.accept(event); } + } else if (payload instanceof CANOpenNetworkPayload) { + if (handle.matches(service, nodeId)) { + logger.trace("Dispatching notification {} for node {} to {}", service, nodeId, handle); + dispatchedHandle = handle; + + final NMTStateRequest state = ((CANOpenNetworkPayload) payload).getRequest(); + Map<String, PlcValue> fields = new HashMap<>(); + fields.put("state", new PlcUSINT(state.getValue())); + fields.put("node", new PlcUSINT(nodeId)); + PlcStruct struct = new PlcStruct(fields); + DefaultPlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent( + Instant.now(), + Collections.singletonMap( + handle.getName(), + new ResponseItem<>(PlcResponseCode.OK, struct) + ) + ); + consumer.accept(event); + } } } } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenPDOSubscriptionHandle.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java similarity index 56% rename from sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenPDOSubscriptionHandle.java rename to sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java index 80876c6..e318da3 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenPDOSubscriptionHandle.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java @@ -1,15 +1,16 @@ package org.apache.plc4x.java.can.protocol; import org.apache.plc4x.java.can.field.CANOpenPDOField; +import org.apache.plc4x.java.can.field.CANOpenSubscriptionField; import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; import org.apache.plc4x.java.spi.messages.PlcSubscriber; import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle; -public class CANOpenPDOSubscriptionHandle extends DefaultPlcSubscriptionHandle { +public class CANOpenSubscriptionHandle extends DefaultPlcSubscriptionHandle { private final String name; - private final CANOpenPDOField field; + private final CANOpenSubscriptionField field; - public CANOpenPDOSubscriptionHandle(PlcSubscriber subscriber, String name, CANOpenPDOField field) { + public CANOpenSubscriptionHandle(PlcSubscriber subscriber, String name, CANOpenSubscriptionField field) { super(subscriber); this.name = name; this.field = field; @@ -19,19 +20,19 @@ public class CANOpenPDOSubscriptionHandle extends DefaultPlcSubscriptionHandle { if (field.getService() != service) { return false; } - return field.getNodeId() == identifier; + return field.isWildcard() || field.getNodeId() == identifier; } public String getName() { return name; } - public CANOpenPDOField getField() { + public CANOpenSubscriptionField getField() { return field; } public String toString() { - return "CANOpenPDOSubscriptionHandle [service=" + field.getService() + ", node=" + intAndHex(field.getNodeId()) + ", cob=" + intAndHex(field.getService().getMin() + field.getNodeId()) + "]"; + return "CANopenSubscriptionHandle [service=" + field.getService() + ", node=" + intAndHex(field.getNodeId()) + ", cob=" + intAndHex(field.getService().getMin() + field.getNodeId()) + "]"; } private static String intAndHex(int val) { diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java index 3f48fc1..06db074 100644 --- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java +++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java @@ -35,12 +35,17 @@ class CANOpenNMTFieldTest { @Test public void testWildcardSyntax() { - final CANOpenNMTField canField = CANOpenNMTField.of("NMT:0"); + CANOpenNMTField canField = CANOpenNMTField.of("NMT:0"); assertEquals(0, canField.getNodeId()); assertTrue(canField.isWildcard()); - } + // an simplified syntax + canField = CANOpenNMTField.of("NMT"); + + assertEquals(0, canField.getNodeId()); + assertTrue(canField.isWildcard()); + } @Test public void testInvalidSyntax() { diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenSDOFieldTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenSDOFieldTest.java new file mode 100644 index 0000000..ddecd2b --- /dev/null +++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenSDOFieldTest.java @@ -0,0 +1,26 @@ +package org.apache.plc4x.java.can.field; + +import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CANOpenSDOFieldTest { + + @Test + public void testNodeSyntax() { + final CANOpenSDOField canField = CANOpenSDOField.of("SDO:20:0x10/0xAA:RECORD"); + + assertEquals(20, canField.getNodeId()); + assertEquals(0x10, canField.getIndex()); + assertEquals(0xAA, canField.getSubIndex()); + assertEquals(CANOpenDataType.RECORD, canField.getCanOpenDataType()); + } + + @Test + public void testInvalidSyntax() { + assertThrows(PlcInvalidFieldException.class, () -> CANOpenSDOField.of("SDO:")); + } + +} \ No newline at end of file diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenDriverSDOIT.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenDriverSDOIT.xml new file mode 100644 index 0000000..190f3be --- /dev/null +++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenDriverSDOIT.xml @@ -0,0 +1,324 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + --> +<test:driver-testsuite xmlns:test="https://plc4x.apache.org/schemas/driver-testsuite.xsd" + bigEndian="false"> + + <name>CANOpen SDO Segmentation</name> + + <driver-name>canopen</driver-name> + <driver-parameters> + <parameter> + <name>nodeId</name> + <value>15</value> + </parameter> + </driver-parameters> + + <testcase> + <name>Expedited SDO read request</name> + <description> + Single field read request which answers with 4 bytes of data. + </description> + <steps> + <api-request name="Receive Read Request from application"> + <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest"> + <fields> + <field className="org.apache.plc4x.test.driver.model.api.TestField"> + <name>sdo1</name> + <address>SDO:1:1000/22:UNSIGNED32</address> + </field> + </fields> + </TestReadRequest> + </api-request> + <outgoing-plc-message name="Send SDO Initialize Upload Request"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>1</nodeId> + <service>RECEIVE_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest"> + <command>INITIATE_UPLOAD</command> + <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadRequest"> + <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress"> + <index>1000</index> + <subindex>22</subindex> + </address> + </request> + </payload> + </CANOpenSocketCANFrame> + </outgoing-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response for other node"> + <!-- one unwanted frame --> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>1</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>INITIATE_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse"> + <expedited>true</expedited> + <indicated>true</indicated> + <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress"> + <index>1001</index> + <subindex>22</subindex> + </address> + <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse"> + <data>YXNkZg==</data> + </payload> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response for from requested node"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>1</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>INITIATE_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse"> + <expedited>true</expedited> + <indicated>true</indicated> + <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress"> + <index>1000</index> + <subindex>22</subindex> + </address> + <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse"> + <data>YXNkZg==</data> + </payload> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + <api-response name="Report Read Response to application"> + <DefaultPlcReadResponse className="org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse"> + <request className="org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest"> + <sdo1 className="org.apache.plc4x.java.can.field.CANOpenSDOField"> + <nodeId>1</nodeId> + <index>1000</index> + <subIndex>22</subIndex> + <canOpenDataType>UNSIGNED32</canOpenDataType> + </sdo1> + </request> + <sdo1> + <code>OK</code> + <value className="org.apache.plc4x.java.api.value.PlcUDINT"> + <object>java.lang.Long</object> + <object>1717859169</object> + </value> + </sdo1> + </DefaultPlcReadResponse> + </api-response> + <delay>1000</delay> + </steps> + </testcase> + + <testcase> + <name>Segmented SDO read request</name> + <description> + Single field read request which answers with 8 bytes of data which must go over two CAN frames. + </description> + <steps> + <api-request name="Receive Read Request from application"> + <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest"> + <fields> + <field className="org.apache.plc4x.test.driver.model.api.TestField"> + <name>sdo1</name> + <address>SDO:2:2000/44:RECORD</address> + </field> + </fields> + </TestReadRequest> + </api-request> + + <outgoing-plc-message name="Send SDO Initialize Upload Request"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>RECEIVE_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest"> + <command>INITIATE_UPLOAD</command> + <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadRequest"> + <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress"> + <index>2000</index> + <subindex>44</subindex> + </address> + </request> + </payload> + </CANOpenSocketCANFrame> + </outgoing-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response with segment information"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>INITIATE_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse"> + <expedited>false</expedited> + <indicated>true</indicated> + <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress"> + <index>2000</index> + <subindex>44</subindex> + </address> + <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateSegmentedUploadResponse"> + <bytes>8</bytes> + </payload> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + + <outgoing-plc-message name="Send first SDO Segment Request"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>RECEIVE_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest"> + <command>SEGMENT_UPLOAD</command> + <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadRequest"> + <toggle>false</toggle> + </request> + </payload> + </CANOpenSocketCANFrame> + </outgoing-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response for first segment"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>SEGMENT_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse"> + <toggle>false</toggle> + <last>false</last> + <data>YXNkZg==</data> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + + <outgoing-plc-message name="Send SDO Initialize Upload Request"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>RECEIVE_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest"> + <command>SEGMENT_UPLOAD</command> + <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadRequest"> + <toggle>true</toggle> + </request> + </payload> + </CANOpenSocketCANFrame> + </outgoing-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response with segment information"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>SEGMENT_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse"> + <toggle>true</toggle> + <last>false</last> + <data>YXNkZg==</data> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + + <outgoing-plc-message name="Send second SDO Segment Request"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>RECEIVE_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest"> + <command>SEGMENT_UPLOAD</command> + <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadRequest"> + <toggle>false</toggle> + </request> + </payload> + </CANOpenSocketCANFrame> + </outgoing-plc-message> + <incoming-plc-message name="Receive SDO Initialize Upload Response for second segment"> + <CANOpenSocketCANFrame className="org.apache.plc4x.java.can.canopen.socketcan.CANOpenSocketCANFrame"> + <nodeId>2</nodeId> + <service>TRANSMIT_SDO</service> + <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse"> + <command>SEGMENT_UPLOAD</command> + <response className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse"> + <toggle>false</toggle> + <last>true</last> + <data>YXNkZg==</data> + </response> + </payload> + </CANOpenSocketCANFrame> + </incoming-plc-message> + + <api-response name="Report Read Response to application"> + <DefaultPlcReadResponse className="org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse"> + <request className="org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest"> + <sdo1 className="org.apache.plc4x.java.can.field.CANOpenSDOField"> + <nodeId>2</nodeId> + <index>2000</index> + <subIndex>44</subIndex> + <canOpenDataType>RECORD</canOpenDataType> + </sdo1> + </request> + <sdo1> + <code>OK</code> + <value className="org.apache.plc4x.java.api.value.PlcList"> + <object>java.util.Collections..UnmodifiableRandomAccessList</object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>97</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>115</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>100</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>102</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>97</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>115</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>100</object> + </object> + <object>org.apache.plc4x.java.api.value.PlcSINT</object> + <object> + <object>java.lang.Byte</object> + <object>102</object> + </object> + </value> + </sdo1> + </DefaultPlcReadResponse> + </api-response> + <delay>1000</delay> + </steps> + </testcase> + +</test:driver-testsuite> \ No newline at end of file
