You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2018/07/26 11:39:02 UTC
[incubator-plc4x] 04/05: modbus: fixed coil parsing
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
commit 18bb3f3a561e1d8d4a71712b7b3df0dfd6d50391
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 26 12:54:47 2018 +0200
modbus: fixed coil parsing
---
.../java/modbus/netty/Plc4XModbusProtocol.java | 7 ++--
.../plc4x/java/modbus/ManualPlc4XModbusTest.java | 44 +++++++++++++++-----
.../java/modbus/netty/Plc4XModbusProtocolTest.java | 47 +++++++++++-----------
3 files changed, 63 insertions(+), 35 deletions(-)
diff --git a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
index b4914a8..769d17d 100644
--- a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
+++ b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
@@ -401,12 +401,13 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
}
byteBuf.readBytes(bytes);
List<T> data = new LinkedList<>();
- for (int i = 0, j = 0; i < readRequestItem.getSize(); i++) {
- if (i != 0 && i % 8 == 0) {
+ for (int i = 0, j = 0; data.size() < readRequestItem.getSize(); i++) {
+ if (i > 7) {
// Every 8 Coils we need to increase the access
j++;
+ i = 0;
}
- boolean coilSet = (1 << i & bytes[j]) == 1;
+ boolean coilSet = (bytes[j] & (1L << i)) != 0;
byte coilFlag = coilSet ? (byte) 1 : (byte) 0;
if (dataType == Boolean.class) {
@SuppressWarnings("unchecked")
diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
index 36c5ff8..a37a702 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
@@ -21,9 +21,12 @@ package org.apache.plc4x.java.modbus;
import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.connection.PlcConnection;
import org.apache.plc4x.java.api.connection.PlcReader;
+import org.apache.plc4x.java.api.connection.PlcWriter;
import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
import org.apache.plc4x.java.api.messages.specific.TypeSafePlcReadRequest;
import org.apache.plc4x.java.api.messages.specific.TypeSafePlcReadResponse;
+import org.apache.plc4x.java.api.messages.specific.TypeSafePlcWriteRequest;
+import org.apache.plc4x.java.api.messages.specific.TypeSafePlcWriteResponse;
import org.apache.plc4x.java.api.model.Address;
import java.util.concurrent.CompletableFuture;
@@ -42,16 +45,39 @@ public class ManualPlc4XModbusTest {
try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionUrl)) {
System.out.println("PlcConnection " + plcConnection);
- PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
+ {
+ PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
- Address address = plcConnection.parseAddress("register:7");
- CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
- .read(new TypeSafePlcReadRequest<>(Integer.class, address));
- TypeSafePlcReadResponse<Integer> readResponse = response.get();
- System.out.println("Response " + readResponse);
- ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
- System.out.println("ResponseItem " + responseItem);
- responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+ Address address = plcConnection.parseAddress("register:7");
+ CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
+ .read(new TypeSafePlcReadRequest<>(Integer.class, address));
+ TypeSafePlcReadResponse<Integer> readResponse = response.get();
+ System.out.println("Response " + readResponse);
+ ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
+ System.out.println("ResponseItem " + responseItem);
+ responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+ }
+
+ {
+ PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
+
+ Address address = plcConnection.parseAddress("coil:1");
+ CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
+ .read(new TypeSafePlcReadRequest<>(Integer.class, address));
+ TypeSafePlcReadResponse<Integer> readResponse = response.get();
+ System.out.println("Response " + readResponse);
+ ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
+ System.out.println("ResponseItem " + responseItem);
+ responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+ }
+
+ {
+ PlcWriter writer = plcConnection.getWriter().orElseThrow(() -> new RuntimeException("No Writer found"));
+ Address address = plcConnection.parseAddress("coil:1");
+ CompletableFuture<TypeSafePlcWriteResponse<Integer>> write = writer.write(new TypeSafePlcWriteRequest<>(Integer.class, address, 1));
+ TypeSafePlcWriteResponse<Integer> writeResponse = write.get();
+ System.out.println("Response " + writeResponse);
+ }
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
index f28cb69..01b8d75 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
@@ -24,7 +24,6 @@ import com.digitalpetri.modbus.requests.*;
import com.digitalpetri.modbus.responses.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.plc4x.java.api.messages.*;
import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
@@ -51,7 +50,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.defaultAssert;
-import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.streamOfLittleEndianDataTypePairs;
+import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.streamOfBigEndianDataTypePairs;
import static org.apache.plc4x.java.base.util.Assert.assertByteEquals;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
@@ -95,7 +94,7 @@ public class Plc4XModbusProtocolTest {
@Parameterized.Parameters(name = "{index} Type:{0} {3} {5}")
public static Collection<Object[]> data() {
- return streamOfLittleEndianDataTypePairs()
+ return streamOfBigEndianDataTypePairs()
.map(pair -> Stream.of(
ImmutablePair.of(
new PlcRequestContainer<>(
@@ -103,7 +102,9 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(pair.getLeft().getClass(), CoilModbusAddress.of("coil:1"))
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new ReadCoilsResponse(Unpooled.wrappedBuffer(pair.getRight())))
+ // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+ // all positive so we return one byte with the first bit set
+ new ModbusTcpPayload((short) 0, (short) 0, new ReadCoilsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x1})))
),
ImmutablePair.of(
new PlcRequestContainer<>(
@@ -111,7 +112,9 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(CoilModbusAddress.of("coil:1"), pair.getLeft())
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, pair.getRight()[0]))
+ // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+ // all positive so we return one byte with the first bit set
+ new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, 1))
),
/* Read request no supported on maskwrite so how to handle?
ImmutablePair.of(
@@ -136,7 +139,9 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(pair.getLeft().getClass(), ReadDiscreteInputsModbusAddress.of("readdiscreteinputs:1"))
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(pair.getRight())))
+ // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+ // all positive so we return one byte with the first bit set
+ new ModbusTcpPayload((short) 0, (short) 0, new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x01})))
),
ImmutablePair.of(
new PlcRequestContainer<>(
@@ -144,7 +149,7 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(pair.getLeft().getClass(), ReadHoldingRegistersModbusAddress.of("readholdingregisters:1"))
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(evenUp(pair.getRight()))))
+ new ModbusTcpPayload((short) 0, (short) 0, new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
),
ImmutablePair.of(
new PlcRequestContainer<>(
@@ -152,7 +157,7 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(pair.getLeft().getClass(), ReadInputRegistersModbusAddress.of("readinputregisters:1"))
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new ReadInputRegistersResponse(Unpooled.wrappedBuffer(evenUp(pair.getRight()))))
+ new ModbusTcpPayload((short) 0, (short) 0, new ReadInputRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
),
ImmutablePair.of(
new PlcRequestContainer<>(
@@ -176,19 +181,15 @@ public class Plc4XModbusProtocolTest {
.builder()
.addItem(RegisterModbusAddress.of("register:1"), pair.getLeft())
.build(), new CompletableFuture<>()),
- new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, pair.getRight()[0]))
+ new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, cutRegister(pair.getRight())[0]))
)
))
.flatMap(stream -> stream)
.map(pair -> new Object[]{pair.left.getRequest().getRequestItem().orElseThrow(IllegalStateException::new).getDatatype().getSimpleName(), pair.left, pair.left.getResponseFuture(), pair.left.getRequest().getClass().getSimpleName(), pair.right, pair.right.getModbusPdu().getClass().getSimpleName()}).collect(Collectors.toList());
}
- private static byte[] evenUp(byte[] bytes) {
- if (bytes.length % 2 == 0) {
- return bytes;
- } else {
- return ArrayUtils.insert(0, bytes, (byte) 0x0);
- }
+ private static byte[] cutRegister(byte[] right) {
+ return new byte[]{right.length > 1 ? right[right.length - 2] : 0x0, right[right.length - 1]};
}
@Before
@@ -371,35 +372,35 @@ public class Plc4XModbusProtocolTest {
ResponseItem responseItem = (ResponseItem) plcResponse.getResponseItem().get();
LOGGER.info("ResponseItem {}", responseItem);
ModbusPdu modbusPdu = modbusTcpPayload.getModbusPdu();
- if (modbusPdu instanceof MaskWriteRegisterRequest) {
+ if (modbusPdu instanceof MaskWriteRegisterResponse) {
WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
- } else if (modbusPdu instanceof ReadCoilsRequest) {
+ } else if (modbusPdu instanceof ReadCoilsResponse) {
ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
Object value = readResponseItem.getValues().get(0);
defaultAssert(value);
- } else if (modbusPdu instanceof ReadDiscreteInputsRequest) {
+ } else if (modbusPdu instanceof ReadDiscreteInputsResponse) {
ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
Object value = readResponseItem.getValues().get(0);
defaultAssert(value);
- } else if (modbusPdu instanceof ReadHoldingRegistersRequest) {
+ } else if (modbusPdu instanceof ReadHoldingRegistersResponse) {
ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
Object value = readResponseItem.getValues().get(0);
defaultAssert(value);
- } else if (modbusPdu instanceof ReadInputRegistersRequest) {
+ } else if (modbusPdu instanceof ReadInputRegistersResponse) {
ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
Object value = readResponseItem.getValues().get(0);
defaultAssert(value);
- } else if (modbusPdu instanceof WriteMultipleCoilsRequest) {
+ } else if (modbusPdu instanceof WriteMultipleCoilsResponse) {
WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
- } else if (modbusPdu instanceof WriteMultipleRegistersRequest) {
+ } else if (modbusPdu instanceof WriteMultipleRegistersResponse) {
WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
} else if (modbusPdu instanceof WriteSingleCoilResponse) {
WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
- } else if (modbusPdu instanceof WriteSingleRegisterRequest) {
+ } else if (modbusPdu instanceof WriteSingleRegisterResponse) {
WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
}