Skip to content

Commit 0ff7356

Browse files
committed
feat(plc4j): Support for CANopen NMT commands.
Fixes #2468. Re-enabling tests for SDO operations. Signed-off-by: Łukasz Dywicki <luke@code-house.org>
1 parent e500266 commit 0ff7356

7 files changed

Lines changed: 294 additions & 84 deletions

File tree

plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
191191
writeInternally((DefaultPlcWriteRequest) writeRequest, (CANOpenPDOTag) tag, response);
192192
return response;
193193
}
194+
if (tag instanceof CANOpenNMTTag) {
195+
writeInternally((DefaultPlcWriteRequest) writeRequest, (CANOpenNMTTag) tag, response);
196+
return response;
197+
}
194198

195199
response.completeExceptionally(new IllegalArgumentException("Only CANOpenSDOTag instances are supported"));
196200
return response;
@@ -238,6 +242,29 @@ private void writeInternally(DefaultPlcWriteRequest writeRequest, CANOpenPDOTag
238242
}
239243
}
240244

245+
private void writeInternally(DefaultPlcWriteRequest writeRequest, CANOpenNMTTag tag, CompletableFuture<PlcWriteResponse> response) {
246+
PlcValue writeValue = writeRequest.getPlcValues().get(0);
247+
248+
NMTStateRequest request = null;
249+
if (writeValue.isInteger() || writeValue.isShort() || writeValue.isByte()) {
250+
request = NMTStateRequest.enumForValue(writeValue.getShort());
251+
}
252+
if (request == null) {
253+
response.completeExceptionally(new PlcRuntimeException("Unsupported NMTStateRequest value: " + writeValue));
254+
return;
255+
}
256+
257+
try {
258+
String tagName = writeRequest.getTagNames().iterator().next();
259+
260+
final CANOpenNetworkPayload payload = new CANOpenNetworkPayload(request, Integer.valueOf(tag.getNodeId()).byteValue());
261+
conversationContext.sendToWire(new CANOpenFrame((short) 0, tag.getService(), payload));
262+
response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(tagName, PlcResponseCode.OK)));
263+
} catch (Exception e) {
264+
response.completeExceptionally(e);
265+
}
266+
}
267+
241268
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
242269
CompletableFuture<PlcReadResponse> response = new CompletableFuture<>();
243270
if (readRequest.getTagNames().size() != 1) {

plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/tag/CANOpenNMTTag.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ public boolean isWildcard() {
5151

5252
@Override
5353
public String getAddressString() {
54-
return "NMT:" + getNodeId();
54+
return isWildcard() ? "NMT" : "NMT:" + getNodeId();
5555
}
5656

5757
@Override
5858
public PlcValueType getPlcValueType() {
59-
return PlcValueType.NULL;
59+
return PlcValueType.USINT;
6060
}
6161

6262
@Override
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* https://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.plc4x.java.canopen;
20+
21+
import org.apache.plc4x.test.driver.DriverTestsuiteRunner;
22+
import org.junit.jupiter.api.Disabled;
23+
24+
class CANOpenDriverNMTIT extends DriverTestsuiteRunner {
25+
26+
public CANOpenDriverNMTIT() {
27+
super("/protocols/canopen/CANOpenDriverNMTIT.xml", true);
28+
}
29+
30+
}

plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/CANOpenDriverSDOIT.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.apache.plc4x.test.driver.DriverTestsuiteRunner;
2222
import org.junit.jupiter.api.Disabled;
2323

24-
@Disabled("Fix this")
2524
class CANOpenDriverSDOIT extends DriverTestsuiteRunner {
2625

2726
public CANOpenDriverSDOIT() {
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
https://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<test:driver-testsuite xmlns:test="https://plc4x.apache.org/schemas/driver-testsuite.xsd"
21+
byteOrder="LITTLE_ENDIAN">
22+
23+
<name>CANOpen SDO Segmentation</name>
24+
25+
<protocolName>canopen</protocolName>
26+
<outputFlavor>read-write</outputFlavor>
27+
28+
<driver-name>canopen</driver-name>
29+
30+
<driver-parameters>
31+
<parameter>
32+
<name>nodeId</name>
33+
<value>15</value>
34+
</parameter>
35+
<parameter>
36+
<name>request-timeout</name>
37+
<value>5000</value>
38+
</parameter>
39+
</driver-parameters>
40+
41+
<testcase>
42+
<name>Send NMT write request</name>
43+
<description>
44+
Trigger write using CANOpen NMT requesting specific node to change its state.
45+
</description>
46+
<steps>
47+
<api-request name="Request node 1 to enter PRE_OPERATIONAL state">
48+
<TestWriteRequest>
49+
<tags isList="true">
50+
<tag className="org.apache.plc4x.test.driver.internal.api.TestValueTag">
51+
<name>boot_up_request</name>
52+
<address>NMT:1</address>
53+
<value>
54+
<PlcUSINT>128</PlcUSINT>
55+
</value>
56+
</tag>
57+
</tags>
58+
</TestWriteRequest>
59+
</api-request>
60+
<outgoing-plc-message name="Send NMT Request">
61+
<CANOpenFrame>
62+
<nodeId dataType="uint" bitLength="8">0</nodeId>
63+
<service>
64+
<CANOpenService dataType="uint" bitLength="4" stringRepresentation="NMT">0</CANOpenService>
65+
</service>
66+
<alignment dataType="uint" bitLength="4">0</alignment>
67+
<payload>
68+
<CANOpenPayload>
69+
<CANOpenNetworkPayload>
70+
<request>
71+
<NMTStateRequest dataType="uint" bitLength="8" stringRepresentation="PRE_OPERATIONAL">128</NMTStateRequest>
72+
</request>
73+
<reserved dataType="uint" bitLength="1">0</reserved>
74+
<node dataType="uint" bitLength="7">1</node>
75+
</CANOpenNetworkPayload>
76+
</CANOpenPayload>
77+
</payload>
78+
<padding isList="true">
79+
<value dataType="uint" bitLength="8">0</value>
80+
<value dataType="uint" bitLength="8">0</value>
81+
<value dataType="uint" bitLength="8">0</value>
82+
<value dataType="uint" bitLength="8">0</value>
83+
<value dataType="uint" bitLength="8">0</value>
84+
<value dataType="uint" bitLength="8">0</value>
85+
</padding>
86+
</CANOpenFrame>
87+
</outgoing-plc-message>
88+
<api-response name="Report Write Response to application">
89+
<PlcWriteResponse>
90+
<request>
91+
<PlcWriteRequest>
92+
<PlcTagRequest>
93+
<tags isList="true">
94+
<boot_up_request>
95+
<PlcTagValueItem>
96+
<tag>
97+
<CANOpenNMTTag>
98+
<service dataType="string" bitLength="24" encoding="UTF-8">NMT</service>
99+
<node dataType="int" bitLength="64">1</node>
100+
</CANOpenNMTTag>
101+
</tag>
102+
<value>
103+
<PlcUSINT dataType="int" bitLength="8">128</PlcUSINT>
104+
</value>
105+
</PlcTagValueItem>
106+
</boot_up_request>
107+
</tags>
108+
</PlcTagRequest>
109+
</PlcWriteRequest>
110+
</request>
111+
<responseCodes isList="true">
112+
<boot_up_request>
113+
<ResponseCode dataType="uint" bitLength="8" stringRepresentation="OK">1</ResponseCode>
114+
</boot_up_request>
115+
</responseCodes>
116+
</PlcWriteResponse>
117+
</api-response>
118+
<delay>1000</delay>
119+
</steps>
120+
</testcase>
121+
122+
</test:driver-testsuite>

0 commit comments

Comments
 (0)