You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by tm...@apache.org on 2019/08/11 18:54:42 UTC

[plc4x] 03/03: fixed some bugs

This is an automated email from the ASF dual-hosted git repository.

tmitsch pushed a commit to branch feature/improve-scraper-tim
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 3bf49bc674d3cd516715ee6e7c61cf652b7cf292
Author: Tim Mitsch <t....@pragmaticindustries.de>
AuthorDate: Sun Aug 11 20:54:30 2019 +0200

    fixed some bugs
---
 .../java/org/apache/plc4x/Plc4XBaseTableTest.java  |   6 +-
 .../org/apache/plc4x/java/s7/model/S7Field.java    |  11 ++
 .../plc4x/java/s7/netty/Plc4XNettyException.java   |  37 ++++
 .../plc4x/java/s7/netty/Plc4XS7Protocol.java       | 202 +++++++++++----------
 .../triggeredscraper/TriggeredScraperTask.java     |   2 +-
 .../plc4x/java/scraper/TriggeredScraperRunner.java |   1 +
 .../test/resources/example_triggered_scraper.yml   |  22 ++-
 7 files changed, 176 insertions(+), 105 deletions(-)

diff --git a/plc4j/integrations/apache-calcite/src/test/java/org/apache/plc4x/Plc4XBaseTableTest.java b/plc4j/integrations/apache-calcite/src/test/java/org/apache/plc4x/Plc4XBaseTableTest.java
index d80cc6b..b031393 100644
--- a/plc4j/integrations/apache-calcite/src/test/java/org/apache/plc4x/Plc4XBaseTableTest.java
+++ b/plc4j/integrations/apache-calcite/src/test/java/org/apache/plc4x/Plc4XBaseTableTest.java
@@ -20,6 +20,7 @@ package org.apache.plc4x;
 
 import org.apache.calcite.linq4j.Enumerator;
 import org.apache.plc4x.java.scraper.config.JobConfigurationClassicImpl;
+import org.apache.plc4x.java.scraper.config.JobConfigurationImpl;
 import org.assertj.core.api.WithAssertions;
 import org.junit.jupiter.api.Test;
 
