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 f74c7bf69efd515dd948d6a8c48388cb80a0c618
Author: Sebastian Rühl <sru...@apache.org>
AuthorDate: Wed Sep 26 12:19:29 2018 +0200

    [Modbus] added possibility to add a quantity to addresses to read multiple 
values.
---
 .../plc4x/java/modbus/model/CoilModbusField.java   |  9 ++++---
 .../modbus/model/MaskWriteRegisterModbusField.java |  9 ++++---
 .../plc4x/java/modbus/model/ModbusField.java       | 16 +++++++++---
 .../model/ReadDiscreteInputsModbusField.java       |  9 ++++---
 .../model/ReadHoldingRegistersModbusField.java     |  9 ++++---
 .../model/ReadInputRegistersModbusField.java       |  9 ++++---
 .../java/modbus/model/RegisterModbusField.java     |  9 ++++---
 .../java/modbus/netty/Plc4XModbusProtocol.java     | 29 ++++++++++++++--------
 .../plc4x/java/modbus/ManualPlc4XModbusTest.java   | 13 +++++-----
 9 files changed, 73 insertions(+), 39 deletions(-)

diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/CoilModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/CoilModbusField.java
index 731e699..adb7600 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/CoilModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/CoilModbusField.java
@@ -27,8 +27,8 @@ public class CoilModbusField extends ModbusField {
 
     public static final Pattern ADDRESS_PATTERN = Pattern.compile("coil:" + 
ModbusField.ADDRESS_PATTERN);
 
-    protected CoilModbusField(int address) {
-        super(address);
+    public CoilModbusField(int address, Integer quantity) {
+        super(address, quantity);
     }
 
     public static CoilModbusField of(String addressString) throws 
PlcInvalidFieldException {
@@ -37,6 +37,9 @@ public class CoilModbusField extends ModbusField {
             throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
         }
         int address = Integer.parseInt(matcher.group("address"));
-        return new CoilModbusField(address);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new CoilModbusField(address, quantity);
     }
 }
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/MaskWriteRegisterModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/MaskWriteRegisterModbusField.java
index 4f33f8b..2d4870d 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/MaskWriteRegisterModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/MaskWriteRegisterModbusField.java
@@ -31,8 +31,8 @@ public class MaskWriteRegisterModbusField extends ModbusField 
{
     private final int andMask;
     private final int orMask;
 
-    protected MaskWriteRegisterModbusField(int address, int andMask, int 
orMask) {
-        super(address);
+    protected MaskWriteRegisterModbusField(int address, int andMask, int 
orMask, Integer quantity) {
+        super(address, quantity);
         this.andMask = andMask;
         this.orMask = orMask;
     }
@@ -45,7 +45,10 @@ public class MaskWriteRegisterModbusField extends 
ModbusField {
         int address = Integer.parseInt(matcher.group("address"));
         int andMask = Integer.parseInt(matcher.group("andMask"));
         int orMask = Integer.parseInt(matcher.group("orMask"));
-        return new MaskWriteRegisterModbusField(address, andMask, orMask);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new MaskWriteRegisterModbusField(address, andMask, orMask, 
quantity);
     }
 
     public int getAndMask() {
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ModbusField.java
index b3ad29a..3254e02 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ModbusField.java
@@ -25,18 +25,28 @@ import java.util.regex.Pattern;
 
 public abstract class ModbusField implements PlcField {
 
-    public static final Pattern ADDRESS_PATTERN = 
Pattern.compile("(?<address>\\d+)");
+    public static final Pattern ADDRESS_PATTERN = 
Pattern.compile("(?<address>\\d+)(\\[(?<quantity>\\d)])?");
 
     private final int address;
 
-    protected ModbusField(int address) {
+    private final int quantity;
+
+    protected ModbusField(int address, Integer quantity) {
         this.address = address;
+        this.quantity = quantity != null ? quantity : 1;
+        if (this.quantity <= 0) {
+            throw new IllegalArgumentException("quantity must be greater then 
zero. Was " + this.quantity);
+        }
     }
 
     public int getAddress() {
         return address;
     }
 
+    public int getQuantity() {
+        return quantity;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -51,7 +61,6 @@ public abstract class ModbusField implements PlcField {
 
     @Override
     public int hashCode() {
-
         return Objects.hash(address);
     }
 
@@ -59,6 +68,7 @@ public abstract class ModbusField implements PlcField {
     public String toString() {
         return "ModbusField{" +
             "address=" + address +
+            "quantity=" + quantity +
             '}';
     }
 }
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadDiscreteInputsModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadDiscreteInputsModbusField.java
index 1c518d2..00cb495 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadDiscreteInputsModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadDiscreteInputsModbusField.java
@@ -27,8 +27,8 @@ public class ReadDiscreteInputsModbusField extends 
ModbusField {
 
     public static final Pattern ADDRESS_PATTERN = 
Pattern.compile("readdiscreteinputs:" + ModbusField.ADDRESS_PATTERN);
 
-    protected ReadDiscreteInputsModbusField(int address) {
-        super(address);
+    public ReadDiscreteInputsModbusField(int address, Integer quantity) {
+        super(address, quantity);
     }
 
     public static ReadDiscreteInputsModbusField of(String addressString) 
throws PlcInvalidFieldException {
@@ -37,6 +37,9 @@ public class ReadDiscreteInputsModbusField extends 
ModbusField {
             throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
         }
         int address = Integer.parseInt(matcher.group("address"));
-        return new ReadDiscreteInputsModbusField(address);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new ReadDiscreteInputsModbusField(address, quantity);
     }
 }
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadHoldingRegistersModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadHoldingRegistersModbusField.java
index e00a510..9f51e1e 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadHoldingRegistersModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadHoldingRegistersModbusField.java
@@ -27,8 +27,8 @@ public class ReadHoldingRegistersModbusField extends 
ModbusField {
 
     public static final Pattern ADDRESS_PATTERN = 
Pattern.compile("readholdingregisters:" + ModbusField.ADDRESS_PATTERN);
 
-    protected ReadHoldingRegistersModbusField(int address) {
-        super(address);
+    protected ReadHoldingRegistersModbusField(int address, Integer quantity) {
+        super(address, quantity);
     }
 
     public static ReadHoldingRegistersModbusField of(String addressString) 
throws PlcInvalidFieldException {
@@ -37,6 +37,9 @@ public class ReadHoldingRegistersModbusField extends 
ModbusField {
             throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
         }
         int address = Integer.parseInt(matcher.group("address"));
-        return new ReadHoldingRegistersModbusField(address);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new ReadHoldingRegistersModbusField(address, quantity);
     }
 }
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadInputRegistersModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadInputRegistersModbusField.java
index c42e3ae..3b61343 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadInputRegistersModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/ReadInputRegistersModbusField.java
@@ -27,8 +27,8 @@ public class ReadInputRegistersModbusField extends 
ModbusField {
 
     public static final Pattern ADDRESS_PATTERN = 
Pattern.compile("readinputregisters:" + ModbusField.ADDRESS_PATTERN);
 
-    protected ReadInputRegistersModbusField(int address) {
-        super(address);
+    protected ReadInputRegistersModbusField(int address, Integer quantity) {
+        super(address, quantity);
     }
 
     public static ReadInputRegistersModbusField of(String addressString) 
throws PlcInvalidFieldException {
@@ -37,6 +37,9 @@ public class ReadInputRegistersModbusField extends 
ModbusField {
             throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
         }
         int address = Integer.parseInt(matcher.group("address"));
-        return new ReadInputRegistersModbusField(address);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new ReadInputRegistersModbusField(address, quantity);
     }
 }
diff --git 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/RegisterModbusField.java
 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/RegisterModbusField.java
index 8b5db79..0697364 100644
--- 
a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/RegisterModbusField.java
+++ 
b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/model/RegisterModbusField.java
@@ -28,8 +28,8 @@ public class RegisterModbusField extends ModbusField {
 
     public static final Pattern ADDRESS_PATTERN = Pattern.compile("register:" 
+ ModbusField.ADDRESS_PATTERN);
 
-    protected RegisterModbusField(int address) {
-        super(address);
+    protected RegisterModbusField(int address, Integer quantity) {
+        super(address, quantity);
     }
 
     public static RegisterModbusField of(String addressString) throws 
PlcInvalidFieldException {
@@ -38,6 +38,9 @@ public class RegisterModbusField extends ModbusField {
             throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
         }
         int address = Integer.parseInt(matcher.group("address"));
-        return new RegisterModbusField(address);
+
+        String quantityString = matcher.group("quantity");
+        Integer quantity = quantityString != null ? 
Integer.valueOf(quantityString) : null;
+        return new RegisterModbusField(address, quantity);
     }
 }
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 f1d1313..774368a 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
@@ -84,6 +84,11 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
         // TODO: for higher data types float, double etc we might need to 
split the bytes into chunks
         String fieldName = request.getFieldNames().iterator().next();
         int quantity = request.getNumberOfValues(fieldName);
+        ModbusField field = (ModbusField) request.getField(fieldName);
+        if (quantity != field.getQuantity()) {
+            LOGGER.warn("Supplied number of values [{}] don't match t the 
addressed quantity of [{}]", field.getQuantity(), quantity);
+        }
+
         short unitId = 0;
 
         /*
@@ -105,7 +110,6 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
          * when addressing them. So if reading 2 32bit integers, this is split 
up into four registers. So for the second
          * int we have to increment the address accordingly.
          */
-        ModbusField field = (ModbusField) request.getField(fieldName);
         ModbusPdu modbusRequest;
         if (field instanceof RegisterModbusField) {
             RegisterModbusField registerModbusField = (RegisterModbusField) 
field;
@@ -171,12 +175,12 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
         // TODO: check if we can map like this. Implication is that we can 
only work with int, short, byte and boolean
         // TODO: for higher data types float, double etc we might need to 
split the bytes into chunks
         String fieldName = request.getFieldNames().iterator().next();
-        // TODO: The quantity is encoded in the field attribute
-        int quantity = 1;
+
+        ModbusField field = (ModbusField) request.getField(fieldName);
+        int quantity = field.getQuantity();
         // TODO: the unit the should be used for multiple Requests
         short unitId = 0;
 
-        ModbusField field = (ModbusField) request.getField(fieldName);
         ModbusPdu modbusRequest;
         if (field instanceof CoilModbusField) {
             CoilModbusField coilModbusField = (CoilModbusField) field;
@@ -258,7 +262,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
             ReadCoilsResponse readCoilsResponse = (ReadCoilsResponse) 
modbusPdu;
             LOGGER.debug("{}: Nothing", readCoilsResponse);
             ByteBuf byteBuf = readCoilsResponse.getCoilStatus();
-            DefaultBooleanFieldItem data = produceCoilValueList(byteBuf);
+            DefaultBooleanFieldItem data = produceCoilValueList(byteBuf, 
field.getQuantity());
             Map<String, Pair<PlcResponseCode, FieldItem>> responseValues = new 
HashMap<>();
             responseValues.put(fieldName, new 
ImmutablePair<>(PlcResponseCode.OK, data));
             plcRequestContainer.getResponseFuture().complete(new 
DefaultPlcReadResponse((InternalPlcReadRequest) request, responseValues));
@@ -267,7 +271,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
             ReadDiscreteInputsResponse readDiscreteInputsResponse = 
(ReadDiscreteInputsResponse) modbusPdu;
             LOGGER.debug("{}: Nothing", readDiscreteInputsResponse);
             ByteBuf byteBuf = readDiscreteInputsResponse.getInputStatus();
-            DefaultBooleanFieldItem data = produceCoilValueList(byteBuf);
+            DefaultBooleanFieldItem data = produceCoilValueList(byteBuf, 
field.getQuantity());
             Map<String, Pair<PlcResponseCode, FieldItem>> responseValues = new 
HashMap<>();
             responseValues.put(fieldName, new 
ImmutablePair<>(PlcResponseCode.OK, data));
             plcRequestContainer.getResponseFuture().complete(new 
DefaultPlcReadResponse((InternalPlcReadRequest) request, responseValues));
@@ -277,7 +281,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
             LOGGER.debug("{}: Nothing", readHoldingRegistersResponse);
             ByteBuf byteBuf = readHoldingRegistersResponse.getRegisters();
             // TODO: use register method
-            DefaultByteArrayFieldItem data = produceRegisterValueList(byteBuf);
+            DefaultByteArrayFieldItem data = produceRegisterValueList(byteBuf, 
field.getQuantity());
             Map<String, Pair<PlcResponseCode, FieldItem>> responseValues = new 
HashMap<>();
             responseValues.put(fieldName, new 
ImmutablePair<>(PlcResponseCode.OK, data));
             plcRequestContainer.getResponseFuture().complete(new 
DefaultPlcReadResponse((InternalPlcReadRequest) request, responseValues));
@@ -287,7 +291,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
             LOGGER.debug("{}: Nothing", readInputRegistersResponse);
             ByteBuf byteBuf = readInputRegistersResponse.getRegisters();
             // TODO: use register method
-            DefaultByteArrayFieldItem data = produceRegisterValueList(byteBuf);
+            DefaultByteArrayFieldItem data = produceRegisterValueList(byteBuf, 
field.getQuantity());
             Map<String, Pair<PlcResponseCode, FieldItem>> responseValues = new 
HashMap<>();
             responseValues.put(fieldName, new 
ImmutablePair<>(PlcResponseCode.OK, data));
             plcRequestContainer.getResponseFuture().complete(new 
DefaultPlcReadResponse((InternalPlcReadRequest) request, responseValues));
@@ -478,7 +482,10 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
     
////////////////////////////////////////////////////////////////////////////////
     // Decoding helpers.
     
////////////////////////////////////////////////////////////////////////////////
-    private DefaultBooleanFieldItem produceCoilValueList(ByteBuf byteBuf) {
+    private DefaultBooleanFieldItem produceCoilValueList(ByteBuf byteBuf, int 
expectedQuantity) {
+        if (byteBuf.readableBytes() < expectedQuantity / 8) {
+            LOGGER.warn("Expected to read {} coils but only max of {} can be 
supplied", expectedQuantity, byteBuf.readableBytes() * 8);
+        }
         byte[] bytes = new byte[byteBuf.readableBytes()];
         if (bytes.length < 1) {
             return new DefaultBooleanFieldItem();
@@ -487,7 +494,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
         List<Boolean> data = new LinkedList<>();
         int bitIndex = 0;
         int coilIndex = 0;
-        while (coilIndex < bytes.length) {
+        while (coilIndex < bytes.length && data.size() < expectedQuantity) {
             if (bitIndex > 7) {
                 // Every 8 Coils we need to increase the access
                 coilIndex++;
@@ -503,7 +510,7 @@ public class Plc4XModbusProtocol extends 
MessageToMessageCodec<ModbusTcpPayload,
         return new DefaultBooleanFieldItem(data.toArray(new Boolean[0]));
     }
 
-    private DefaultByteArrayFieldItem produceRegisterValueList(ByteBuf 
byteBuf) throws PlcProtocolException {
+    private DefaultByteArrayFieldItem produceRegisterValueList(ByteBuf 
byteBuf, int expectedQuantity) throws PlcProtocolException {
         int readableBytes = byteBuf.readableBytes();
         if (readableBytes % 2 != 0) {
             throw new PlcProtocolException("Readables bytes should even: " + 
readableBytes);
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 70ca7a2..6c2fab3 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
@@ -43,29 +43,28 @@ public class ManualPlc4XModbusTest {
             {
                 PlcReader reader = plcConnection.getReader().orElseThrow(() -> 
new RuntimeException("No Reader found"));
 
-                PlcReadResponse<?> readResponse = reader.read(builder -> 
builder.addItem("randomRegister", "register:7")).get();
+                PlcReadResponse<?> readResponse = reader.read(builder -> 
builder.addItem("randomRegister", "register:7[3]")).get();
                 System.out.println("Response " + readResponse);
                 readResponse.getAllByteArrays("randomRegister").stream()
                     .map(HexUtil::toHex)
-                    .map(hex -> "Value: " + hex)
+                    .map(hex -> "Register Value: " + hex)
                     .forEach(System.out::println);
             }
 
             {
                 PlcReader reader = plcConnection.getReader().orElseThrow(() -> 
new RuntimeException("No Reader found"));
 
-                PlcReadResponse<?> readResponse = reader.read(builder -> 
builder.addItem("randomRegister", "coil:1")).get();
+                PlcReadResponse<?> readResponse = reader.read(builder -> 
builder.addItem("randomCoil", "coil:1[9]")).get();
                 System.out.println("Response " + readResponse);
-                readResponse.getAllByteArrays("randomRegister").stream()
-                    .map(HexUtil::toHex)
-                    .map(hex -> "Value: " + hex)
+                readResponse.getAllBooleans("randomCoil").stream()
+                    .map(hex -> "Coil Value: " + hex)
                     .forEach(System.out::println);
             }
 
             {
                 PlcWriter writer = plcConnection.getWriter().orElseThrow(() -> 
new RuntimeException("No Writer found"));
 
-                PlcWriteResponse<?> writeResponse = writer.write(builder -> 
builder.addItem("randomCoilField", "coil:1", 1)).get();
+                PlcWriteResponse<?> writeResponse = writer.write(builder -> 
builder.addItem("randomCoilField", "coil:1", true)).get();
                 System.out.println("Response " + writeResponse);
             }
         } catch (Exception e) {

Reply via email to