JulianFeinauer closed pull request #25: PLC4X-57 Bugfix
URL: https://github.com/apache/incubator-plc4x/pull/25
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/examples/hello-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
 
b/examples/hello-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
index bbf7c1be9..e0784349f 100644
--- 
a/examples/hello-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
+++ 
b/examples/hello-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
@@ -70,26 +70,7 @@ public static void main(String[] args) {
                 System.out.println("\nSynchronous request ...");
                 PlcReadResponse<?> syncResponse = 
plcReader.read(plcReadRequest).get();
                 // Simply iterating over the field names returned in the 
response.
-                for (String fieldName : syncResponse.getFieldNames()) {
-                    if(syncResponse.getResponseCode(fieldName) == 
PlcResponseCode.OK) {
-                        int numValues = 
syncResponse.getNumberOfValues(fieldName);
-                        // If it's just one element, output just one single 
line.
-                        if(numValues == 1) {
-                            System.out.println("Value[" + fieldName + "]: " + 
syncResponse.getObject(fieldName));
-                        }
-                        // If it's more than one element, output each in a 
single row.
-                        else {
-                            System.out.println("Value[" + fieldName + "]:");
-                            for(int i = 0; i < numValues; i++) {
-                                System.out.println(" - " + 
syncResponse.getObject(fieldName, i));
-                            }
-                        }
-                    }
-                    // Something went wrong, to output an error message 
instead.
-                    else {
-                        System.out.println("Error[" + fieldName + "]: " + 
syncResponse.getResponseCode(fieldName).name());
-                    }
-                }
+                printResponse(syncResponse);
 
                 //////////////////////////////////////////////////////////
                 // Read asynchronously ...
@@ -98,13 +79,7 @@ public static void main(String[] args) {
                 CompletableFuture<PlcReadResponse<?>> asyncResponse = 
plcReader.read(plcReadRequest);
                 asyncResponse.whenComplete((readResponse, throwable) -> {
                     if (readResponse != null) {
-                        for (String fieldName : syncResponse.getFieldNames()) {
-                            if (syncResponse.getResponseCode(fieldName) == 
PlcResponseCode.OK) {
-                                System.out.println("Value[" + fieldName + "]: 
" + syncResponse.getObject(fieldName));
-                            } else {
-                                System.out.println("Error[" + fieldName + "]: 
" + syncResponse.getResponseCode(fieldName).name());
-                            }
-                        }
+                        printResponse(syncResponse);
                     } else {
                         logger.error("An error occurred", throwable);
                     }
@@ -119,4 +94,27 @@ public static void main(String[] args) {
         }
     }
 
+    private static void printResponse(PlcReadResponse<?> syncResponse) {
+        for (String fieldName : syncResponse.getFieldNames()) {
+            if(syncResponse.getResponseCode(fieldName) == PlcResponseCode.OK) {
+                int numValues = syncResponse.getNumberOfValues(fieldName);
+                // If it's just one element, output just one single line.
+                if(numValues == 1) {
+                    System.out.println("Value[" + fieldName + "]: " + 
syncResponse.getObject(fieldName));
+                }
+                // If it's more than one element, output each in a single row.
+                else {
+                    System.out.println("Value[" + fieldName + "]:");
+                    for(int i = 0; i < numValues; i++) {
+                        System.out.println(" - " + 
syncResponse.getObject(fieldName, i));
+                    }
+                }
+            }
+            // Something went wrong, to output an error message instead.
+            else {
+                System.out.println("Error[" + fieldName + "]: " + 
syncResponse.getResponseCode(fieldName).name());
+            }
+        }
+    }
+
 }
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
index 83b7f3b53..e2963d371 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
@@ -21,12 +21,10 @@ Licensed to the Apache Software Foundation (ASF) under one
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.plc4x.java.api.exceptions.PlcException;
-import org.apache.plc4x.java.api.exceptions.PlcIoException;
-import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
-import org.apache.plc4x.java.api.exceptions.PlcProtocolPayloadTooBigException;
+import org.apache.plc4x.java.api.exceptions.*;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcRequest;
 import org.apache.plc4x.java.api.messages.PlcResponse;
@@ -51,11 +49,15 @@ Licensed to the Apache Software Foundation (ASF) under one
 import org.apache.plc4x.java.s7.netty.model.types.*;
 
 import java.io.IOException;
+import java.lang.reflect.Array;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * This layer transforms between {@link PlcRequestContainer}s {@link 
S7Message}s.
@@ -420,22 +422,25 @@ private PlcResponse decodeReadResponse(S7ResponseMessage 
responseMessage, PlcReq
             FieldItem fieldItem = null;
             ByteBuf data = Unpooled.wrappedBuffer(payloadItem.getData());
             if (responseCode == PlcResponseCode.OK) {
+                // TODO 2018-09-27 jf: array returning only implemented for 
BOOL, BYTE, INTEGERS, FP
+                // not for CHARS & STRINGS and not for all other bit-strings 
except for BYTE
                 switch (field.getDataType()) {
                     // -----------------------------------------
                     // Bit
                     // -----------------------------------------
                     case BOOL: {
-                        byte byteValue = data.readByte();
-                        fieldItem = new 
S7BooleanFieldItem(field.getDataType(),byteValue != 0x00);
+                        Boolean[] booleans = readAllValues(Boolean.class, 
field, i -> data.readByte() != 0x00);
+                        fieldItem = new 
S7BooleanFieldItem(field.getDataType(),booleans);
                         break;
                     }
                     // -----------------------------------------
                     // Bit-strings
                     // -----------------------------------------
                     case BYTE: { // 1 byte
-                        BitSet bitSet = BitSet.valueOf(new 
byte[]{data.readByte()});
-                        Boolean[] booleanValues = new Boolean[8];
-                        for(int i = 0; i < 8; i++) {
+                        byte[] bytes = 
ArrayUtils.toPrimitive(readAllValues(Byte.class, field, i -> data.readByte()));
+                        BitSet bitSet = BitSet.valueOf(bytes);
+                        Boolean[] booleanValues = new Boolean[8 * 
bytes.length];
+                        for(int i = 0; i < 8 * bytes.length; i++) {
                             booleanValues[i] = bitSet.get(i);
                         }
                         fieldItem = new 
S7BooleanFieldItem(field.getDataType(),booleanValues);
@@ -474,59 +479,59 @@ private PlcResponse decodeReadResponse(S7ResponseMessage 
responseMessage, PlcReq
                     // -----------------------------------------
                     // 8 bit:
                     case SINT: {
-                        Long longValue = (long) data.readByte();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
(long)data.readByte());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     case USINT: {
-                        Long longValue = (long) data.readUnsignedByte();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
(long)data.readUnsignedByte());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     // 16 bit:
                     case INT: {
-                        Long longValue = (long) data.readShort();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
(long)data.readShort());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     case UINT: {
-                        Long longValue = (long) data.readUnsignedShort();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
(long)data.readUnsignedShort());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     // 32 bit:
                     case DINT: {
-                        Long longValue = (long) data.readInt();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
(long)data.readInt());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     case UDINT: {
-                        Long longValue = data.readUnsignedInt();
-                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longValue);
+                        Long[] longs = readAllValues(Long.class, field, i -> 
data.readUnsignedInt());
+                        fieldItem = new S7LongFieldItem(field.getDataType(), 
longs);
                         break;
                     }
                     // 64 bit:
                     case LINT: {
-                        BigInteger bigIntegerValue = 
readSigned64BitInteger(data);
-                        fieldItem = new 
S7BigIntegerFieldItem(field.getDataType(), bigIntegerValue);
+                        BigInteger[] bigIntegers = 
readAllValues(BigInteger.class, field, i -> readSigned64BitInteger(data));
+                        fieldItem = new 
S7BigIntegerFieldItem(field.getDataType(), bigIntegers);
                         break;
                     }
                     case ULINT: {
-                        BigInteger bigIntegerValue = 
readUnsigned64BitInteger(data);
-                        fieldItem = new 
S7BigIntegerFieldItem(field.getDataType(), bigIntegerValue);
+                        BigInteger[] bigIntegers = 
readAllValues(BigInteger.class, field, i -> readUnsigned64BitInteger(data));
+                        fieldItem = new 
S7BigIntegerFieldItem(field.getDataType(), bigIntegers);
                         break;
                     }
                     // -----------------------------------------
                     // Floating point values
                     // -----------------------------------------
                     case REAL: {
-                        double doubleValue = data.readFloat();
-                        fieldItem = new 
S7FloatingPointFieldItem(field.getDataType(), doubleValue);
+                        Double[] doubles = readAllValues(Double.class, field, 
i -> (double)data.readFloat());
+                        fieldItem = new 
S7FloatingPointFieldItem(field.getDataType(), doubles);
                         break;
                     }
                     case LREAL: {
-                        double doubleValue = data.readDouble();
-                        fieldItem = new 
S7FloatingPointFieldItem(field.getDataType(), doubleValue);
+                        Double[] doubles = readAllValues(Double.class, field, 
i -> data.readDouble());
+                        fieldItem = new 
S7FloatingPointFieldItem(field.getDataType(), doubles);
                         break;
                     }
                     // -----------------------------------------
@@ -575,6 +580,17 @@ private PlcResponse decodeReadResponse(S7ResponseMessage 
responseMessage, PlcReq
         return new DefaultPlcReadResponse(plcReadRequest, values);
     }
 
+    private static <T> T[] readAllValues(Class<T> clazz, S7Field field, 
Function<Integer, T> extract) {
+        try {
+            return IntStream.rangeClosed(1, field.getNumElements())
+                .mapToObj(extract::apply)
+                .collect(Collectors.toList())
+                .toArray((T[])Array.newInstance(clazz, 0));
+        } catch (IndexOutOfBoundsException e) {
+            throw new PlcRuntimeException("To few bytes in the buffer to read 
requested type", e);
+        }
+    }
+
     @SuppressWarnings("unchecked")
     private PlcResponse decodeWriteResponse(S7ResponseMessage responseMessage, 
PlcRequestContainer requestContainer) throws PlcProtocolException {
         InternalPlcWriteRequest plcWriteRequest = (InternalPlcWriteRequest) 
requestContainer.getRequest();
diff --git 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/model/S7FieldTests.java
 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/model/S7FieldTests.java
index d6c11d9ca..0f3545ee8 100644
--- 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/model/S7FieldTests.java
+++ 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/model/S7FieldTests.java
@@ -24,6 +24,7 @@ Licensed to the Apache Software Foundation (ASF) under one
 import org.apache.plc4x.java.s7.netty.model.types.TransportSize;
 import org.apache.plc4x.test.FastTests;
 import org.junit.experimental.categories.Category;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -32,6 +33,7 @@ Licensed to the Apache Software Foundation (ASF) under one
 
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
@@ -85,5 +87,10 @@ void testInvalidFieldQueryParsing(String fieldQuery) {
         }
     }
 
+    @Test
+    void checkGreedyNumFieldsParsing() {
+        S7Field field = S7Field.of("%DB56.DBB100:SINT[25]");
 
+        assertEquals(25, field.getNumElements());
+    }
 }
\ No newline at end of file


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to