@@ -33,7 +34,10 @@ class Plc4XBaseTableTest implements WithAssertions {
     @Test
     void testOnBlockingQueue() {
         ArrayBlockingQueue<Plc4xSchema.Record> queue = new ArrayBlockingQueue<>(100);
-        Plc4xStreamTable table = new Plc4xStreamTable(queue, new JobConfigurationClassicImpl("job1", 100,
+        Plc4xStreamTable table = new Plc4xStreamTable(queue, new JobConfigurationImpl(
+            "job1",
+            null,
+            100,
             Collections.emptyList(),
             Collections.singletonMap("key", "address")));
 
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/model/S7Field.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/model/S7Field.java
index 5629a3a..7f93a1e 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/model/S7Field.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/model/S7Field.java
@@ -232,4 +232,15 @@ public class S7Field implements PlcField {
 
     }
 
+    @Override
+    public String toString() {
+        return "S7Field{" +
+            "dataType=" + dataType +
+            ", memoryArea=" + memoryArea +
+            ", blockNumber=" + blockNumber +
+            ", byteOffset=" + byteOffset +
+            ", bitOffset=" + bitOffset +
+            ", numElements=" + numElements +
+            '}';
+    }
 }
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XNettyException.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XNettyException.java
new file mode 100644
index 0000000..4b370d3
--- /dev/null
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XNettyException.java
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.s7.netty;
+
+/**
+ * when exceptions within netty-implementations are thrown this class will be used
+ */
+public class Plc4XNettyException extends RuntimeException{
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public Plc4XNettyException(String message) {
+        super(message);
+    }
+}
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 6d734aa..6c789dd 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
@@ -45,6 +45,8 @@ import org.apache.plc4x.java.s7.netty.model.params.items.VarParameterItem;
 import org.apache.plc4x.java.s7.netty.model.payloads.VarPayload;
 import org.apache.plc4x.java.s7.netty.model.payloads.items.VarPayloadItem;
 import org.apache.plc4x.java.s7.netty.model.types.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.lang.reflect.Array;
@@ -72,6 +74,7 @@ import java.util.stream.IntStream;
  * the {@link PlcRequestContainer}s future with the {@link PlcResponse}.
  */
 public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequestContainer> {
+    private static final Logger logger = LoggerFactory.getLogger( Plc4XS7Protocol.class );
 
     private static final AtomicInteger tpduGenerator = new AtomicInteger(10);
 
@@ -450,99 +453,105 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ
             BaseDefaultFieldItem 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:
-                        fieldItem = decodeReadResponseBitField(field, data);
-                        break;
-                    // -----------------------------------------
-                    // Bit-strings
-                    // -----------------------------------------
-                    case BYTE:  // 1 byte
-                        fieldItem = decodeReadResponseByteBitStringField(field, data);
-                        break;
-                    case WORD:  // 2 byte (16 bit)
-                        fieldItem = decodeReadResponseShortBitStringField(field, data);
-                        break;
-                    case DWORD:  // 4 byte (32 bit)
-                        fieldItem = decodeReadResponseIntegerBitStringField(field, data);
-                        break;
-                    case LWORD:  // 8 byte (64 bit)
-                        fieldItem = decodeReadResponseLongBitStringField(field, data);
-                        break;
-                    // -----------------------------------------
-                    // Integers
-                    // -----------------------------------------
-                    // 8 bit:
-                    case SINT:
-                        fieldItem = decodeReadResponseSignedByteField(field, data);
-                        break;
-                    case USINT:
-                        fieldItem = decodeReadResponseUnsignedByteField(field, data);
-                        break;
-                    // 16 bit:
-                    case INT:
-                        fieldItem = decodeReadResponseSignedShortField(field, data);
-                        break;
-                    case UINT:
-                        fieldItem = decodeReadResponseUnsignedShortField(field, data);
-                        break;
-                    // 32 bit:
-                    case DINT:
-                        fieldItem = decodeReadResponseSignedIntegerField(field, data);
-                        break;
-                    case UDINT:
-                        fieldItem = decodeReadResponseUnsignedIntegerField(field, data);
-                        break;
-                    // 64 bit:
-                    case LINT:
-                        fieldItem = decodeReadResponseSignedLongField(field, data);
-                        break;
-                    case ULINT:
-                        fieldItem = decodeReadResponseUnsignedLongField(field, data);
-                        break;
-                    // -----------------------------------------
-                    // Floating point values
-                    // -----------------------------------------
-                    case REAL:
-                        fieldItem = decodeReadResponseFloatField(field, data);
-                        break;
-                    case LREAL:
-                        fieldItem = decodeReadResponseDoubleField(field, data);
-                        break;
-                    // -----------------------------------------
-                    // Characters & Strings
-                    // -----------------------------------------
-                    case CHAR: // 1 byte (8 bit)
-                        fieldItem = decodeReadResponseFixedLengthStringField(1, false, data);
-                        break;
-                    case WCHAR: // 2 byte
-                        fieldItem = decodeReadResponseFixedLengthStringField(1, true, data);
-                        break;
-                    case STRING:
-                        fieldItem = decodeReadResponseVarLengthStringField(false, data);
-                        break;
-                    case WSTRING:
-                        fieldItem = decodeReadResponseVarLengthStringField(true, data);
-                        break;
-                    // -----------------------------------------
-                    // TIA Date-Formats
-                    // -----------------------------------------
-                    case DATE_AND_TIME:
-                        fieldItem = decodeReadResponseDateAndTime(field,data);
-                        break;
-                    case TIME_OF_DAY:
-                        fieldItem = decodeReadResponseTimeOfDay(field,data);
-                        break;
-                    case DATE:
-                        fieldItem = decodeReadResponseDate(field,data);
-                        break;
-                    default:
-                        throw new PlcProtocolException("Unsupported type " + field.getDataType());
+                try {
+                    switch (field.getDataType()) {
+                        // -----------------------------------------
+                        // Bit
+                        // -----------------------------------------
+                        case BOOL:
+                            fieldItem = decodeReadResponseBitField(field, data);
+                            break;
+                        // -----------------------------------------
+                        // Bit-strings
+                        // -----------------------------------------
+                        case BYTE:  // 1 byte
+                            fieldItem = decodeReadResponseByteBitStringField(field, data);
+                            break;
+                        case WORD:  // 2 byte (16 bit)
+                            fieldItem = decodeReadResponseShortBitStringField(field, data);
+                            break;
+                        case DWORD:  // 4 byte (32 bit)
+                            fieldItem = decodeReadResponseIntegerBitStringField(field, data);
+                            break;
+                        case LWORD:  // 8 byte (64 bit)
+                            fieldItem = decodeReadResponseLongBitStringField(field, data);
+                            break;
+                        // -----------------------------------------
+                        // Integers
+                        // -----------------------------------------
+                        // 8 bit:
+                        case SINT:
+                            fieldItem = decodeReadResponseSignedByteField(field, data);
+                            break;
+                        case USINT:
+                            fieldItem = decodeReadResponseUnsignedByteField(field, data);
+                            break;
+                        // 16 bit:
+                        case INT:
+                            fieldItem = decodeReadResponseSignedShortField(field, data);
+                            break;
+                        case UINT:
+                            fieldItem = decodeReadResponseUnsignedShortField(field, data);
+                            break;
+                        // 32 bit:
+                        case DINT:
+                            fieldItem = decodeReadResponseSignedIntegerField(field, data);
+                            break;
+                        case UDINT:
+                            fieldItem = decodeReadResponseUnsignedIntegerField(field, data);
+                            break;
+                        // 64 bit:
+                        case LINT:
+                            fieldItem = decodeReadResponseSignedLongField(field, data);
+                            break;
+                        case ULINT:
+                            fieldItem = decodeReadResponseUnsignedLongField(field, data);
+                            break;
+                        // -----------------------------------------
+                        // Floating point values
+                        // -----------------------------------------
+                        case REAL:
+                            fieldItem = decodeReadResponseFloatField(field, data);
+                            break;
+                        case LREAL:
+                            fieldItem = decodeReadResponseDoubleField(field, data);
+                            break;
+                        // -----------------------------------------
+                        // Characters & Strings
+                        // -----------------------------------------
+                        case CHAR: // 1 byte (8 bit)
+                            fieldItem = decodeReadResponseFixedLengthStringField(1, false, data);
+                            break;
+                        case WCHAR: // 2 byte
+                            fieldItem = decodeReadResponseFixedLengthStringField(1, true, data);
+                            break;
+                        case STRING:
+                            fieldItem = decodeReadResponseVarLengthStringField(false, data);
+                            break;
+                        case WSTRING:
+                            fieldItem = decodeReadResponseVarLengthStringField(true, data);
+                            break;
+                        // -----------------------------------------
+                        // TIA Date-Formats
+                        // -----------------------------------------
+                        case DATE_AND_TIME:
+                            fieldItem = decodeReadResponseDateAndTime(field, data);
+                            break;
+                        case TIME_OF_DAY:
+                            fieldItem = decodeReadResponseTimeOfDay(field, data);
+                            break;
+                        case DATE:
+                            fieldItem = decodeReadResponseDate(field, data);
+                            break;
+                        default:
+                            throw new PlcProtocolException("Unsupported type " + field.getDataType());
+                    }
+                }
+                catch (Plc4XNettyException e){
+                    logger.warn("Problem during casting of field {}: Exception: {}; FieldInformation: {}",fieldName,e.getMessage(),field);
+                }
+                catch (Exception e){
+                    logger.warn("Some other error occurred casting field {}, FieldInformation: {}",fieldName, field,e);
                 }
             }
             Pair<PlcResponseCode, BaseDefaultFieldItem> result = new ImmutablePair<>(responseCode, fieldItem);
@@ -653,8 +662,11 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ
     BaseDefaultFieldItem decodeReadResponseVarLengthStringField(boolean isUtf16, ByteBuf data) {
         // Max length ... ignored.
         data.skipBytes(1);
-        byte actualLength = data.readByte();
-        return decodeReadResponseFixedLengthStringField(actualLength, isUtf16, data);
+
+        //reading out byte and transforming that to an unsigned byte within an integer, otherwise longer strings are failing
+        byte currentLengthByte = data.readByte();
+        int currentLength = currentLengthByte & 0xFF;
+        return decodeReadResponseFixedLengthStringField(currentLength, isUtf16, data);
     }
 
     BaseDefaultFieldItem decodeReadResponseDateAndTime(S7Field field,ByteBuf data) {
diff --git a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
index ca18021..6465790 100644
--- a/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
+++ b/plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/TriggeredScraperTask.java
@@ -146,7 +146,7 @@ public class TriggeredScraperTask implements ScraperTask, TriggeredScraperTaskMB
                 // Handle response (Async)
                 CompletableFuture.runAsync(() -> resultHandler.handle(jobName, connectionAlias, TriggeredScraperImpl.convertPlcResponseToMap(plcReadResponse)), executorService);
             } catch (Exception e) {
-                LOGGER.warn("Exception during scraping of Job {}, Connection-Alias {}: Error-message: {} - for stack-trace change logging to DEBUG", jobName,connectionAlias,e.getMessage());
+                LOGGER.warn("Exception during scraping of Job {}, Connection-Alias {}: Error-message: {} - for stack-trace change logging to DEBUG", jobName,connectionAlias,e.getCause());
                 handleException(e);
             } finally {
                 if (connection != null) {
diff --git a/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java b/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
index 545b4aa..381df5a 100644
--- a/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
+++ b/plc4j/utils/scraper/src/test/java/org/apache/plc4x/java/scraper/TriggeredScraperRunner.java
@@ -42,6 +42,7 @@ public class TriggeredScraperRunner {
      * testing of TriggeredScraper vs real device
      */
     public static void main(String[] args) throws IOException, ScraperException {
+
         ScraperConfiguration configuration = ScraperConfiguration.fromFile("plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml", ScraperConfigurationTriggeredImpl.class);
 
         PlcDriverManager plcDriverManager = new PooledPlcDriverManager();
diff --git a/plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml b/plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml
index 99ad571..ec79e17 100644
--- a/plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml
+++ b/plc4j/utils/scraper/src/test/resources/example_triggered_scraper.yml
@@ -18,7 +18,7 @@
 # ----------------------------------------------------------------------------
 ---
 sources:
-  S7_PI: s7://192.168.167.210/0/1
+  S7_PI: s7://192.168.167.210/1/1
 
 jobs:
   - name: scheduled-demo-job1
@@ -36,7 +36,7 @@ jobs:
       test1: '%DB810:DBW0:INT'
 
   - name: triggered-demo-job2
-    triggerConfig: (S7_TRIGGER_VAR,250,(%M0.7:BOOL)==(true))
+    triggerConfig: (S7_TRIGGER_VAR,1000,(%M0.7:BOOL)==(true))
     sources:
       - S7_PI
     fields:
@@ -45,13 +45,19 @@ jobs:
       test3: '%DB810:DBX266:STRING'
       test4: '%DB810:DBX526:STRING'
       test5: '%DB810:DBX786:STRING'
-      test6: '%DB810:DBX46806:STRING'
       test7: '%DB810:DBD2:REAL'
-      test8: '%DB811:DBX12:STRING'
-      test9: '%DB811:DBX280:STRING'
-      test10: '%DB811:DBB1000:BYTE[8]'
-      test11: '%DB811:DBX268.3:BOOL'
-      test12: '%DB811:DBB270:BYTE[8]'
+      test8: '%DB811:DBB1000:BYTE[8]'
+      test9: '%DB811:DBX268.3:BOOL'
+      test10: '%DB811:DBB270:BYTE[8]'
+
+  - name: scheduled-string-job3
+    triggerConfig: (SCHEDULED,2000)
+    sources:
+      - S7_PI
+    fields:
+      test3_8: '%DB811:DBX14:STRING'
+      test3_9: '%DB811:DBX282:STRING'
+
 
   - name: triggered-demo-job3-prev_value
     triggerConfig: (S7_TRIGGER_VAR,500,(%M0:USINT)>=(PREV))