You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2022/03/18 17:13:27 UTC

[plc4x] branch develop updated: feat(modbus): Added first working support for modbus-rtu and modbus-ascii (currently only tested with tcp transport)

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

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 9798d9b  feat(modbus): Added first working support for modbus-rtu and modbus-ascii (currently only tested with tcp transport)
9798d9b is described below

commit 9798d9b192c7ea9f85567e639f77a6e717fe4621
Author: cdutz <ch...@c-ware.de>
AuthorDate: Fri Mar 18 18:10:33 2022 +0100

    feat(modbus): Added first working support for modbus-rtu and modbus-ascii (currently only tested with tcp transport)
---
 plc4go/go.mod                                      |  2 +-
 plc4go/go.sum                                      |  6 +++
 .../knxnetip/readwrite/model/KnxManufacturer.go    | 26 ++++++++--
 .../canopen/transport/CANOpenFrameDataAdapter.java |  1 -
 plc4j/drivers/modbus/pom.xml                       |  4 ++
 .../plc4x/java/modbus/ascii/ModbusAsciiDriver.java | 59 ++++++++++++++++++++--
 .../java/modbus/readwrite/utils/StaticHelper.java  |  2 +-
 .../plc4x/java/modbus/rtu/ModbusRtuDriver.java     |  7 +--
 .../plc4x/java/modbus/tcp/ModbusTcpDriver.java     |  3 +-
 .../services/org.apache.plc4x.java.api.PlcDriver   |  2 +
 .../java/modbus/ManualModbusDiscoveryTest.java     |  2 +
 .../plc4x/java/modbus/ManualModbusDriverTest.java  |  2 +
 .../plc4x/java/modbus/ManualPacketTest.java}       | 18 ++++++-
 plc4j/spi/pom.xml                                  |  2 +-
 .../spi/GeneratedDriverByteToMessageCodec.java     | 22 +++++---
 .../connection/GeneratedProtocolMessageCodec.java  | 17 ++++++-
 .../connection/SingleProtocolStackConfigurer.java  | 30 +++++++----
 .../plc4x/java/spi/generation/MessageOutput.java   |  2 +-
 .../plc4x/java/transport/can/CANTransport.java     |  1 -
 .../apache/plc4x/java/transport/can/FrameData.java |  1 -
 .../transport/socketcan/SocketCANFrameBuilder.java |  4 --
 .../knxnetip/readwrite/model/KnxManufacturer.cs    | 19 ++++---
 .../plc4x/simulator/server/s7/S7ServerModule.java  |  3 +-
 23 files changed, 184 insertions(+), 51 deletions(-)

diff --git a/plc4go/go.mod b/plc4go/go.mod
index c0f8fac..0da7a2f 100644
--- a/plc4go/go.mod
+++ b/plc4go/go.mod
@@ -37,6 +37,6 @@ require (
 	golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 	golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 // indirect
-	golang.org/x/tools v0.1.9 // indirect
+	golang.org/x/tools v0.1.10 // indirect
 	gotest.tools/gotestsum v1.7.0 // indirect
 )
diff --git a/plc4go/go.sum b/plc4go/go.sum
index d1615b5..d38b91d 100644
--- a/plc4go/go.sum
+++ b/plc4go/go.sum
@@ -57,6 +57,7 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -64,10 +65,13 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
 golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -105,6 +109,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
 golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
 golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
index d56a508..6e5ebe0 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/KnxManufacturer.go
@@ -620,8 +620,9 @@ const (
 	KnxManufacturer_M_REMKO_GMBH_AND_CO__KG                              KnxManufacturer = 582
 	KnxManufacturer_M_SHENZHEN_CONGXUN_INTELLIGENT_TECHNOLOGY_CO___LTD   KnxManufacturer = 583
 	KnxManufacturer_M_ANDAS                                              KnxManufacturer = 584
-	KnxManufacturer_M_ABB___RESERVED                                     KnxManufacturer = 585
-	KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED                    KnxManufacturer = 586
+	KnxManufacturer_M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD    KnxManufacturer = 585
+	KnxManufacturer_M_ABB___RESERVED                                     KnxManufacturer = 586
+	KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED                    KnxManufacturer = 587
 )
 
 var KnxManufacturerValues []KnxManufacturer
