You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2018/03/08 10:51:34 UTC

[incubator-plc4x] 05/08: added ads serial protocol implementation

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 965f1e573ff9dea7808a4cc53a49f5d78d099c2b
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Mar 8 10:34:30 2018 +0100

    added ads serial protocol implementation
---
 .../plc4x/java/ads/api/generic/AMSPacket.java      |  43 +++++++
 .../plc4x/java/ads/api/generic/AMSTCPPacket.java   |   5 +
 .../ads/api/serial/AMSSerialAcknowledgeFrame.java  | 114 +++++++++++++++++
 .../plc4x/java/ads/api/serial/AMSSerialFrame.java  | 136 +++++++++++++++++++++
 .../java/ads/api/serial/AMSSerialResetFrame.java   | 113 +++++++++++++++++
 .../plc4x/java/ads/api/serial/types/CRC.java       |  59 +++++++++
 .../java/ads/api/serial/types/FragmentNumber.java  |  44 +++++++
 .../java/ads/api/serial/types/MagicCookie.java     |  59 +++++++++
 .../java/ads/api/serial/types/ReceiverAddress.java |  46 +++++++
 .../ads/api/serial/types/TransmitterAddress.java   |  46 +++++++
 .../plc4x/java/ads/api/serial/types/UserData.java  |  52 ++++++++
 .../java/ads/api/serial/types/UserDataLength.java  |  44 +++++++
 12 files changed, 761 insertions(+)

diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSPacket.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSPacket.java
new file mode 100644
index 0000000..cf84f3f
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSPacket.java
@@ -0,0 +1,43 @@
+/*
+ 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.generic;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.ByteReadable;
+
+public class AMSPacket implements ByteReadable {
+
+    private final AMSHeader amsHeader;
+
+    private final ADSData adsData;
+
+    private AMSPacket(AMSHeader amsHeader, ADSData adsData) {
+        this.amsHeader = amsHeader;
+        this.adsData = adsData;
+    }
+
+    public static AMSPacket of(AMSHeader amsHeader, ADSData adsData) {
+        return new AMSPacket(amsHeader, adsData);
+    }
+
+    @Override
+    public ByteBuf getByteBuf() {
+        return buildByteBuff(amsHeader, adsData);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPacket.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPacket.java
index d9b2626..fea4708 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPacket.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPacket.java
@@ -25,6 +25,7 @@ import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
 import static java.util.Objects.requireNonNull;
 
+// TODO: maybe don't let all commands extend from tcp as in serial these look different...
 public abstract class AMSTCPPacket implements ByteReadable {
     private final AMSTCPHeader amsTcpHeader;
 
@@ -78,6 +79,10 @@ public abstract class AMSTCPPacket implements ByteReadable {
         return () -> buildByteBuff(byteReadables);
     }
 
+    public AMSPacket getAMSPacket() {
+        return AMSPacket.of(amsHeader, getAdsData());
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o)
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java
new file mode 100644
index 0000000..ebdf8bb
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java
@@ -0,0 +1,114 @@
+/*
+ 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.serial;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.serial.types.*;
+import org.apache.plc4x.java.ads.api.util.ByteReadable;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * If an AMS serial frame has been received and the frame is OK (magic cookie OK, CRC OK, correct fragment number etc.),
+ * then the receiver has to send an acknowledge frame, to inform the transmitter that the frame has arrived.
+ *
+ * @see <a href="https://infosys.beckhoff.com/content/1033/tcadsamsserialspec/html/tcamssericalspec_amsframe.htm?id=8115637053270715044">TwinCAT AMS via RS232 Specification</a>
+ */
+public class AMSSerialAcknowledgeFrame implements ByteReadable {
+
+    public static final int ID = 0x5A01;
+
+    /**
+     * Id for detecting an AMS serial frame.
+     */
+    private final MagicCookie magicCookie;
+
+    /**
+     * Address of the sending participant. This value can always be set to 0 for an RS232 communication,
+     * since it is a 1 to 1 connection and hence the participants are unique.
+     */
+    private final TransmitterAddress transmitterAddress;
+
+    /**
+     * Receiver’s address. This value can always be set to 0 for an RS232 communication, since it is a 1 to 1
+     * connection and hence the participants are unique.
+     */
+    private final ReceiverAddress receiverAddress;
+
+    /**
+     * Number of the frame sent. Once the number 255 has been sent, it starts again from 0. The receiver checks this
+     * number with an internal counter.
+     */
+    private final FragmentNumber fragmentNumber;
+
+    /**
+     * The max. length of the AMS packet to be sent is 255. If larger AMS packets are to be sent then they have to be
+     * fragmented (not published at the moment).
+     */
+    private final UserDataLength userDataLength;
+
+    private final CRC crc;
+
+    private AMSSerialAcknowledgeFrame(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, CRC crc) {
+        this.magicCookie = magicCookie;
+        this.transmitterAddress = transmitterAddress;
+        this.receiverAddress = receiverAddress;
+        this.fragmentNumber = fragmentNumber;
+        this.userDataLength = userDataLength;
+        this.crc = crc;
+    }
+
+    private AMSSerialAcknowledgeFrame(TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber) {
+        this.magicCookie = MagicCookie.of(ID);
+        this.transmitterAddress = transmitterAddress;
+        this.receiverAddress = receiverAddress;
+        this.fragmentNumber = fragmentNumber;
+        this.userDataLength = UserDataLength.of((byte) 0);
+        MessageDigest messageDigest;
+        try {
+            messageDigest = MessageDigest.getInstance("CRC-16");
+        } catch (NoSuchAlgorithmException e) {
+            throw new PlcRuntimeException(e);
+        }
+        messageDigest.update(magicCookie.getBytes());
+        messageDigest.update(transmitterAddress.getBytes());
+        messageDigest.update(receiverAddress.getBytes());
+        messageDigest.update(fragmentNumber.getBytes());
+        byte[] digest = messageDigest.digest(userDataLength.getBytes());
+        if (digest.length > 2) {
+            throw new PlcRuntimeException("Digest length too great " + digest.length);
+        }
+        this.crc = CRC.of(digest[0], digest[1]);
+    }
+
+    public static AMSSerialAcknowledgeFrame of(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, CRC crc) {
+        return new AMSSerialAcknowledgeFrame(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
+    }
+
+    public static AMSSerialAcknowledgeFrame of(TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber) {
+        return new AMSSerialAcknowledgeFrame(transmitterAddress, receiverAddress, fragmentNumber);
+    }
+
+    @Override
+    public ByteBuf getByteBuf() {
+        return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java
new file mode 100644
index 0000000..3952773
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java
@@ -0,0 +1,136 @@
+/*
+ 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.serial;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.generic.AMSPacket;
+import org.apache.plc4x.java.ads.api.generic.AMSTCPPacket;
+import org.apache.plc4x.java.ads.api.serial.types.*;
+import org.apache.plc4x.java.ads.api.util.ByteReadable;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * An AMS packet can be transferred via RS232 with the help of an AMS serial frame.
+ * The actual AMS packet is in the user data field of the frame.
+ * The max. length of the AMS packet is limited to 255 bytes.
+ * Therefore the max. size of an AMS serial frame is 263 bytes.
+ * The fragment number is compared with an internal counter by the receiver.
+ * The frame number is simply accepted and not checked when receiving the first AMS frame or in case a timeout is
+ * exceeded. The CRC16 algorithm is used for calculating the checksum.
+ *
+ * @see <a href="https://infosys.beckhoff.com/content/1033/tcadsamsserialspec/html/tcamssericalspec_amsframe.htm?id=8115637053270715044">TwinCAT AMS via RS232 Specification</a>
+ */
+public class AMSSerialFrame implements ByteReadable {
+
+    public static final int ID = 0xA501;
+
+    /**
+     * Id for detecting an AMS serial frame.
+     */
+    private final MagicCookie magicCookie;
+
+    /**
+     * Address of the sending participant. This value can always be set to 0 for an RS232 communication,
+     * since it is a 1 to 1 connection and hence the participants are unique.
+     */
+    private final TransmitterAddress transmitterAddress;
+
+    /**
+     * Receiver’s address. This value can always be set to 0 for an RS232 communication, since it is a 1 to 1
+     * connection and hence the participants are unique.
+     */
+    private final ReceiverAddress receiverAddress;
+
+    /**
+     * Number of the frame sent. Once the number 255 has been sent, it starts again from 0. The receiver checks this
+     * number with an internal counter.
+     */
+    private final FragmentNumber fragmentNumber;
+
+    /**
+     * The max. length of the AMS packet to be sent is 255. If larger AMS packets are to be sent then they have to be
+     * fragmented (not published at the moment).
+     */
+    private final UserDataLength userDataLength;
+
+    /**
+     * The AMS packet to be sent.
+     */
+    private final UserData userData;
+
+    private final CRC crc;
+
+    private AMSSerialFrame(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, UserData userData, CRC crc) {
+        this.magicCookie = magicCookie;
+        this.transmitterAddress = transmitterAddress;
+        this.receiverAddress = receiverAddress;
+        this.fragmentNumber = fragmentNumber;
+        this.userDataLength = userDataLength;
+        this.userData = userData;
+        this.crc = crc;
+    }
+
+    private AMSSerialFrame(FragmentNumber fragmentNumber, AMSTCPPacket amstcpPacket) {
+        this.magicCookie = MagicCookie.of(ID);
+        this.transmitterAddress = TransmitterAddress.RS232_COMM_ADDRESS;
+        this.receiverAddress = ReceiverAddress.RS232_COMM_ADDRESS;
+        this.fragmentNumber = fragmentNumber;
+        AMSPacket amsPacket = amstcpPacket.getAMSPacket();
+        long calculatedLength = amsPacket.getCalculatedLength();
+        if (calculatedLength > 255) {
+            throw new IllegalArgumentException("Paket length must not exceed 255");
+        }
+        this.userDataLength = UserDataLength.of((byte) calculatedLength);
+        byte[] amsPacketBytes = amsPacket.getBytes();
+        this.userData = UserData.of(amsPacketBytes);
+        MessageDigest messageDigest;
+        try {
+            messageDigest = MessageDigest.getInstance("CRC-16");
+        } catch (NoSuchAlgorithmException e) {
+            throw new PlcRuntimeException(e);
+        }
+        messageDigest.update(magicCookie.getBytes());
+        messageDigest.update(transmitterAddress.getBytes());
+        messageDigest.update(receiverAddress.getBytes());
+        messageDigest.update(fragmentNumber.getBytes());
+        messageDigest.update(userDataLength.getBytes());
+        messageDigest.update(amsPacketBytes);
+        byte[] digest = messageDigest.digest(amsPacketBytes);
+        if (digest.length > 2) {
+            throw new PlcRuntimeException("Digest length too great " + digest.length);
+        }
+        this.crc = CRC.of(digest[0], digest[1]);
+    }
+
+    public static AMSSerialFrame of(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, UserData userData, CRC crc) {
+        return new AMSSerialFrame(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData, crc);
+    }
+
+    public static AMSSerialFrame of(FragmentNumber fragmentNumber, AMSTCPPacket amstcpPacket) {
+        return new AMSSerialFrame(fragmentNumber, amstcpPacket);
+    }
+
+    @Override
+    public ByteBuf getByteBuf() {
+        return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData, crc);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java
new file mode 100644
index 0000000..0524643
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java
@@ -0,0 +1,113 @@
+/*
+ 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.serial;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.serial.types.*;
+import org.apache.plc4x.java.ads.api.util.ByteReadable;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * In case the transmitter does not receive a valid acknowledgement after multiple transmission, then a reset frame is
+ * sent. In this way the receiver is informed that a new communication is running and the receiver then accepts the
+ * fragment number during the next AMS-Frame, without carrying out a check.
+ */
+public class AMSSerialResetFrame implements ByteReadable {
+
+    public static final int ID = 0xA503;
+
+    /**
+     * Id for detecting an AMS serial frame.
+     */
+    private final MagicCookie magicCookie;
+
+    /**
+     * Address of the sending participant. This value can always be set to 0 for an RS232 communication,
+     * since it is a 1 to 1 connection and hence the participants are unique.
+     */
+    private final TransmitterAddress transmitterAddress;
+
+    /**
+     * Receiver’s address. This value can always be set to 0 for an RS232 communication, since it is a 1 to 1
+     * connection and hence the participants are unique.
+     */
+    private final ReceiverAddress receiverAddress;
+
+    /**
+     * Number of the frame sent. Once the number 255 has been sent, it starts again from 0. The receiver checks this
+     * number with an internal counter.
+     */
+    private final FragmentNumber fragmentNumber;
+
+    /**
+     * The max. length of the AMS packet to be sent is 255. If larger AMS packets are to be sent then they have to be
+     * fragmented (not published at the moment).
+     */
+    private final UserDataLength userDataLength;
+
+    private final CRC crc;
+
+    private AMSSerialResetFrame(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, CRC crc) {
+        this.magicCookie = magicCookie;
+        this.transmitterAddress = transmitterAddress;
+        this.receiverAddress = receiverAddress;
+        this.fragmentNumber = fragmentNumber;
+        this.userDataLength = userDataLength;
+        this.crc = crc;
+    }
+
+    private AMSSerialResetFrame(TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber) {
+        this.magicCookie = MagicCookie.of(ID);
+        this.transmitterAddress = transmitterAddress;
+        this.receiverAddress = receiverAddress;
+        this.fragmentNumber = FragmentNumber.of((byte) 0);
+        this.userDataLength = UserDataLength.of((byte) 0);
+        MessageDigest messageDigest;
+        try {
+            messageDigest = MessageDigest.getInstance("CRC-16");
+        } catch (NoSuchAlgorithmException e) {
+            throw new PlcRuntimeException(e);
+        }
+        messageDigest.update(magicCookie.getBytes());
+        messageDigest.update(transmitterAddress.getBytes());
+        messageDigest.update(receiverAddress.getBytes());
+        messageDigest.update(fragmentNumber.getBytes());
+        byte[] digest = messageDigest.digest(userDataLength.getBytes());
+        if (digest.length > 2) {
+            throw new PlcRuntimeException("Digest length too great " + digest.length);
+        }
+        this.crc = CRC.of(digest[0], digest[1]);
+    }
+
+    public static AMSSerialResetFrame of(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, CRC crc) {
+        return new AMSSerialResetFrame(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
+    }
+
+    public static AMSSerialResetFrame of(TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber) {
+        return new AMSSerialResetFrame(transmitterAddress, receiverAddress, fragmentNumber);
+    }
+
+    @Override
+    public ByteBuf getByteBuf() {
+        return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/CRC.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/CRC.java
new file mode 100644
index 0000000..9ece6c1
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/CRC.java
@@ -0,0 +1,59 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.UnsignedShortLEByteValue;
+
+public class CRC extends UnsignedShortLEByteValue {
+
+    public static final int NUM_BYTES = UnsignedShortLEByteValue.UNSIGNED_SHORT_LE_NUM_BYTES;
+
+    private CRC(byte... values) {
+        super(values);
+    }
+
+    private CRC(int value) {
+        super(value);
+    }
+
+    private CRC(String length) {
+        super(length);
+    }
+
+    private CRC(ByteBuf byteBuf) {
+        super(byteBuf);
+    }
+
+    public static CRC of(byte... values) {
+        return new CRC(values);
+    }
+
+    public static CRC of(int value) {
+        return new CRC(value);
+    }
+
+    public static CRC of(String length) {
+        return new CRC(length);
+    }
+
+    public static CRC of(ByteBuf byteBuf) {
+        return new CRC(byteBuf);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/FragmentNumber.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/FragmentNumber.java
new file mode 100644
index 0000000..808049a
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/FragmentNumber.java
@@ -0,0 +1,44 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.ByteValue;
+
+public class FragmentNumber extends ByteValue {
+
+    public static final int NUM_BYTES = 1;
+
+    private FragmentNumber(byte value) {
+        super(value);
+    }
+
+    private FragmentNumber(ByteBuf byteBuf) {
+        this(byteBuf.readByte());
+    }
+
+    public static FragmentNumber of(byte value) {
+        return new FragmentNumber(value);
+    }
+
+    public static FragmentNumber of(ByteBuf byteBuf) {
+        return new FragmentNumber(byteBuf);
+    }
+
+}
\ No newline at end of file
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/MagicCookie.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/MagicCookie.java
new file mode 100644
index 0000000..cd3b77d
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/MagicCookie.java
@@ -0,0 +1,59 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.UnsignedShortLEByteValue;
+
+public class MagicCookie extends UnsignedShortLEByteValue {
+
+    public static final int NUM_BYTES = UnsignedShortLEByteValue.UNSIGNED_SHORT_LE_NUM_BYTES;
+
+    private MagicCookie(byte... values) {
+        super(values);
+    }
+
+    private MagicCookie(int value) {
+        super(value);
+    }
+
+    private MagicCookie(String length) {
+        super(length);
+    }
+
+    private MagicCookie(ByteBuf byteBuf) {
+        super(byteBuf);
+    }
+
+    public static MagicCookie of(byte... values) {
+        return new MagicCookie(values);
+    }
+
+    public static MagicCookie of(int value) {
+        return new MagicCookie(value);
+    }
+
+    public static MagicCookie of(String length) {
+        return new MagicCookie(length);
+    }
+
+    public static MagicCookie of(ByteBuf byteBuf) {
+        return new MagicCookie(byteBuf);
+    }
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/ReceiverAddress.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/ReceiverAddress.java
new file mode 100644
index 0000000..f1809f3
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/ReceiverAddress.java
@@ -0,0 +1,46 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.ByteValue;
+
+public class ReceiverAddress extends ByteValue {
+
+    public static final int NUM_BYTES = 1;
+
+    public static final ReceiverAddress RS232_COMM_ADDRESS = ReceiverAddress.of((byte) 0);
+
+    private ReceiverAddress(byte value) {
+        super(value);
+    }
+
+    private ReceiverAddress(ByteBuf byteBuf) {
+        this(byteBuf.readByte());
+    }
+
+    public static ReceiverAddress of(byte value) {
+        return new ReceiverAddress(value);
+    }
+
+    public static ReceiverAddress of(ByteBuf byteBuf) {
+        return new ReceiverAddress(byteBuf);
+    }
+
+}
\ No newline at end of file
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/TransmitterAddress.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/TransmitterAddress.java
new file mode 100644
index 0000000..1c90591
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/TransmitterAddress.java
@@ -0,0 +1,46 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.ByteValue;
+
+public class TransmitterAddress extends ByteValue {
+
+    public static final int NUM_BYTES = 1;
+
+    public static final TransmitterAddress RS232_COMM_ADDRESS = TransmitterAddress.of((byte) 0);
+
+    private TransmitterAddress(byte value) {
+        super(value);
+    }
+
+    private TransmitterAddress(ByteBuf byteBuf) {
+        this(byteBuf.readByte());
+    }
+
+    public static TransmitterAddress of(byte value) {
+        return new TransmitterAddress(value);
+    }
+
+    public static TransmitterAddress of(ByteBuf byteBuf) {
+        return new TransmitterAddress(byteBuf);
+    }
+
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserData.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserData.java
new file mode 100644
index 0000000..10d2c0c
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserData.java
@@ -0,0 +1,52 @@
+/*
+ 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.serial.types;
+
+import org.apache.plc4x.java.ads.api.util.ByteValue;
+
+import java.nio.charset.Charset;
+
+import static java.util.Objects.requireNonNull;
+
+public class UserData extends ByteValue {
+
+    private UserData(byte... values) {
+        super(values);
+    }
+
+    public static UserData of(byte... values) {
+        return new UserData(values);
+    }
+
+    public static UserData of(String value) {
+        requireNonNull(value);
+        return new UserData(value.getBytes());
+    }
+
+    public static UserData of(String value, Charset charset) {
+        requireNonNull(value);
+        return new UserData(value.getBytes(charset));
+    }
+
+    @Override
+    public String toString() {
+        // TODO: maybe we could find a way to implement this to string
+        return "UserData{" + value.length + "bytes} ";
+    }
+}
\ No newline at end of file
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserDataLength.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserDataLength.java
new file mode 100644
index 0000000..b8d0e9a
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/types/UserDataLength.java
@@ -0,0 +1,44 @@
+/*
+ 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.serial.types;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.util.ByteValue;
+
+public class UserDataLength extends ByteValue {
+
+    public static final int NUM_BYTES = 1;
+
+    private UserDataLength(byte value) {
+        super(value);
+    }
+
+    private UserDataLength(ByteBuf byteBuf) {
+        this(byteBuf.readByte());
+    }
+
+    public static UserDataLength of(byte value) {
+        return new UserDataLength(value);
+    }
+
+    public static UserDataLength of(ByteBuf byteBuf) {
+        return new UserDataLength(byteBuf);
+    }
+
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
sruehl@apache.org.