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 728012dd6571d4f1e7b2e5b0dc1529dd41f37463 Author: Ćukasz Dywicki <[email protected]> AuthorDate: Fri Nov 6 12:41:13 2020 +0100 Support for custom answer node identifiers (offsets in TRANSMIT_SDO). --- .../canopen/CANOpenConversationBase.java | 6 +- .../canopen/SDODownloadConversation.java | 4 +- .../canopen/SDOUploadConversation.java | 4 +- .../plc4x/java/can/field/CANOpenSDOField.java | 18 +++- .../java/can/protocol/CANOpenProtocolLogic.java | 4 +- .../plc4x/java/can/field/CANOpenSDOFieldTest.java | 12 +++ .../resources/testsuite/CANOpenDriverSDOIT.xml | 98 ++++++++++++++++++++++ 7 files changed, 137 insertions(+), 9 deletions(-) diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java index 28a6941..d3a41ae 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java @@ -14,10 +14,12 @@ public abstract class CANOpenConversationBase { protected final CANConversation<CANOpenFrame> delegate; protected final int nodeId; + private final int answerNodeId; - public CANOpenConversationBase(CANConversation<CANOpenFrame> delegate, int nodeId) { + public CANOpenConversationBase(CANConversation<CANOpenFrame> delegate, int nodeId, int answerNodeId) { this.delegate = delegate; this.nodeId = nodeId; + this.answerNodeId = answerNodeId; } protected PlcValue decodeFrom(byte[] data, CANOpenDataType type, int length) throws ParseException { @@ -25,7 +27,7 @@ public abstract class CANOpenConversationBase { } protected boolean isTransmitSDOFromReceiver(CANOpenFrame frame) { - return frame.getNodeId() == nodeId && frame.getService() == CANOpenService.TRANSMIT_SDO; + return frame.getNodeId() == answerNodeId && frame.getService() == CANOpenService.TRANSMIT_SDO; } protected CANOpenFrame createFrame(SDORequest rq) { diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java index ba0bffb..689aec9 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java @@ -20,8 +20,8 @@ public class SDODownloadConversation extends CANOpenConversationBase { private final IndexAddress indexAddress; private final byte[] data; - public SDODownloadConversation(CANConversation<CANOpenFrame> delegate, int nodeId, IndexAddress indexAddress, PlcValue value, CANOpenDataType type) { - super(delegate, nodeId); + public SDODownloadConversation(CANConversation<CANOpenFrame> delegate, int nodeId, int answerNodeId, IndexAddress indexAddress, PlcValue value, CANOpenDataType type) { + super(delegate, nodeId, answerNodeId); this.delegate = delegate; this.indexAddress = indexAddress; diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java index 6be036a..7e0b3b0 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java @@ -19,8 +19,8 @@ public class SDOUploadConversation extends CANOpenConversationBase { private final IndexAddress address; private final CANOpenDataType type; - public SDOUploadConversation(CANConversation<CANOpenFrame> delegate, int nodeId, IndexAddress address, CANOpenDataType type) { - super(delegate, nodeId); + public SDOUploadConversation(CANConversation<CANOpenFrame> delegate, int nodeId, int answerNodeId, IndexAddress address, CANOpenDataType type) { + super(delegate, nodeId, answerNodeId); this.address = address; this.type = type; } diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java index 86882c0..0997087 100644 --- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java +++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java @@ -26,18 +26,28 @@ import java.util.regex.Pattern; public class CANOpenSDOField extends CANOpenField { - public static final Pattern ADDRESS_PATTERN = Pattern.compile("SDO:" + CANOpenField.NODE_PATTERN + ":" + CANOpenField.ADDRESS_PATTERN); + public static final Pattern ADDRESS_PATTERN = Pattern.compile("SDO:" + CANOpenField.NODE_PATTERN + "(?:/(?<answerNodeId>\\d+))?:" + CANOpenField.ADDRESS_PATTERN); + private final int answerNode; private final short index; private final short subIndex; private final CANOpenDataType canOpenDataType; public CANOpenSDOField(int node, short index, short subIndex, CANOpenDataType canOpenDataType) { + this(node, node, index, subIndex, canOpenDataType); + } + + public CANOpenSDOField(int node, int answerNode, short index, short subIndex, CANOpenDataType canOpenDataType) { super(node); + this.answerNode = answerNode; this.index = index; this.subIndex = subIndex; this.canOpenDataType = canOpenDataType; } + public int getAnswerNodeId() { + return answerNode; + } + public short getIndex() { return index; } @@ -73,6 +83,12 @@ public class CANOpenSDOField extends CANOpenField { String canDataTypeString = matcher.group("canDataType"); CANOpenDataType canOpenDataType = CANOpenDataType.valueOf(canDataTypeString); + String answerNode = matcher.group("answerNodeId"); + if (answerNode != null) { + int answerNodeId = Integer.parseInt(matcher.group("answerNodeId")); + return new CANOpenSDOField(nodeId, answerNodeId, index, subIndex, canOpenDataType); + } + //String numberOfElementsString = matcher.group("numberOfElements"); //Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null; 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 f751b7c..830656d 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 @@ -185,7 +185,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem }); PlcValue writeValue = writeRequest.getPlcValues().get(0); - SDODownloadConversation download = new SDODownloadConversation(conversation, field.getNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), writeValue, field.getCanOpenDataType()); + SDODownloadConversation download = new SDODownloadConversation(conversation, field.getNodeId(), field.getAnswerNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), writeValue, field.getCanOpenDataType()); transaction.submit(() -> download.execute(callback)); } @@ -283,7 +283,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem transaction.endRequest(); }); - SDOUploadConversation upload = new SDOUploadConversation(conversation, field.getNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), field.getCanOpenDataType()); + SDOUploadConversation upload = new SDOUploadConversation(conversation, field.getNodeId(), field.getAnswerNodeId(), new IndexAddress(field.getIndex(), field.getSubIndex()), field.getCanOpenDataType()); transaction.submit(() -> upload.execute(callback)); } 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 index ddecd2b..8065bdc 100644 --- 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 @@ -13,6 +13,18 @@ class CANOpenSDOFieldTest { final CANOpenSDOField canField = CANOpenSDOField.of("SDO:20:0x10/0xAA:RECORD"); assertEquals(20, canField.getNodeId()); + assertEquals(20, canField.getAnswerNodeId()); + assertEquals(0x10, canField.getIndex()); + assertEquals(0xAA, canField.getSubIndex()); + assertEquals(CANOpenDataType.RECORD, canField.getCanOpenDataType()); + } + + @Test + public void testAnswerNodeSyntax() { + final CANOpenSDOField canField = CANOpenSDOField.of("SDO:20/22:0x10/0xAA:RECORD"); + + assertEquals(20, canField.getNodeId()); + assertEquals(22, canField.getAnswerNodeId()); assertEquals(0x10, canField.getIndex()); assertEquals(0xAA, canField.getSubIndex()); assertEquals(CANOpenDataType.RECORD, canField.getCanOpenDataType()); 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 index 190f3be..f0e7e0d 100644 --- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenDriverSDOIT.xml +++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenDriverSDOIT.xml @@ -110,6 +110,103 @@ <index>1000</index> <subIndex>22</subIndex> <canOpenDataType>UNSIGNED32</canOpenDataType> + <answerNodeId>1</answerNodeId> + </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>Expedited SDO read request - custom answer node id</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/2: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>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>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> + <answerNodeId>2</answerNodeId> </sdo1> </request> <sdo1> @@ -267,6 +364,7 @@ <index>2000</index> <subIndex>44</subIndex> <canOpenDataType>RECORD</canOpenDataType> + <answerNodeId>2</answerNodeId> </sdo1> </request> <sdo1>