@@ -1214,6 +1215,7 @@ func init() {
 		KnxManufacturer_M_REMKO_GMBH_AND_CO__KG,
 		KnxManufacturer_M_SHENZHEN_CONGXUN_INTELLIGENT_TECHNOLOGY_CO___LTD,
 		KnxManufacturer_M_ANDAS,
+		KnxManufacturer_M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD,
 		KnxManufacturer_M_ABB___RESERVED,
 		KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED,
 	}
@@ -3383,10 +3385,14 @@ func (e KnxManufacturer) Number() uint16 {
 		}
 	case 585:
 		{ /* '585' */
-			return 43954
+			return 643
 		}
 	case 586:
 		{ /* '586' */
+			return 43954
+		}
+	case 587:
+		{ /* '587' */
 			return 43959
 		}
 	case 59:
@@ -5749,10 +5755,14 @@ func (e KnxManufacturer) Name() string {
 		}
 	case 585:
 		{ /* '585' */
-			return "ABB - reserved"
+			return "Hefei Chuang Yue Intelligent Technology Co.,LTD"
 		}
 	case 586:
 		{ /* '586' */
+			return "ABB - reserved"
+		}
+	case 587:
+		{ /* '587' */
 			return "Busch-Jaeger Elektro - reserved"
 		}
 	case 59:
