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

sruehl pushed a commit to branch feature/Beckhoff_ADS_protocol
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git


The following commit(s) were added to refs/heads/feature/Beckhoff_ADS_protocol 
by this push:
     new 1833df7  + continued on plc protocol layer + added readable error 
codes from specification.
1833df7 is described below

commit 1833df73d4b59da430b2bfe27f956b262f92460d
Author: Sebastian Rühl <[email protected]>
AuthorDate: Wed Feb 7 22:42:59 2018 +0100

    + continued on plc protocol layer
    + added readable error codes from specification.
---
 .../java/ads/api/commands/ADSReadResponse.java     |  11 ++
 .../java/ads/api/commands/ADSWriteResponse.java    |   3 +
 .../java/ads/api/commands/types/AdsReturnCode.java | 199 +++++++++++++++++++++
 .../plc4x/java/ads/api/commands/types/Result.java  |   9 +
 .../plc4x/java/ads/api/generic/AMSTCPPaket.java    |   6 +-
 .../generic/calculated/CalculatedAMSTCPHeader.java |   2 +-
 .../plc4x/java/ads/api/generic/types/AMSError.java |  10 ++
 .../plc4x/java/ads/api/util/ByteReadable.java      |   2 +-
 .../plc4x/java/ads/api/util/LengthSupplier.java    |   2 +-
 .../apache/plc4x/java/ads/netty/ADSProtocol.java   |  16 +-
 .../plc4x/java/ads/netty/Plc4XADSProtocol.java     | 106 ++++++++---
 11 files changed, 334 insertions(+), 32 deletions(-)

diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
index 7bc9b2a..479d48e 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
@@ -58,4 +58,15 @@ public class ADSReadResponse extends AMSTCPPaket {
         return buildADSData(result, length, data);
     }
 
+    public Result getResult() {
+        return result;
+    }
+
+    public Length getLength() {
+        return length;
+    }
+
+    public Data getData() {
+        return data;
+    }
 }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
index a9c4188..97a5f90 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
@@ -46,4 +46,7 @@ public class ADSWriteResponse extends AMSTCPPaket {
         return buildADSData(result);
     }
 
+    public Result getResult() {
+        return result;
+    }
 }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