@@ -7033,8 +7043,10 @@ func KnxManufacturerByValue(value uint16) KnxManufacturer {
 	case 584:
 		return KnxManufacturer_M_ANDAS
 	case 585:
-		return KnxManufacturer_M_ABB___RESERVED
+		return KnxManufacturer_M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD
 	case 586:
+		return KnxManufacturer_M_ABB___RESERVED
+	case 587:
 		return KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED
 	case 59:
 		return KnxManufacturer_M_ELECTRAK
@@ -8212,6 +8224,8 @@ func KnxManufacturerByName(value string) KnxManufacturer {
 		return KnxManufacturer_M_SHENZHEN_CONGXUN_INTELLIGENT_TECHNOLOGY_CO___LTD
 	case "M_ANDAS":
 		return KnxManufacturer_M_ANDAS
+	case "M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD":
+		return KnxManufacturer_M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD
 	case "M_ABB___RESERVED":
 		return KnxManufacturer_M_ABB___RESERVED
 	case "M_BUSCH_JAEGER_ELEKTRO___RESERVED":
@@ -9431,6 +9445,8 @@ func (e KnxManufacturer) name() string {
 		return "M_SHENZHEN_CONGXUN_INTELLIGENT_TECHNOLOGY_CO___LTD"
 	case KnxManufacturer_M_ANDAS:
 		return "M_ANDAS"
+	case KnxManufacturer_M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD:
+		return "M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD"
 	case KnxManufacturer_M_ABB___RESERVED:
 		return "M_ABB___RESERVED"
 	case KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED:
diff --git a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java
index 954c242..44cfdf7 100644
--- a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java
+++ b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java
@@ -20,7 +20,6 @@ package org.apache.plc4x.java.canopen.transport;
 
 import org.apache.plc4x.java.canopen.readwrite.CANOpenFrame;
 import org.apache.plc4x.java.spi.generation.Message;
-import org.apache.plc4x.java.spi.generation.MessageIO;
 import org.apache.plc4x.java.spi.generation.MessageInput;
 import org.apache.plc4x.java.transport.can.FrameData;
 
diff --git a/plc4j/drivers/modbus/pom.xml b/plc4j/drivers/modbus/pom.xml
index de8eba5..6c0a153 100644
--- a/plc4j/drivers/modbus/pom.xml
+++ b/plc4j/drivers/modbus/pom.xml
@@ -158,6 +158,10 @@
       <artifactId>commons-lang3</artifactId>
     </dependency>
     <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.pcap4j</groupId>
       <artifactId>pcap4j-core</artifactId>
     </dependency>
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
index f4afd20..529ac0e 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java
@@ -19,6 +19,8 @@
 package org.apache.plc4x.java.modbus.ascii;
 
 import io.netty.buffer.ByteBuf;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.modbus.ascii.config.ModbusAsciiConfiguration;
 import org.apache.plc4x.java.modbus.ascii.protocol.ModbusAsciiProtocolLogic;
@@ -30,10 +32,12 @@ import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
 import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 
+import java.nio.charset.StandardCharsets;
 import java.util.function.ToIntFunction;
 
 public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
@@ -103,7 +107,8 @@ public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
 
     @Override
     protected ProtocolStackConfigurer<ModbusAsciiADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusAsciiADU.class,  (io, args) -> (ModbusAsciiADU) ModbusAsciiADU.staticParse(io, args))
+        return SingleProtocolStackConfigurer.builder(ModbusAsciiADU.class,
+                new ModbusAsciiInput(), new ModbusAsciiOutput())
             .withProtocol(ModbusAsciiProtocolLogic.class)
             .withPacketSizeEstimator(ModbusAsciiDriver.ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
@@ -115,8 +120,8 @@ public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
     public static class ByteLengthEstimator implements ToIntFunction<ByteBuf> {
         @Override
         public int applyAsInt(ByteBuf byteBuf) {
-            if (byteBuf.readableBytes() >= 6) {
-                return byteBuf.getUnsignedShort(byteBuf.readerIndex() + 4) + 6;
+            if (byteBuf.readableBytes() >= 1) {
+                return byteBuf.readableBytes();
             }
             return -1;
         }
@@ -127,4 +132,52 @@ public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
         return ModbusField.of(query);
     }
 
+    public static class ModbusAsciiInput implements MessageInput<ModbusAsciiADU> {
+        @Override
+        public ModbusAsciiADU parse(ReadBuffer io, Object... args) throws ParseException {
+            final short startChar = io.readShort(8);
+            // Check if the message starts with the ":" char.
+            if(startChar != 0x3A) {
+                throw new ParseException(String.format("Expected starting ':' character but got %c", startChar));
+            }
+            // Read in all the bytes in the message.
+            final ReadBufferByteBased bufferByteBased = (ReadBufferByteBased) io;
+            // Read in all bytes except the last two ones, which contain a line-break and carriage-return.
+            final byte[] bytes = bufferByteBased.getBytes(bufferByteBased.getPos(), (int) bufferByteBased.getTotalBytes() - 2);
+            // Convert the bytes into a string (Which is the hex-encoded message)
+            final String inputString = new String(bytes, StandardCharsets.UTF_8);
+            // Decode the encoded string back into a byte-array.
+            try {
+                final byte[] decodedBytes = Hex.decodeHex(inputString);
+                // Parse the now decoded bytes as normal Message.
+                final ReadBufferByteBased readBuffer = new ReadBufferByteBased(decodedBytes);
+                return (ModbusAsciiADU) ModbusAsciiADU.staticParse(readBuffer, DriverType.MODBUS_ASCII, true);
+            } catch (DecoderException e) {
+                throw new ParseException(String.format("Error parsing incoming message: %s", inputString), e);
+            }
+        }
+    }
+
+    public static class ModbusAsciiOutput implements MessageOutput<ModbusAsciiADU> {
+        @Override
+        public WriteBufferByteBased serialize(ModbusAsciiADU value, Object... args) throws SerializationException {
+            // First serialize the packet the normal way.
+            WriteBufferByteBased writeBufferByteBased = new WriteBufferByteBased(value.getLengthInBytes());
+            value.serialize(writeBufferByteBased);
+            // Get the bytes.
+            final byte[] decodedBytes = writeBufferByteBased.getBytes();
+            // Now encode each byte as two hex values.
+            final String hexString = Hex.encodeHexString(decodedBytes).toUpperCase();
+            // Create a new WriteBuffer with the encoded data.
+            WriteBufferByteBased encodedWriteBuffer = new WriteBufferByteBased(hexString.length() + 3);
+            // Write the leading ":"
+            encodedWriteBuffer.writeShort(8, (short) 0x3a);
+            encodedWriteBuffer.writeByteArray(hexString.getBytes(StandardCharsets.UTF_8));
+            // Write the ending line-break, carriage return.
+            encodedWriteBuffer.writeShort(8, (short) 0x0d);
+            encodedWriteBuffer.writeShort(8, (short) 0x0a);
+            return encodedWriteBuffer;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
index b865381..1968f09 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/readwrite/utils/StaticHelper.java
@@ -47,7 +47,7 @@ public class StaticHelper {
         for (byte aByte : bytes) {
             lrc = (short) (lrc + aByte);
         }
-        lrc = (short) ((0xFF - lrc) + 1);
+        lrc = (short) -lrc;
         return (short) (lrc & 0xFF);
     }
 
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
index 8841acc..a3ef60b 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java
@@ -103,7 +103,8 @@ public class ModbusRtuDriver extends GeneratedDriverBase<ModbusRtuADU> {
 
     @Override
     protected ProtocolStackConfigurer<ModbusRtuADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusRtuADU.class,  (io, args) -> (ModbusRtuADU) ModbusRtuADU.staticParse(io, args))
+        return SingleProtocolStackConfigurer.builder(ModbusRtuADU.class,
+                (io, args) -> (ModbusRtuADU) ModbusRtuADU.staticParse(io, args))
             .withProtocol(ModbusRtuProtocolLogic.class)
             .withPacketSizeEstimator(ModbusRtuDriver.ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
@@ -115,8 +116,8 @@ public class ModbusRtuDriver extends GeneratedDriverBase<ModbusRtuADU> {
     public static class ByteLengthEstimator implements ToIntFunction<ByteBuf> {
         @Override
         public int applyAsInt(ByteBuf byteBuf) {
-            if (byteBuf.readableBytes() >= 6) {
-                return byteBuf.getUnsignedShort(byteBuf.readerIndex() + 4) + 6;
+            if (byteBuf.readableBytes() >= 1) {
+                return byteBuf.readableBytes();
             }
             return -1;
         }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
index 24cf92f..2c2a3ac 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java
@@ -122,7 +122,8 @@ public class ModbusTcpDriver extends GeneratedDriverBase<ModbusTcpADU> {
 
     @Override
     protected ProtocolStackConfigurer<ModbusTcpADU> getStackConfigurer() {
-        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, (io, args) -> (ModbusTcpADU) ModbusTcpADU.staticParse(io, args))
+        return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class,
+                (io, args) -> (ModbusTcpADU) ModbusTcpADU.staticParse(io, args))
             .withProtocol(ModbusTcpProtocolLogic.class)
             .withPacketSizeEstimator(ByteLengthEstimator.class)
             // Every incoming message is to be treated as a response.
diff --git a/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
index ad318fe..0fe4b9e 100644
--- a/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
+++ b/plc4j/drivers/modbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -16,4 +16,6 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+org.apache.plc4x.java.modbus.ascii.ModbusAsciiDriver
+org.apache.plc4x.java.modbus.rtu.ModbusRtuDriver
 org.apache.plc4x.java.modbus.tcp.ModbusTcpDriver
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
index 383d2d1..07b2f60 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDiscoveryTest.java
@@ -21,7 +21,9 @@ package org.apache.plc4x.java.modbus;
 import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryResponse;
+import org.junit.jupiter.api.Disabled;
 
+@Disabled("Manual Test")
 public class ManualModbusDiscoveryTest {
 
     public static void main(String[] args) throws Exception {
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
index 6763ffe..d2f85d8 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualModbusDriverTest.java
@@ -19,9 +19,11 @@
 package org.apache.plc4x.java.modbus;
 
 import org.apache.plc4x.test.manual.ManualTest;
+import org.junit.jupiter.api.Disabled;
 
 import java.util.Arrays;
 
+@Disabled("Manual Test")
 public class ManualModbusDriverTest extends ManualTest {
 
     /*
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageIO.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPacketTest.java
similarity index 51%
rename from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageIO.java
rename to plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPacketTest.java
index 1323320..0a0f2ef 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageIO.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPacketTest.java
@@ -16,8 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.spi.generation;
+package org.apache.plc4x.java.modbus;
 
-public interface MessageIO<PARSER_TYPE extends Message, SERIALIZER_TYPE extends Message> extends MessageInput<PARSER_TYPE>, MessageOutput<SERIALIZER_TYPE> {
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.modbus.readwrite.DriverType;
+import org.apache.plc4x.java.modbus.readwrite.ModbusADU;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
+import org.junit.jupiter.api.Disabled;
+
+@Disabled("Manual Test")
+public class ManualPacketTest {
+
+    public static void main(String[] args) throws Exception {
+        final byte[] bytes = Hex.decodeHex("0103140000000000000000000000000000000000000000a367");
+        final ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+        final ModbusADU modbusADU = ModbusADU.staticParse(readBufferByteBased, DriverType.MODBUS_RTU, true);
+        System.out.println(modbusADU);
+    }
 
 }
diff --git a/plc4j/spi/pom.xml b/plc4j/spi/pom.xml
index a233518..e47e983 100644
--- a/plc4j/spi/pom.xml
+++ b/plc4j/spi/pom.xml
@@ -102,7 +102,7 @@
           <instructions>
             <Import-Package>
                 com.fasterxml.jackson.annotation;resolution:=optional,   
-                com.github.jinahya.bit.io;resolution:=optional,   
+                com.github.jinahya.bit.io;resolution:=optional,
                 *
             </Import-Package>
             <Private-Package>com.github.jinahya.bit.io</Private-Package>
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
index 261fdde..2d9609a 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
@@ -34,11 +34,14 @@ public abstract class GeneratedDriverByteToMessageCodec<T extends Message> exten
 
     private final ByteOrder byteOrder;
     private final Object[] parserArgs;
-    private final MessageInput<T> io;
+    private final MessageInput<T> messageInput;
+    private final MessageOutput<T> messageOutput;
 
-    protected GeneratedDriverByteToMessageCodec(MessageInput<T> io, Class<T> clazz, ByteOrder byteOrder, Object[] parserArgs) {
-        super(clazz);
-        this.io = io;
+    protected GeneratedDriverByteToMessageCodec(MessageInput<T> messageInput, MessageOutput<T> messageOutput,
+                                                Class<T> outboundMessageType, ByteOrder byteOrder, Object[] parserArgs) {
+        super(outboundMessageType);
+        this.messageInput = messageInput;
+        this.messageOutput = messageOutput;
         this.byteOrder = byteOrder;
         this.parserArgs = parserArgs;
     }
@@ -46,8 +49,13 @@ public abstract class GeneratedDriverByteToMessageCodec<T extends Message> exten
     @Override
     protected void encode(ChannelHandlerContext ctx, T packet, ByteBuf byteBuf) {
         try {
-            WriteBufferByteBased buffer = new WriteBufferByteBased(packet.getLengthInBytes(), byteOrder);
-            packet.serialize(buffer);
+            WriteBufferByteBased buffer;
+            if(messageOutput != null) {
+                buffer = messageOutput.serialize(packet);
+            } else {
+                buffer = new WriteBufferByteBased(packet.getLengthInBytes(), byteOrder);
+                packet.serialize(buffer);
+            }
             byteBuf.writeBytes(buffer.getData());
             if (LOGGER.isDebugEnabled()) {
                 LOGGER.debug("Sending bytes to PLC for message {} as data {}", packet, Hex.encodeHexString(buffer.getData()));
@@ -76,7 +84,7 @@ public abstract class GeneratedDriverByteToMessageCodec<T extends Message> exten
                 ReadBuffer readBuffer = new ReadBufferByteBased(bytes, byteOrder);
 
                 // Parse the packet.
-                T packet = io.parse(readBuffer, parserArgs);
+                T packet = messageInput.parse(readBuffer, parserArgs);
 
                 // Pass the packet to the pipeline.
                 out.add(packet);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
index b299e3e..e521c79 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
@@ -32,12 +32,25 @@ public class GeneratedProtocolMessageCodec<BASE_PACKET_CLASS extends Message> ex
 
     public GeneratedProtocolMessageCodec(
         Class<BASE_PACKET_CLASS> basePacketClass,
-        MessageInput<BASE_PACKET_CLASS> messageIO,
+        MessageInput<BASE_PACKET_CLASS> messageInput,
         ByteOrder byteOrder,
         Object[] parserArgs,
         ToIntFunction<ByteBuf> packetSizeEstimator,
         Consumer<ByteBuf> corruptPackageRemover) {
-        super(messageIO, basePacketClass, byteOrder, parserArgs);
+        super(messageInput, null, basePacketClass, byteOrder, parserArgs);
+        this.packetSizeEstimator = packetSizeEstimator;
+        this.corruptPackageRemover = corruptPackageRemover;
+    }
+
+    public GeneratedProtocolMessageCodec(
+        Class<BASE_PACKET_CLASS> basePacketClass,
+        MessageInput<BASE_PACKET_CLASS> messageInput,
+        MessageOutput<BASE_PACKET_CLASS> messageOutput,
+        ByteOrder byteOrder,
+        Object[] parserArgs,
+        ToIntFunction<ByteBuf> packetSizeEstimator,
+        Consumer<ByteBuf> corruptPackageRemover) {
+        super(messageInput, messageOutput, basePacketClass, byteOrder, parserArgs);
         this.packetSizeEstimator = packetSizeEstimator;
         this.corruptPackageRemover = corruptPackageRemover;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
index 7e08f75..8567f83 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
@@ -33,6 +33,7 @@ import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.generation.ByteOrder;
 import org.apache.plc4x.java.spi.generation.Message;
 import org.apache.plc4x.java.spi.generation.MessageInput;
+import org.apache.plc4x.java.spi.generation.MessageOutput;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.List;
@@ -48,14 +49,19 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
     private final ByteOrder byteOrder;
     private final Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocolClass;
     private final Class<? extends DriverContext> driverContextClass;
-    private final MessageInput<BASE_PACKET_CLASS> messageIoClass;
+    private final MessageInput<BASE_PACKET_CLASS> messageInput;
+    private final MessageOutput<BASE_PACKET_CLASS> messageOutput;
     private final Class<? extends ToIntFunction<ByteBuf>> packetSizeEstimatorClass;
     private final Class<? extends Consumer<ByteBuf>> corruptPacketRemoverClass;
     private final MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
     private final Object[] parserArgs;
 
-    public static <BPC extends Message> SingleProtocolStackBuilder<BPC> builder(Class<BPC> basePacketClass, MessageInput<BPC> messageIo) {
-        return new SingleProtocolStackBuilder<>(basePacketClass, messageIo);
+    public static <BPC extends Message> SingleProtocolStackBuilder<BPC> builder(Class<BPC> basePacketClass, MessageInput<BPC> messageInput) {
+        return new SingleProtocolStackBuilder<>(basePacketClass, messageInput, null);
+    }
+
+    public static <BPC extends Message> SingleProtocolStackBuilder<BPC> builder(Class<BPC> basePacketClass, MessageInput<BPC> messageInput, MessageOutput<BPC> messageOutput) {
+        return new SingleProtocolStackBuilder<>(basePacketClass, messageInput, messageOutput);
     }
 
     /**
@@ -66,7 +72,8 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
                                   Object[] parserArgs,
                                   Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocol,
                                   Class<? extends DriverContext> driverContextClass,
-                                  MessageInput<BASE_PACKET_CLASS> messageIoClass,
+                                  MessageInput<BASE_PACKET_CLASS> messageInput,
+                                  MessageOutput<BASE_PACKET_CLASS> messageOutput,
                                   Class<? extends ToIntFunction<ByteBuf>> packetSizeEstimatorClass,
                                   Class<? extends Consumer<ByteBuf>> corruptPacketRemoverClass,
                                   MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler) {
@@ -75,14 +82,15 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         this.parserArgs = parserArgs;
         this.protocolClass = protocol;
         this.driverContextClass = driverContextClass;
-        this.messageIoClass = messageIoClass;
+        this.messageInput = messageInput;
+        this.messageOutput = messageOutput;
         this.packetSizeEstimatorClass = packetSizeEstimatorClass;
         this.corruptPacketRemoverClass = corruptPacketRemoverClass;
         this.encryptionHandler = encryptionHandler;
     }
 
     private ChannelHandler getMessageCodec(Configuration configuration) {
-        return new GeneratedProtocolMessageCodec<>(basePacketClass, messageIoClass, byteOrder, parserArgs,
+        return new GeneratedProtocolMessageCodec<>(basePacketClass, messageInput, messageOutput, byteOrder, parserArgs,
             packetSizeEstimatorClass != null ? configure(configuration, createInstance(packetSizeEstimatorClass)) : null,
             corruptPacketRemoverClass != null ? configure(configuration, createInstance(corruptPacketRemoverClass)) : null);
     }
@@ -126,7 +134,8 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
     public static final class SingleProtocolStackBuilder<BASE_PACKET_CLASS extends Message> {
 
         private final Class<BASE_PACKET_CLASS> basePacketClass;
-        private final MessageInput<BASE_PACKET_CLASS> messageIo;
+        private final MessageInput<BASE_PACKET_CLASS> messageInput;
+        private final MessageOutput<BASE_PACKET_CLASS> messageOutput;
         private Class<? extends DriverContext> driverContextClass;
         private ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
         private Object[] parserArgs;
@@ -135,9 +144,10 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         private Class<? extends Consumer<ByteBuf>> corruptPacketRemover;
         private MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
 
-        public SingleProtocolStackBuilder(Class<BASE_PACKET_CLASS> basePacketClass, MessageInput<BASE_PACKET_CLASS> messageIo) {
+        public SingleProtocolStackBuilder(Class<BASE_PACKET_CLASS> basePacketClass, MessageInput<BASE_PACKET_CLASS> messageInput, MessageOutput<BASE_PACKET_CLASS> messageOutput) {
             this.basePacketClass = basePacketClass;
-            this.messageIo = messageIo;
+            this.messageInput = messageInput;
+            this.messageOutput = messageOutput;
         }
 
         public SingleProtocolStackBuilder<BASE_PACKET_CLASS> withDriverContext(Class<? extends DriverContext> driverContextClass) {
@@ -187,7 +197,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
 
         public SingleProtocolStackConfigurer<BASE_PACKET_CLASS> build() {
             assert this.protocol != null;
-            return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol, driverContextClass, messageIo, packetSizeEstimator, corruptPacketRemover, encryptionHandler);
+            return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol, driverContextClass, messageInput, messageOutput, packetSizeEstimator, corruptPacketRemover, encryptionHandler);
         }
 
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java
index 22c9e70..9629f4c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java
@@ -20,6 +20,6 @@ package org.apache.plc4x.java.spi.generation;
 
 public interface MessageOutput<SERIALIZER_TYPE> {
 
-    void serialize(WriteBuffer io, SERIALIZER_TYPE value, Object... args) throws SerializationException;
+    WriteBufferByteBased serialize(SERIALIZER_TYPE value, Object... args) throws SerializationException;
 
 }
diff --git a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/CANTransport.java b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/CANTransport.java
index 7e89051..529f2c8 100644
--- a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/CANTransport.java
+++ b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/CANTransport.java
@@ -24,7 +24,6 @@ import java.util.function.Function;
 import java.util.function.ToIntFunction;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.generation.Message;
-import org.apache.plc4x.java.spi.generation.MessageIO;
 import org.apache.plc4x.java.spi.generation.MessageInput;
 import org.apache.plc4x.java.spi.transport.Transport;
 
diff --git a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java
index bc86e5e..51deb6c 100644
--- a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java
+++ b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.transport.can;
 
 import org.apache.plc4x.java.spi.generation.Message;
-import org.apache.plc4x.java.spi.generation.MessageIO;
 import org.apache.plc4x.java.spi.generation.MessageInput;
 
 public interface FrameData {
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANFrameBuilder.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANFrameBuilder.java
index a7d24e3..f0e9e2f 100644
--- a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANFrameBuilder.java
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANFrameBuilder.java
@@ -20,10 +20,6 @@ package org.apache.plc4x.java.transport.socketcan;
 
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
-import org.apache.plc4x.java.spi.generation.Message;
-import org.apache.plc4x.java.spi.generation.MessageIO;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 import org.apache.plc4x.java.transport.can.CANFrameBuilder;
 
 public class SocketCANFrameBuilder implements CANFrameBuilder<SocketCANFrame> {
diff --git a/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxManufacturer.cs b/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxManufacturer.cs
index 1deb8d1..706264e 100644
--- a/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxManufacturer.cs
+++ b/plc4net/drivers/knxnetip/src/drivers/knxnetip/readwrite/model/KnxManufacturer.cs
@@ -609,8 +609,9 @@ namespace org.apache.plc4net.drivers.knxnetip.readwrite.model
         M_REMKO_GMBH_AND_CO__KG = 582,
         M_SHENZHEN_CONGXUN_INTELLIGENT_TECHNOLOGY_CO___LTD = 583,
         M_ANDAS = 584,
-        M_ABB___RESERVED = 585,
-        M_BUSCH_JAEGER_ELEKTRO___RESERVED = 586,
+        M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD = 585,
+        M_ABB___RESERVED = 586,
+        M_BUSCH_JAEGER_ELEKTRO___RESERVED = 587,
     }
 
     public static class KnxManufacturerInfo
@@ -2240,10 +2241,13 @@ namespace org.apache.plc4net.drivers.knxnetip.readwrite.model
                 case KnxManufacturer.M_ANDAS: { /* '584' */
                     return 642;
                 }
-                case KnxManufacturer.M_ABB___RESERVED: { /* '585' */
+                case KnxManufacturer.M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD: { /* '585' */
+                    return 643;
+                }
+                case KnxManufacturer.M_ABB___RESERVED: { /* '586' */
                     return 43954;
                 }
-                case KnxManufacturer.M_BUSCH_JAEGER_ELEKTRO___RESERVED: { /* '586' */
+                case KnxManufacturer.M_BUSCH_JAEGER_ELEKTRO___RESERVED: { /* '587' */
                     return 43959;
                 }
                 case KnxManufacturer.M_ELECTRAK: { /* '59' */
@@ -4011,10 +4015,13 @@ namespace org.apache.plc4net.drivers.knxnetip.readwrite.model
                 case KnxManufacturer.M_ANDAS: { /* '584' */
                     return "ANDAS";
                 }
-                case KnxManufacturer.M_ABB___RESERVED: { /* '585' */
+                case KnxManufacturer.M_HEFEI_CHUANG_YUE_INTELLIGENT_TECHNOLOGY_CO__LTD: { /* '585' */
+                    return "Hefei Chuang Yue Intelligent Technology Co.,LTD";
+                }
+                case KnxManufacturer.M_ABB___RESERVED: { /* '586' */
                     return "ABB - reserved";
                 }
-                case KnxManufacturer.M_BUSCH_JAEGER_ELEKTRO___RESERVED: { /* '586' */
+                case KnxManufacturer.M_BUSCH_JAEGER_ELEKTRO___RESERVED: { /* '587' */
                     return "Busch-Jaeger Elektro - reserved";
                 }
                 case KnxManufacturer.M_ELECTRAK: { /* '59' */
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
index 7ee87fc..30fe37e 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
@@ -70,7 +70,8 @@ public class S7ServerModule implements ServerModule {
                     @Override
                     public void initChannel(SocketChannel channel) {
                         ChannelPipeline pipeline = channel.pipeline();
-                        pipeline.addLast(new GeneratedProtocolMessageCodec<>(TPKTPacket.class, TPKTPacket::staticParse, ByteOrder.BIG_ENDIAN, null,
+                        pipeline.addLast(new GeneratedProtocolMessageCodec<>(TPKTPacket.class,
+                            TPKTPacket::staticParse, ByteOrder.BIG_ENDIAN, null,
                             new S7Driver.ByteLengthEstimator(),
                             new S7Driver.CorruptPackageCleaner()));
                         pipeline.addLast(new S7Step7ServerAdapter(context));