new file mode 100644
index 0000000..0809d66
--- /dev/null
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
@@ -0,0 +1,199 @@
+/*
+ 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.ads.api.commands.types;
+
+/**
+ * Based on spec from: 
https://infosys.beckhoff.com/content/1033/tcadscommon/html/ads_returncodes.htm
+ */
+// TODO: give the codes useful names
+// Error codes: 0x000..., 0x500..., 0x700..., 0x1000..., 0x274C...
+public enum AdsReturnCode {
+    // Global Error Codes
+    ADS_CODE_0(0x0, 0, "no error", "", ""),
+    ADS_CODE_1(0x1, 1, "Internal error", "", ""),
+    ADS_CODE_2(0x2, 2, "No Rtime", "", ""),
+    ADS_CODE_3(0x3, 3, "Allocation locked memory error", "", ""),
+    ADS_CODE_4(0x4, 4, "Insert mailbox error", "No ADS mailbox was available 
to process this message.", "Reduce the number of ADS calls (e.g ADS-Sum 
commands or Max Delay Parameter)"),
+    ADS_CODE_5(0x5, 5, "Wrong receive HMSG", "", ""),
+    ADS_CODE_6(0x6, 6, "target port not foundADS ", "Server not started", ""),
+    ADS_CODE_7(0x7, 7, "target machine not found", "Missing ADS routes", ""),
+    ADS_CODE_8(0x8, 8, "Unknown command ID", "", ""),
+    ADS_CODE_9(0x9, 9, "Bad task ID", "", ""),
+    ADS_CODE_10(0xA, 10, "No IO", "", ""),
+    ADS_CODE_11(0xB, 11, "Unknown ADS command", "", ""),
+    ADS_CODE_12(0xC, 12, "Win 32 error", "", ""),
+    ADS_CODE_13(0xD, 13, "Port not connected", "", ""),
+    ADS_CODE_14(0xE, 14, "Invalid ADS length", "", ""),
+    ADS_CODE_15(0xF, 15, "Invalid ADS Net ID", "", ""),
+    ADS_CODE_16(0x10, 16, "Low Installation level", "", ""),
+    ADS_CODE_17(0x11, 17, "No debug available", "", ""),
+    ADS_CODE_18(0x12, 18, "Port disabled", "", ""),
+    ADS_CODE_19(0x13, 19, "Port already connected", "", ""),
+    ADS_CODE_20(0x14, 20, "ADS Sync Win32 error", "", ""),
+    ADS_CODE_21(0x15, 21, "ADS Sync Timeout", "", ""),
+    ADS_CODE_22(0x16, 22, "ADS Sync AMS error", "", ""),
+    ADS_CODE_23(0x17, 23, "ADS Sync no index map", "", ""),
+    ADS_CODE_24(0x18, 24, "Invalid ADS port", "", ""),
+    ADS_CODE_25(0x19, 25, "No memory", "", ""),
+    ADS_CODE_26(0x1A, 26, "TCP send error", "", ""),
+    ADS_CODE_27(0x1B, 27, "Host unreachable", "", ""),
+    ADS_CODE_28(0x1C, 28, "Invalid AMS fragment", "", ""),
+
+
+    // Router Error Codes
+    ADS_CODE_1280(0x500, 1280, "ROUTERERR_NOLOCKEDMEMORY", "No locked memory 
can be allocated", ""),
+    ADS_CODE_1281(0x501, 1281, "ROUTERERR_RESIZEMEMORY", "The size of the  
router memory could not be changed", ""),
+    ADS_CODE_1282(0x502, 1282, "ROUTERERR_MAILBOXFULL", "The mailbox has 
reached the maximum number of possible messages. The current sent message was 
rejected", "Check the connection between the communication partners"),
+    ADS_CODE_1283(0x503, 1283, "ROUTERERR_DEBUGBOXFULL ", "The mailbox has 
reached the maximum number of possible messages.The sent message will not be 
displayed in the debug monitor", "Check the connection to the debug monitor"),
+    ADS_CODE_1284(0x504, 1284, "ROUTERERR_UNKNOWNPORTTYPE ", "The port type is 
unknown", ""),
+    ADS_CODE_1285(0x505, 1285, "ROUTERERR_NOTINITIALIZED", "Router is not 
initialised", ""),
+    ADS_CODE_1286(0x506, 1286, "ROUTERERR_PORTALREADYINUSE ", "The desired 
port number is already assigned", ""),
+    ADS_CODE_1287(0x507, 1287, "ROUTERERR_NOTREGISTERED ", "Port not 
registered", ""),
+    ADS_CODE_1288(0x508, 1288, "ROUTERERR_NOMOREQUEUES", "The maximum number 
of Ports reached", ""),
+    ADS_CODE_1289(0x509, 1289, "ROUTERERR_INVALIDPORT ", "The port is 
invalid.", ""),
+    ADS_CODE_1290(0x50A, 1290, "ROUTERERR_NOTACTIVATED ", "TwinCAT Router not 
active", ""),
+    ADS_CODE_1291(0x50B, 1291, "ROUTERERR_FRAGMENTBOXFULL", "", ""),
+    ADS_CODE_1292(0x50C, 1292, "ROUTERERR_FRAGMENTTIMEOUT", "", ""),
+    ADS_CODE_1293(0x50D, 1293, "ROUTERERR_TOBEREMOVED", "", ""),
+
+
+    // General ADS Error Codes
+    ADS_CODE_1792(0x700, 1792, "error class <device error>", "", ""),
+    ADS_CODE_1793(0x701, 1793, "Service is not supported by server", "", ""),
+    ADS_CODE_1794(0x702, 1794, "invalid index group", "", ""),
+    ADS_CODE_1795(0x703, 1795, "invalid index offset", "", ""),
+    ADS_CODE_1796(0x704, 1796, "reading/writing not permitted", "", ""),
+    ADS_CODE_1797(0x705, 1797, "parameter size not correct", "", ""),
+    ADS_CODE_1798(0x706, 1798, "invalid parameter value(s)", "", ""),
+    ADS_CODE_1799(0x707, 1799, "device is not in a ready state", "", ""),
+    ADS_CODE_1800(0x708, 1800, "device is busy", "", ""),
+    ADS_CODE_1801(0x709, 1801, "invalid context (must be in Windows)", "", ""),
+    ADS_CODE_1802(0x70A, 1802, "out of memory", "", ""),
+    ADS_CODE_1803(0x70B, 1803, "invalid parameter value(s)", "", ""),
+    ADS_CODE_1804(0x70C, 1804, "not found (files, ...)", "", ""),
+    ADS_CODE_1805(0x70D, 1805, "syntax error in command or file", "", ""),
+    ADS_CODE_1806(0x70E, 1806, "objects do not match", "", ""),
+    ADS_CODE_1807(0x70F, 1807, "object already exists", "", ""),
+    ADS_CODE_1808(0x710, 1808, "symbol not found", "", ""),
+    ADS_CODE_1809(0x711, 1809, "symbol version invalid", "Onlinechange", 
"Release handle and get a new one"),
+    ADS_CODE_1810(0x712, 1810, "server is in invalid state", "", ""),
+    ADS_CODE_1811(0x713, 1811, "AdsTransMode not supported", "", ""),
+    ADS_CODE_1812(0x714, 1812, "Notification handle is invalid", 
"Onlinechange", "Release handle and get a new one"),
+    ADS_CODE_1813(0x715, 1813, "Notification client not registered", "", ""),
+    ADS_CODE_1814(0x716, 1814, "no more notification handles", "", ""),
+    ADS_CODE_1815(0x717, 1815, "size for watch too big", "", ""),
+    ADS_CODE_1816(0x718, 1816, "device not initialized", "", ""),
+    ADS_CODE_1817(0x719, 1817, "device has a timeout", "", ""),
+    ADS_CODE_1818(0x71A, 1818, "query interface failed", "", ""),
+    ADS_CODE_1819(0x71B, 1819, "wrong interface required", "", ""),
+    ADS_CODE_1820(0x71C, 1820, "class ID is invalid", "", ""),
+    ADS_CODE_1821(0x71D, 1821, "object ID is invalid", "", ""),
+    ADS_CODE_1822(0x71E, 1822, "request is pending", "", ""),
+    ADS_CODE_1823(0x71F, 1823, "request is aborted", "", ""),
+    ADS_CODE_1824(0x720, 1824, "signal warning", "", ""),
+    ADS_CODE_1825(0x721, 1825, "invalid array index", "", ""),
+    ADS_CODE_1826(0x722, 1826, "symbol not active", "Onlinechange", "Release 
handle and get a new one"),
+    ADS_CODE_1827(0x723, 1827, "access denied", "", ""),
+    ADS_CODE_1828(0x724, 1828, "missing license ", "", "Activate license for 
TwinCAT 3 function"),
+    ADS_CODE_1836(0x72c, 1836, "exception occured during system start", "", 
"Check each device transistions"),
+    ADS_CODE_1856(0x740, 1856, "Error class <client error>", "", ""),
+    ADS_CODE_1857(0x741, 1857, "invalid parameter at service", "", ""),
+    ADS_CODE_1858(0x742, 1858, "polling list is empty", "", ""),
+    ADS_CODE_1859(0x743, 1859, "var connection already in use", "", ""),
+    ADS_CODE_1860(0x744, 1860, "invoke ID in use", "", ""),
+    ADS_CODE_1861(0x745, 1861, "timeout elapsedCheck ADS routes of sender and 
receiver and your  firewall setting", "", ""),
+    ADS_CODE_1862(0x746, 1862, "error in win32 subsystem", "", ""),
+    ADS_CODE_1863(0x747, 1863, "Invalid client timeout value", "", ""),
+    ADS_CODE_1864(0x748, 1864, "ads-port not opened", "", ""),
+    ADS_CODE_1872(0x750, 1872, "internal error in ads sync", "", ""),
+    ADS_CODE_1873(0x751, 1873, "hash table overflow", "", ""),
+    ADS_CODE_1874(0x752, 1874, "key not found in hash", "", ""),
+    ADS_CODE_1875(0x753, 1875, "no more symbols in cache", "", ""),
+    ADS_CODE_1876(0x754, 1876, "invalid response received", "", ""),
+    ADS_CODE_1877(0x755, 1877, "sync port is locked", "", ""),
+
+
+    // RTime Error Codes
+    ADS_CODE_4096(0x1000, 4096, "RTERR_INTERNAL ", "Internal fatal error in 
the TwinCAT real-time system", ""),
+    ADS_CODE_4097(0x1001, 4097, "RTERR_BADTIMERPERIODS", "Timer value not 
vaild", ""),
+    ADS_CODE_4098(0x1002, 4098, "RTERR_INVALIDTASKPTR", "Task pointer has the 
invalid value ZERO", ""),
+    ADS_CODE_4099(0x1003, 4099, "RTERR_INVALIDSTACKPTR", "Task stack pointer 
has the invalid value ZERO", ""),
+    ADS_CODE_4100(0x1004, 4100, "RTERR_PRIOEXISTS", "The demand task priority 
is already assigned", ""),
+    ADS_CODE_4101(0x1005, 4101, "RTERR_NOMORETCB", "No more free TCB (Task 
Control Block) available. Maximum number of TCBs is 64", ""),
+    ADS_CODE_4102(0x1006, 4102, "RTERR_NOMORESEMAS", "No more free semaphores 
available. Maximum number of semaphores is 64", ""),
+    ADS_CODE_4103(0x1007, 4103, "RTERR_NOMOREQUEUES", "No more free queue 
available. Maximum number of queue is 64", ""),
+    ADS_CODE_4104(0x1008, 4104, "TwinCAT ", "reserved.", ""),
+    ADS_CODE_4105(0x1009, 4105, "TwinCAT ", "reserved.", ""),
+    ADS_CODE_4106(0x100A, 4106, "TwinCAT ", "reserved.", ""),
+    ADS_CODE_4107(0x100B, 4107, "TwinCAT ", "reserved.", ""),
+    ADS_CODE_4108(0x100C, 4108, "TwinCAT ", "reserved.", ""),
+    ADS_CODE_4109(0x100D, 4109, "RTERR_EXTIRQALREADYDEF", "An external 
synchronisation interrupt is already applied", ""),
+    ADS_CODE_4110(0x100E, 4110, "RTERR_EXTIRQNOTDEF", "No external 
synchronsiation interrupt applied", ""),
+    ADS_CODE_4111(0x100F, 4111, "RTERR_EXTIRQINSTALLFAILED", "The apply of the 
external synchronisation interrupt failed", ""),
+    ADS_CODE_4112(0x1010, 4112, "RTERR_IRQLNOTLESSOREQUAL", "Call of a service 
function in the wrong context", ""),
+    ADS_CODE_4119(0x1017, 4119, "RTERR_VMXNOTSUPPORTED", "Intel VT-x extension 
is not supported.", ""),
+    ADS_CODE_4120(0x1018, 4120, "RTERR_VMXDISABLED", "Intel VT-x extension is 
not enabled in BIOS.", ""),
+    ADS_CODE_4121(0x1019, 4121, "RTERR_VMXCONTROLSMISSING", "Missing feature 
in Intel VT-x extension.", ""),
+    ADS_CODE_4122(0x101A, 4122, "RTERR_VMXENABLEFAILS", "Enabling Intel VT-x 
fails.", ""),
+
+
+    // TCP Winsock Error Codes
+    ADS_CODE_10060(0x274c, 10060, "A socket operation was attempted to an 
unreachable host", "Host unreachable", "Check network connection via ping"),
+    ADS_CODE_10061(0x274d, 10061, "A connection attempt failed because the 
connected party did not properly respond after a period of time,or established 
connection failed because connected host has failed to respond.", "Host 
unreachable", "Check network connection via ping"),
+    ADS_CODE_10065(0x2751, 10065, "No connection could be made because the 
target machine actively refused it", "", ""),
+    UNKNOWN(0, 0, "", "", "");
+
+    long hex;
+    long dec;
+    String description;
+    String possibleCauses;
+    String solution;
+
+    AdsReturnCode(long hex, long dec, String description, String 
possibleCauses, String solution) {
+        this.hex = hex;
+        this.dec = dec;
+        if (hex != dec) {
+            throw new IllegalArgumentException("hex " + hex + " is different 
from dec " + dec);
+        }
+        this.description = description;
+        this.possibleCauses = possibleCauses;
+        this.solution = solution;
+    }
+
+    // TODO: optimize with map
+    public static AdsReturnCode of(long hex) {
+        for (AdsReturnCode adsReturnCode : values()) {
+            if (adsReturnCode.hex == hex) {
+                return adsReturnCode;
+            }
+        }
+        return UNKNOWN;
+    }
+
+    @Override
+    public String toString() {
+        return "AdsReturnCode{\n" +
+            "hex=" + hex +
+            ",\n dec=" + dec +
+            ",\n description='" + description + '\'' +
+            ",\n possibleCauses='" + possibleCauses + '\'' +
+            ",\n solution='" + solution + '\'' +
+            '}';
+    }
+}
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Result.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Result.java
index 402bca5..5a3dd68 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Result.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Result.java
@@ -49,4 +49,13 @@ public class Result extends UnsignedIntLEByteValue {
     public static Result of(ByteBuf byteBuf) {
         return new Result(byteBuf);
     }
+
+    public AdsReturnCode toAdsReturnCode() {
+        return AdsReturnCode.of(getAsLong());
+    }
+
+    @Override
+    public String toString() {
+        return "Result{" + toAdsReturnCode() + "}";
+    }
 }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
index 933e4af..85ba515 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
@@ -40,7 +40,7 @@ public abstract class AMSTCPPaket implements ByteReadable {
     public AMSTCPPaket(AMSHeader amsHeader) {
         // It is important that we wrap the ads data call as this will 
initialized in the constructor
         // so this value will be null if we call adsData now.
-        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> 
getAdsData().getLength());
+        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> 
getAdsData().getCalculatedLength());
         this.amsHeader = amsHeader;
     }
 
@@ -55,9 +55,9 @@ public abstract class AMSTCPPaket implements ByteReadable {
             sourceAmsPort,
             getClass().getAnnotation(ADSCommandType.class).value(),
             State.DEFAULT,
-            () -> DataLength.of(getAdsData().getLength()),
+            () -> DataLength.of(getAdsData().getCalculatedLength()),
             invokeId);
-        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> 
getAdsData().getLength());
+        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> 
getAdsData().getCalculatedLength());
     }
 
     public AMSTCPHeader getAmstcpHeader() {
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
index ddbf615..94c033b 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
@@ -46,7 +46,7 @@ public class CalculatedAMSTCPHeader extends AMSTCPHeader {
     public ByteBuf getByteBuf() {
         long aggregateLength = 0;
         for (LengthSupplier supplier : lengthSupplier) {
-            aggregateLength += supplier.getLength();
+            aggregateLength += supplier.getCalculatedLength();
         }
         return buildByteBuff(reserved, Length.of(aggregateLength));
     }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/AMSError.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/AMSError.java
index 672b34e..d829933 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/AMSError.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/AMSError.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.ads.api.generic.types;
 
 import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.commands.types.AdsReturnCode;
 import org.apache.plc4x.java.ads.api.util.UnsignedIntLEByteValue;
 
 public class AMSError extends UnsignedIntLEByteValue {
@@ -51,4 +52,13 @@ public class AMSError extends UnsignedIntLEByteValue {
     public static AMSError of(ByteBuf byteBuf) {
         return new AMSError(byteBuf);
     }
+
+    public AdsReturnCode toAdsReturnCode() {
+        return AdsReturnCode.of(getAsLong());
+    }
+
+    @Override
+    public String toString() {
+        return "AMSError{" + toAdsReturnCode() + "}";
+    }
 }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteReadable.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteReadable.java
index 39e08aa..9c3bd97 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteReadable.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteReadable.java
@@ -29,7 +29,7 @@ public interface ByteReadable extends LengthSupplier {
 
     ByteBuf getByteBuf();
 
-    default long getLength() {
+    default long getCalculatedLength() {
         return getBytes().length;
     }
 
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/LengthSupplier.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/LengthSupplier.java
index 3401054..082d017 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/LengthSupplier.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/LengthSupplier.java
@@ -21,5 +21,5 @@ package org.apache.plc4x.java.ads.api.util;
 @FunctionalInterface
 public interface LengthSupplier {
 
-    long getLength();
+    long getCalculatedLength();
 }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
index f7d8ac8..c98ce36 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
@@ -31,16 +31,20 @@ import org.apache.plc4x.java.ads.api.generic.types.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ADSProtocol.class);
 
-    private Map<Invoke, AMSTCPPaket> requests;
+    private ConcurrentMap<Invoke, AMSTCPPaket> requests;
 
     public ADSProtocol() {
-        this.requests = new HashMap<>();
+        this.requests = new ConcurrentHashMap<>();
     }
 
     @Override
@@ -68,8 +72,10 @@ public class ADSProtocol extends 
MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
         DataLength dataLength = DataLength.of(byteBuf);
         AMSError errorCode = AMSError.of(byteBuf);
         Invoke invoke = Invoke.of(byteBuf);
-        AMSTCPPaket correlatedAmstcpPacket = requests.get(invoke);
-        LOGGER.debug("Correlated packet received {}", correlatedAmstcpPacket);
+        AMSTCPPaket correlatedAmstcpPacket = requests.remove(invoke);
+        if (correlatedAmstcpPacket != null) {
+            LOGGER.debug("Correlated packet received {}", 
correlatedAmstcpPacket);
+        }
         if (dataLength.getAsLong() > Integer.MAX_VALUE) {
             throw new IllegalStateException("Overflow in datalength: " + 
dataLength.getAsLong());
         }
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
index 192af39..9430e91 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
@@ -24,10 +24,7 @@ import org.apache.plc4x.java.ads.api.commands.ADSReadRequest;
 import org.apache.plc4x.java.ads.api.commands.ADSReadResponse;
 import org.apache.plc4x.java.ads.api.commands.ADSWriteRequest;
 import org.apache.plc4x.java.ads.api.commands.ADSWriteResponse;
-import org.apache.plc4x.java.ads.api.commands.types.Data;
-import org.apache.plc4x.java.ads.api.commands.types.IndexGroup;
-import org.apache.plc4x.java.ads.api.commands.types.IndexOffset;
-import org.apache.plc4x.java.ads.api.commands.types.Length;
+import org.apache.plc4x.java.ads.api.commands.types.*;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.ads.api.generic.types.AMSNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
@@ -35,24 +32,33 @@ import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 import org.apache.plc4x.java.ads.model.ADSAddress;
 import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.api.messages.PlcRequest;
-import org.apache.plc4x.java.api.messages.PlcRequestContainer;
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.messages.items.ReadRequestItem;
+import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
 import org.apache.plc4x.java.api.messages.items.WriteRequestItem;
+import org.apache.plc4x.java.api.messages.items.WriteResponseItem;
+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 org.apache.plc4x.java.api.types.ResponseCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 public class Plc4XADSProtocol extends MessageToMessageCodec<AMSTCPPaket, 
PlcRequestContainer> {
 
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(Plc4XADSProtocol.class);
+
     private static final AtomicLong correlationBuilder = new AtomicLong(1);
 
-    private Map<Short, PlcRequestContainer> requests;
+    private ConcurrentMap<Long, PlcRequestContainer<PlcRequest, PlcResponse>> 
requests;
 
     private final AMSNetId targetAmsNetId;
     private final AMSPort targetAmsPort;
@@ -64,7 +70,7 @@ public class Plc4XADSProtocol extends 
MessageToMessageCodec<AMSTCPPaket, PlcRequ
         this.targetAmsPort = targetAmsPort;
         this.sourceAmsNetId = sourceAmsNetId;
         this.sourceAmsPort = sourceAmsPort;
-        this.requests = new HashMap<>();
+        this.requests = new ConcurrentHashMap<>();
     }
 
     @Override
@@ -77,14 +83,6 @@ public class Plc4XADSProtocol extends 
MessageToMessageCodec<AMSTCPPaket, PlcRequ
         }
     }
 
-    @Override
-    protected void decode(ChannelHandlerContext channelHandlerContext, 
AMSTCPPaket amstcpPaket, List<Object> out) throws Exception {
-        if (amstcpPaket instanceof ADSReadResponse) {
-            // TODO: implement me
-        } else if (amstcpPaket instanceof ADSWriteResponse) {
-            // TODO: implement me
-        }
-    }
 
     private void encodeWriteRequest(PlcRequestContainer msg, List<Object> out) 
throws PlcException {
         PlcWriteRequest writeRequest = (PlcWriteRequest) msg.getRequest();
@@ -100,7 +98,7 @@ public class Plc4XADSProtocol extends 
MessageToMessageCodec<AMSTCPPaket, PlcRequ
         Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
         IndexGroup indexGroup = IndexGroup.of(adsAddress.getIndexGroup());
         IndexOffset indexOffset = IndexOffset.of(adsAddress.getIndexOffset());
-        // TODO: how to get length and data. Serialization of plc is the 
problem here
+        // TODO: implement serialization
         Length length = Length.of(1);
         Data data = Data.of(new byte[]{0x42});
         AMSTCPPaket amstcpPaket = new ADSWriteRequest(targetAmsNetId, 
targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, 
indexOffset, length, data);
@@ -127,4 +125,70 @@ public class Plc4XADSProtocol extends 
MessageToMessageCodec<AMSTCPPaket, PlcRequ
         out.add(amstcpPaket);
     }
 
+    @Override
+    protected void decode(ChannelHandlerContext channelHandlerContext, 
AMSTCPPaket amstcpPaket, List<Object> out) throws Exception {
+        PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer = 
requests.remove(amstcpPaket.getAmsHeader().getInvokeId().getAsLong());
+        if (plcRequestContainer == null) {
+            LOGGER.info("Unmapped packet received {}", amstcpPaket);
+            return;
+        }
+        PlcRequest request = plcRequestContainer.getRequest();
+        PlcResponse response = null;
+
+        // Handle the response to a read request.
+        if (request instanceof PlcReadRequest) {
+            if (amstcpPaket instanceof ADSReadResponse) {
+                response = decodeReadResponse((ADSReadResponse) amstcpPaket, 
plcRequestContainer);
+            } else {
+                throw new PlcProtocolException("Wrong type correlated " + 
amstcpPaket);
+            }
+        } else if (request instanceof PlcWriteRequest) {
+            if (amstcpPaket instanceof ADSWriteResponse) {
+                response = decodeWriteResponse((ADSWriteResponse) amstcpPaket, 
plcRequestContainer);
+            } else {
+                throw new PlcProtocolException("Wrong type correlated " + 
amstcpPaket);
+            }
+        }
+
+        // Confirm the response being handled.
+        if (response != null) {
+            plcRequestContainer.getResponseFuture().complete(response);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private PlcResponse decodeWriteResponse(ADSWriteResponse responseMessage, 
PlcRequestContainer<PlcRequest, PlcResponse> requestContainer) throws 
PlcProtocolException {
+        PlcWriteRequest plcWriteRequest = (PlcWriteRequest) 
requestContainer.getRequest();
+        WriteRequestItem requestItem = 
plcWriteRequest.getRequestItems().get(0);
+
+        ResponseCode responseCode = 
decodeResponseCode(responseMessage.getResult());
+
+        if (plcWriteRequest instanceof TypeSafePlcWriteRequest) {
+            return new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) 
plcWriteRequest, Collections.singletonList(new WriteResponseItem<>(requestItem, 
responseCode)));
+        } else {
+            return new PlcWriteResponse(plcWriteRequest, 
Collections.singletonList(new WriteResponseItem<>(requestItem, responseCode)));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private PlcResponse decodeReadResponse(ADSReadResponse responseMessage, 
PlcRequestContainer<PlcRequest, PlcResponse> requestContainer) throws 
PlcProtocolException {
+        PlcReadRequest plcReadRequest = (PlcReadRequest) 
requestContainer.getRequest();
+        ReadRequestItem requestItem = plcReadRequest.getRequestItems().get(0);
+
+        ResponseCode responseCode = 
decodeResponseCode(responseMessage.getResult());
+        byte[] bytes = responseMessage.getData().getBytes();
+
+        // TODO: implement deserialization
+        if (plcReadRequest instanceof TypeSafePlcReadRequest) {
+            return new TypeSafePlcReadResponse((TypeSafePlcReadRequest) 
plcReadRequest, Collections.singletonList(new ReadResponseItem<>(requestItem, 
responseCode, Collections.singletonList(bytes))));
+        } else {
+            return new PlcReadResponse(plcReadRequest, 
Collections.singletonList(new ReadResponseItem<>(requestItem, responseCode, 
Collections.singletonList(bytes))));
+        }
+    }
+
+    private ResponseCode decodeResponseCode(Result result) {
+        // TODO: complete mapping
+        return result.getAsLong() == 0 ? ResponseCode.OK : 
ResponseCode.INTERNAL_ERROR;
+    }
+
 }

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to