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 2026/08/19 20:45:20 UTC

(plc4x) 01/07: feat(plc4j/eip): Detect Connection Manager and Message using "Get Attribute Single" (#2674)

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

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

commit 4b4aea691d8ec10730f6e44c1b5ca2549ce9dbb2
Author: Anderson Vasconcelos Pires <an...@gmail.com>
AuthorDate: Wed Aug 19 12:42:19 2026 -0300

    feat(plc4j/eip):  Detect Connection Manager and Message using "Get Attribute Single"  (#2674)
    
    * feat(plc4j/eip): Implement "Get Attribute Single" on EIP protocol for cases where "Get Attribute All" is not supported by the device.
---
 .../{LogicalSegmentType.java => AttributeID.java}  |  99 ++--
 .../eip/readwrite/GetAttributeSingleRequest.java   |  90 ++-
 .../eip/readwrite/GetAttributeSingleResponse.java  | 112 +++-
 .../java/eip/readwrite/LogicalSegmentType.java     |   2 +
 .../plc4x/java/eip/base/EipTcpConnection.java      |  83 ++-
 .../eip/src/main/resources/protocols/eip/eip.mspec |  15 +-
 .../resources/protocols/eip/DriverTestsuite.xml    | 644 +--------------------
 7 files changed, 348 insertions(+), 697 deletions(-)

diff --git a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/AttributeID.java
similarity index 50%
copy from plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java
copy to plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/AttributeID.java
index 28776467a5..9982e11ecf 100644
--- a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java
+++ b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/AttributeID.java
@@ -25,59 +25,67 @@ import org.apache.plc4x.java.spi.fields.data.reader.DataReaderFactory;
 import org.apache.plc4x.java.spi.fields.data.writer.DataWriterFactory;
 import org.apache.plc4x.java.spi.fields.fields.reader.FieldReaderFactory;
 import org.apache.plc4x.java.spi.fields.fields.writer.FieldWriterFactory;
-import org.apache.plc4x.java.spi.fields.utils.EvaluationHelper;
 import org.apache.plc4x.java.spi.fields.utils.ThreadLocalHelper;
 
 /**
  * Code generated by code-generation. DO NOT EDIT.
  */
-public abstract class LogicalSegmentType implements Message {
-  public LogicalSegmentType() {
+public class AttributeID extends LogicalSegmentType implements Message {
+  protected final byte format;
+
+  protected final short attribute;
+
+  public AttributeID(Byte format, Short attribute) {
+    this.format = format;
+    this.attribute = attribute;
   }
 
   /**
    * Discriminator field logicalSegmentType
    */
-  public abstract byte getLogicalSegmentType();
+  @Override
+  public byte getLogicalSegmentType() {
+    return (byte) 0x04;
+  }
+
+  /**
+   * Property field format
+   */
+  public byte getFormat() {
+    return format;
+  }
 
-  protected abstract void serializeLogicalSegmentTypeChild(WriteBuffer writeBuffer) throws
-      BufferException;
+  /**
+   * Property field attribute
+   */
+  public short getAttribute() {
+    return attribute;
+  }
 
-  public static LogicalSegmentType staticParse(ReadBuffer readBuffer) throws BufferException {
-    readBuffer.pushContext(WithOption.WithName("LogicalSegmentType"));
+  public static LogicalSegmentTypeBuilder staticParseLogicalSegmentTypeBuilder(
+      ReadBuffer readBuffer) throws BufferException {
+    readBuffer.pushContext(WithOption.WithName("AttributeID"));
     int startPos = readBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
-    // Discriminator Field: logicalSegmentType
-    byte logicalSegmentType = FieldReaderFactory.readDiscriminatorField(DataReaderFactory.readUnsignedByte(readBuffer, 3), WithOption.WithName("logicalSegmentType"));
-
-    // Switch Field
-    LogicalSegmentTypeBuilder builder = null;
-    if (EvaluationHelper.equals(logicalSegmentType, (byte) (0x00))) {
-      builder = ClassID.staticParseLogicalSegmentTypeBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(logicalSegmentType, (byte) (0x01))) {
-      builder = InstanceID.staticParseLogicalSegmentTypeBuilder(readBuffer);
-    } else if (EvaluationHelper.equals(logicalSegmentType, (byte) (0x02))) {
-      builder = MemberID.staticParseLogicalSegmentTypeBuilder(readBuffer);
-    }
-    if (builder == null) {
-      throw new BufferException("Unsupported case for discriminated type parameters parameters [logicalSegmentType]");
-    }
+    // Simple Field: format
+    byte format = FieldReaderFactory.readSimpleField(DataReaderFactory.readUnsignedByte(readBuffer, 2), WithOption.WithName("format"));
+
+    // Simple Field: attribute
+    short attribute = FieldReaderFactory.readSimpleField(DataReaderFactory.readUnsignedShort(readBuffer, 8), WithOption.WithName("attribute"));
 
     readBuffer.popContext();
-    return builder.build();
+    return new LogicalSegmentTypeBuilderImpl(format, attribute);
   }
 
-  @Override
-  public void serialize(WriteBuffer writeBuffer) throws BufferException {
-    writeBuffer.pushContext(WithOption.WithName("LogicalSegmentType"));
+  protected void serializeLogicalSegmentTypeChild(WriteBuffer writeBuffer) throws BufferException {
+    writeBuffer.pushContext(WithOption.WithName("AttributeID"));
     int startPos = writeBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
-    byte logicalSegmentType = (byte) getLogicalSegmentType();
-    // Discriminator Field: logicalSegmentType
-    FieldWriterFactory.writeDiscriminatorField((byte) logicalSegmentType, DataWriterFactory.writeUnsignedByte(writeBuffer, 3), WithOption.WithName("logicalSegmentType"));
+    // Simple Field: format
+    FieldWriterFactory.writeSimpleField((byte) format, DataWriterFactory.writeUnsignedByte(writeBuffer, 2), WithOption.WithName("format"));
 
-    // Switch Field
-    serializeLogicalSegmentTypeChild(writeBuffer);
+    // Simple Field: attribute
+    FieldWriterFactory.writeSimpleField((short) attribute, DataWriterFactory.writeUnsignedShort(writeBuffer, 8), WithOption.WithName("attribute"));
 
     writeBuffer.popContext();
   }
@@ -89,19 +97,30 @@ public abstract class LogicalSegmentType implements Message {
 
   @Override
   public int getLengthInBits() {
-    int lengthInBits = 0;
-    LogicalSegmentType _value = this;
+    int lengthInBits = super.getLengthInBits();
+    AttributeID _value = this;
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
-    // Discriminator Field: logicalSegmentType
-    lengthInBits += 3;
+    // Simple Field: format
+    lengthInBits += 2;
 
-    // Switch Field
-    // (the subtype will instead add the actual length of subtype elements)
+    // Simple Field: attribute
+    lengthInBits += 8;
 
     return lengthInBits;
   }
 
-  public interface LogicalSegmentTypeBuilder {
-    LogicalSegmentType build();
+  public static class LogicalSegmentTypeBuilderImpl implements LogicalSegmentType.LogicalSegmentTypeBuilder {
+    private final byte format;
+
+    private final short attribute;
+
+    public LogicalSegmentTypeBuilderImpl(byte format, short attribute) {
+      this.format = format;
+      this.attribute = attribute;
+    }
+
+    public LogicalSegmentType build() {
+      return new AttributeID(format, attribute);
+    }
   }
 }
diff --git a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleRequest.java b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleRequest.java
index a14814da0a..efea7404ff 100644
--- a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleRequest.java
+++ b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleRequest.java
@@ -21,13 +21,27 @@ import org.apache.plc4x.java.spi.buffers.api.ReadBuffer;
 import org.apache.plc4x.java.spi.buffers.api.WithOption;
 import org.apache.plc4x.java.spi.buffers.api.WriteBuffer;
 import org.apache.plc4x.java.spi.buffers.api.exceptions.BufferException;
+import org.apache.plc4x.java.spi.fields.data.reader.DataReaderFactory;
+import org.apache.plc4x.java.spi.fields.data.writer.DataWriterFactory;
+import org.apache.plc4x.java.spi.fields.fields.reader.FieldReaderFactory;
+import org.apache.plc4x.java.spi.fields.fields.writer.FieldWriterFactory;
 import org.apache.plc4x.java.spi.fields.utils.ThreadLocalHelper;
 
 /**
  * Code generated by code-generation. DO NOT EDIT.
  */
 public class GetAttributeSingleRequest extends CipService implements Message {
-  public GetAttributeSingleRequest() {
+  protected final PathSegment classSegment;
+
+  protected final PathSegment instanceSegment;
+
+  protected final PathSegment attributeSegment;
+
+  public GetAttributeSingleRequest(PathSegment classSegment, PathSegment instanceSegment,
+      PathSegment attributeSegment) {
+    this.classSegment = classSegment;
+    this.instanceSegment = instanceSegment;
+    this.attributeSegment = attributeSegment;
   }
 
   /**
@@ -54,19 +68,65 @@ public class GetAttributeSingleRequest extends CipService implements Message {
     return false;
   }
 
+  /**
+   * Property field classSegment
+   */
+  public PathSegment getClassSegment() {
+    return classSegment;
+  }
+
+  /**
+   * Property field instanceSegment
+   */
+  public PathSegment getInstanceSegment() {
+    return instanceSegment;
+  }
+
+  /**
+   * Property field attributeSegment
+   */
+  public PathSegment getAttributeSegment() {
+    return attributeSegment;
+  }
+
   public static CipServiceBuilder staticParseCipServiceBuilder(ReadBuffer readBuffer,
       boolean connected, int serviceLen) throws BufferException {
     readBuffer.pushContext(WithOption.WithName("GetAttributeSingleRequest"));
     int startPos = readBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Implicit Field: requestPathSize
+    short requestPathSize = FieldReaderFactory.readImplicitField(DataReaderFactory.readUnsignedShort(readBuffer, 8), WithOption.WithName("requestPathSize"));
+
+    // Simple Field: classSegment
+    PathSegment classSegment = FieldReaderFactory.readSimpleField(DataReaderFactory.readComplex(() -> (PathSegment) PathSegment.staticParse(readBuffer), readBuffer), WithOption.WithName("classSegment"));
+
+    // Simple Field: instanceSegment
+    PathSegment instanceSegment = FieldReaderFactory.readSimpleField(DataReaderFactory.readComplex(() -> (PathSegment) PathSegment.staticParse(readBuffer), readBuffer), WithOption.WithName("instanceSegment"));
+
+    // Simple Field: attributeSegment
+    PathSegment attributeSegment = FieldReaderFactory.readSimpleField(DataReaderFactory.readComplex(() -> (PathSegment) PathSegment.staticParse(readBuffer), readBuffer), WithOption.WithName("attributeSegment"));
+
     readBuffer.popContext();
-    return new CipServiceBuilderImpl();
+    return new CipServiceBuilderImpl(classSegment, instanceSegment, attributeSegment);
   }
 
   protected void serializeCipServiceChild(WriteBuffer writeBuffer) throws BufferException {
     writeBuffer.pushContext(WithOption.WithName("GetAttributeSingleRequest"));
     int startPos = writeBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Implicit Field: requestPathSize
+    short requestPathSize = (short) (((((classSegment.getLengthInBytes()) + (instanceSegment.getLengthInBytes())) + (attributeSegment.getLengthInBytes()))) / (2));
+    FieldWriterFactory.writeImplicitField((short) requestPathSize, DataWriterFactory.writeUnsignedShort(writeBuffer, 8), WithOption.WithName("requestPathSize"));
+
+    // Simple Field: classSegment
+    FieldWriterFactory.writeSimpleField((PathSegment) classSegment, DataWriterFactory.writeComplex(writeBuffer), WithOption.WithName("classSegment"));
+
+    // Simple Field: instanceSegment
+    FieldWriterFactory.writeSimpleField((PathSegment) instanceSegment, DataWriterFactory.writeComplex(writeBuffer), WithOption.WithName("instanceSegment"));
+
+    // Simple Field: attributeSegment
+    FieldWriterFactory.writeSimpleField((PathSegment) attributeSegment, DataWriterFactory.writeComplex(writeBuffer), WithOption.WithName("attributeSegment"));
+
     writeBuffer.popContext();
   }
 
@@ -80,15 +140,37 @@ public class GetAttributeSingleRequest extends CipService implements Message {
     int lengthInBits = super.getLengthInBits();
     GetAttributeSingleRequest _value = this;
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Implicit Field: requestPathSize
+    lengthInBits += 8;
+
+    // Simple Field: classSegment
+    lengthInBits += classSegment.getLengthInBits();
+
+    // Simple Field: instanceSegment
+    lengthInBits += instanceSegment.getLengthInBits();
+
+    // Simple Field: attributeSegment
+    lengthInBits += attributeSegment.getLengthInBits();
+
     return lengthInBits;
   }
 
   public static class CipServiceBuilderImpl implements CipService.CipServiceBuilder {
-    public CipServiceBuilderImpl() {
+    private final PathSegment classSegment;
+
+    private final PathSegment instanceSegment;
+
+    private final PathSegment attributeSegment;
+
+    public CipServiceBuilderImpl(PathSegment classSegment, PathSegment instanceSegment,
+        PathSegment attributeSegment) {
+      this.classSegment = classSegment;
+      this.instanceSegment = instanceSegment;
+      this.attributeSegment = attributeSegment;
     }
 
     public CipService build() {
-      return new GetAttributeSingleRequest();
+      return new GetAttributeSingleRequest(classSegment, instanceSegment, attributeSegment);
     }
   }
 }
diff --git a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleResponse.java b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleResponse.java
index 2e06093730..e96143e065 100644
--- a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleResponse.java
+++ b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/GetAttributeSingleResponse.java
@@ -16,18 +16,36 @@
 // under the License.
 package org.apache.plc4x.java.eip.readwrite;
 
+import java.util.List;
 import org.apache.plc4x.java.spi.buffers.api.Message;
 import org.apache.plc4x.java.spi.buffers.api.ReadBuffer;
 import org.apache.plc4x.java.spi.buffers.api.WithOption;
 import org.apache.plc4x.java.spi.buffers.api.WriteBuffer;
 import org.apache.plc4x.java.spi.buffers.api.exceptions.BufferException;
+import org.apache.plc4x.java.spi.fields.data.reader.DataReaderFactory;
+import org.apache.plc4x.java.spi.fields.data.writer.DataWriterFactory;
+import org.apache.plc4x.java.spi.fields.fields.reader.FieldReaderFactory;
+import org.apache.plc4x.java.spi.fields.fields.writer.FieldWriterFactory;
 import org.apache.plc4x.java.spi.fields.utils.ThreadLocalHelper;
 
 /**
  * Code generated by code-generation. DO NOT EDIT.
  */
 public class GetAttributeSingleResponse extends CipService implements Message {
-  public GetAttributeSingleResponse() {
+  protected final short status;
+
+  protected final short extStatusSize;
+
+  protected final List<Integer> extStatus;
+
+  protected final byte[] servicesData;
+
+  public GetAttributeSingleResponse(Short status, Short extStatusSize, List<Integer> extStatus,
+      byte[] servicesData) {
+    this.status = status;
+    this.extStatusSize = extStatusSize;
+    this.extStatus = extStatus;
+    this.servicesData = servicesData;
   }
 
   /**
@@ -54,19 +72,77 @@ public class GetAttributeSingleResponse extends CipService implements Message {
     return false;
   }
 
+  /**
+   * Property field status
+   */
+  public short getStatus() {
+    return status;
+  }
+
+  /**
+   * Property field extStatusSize
+   */
+  public short getExtStatusSize() {
+    return extStatusSize;
+  }
+
+  /**
+   * Property field extStatus
+   */
+  public List<Integer> getExtStatus() {
+    return extStatus;
+  }
+
+  /**
+   * Property field servicesData
+   */
+  public byte[] getServicesData() {
+    return servicesData;
+  }
+
   public static CipServiceBuilder staticParseCipServiceBuilder(ReadBuffer readBuffer,
       boolean connected, int serviceLen) throws BufferException {
     readBuffer.pushContext(WithOption.WithName("GetAttributeSingleResponse"));
     int startPos = readBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Reserved Field
+    FieldReaderFactory.readReservedField(DataReaderFactory.readUnsignedShort(readBuffer, 8), (short) 0x00, WithOption.WithName("GetAttributeSingleResponse.reserved0"));
+
+    // Simple Field: status
+    short status = FieldReaderFactory.readSimpleField(DataReaderFactory.readUnsignedShort(readBuffer, 8), WithOption.WithName("status"));
+
+    // Simple Field: extStatusSize
+    short extStatusSize = FieldReaderFactory.readSimpleField(DataReaderFactory.readUnsignedShort(readBuffer, 8), WithOption.WithName("extStatusSize"));
+
+    // Array Field: extStatus
+    List<Integer> extStatus = FieldReaderFactory.readCountArrayField(DataReaderFactory.readUnsignedInt(readBuffer, 16), extStatusSize, WithOption.WithName("extStatus"));
+
+    // Array Field: servicesData
+    byte[] servicesData = readBuffer.readBits(Math.toIntExact((((serviceLen) - (4)) - ((2) * (extStatusSize))) * 8), WithOption.WithName("servicesData"));
+
     readBuffer.popContext();
-    return new CipServiceBuilderImpl();
+    return new CipServiceBuilderImpl(status, extStatusSize, extStatus, servicesData);
   }
 
   protected void serializeCipServiceChild(WriteBuffer writeBuffer) throws BufferException {
     writeBuffer.pushContext(WithOption.WithName("GetAttributeSingleResponse"));
     int startPos = writeBuffer.getPositionInBits();
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Reserved Field
+    FieldWriterFactory.writeReservedField((short) 0x00, DataWriterFactory.writeUnsignedShort(writeBuffer, 8));
+
+    // Simple Field: status
+    FieldWriterFactory.writeSimpleField((short) status, DataWriterFactory.writeUnsignedShort(writeBuffer, 8), WithOption.WithName("status"));
+
+    // Simple Field: extStatusSize
+    FieldWriterFactory.writeSimpleField((short) extStatusSize, DataWriterFactory.writeUnsignedShort(writeBuffer, 8), WithOption.WithName("extStatusSize"));
+
+    // Array Field: extStatus
+    FieldWriterFactory.writeSimpleTypeArrayField(extStatus, DataWriterFactory.writeUnsignedInt(writeBuffer, 16), WithOption.WithName("extStatus"));
+
+    // Array Field: servicesData
+    FieldWriterFactory.writeByteArrayField(servicesData, DataWriterFactory.writeByteArray(writeBuffer, (int) ((servicesData != null) ? servicesData.length : 0)), WithOption.WithName("servicesData"));
+
     writeBuffer.popContext();
   }
 
@@ -80,15 +156,43 @@ public class GetAttributeSingleResponse extends CipService implements Message {
     int lengthInBits = super.getLengthInBits();
     GetAttributeSingleResponse _value = this;
     boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+    // Reserved Field
+    lengthInBits += 8;
+
+    // Simple Field: status
+    lengthInBits += 8;
+
+    // Simple Field: extStatusSize
+    lengthInBits += 8;
+
+    // Array Field: extStatus
+    lengthInBits += 16 * extStatus.size();
+
+    // Array Field: servicesData
+    lengthInBits += 8 * ((servicesData != null) ? servicesData.length : 0);
+
     return lengthInBits;
   }
 
   public static class CipServiceBuilderImpl implements CipService.CipServiceBuilder {
-    public CipServiceBuilderImpl() {
+    private final short status;
+
+    private final short extStatusSize;
+
+    private final List<Integer> extStatus;
+
+    private final byte[] servicesData;
+
+    public CipServiceBuilderImpl(short status, short extStatusSize, List<Integer> extStatus,
+        byte[] servicesData) {
+      this.status = status;
+      this.extStatusSize = extStatusSize;
+      this.extStatus = extStatus;
+      this.servicesData = servicesData;
     }
 
     public CipService build() {
-      return new GetAttributeSingleResponse();
+      return new GetAttributeSingleResponse(status, extStatusSize, extStatus, servicesData);
     }
   }
 }
diff --git a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java
index 28776467a5..a02ac13ea8 100644
--- a/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java
+++ b/plc4j/drivers/eip/src/main/generated/org/apache/plc4x/java/eip/readwrite/LogicalSegmentType.java
@@ -58,6 +58,8 @@ public abstract class LogicalSegmentType implements Message {
       builder = InstanceID.staticParseLogicalSegmentTypeBuilder(readBuffer);
     } else if (EvaluationHelper.equals(logicalSegmentType, (byte) (0x02))) {
       builder = MemberID.staticParseLogicalSegmentTypeBuilder(readBuffer);
+    } else if (EvaluationHelper.equals(logicalSegmentType, (byte) (0x04))) {
+      builder = AttributeID.staticParseLogicalSegmentTypeBuilder(readBuffer);
     }
     if (builder == null) {
       throw new BufferException("Unsupported case for discriminated type parameters parameters [logicalSegmentType]");
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EipTcpConnection.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EipTcpConnection.java
index 629f6dfda6..ed3525af2e 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EipTcpConnection.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EipTcpConnection.java
@@ -220,7 +220,7 @@ public class EipTcpConnection extends PollingSubscriptionConnectionBase<EIPConfi
             this.sessionHandle = sessionResponse.getSessionHandle();
             LOGGER.debug("Got assigned with Session handle {}", sessionHandle);
 
-            // 3) GetAttributeAll on the message router to probe capabilities.
+            // 3) Probe connection-manager and message-router capabilities.
             //    Skipped when the user has already committed to the unconnected
             //    path — the probe is only useful for choosing between the
             //    connection-manager and message-router code paths, and some
@@ -229,7 +229,7 @@ public class EipTcpConnection extends PollingSubscriptionConnectionBase<EIPConfi
             if (getConfiguration().isForceUnconnectedOperation()) {
                 return CompletableFuture.completedFuture(null);
             }
-            return probeAttributes().thenCompose(v -> {
+            return probeClassObjectSupport().thenCompose(v -> {
                 if (useConnectionManager) {
                     return openConnectionManager();
                 }
@@ -238,8 +238,9 @@ public class EipTcpConnection extends PollingSubscriptionConnectionBase<EIPConfi
         });
     }
 
-    private CompletableFuture<Void> probeAttributes() {
-        PathSegment classSegment = new LogicalSegment(new ClassID((byte) 0, (short) 2));
+    // Using this method to continue having the GetAttributeAll that can be useful in the future
+    private CompletableFuture<Void> checkClassObjectAttributes(CIPClassID classId) {
+        PathSegment classSegment = new LogicalSegment(new ClassID((byte) 0, (short) classId.getValue()));
         PathSegment instanceSegment = new LogicalSegment(new InstanceID((byte) 0, (short) 1));
         UnConnectedDataItem exchange = new UnConnectedDataItem(
             new GetAttributeAllRequest(classSegment, instanceSegment));
@@ -248,40 +249,68 @@ public class EipTcpConnection extends PollingSubscriptionConnectionBase<EIPConfi
             DEFAULT_SENDER_CONTEXT, 0L, EMPTY_INTERFACE_HANDLE, 0, typeIds);
 
         return sendRequest(eipWrapper).thenAccept(response -> {
-            if (!(response instanceof CipRRData rr) || rr.getStatus() != CIPStatus.Success.getValue()) {
-                return;
-            }
-            UnConnectedDataItem dataItem = (UnConnectedDataItem) rr.getTypeIds().get(1);
-            if (!(dataItem.getService() instanceof GetAttributeAllResponse gar)) {
-                return;
-            }
-            if (gar.getStatus() == CIPStatus.ServiceNotSupported.getValue()) {
-                return;
-            }
-            if (gar.getAttributes() != null) {
-                for (Integer classId : gar.getAttributes().getClassId()) {
-                    if (CIPClassID.enumForValue(classId) == CIPClassID.MessageRouter) {
-                        this.useMessageRouter = true;
-                    }
-                    if (CIPClassID.enumForValue(classId) == CIPClassID.ConnectionManager) {
-                        this.useConnectionManager = true;
-                    }
-                }
+
+            if (extractCipService(response) instanceof GetAttributeAllResponse gar &&
+                gar.getStatus() == CIPStatus.Success.getValue() &&
+                gar.getAttributes() != null) {
+                LOGGER.debug("Identity getNumberActive {}", gar.getAttributes().getNumberActive());
             }
+        });
+    }
+
+    private CipService extractCipService(EipPacket response) {
+        if (response instanceof CipRRData rr
+            && rr.getStatus() == CIPStatus.Success.getValue()
+            && rr.getTypeIds().size() > 1
+            && rr.getTypeIds().get(1) instanceof UnConnectedDataItem di) {
+            return di.getService();
+        }
+        return null;
+    }
+
+    private CompletableFuture<Void> probeClassObjectSupport() {
+
+        return checkClassObjectSupport(CIPClassID.ConnectionManager).thenCompose(hasSupport -> {
+            useConnectionManager = hasSupport;
+            return checkClassObjectSupport(CIPClassID.MessageRouter);
+        }).thenCompose(hasSupport -> {
+            useMessageRouter = hasSupport;
+            return checkClassObjectAttributes(CIPClassID.Identity);
         }).exceptionally(e -> {
             // Treat any probe failure (timeout, parse error, malformed response,
-            // ServiceNotSupported) as "device has no message router / connection
-            // manager" and fall through to the unconnected code path. This keeps
+            // ServiceNotSupported) as the state that was achieved. This keeps
             // the handshake working against non-Logix devices and simulators.
-            LOGGER.debug("GetAttributeAll probe failed, falling back to unconnected mode", e);
+            LOGGER.debug("probeClassObjectSupport probe failed, keeping the state achieved", e);
             return null;
         });
     }
 
+    private CompletableFuture<Boolean> checkClassObjectSupport(CIPClassID classId) {
+
+        UnConnectedDataItem exchange = new UnConnectedDataItem(new GetAttributeSingleRequest(
+            new LogicalSegment(new ClassID((byte) 0, (short) classId.getValue())),
+            new LogicalSegment(new InstanceID((byte) 0, (short) 0)), // Class level discovery
+            new LogicalSegment(new AttributeID((byte) 0, (short) 1))) // Attribute ID 1: Revision
+        );
+        List<TypeId> typeIds = Arrays.asList(nullAddressItem, exchange);
+        CipRRData eipWrapper = new CipRRData(sessionHandle, CIPStatus.Success.getValue(),
+            DEFAULT_SENDER_CONTEXT, 0L, EMPTY_INTERFACE_HANDLE, 0, typeIds);
+
+        return sendRequest(eipWrapper).thenCompose(response -> {
+
+            if (extractCipService(response) instanceof GetAttributeSingleResponse gsr) {
+                boolean hasSupport = gsr.getStatus() == CIPStatus.Success.getValue();
+                LOGGER.debug("ClassId: {} status: {} hasSupport: {}", classId, gsr.getStatus(), hasSupport);
+                return CompletableFuture.completedFuture(hasSupport);
+            }
+            return CompletableFuture.completedFuture(false);
+        });
+    }
+
     private CompletableFuture<Void> openConnectionManager() {
         UnConnectedDataItem exchange = new UnConnectedDataItem(
             new CipConnectionManagerRequest(
-                new LogicalSegment(new ClassID((byte) 0, (short) 6)),
+                new LogicalSegment(new ClassID((byte) 0, (short) CIPClassID.ConnectionManager.getValue())),
                 new LogicalSegment(new InstanceID((byte) 0, (short) 1)),
                 (byte) 0, (byte) 10, (short) 14, 536870914L, 33944L,
                 this.connectionSerialNumber, 4919, 42L, (short) 3, 2101812L,
diff --git a/protocols/eip/src/main/resources/protocols/eip/eip.mspec b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
index e7e2957e7c..e0c79089d1 100644
--- a/protocols/eip/src/main/resources/protocols/eip/eip.mspec
+++ b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
@@ -157,10 +157,17 @@
             [array      byte   servicesData count 'serviceLen - 6 - (2 * serviceNb)'                                   ]
         ]
         ['0x0E','false' GetAttributeSingleRequest
-            // TODO: Implement
+            [implicit   uint    8           requestPathSize '(classSegment.lengthInBytes + instanceSegment.lengthInBytes + attributeSegment.lengthInBytes)/2']
+            [simple     PathSegment         classSegment                                                               ]
+            [simple     PathSegment         instanceSegment                                                            ]
+            [simple     PathSegment         attributeSegment                                                           ]
         ]
         ['0x0E','true'  GetAttributeSingleResponse
-            // TODO: Implement
+            [reserved   uint    8           '0x00'                                                                     ]
+            [simple     uint    8           status                                                                     ]
+            [simple     uint    8           extStatusSize                                                              ]
+            [array      uint    16          extStatus count 'extStatusSize'                                            ]
+            [array      byte   servicesData count 'serviceLen - 4 - 2 * extStatusSize'                                 ]
         ]
         ['0x10','false' SetAttributeSingleRequest
             // TODO: Implement
@@ -358,6 +365,10 @@
             [simple uint    2   format]
             [simple uint    8   instance]
         ]
+        ['0x04' AttributeID
+            [simple uint 2 format]
+            [simple uint 8 attribute]
+        ]
     ]
 ]
 
diff --git a/protocols/eip/src/test/resources/protocols/eip/DriverTestsuite.xml b/protocols/eip/src/test/resources/protocols/eip/DriverTestsuite.xml
index 1b5d94cdba..20c5f68f71 100644
--- a/protocols/eip/src/test/resources/protocols/eip/DriverTestsuite.xml
+++ b/protocols/eip/src/test/resources/protocols/eip/DriverTestsuite.xml
@@ -428,379 +428,15 @@
   </testcase>
 
   <testcase>
-    <name>Two element read request</name>
+    <name>Get Attribute Single Request</name>
     <steps>
-      <api-request name="Receive Read Request from application">
-        <TestReadRequest>
-          <tags isList="true">
-            <tag className="org.apache.plc4x.test.driver.internal.api.TestTag">
-              <name>hurz1</name>
-              <address>%rate</address>
-            </tag>
-            <tag className="org.apache.plc4x.test.driver.internal.api.TestTag">
-              <name>hurz2</name>
-              <address>%count</address>
-            </tag>
-          </tags>
-        </TestReadRequest>
-      </api-request>
-      <outgoing-plc-message name="Send CipReadRequest to PLC">
-        <parser-arguments>
-          <response>false</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">40</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">24</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">false</response>
-                      <service dataType="uint" bitLength="7">82</service>
-                      <CipUnconnectedRequest>
-                        <requestPathSize dataType="uint" bitLength="8">2</requestPathSize>
-                        <classSegment>
-                          <PathSegment>
-                            <pathSegment dataType="uint" bitLength="3">1</pathSegment>
-                            <LogicalSegment>
-                              <segmentType>
-                                <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">0</logicalSegmentType>
-                                  <ClassID>
-                                    <format dataType="uint" bitLength="2">0</format>
-                                    <segmentClass dataType="uint" bitLength="8">6</segmentClass>
-                                  </ClassID>
-                                </LogicalSegmentType>
-                              </segmentType>
-                            </LogicalSegment>
-                          </PathSegment>
-                        </classSegment>
-                        <instanceSegment>
-                          <PathSegment>
-                            <pathSegment dataType="uint" bitLength="3">1</pathSegment>
-                            <LogicalSegment>
-                              <segmentType>
-                                <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">1</logicalSegmentType>
-                                  <InstanceID>
-                                    <format dataType="uint" bitLength="2">0</format>
-                                    <instance dataType="uint" bitLength="8">1</instance>
-                                  </InstanceID>
-                                </LogicalSegmentType>
-                              </segmentType>
-                            </LogicalSegment>
-                          </PathSegment>
-                        </instanceSegment>
-                        <reserved dataType="uint" bitLength="16">40197</reserved>
-                        <messageSize dataType="uint" bitLength="16">10</messageSize>
-                        <unconnectedService>
-                          <CipService>
-                            <response dataType="bit" bitLength="1">false</response>
-                            <service dataType="uint" bitLength="7">76</service>
-                            <CipReadRequest>
-                              <requestPathSize dataType="uint" bitLength="8">3</requestPathSize>
-                              <tag dataType="byte" bitLength="48">0x910472617465</tag>
-                              <elementNb dataType="uint" bitLength="16">1</elementNb>
-                            </CipReadRequest>
-                          </CipService>
-                        </unconnectedService>
-                        <route dataType="uint" bitLength="16">1</route>
-                        <backPlane dataType="int" bitLength="8">1</backPlane>
-                        <slot dataType="int" bitLength="8">0</slot>
-                      </CipUnconnectedRequest>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </outgoing-plc-message>
-      <incoming-plc-message name="Get CipReadResponse from PLC">
-        <parser-arguments>
-          <response>true</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">36</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">10</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">true</response>
-                      <service dataType="uint" bitLength="7">76</service>
-                      <CipReadResponse>
-                        <reserved dataType="uint" bitLength="8">0</reserved>
-                        <status dataType="uint" bitLength="8">0</status>
-                        <extStatus dataType="uint" bitLength="8">0</extStatus>
-                        <data>
-                          <CIPData>
-                            <dataType>
-                              <CIPDataTypeCode dataType="uint" bitLength="16" stringRepresentation="DINT">196
-                              </CIPDataTypeCode>
-                            </dataType>
-                            <data dataType="byte" bitLength="32">0x00000216</data>
-                          </CIPData>
-                        </data>
-                      </CipReadResponse>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </incoming-plc-message>
-      <outgoing-plc-message name="Send CipReadRequest to PLC">
-        <parser-arguments>
-          <response>false</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">42</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">26</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">false</response>
-                      <service dataType="uint" bitLength="7">82</service>
-                      <CipUnconnectedRequest>
-                        <requestPathSize dataType="uint" bitLength="8">2</requestPathSize>
-                        <classSegment>
-                          <PathSegment>
-                            <pathSegment dataType="uint" bitLength="3">1</pathSegment>
-                            <LogicalSegment>
-                              <segmentType>
-                                <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">0</logicalSegmentType>
-                                  <ClassID>
-                                    <format dataType="uint" bitLength="2">0</format>
-                                    <segmentClass dataType="uint" bitLength="8">6</segmentClass>
-                                  </ClassID>
-                                </LogicalSegmentType>
-                              </segmentType>
-                            </LogicalSegment>
-                          </PathSegment>
-                        </classSegment>
-                        <instanceSegment>
-                          <PathSegment>
-                            <pathSegment dataType="uint" bitLength="3">1</pathSegment>
-                            <LogicalSegment>
-                              <segmentType>
-                                <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">1</logicalSegmentType>
-                                  <InstanceID>
-                                    <format dataType="uint" bitLength="2">0</format>
-                                    <instance dataType="uint" bitLength="8">1</instance>
-                                  </InstanceID>
-                                </LogicalSegmentType>
-                              </segmentType>
-                            </LogicalSegment>
-                          </PathSegment>
-                        </instanceSegment>
-                        <reserved dataType="uint" bitLength="16">40197</reserved>
-                        <messageSize dataType="uint" bitLength="16">12</messageSize>
-                        <unconnectedService>
-                          <CipService>
-                            <response dataType="bit" bitLength="1">false</response>
-                            <service dataType="uint" bitLength="7">76</service>
-                            <CipReadRequest>
-                              <requestPathSize dataType="uint" bitLength="8">4</requestPathSize>
-                              <tag dataType="byte" bitLength="64">0x9105636f756e7400</tag>
-                              <elementNb dataType="uint" bitLength="16">1</elementNb>
-                            </CipReadRequest>
-                          </CipService>
-                        </unconnectedService>
-                        <route dataType="uint" bitLength="16">1</route>
-                        <backPlane dataType="int" bitLength="8">1</backPlane>
-                        <slot dataType="int" bitLength="8">0</slot>
-                      </CipUnconnectedRequest>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </outgoing-plc-message>
-      <incoming-plc-message name="Get CipReadResponse from PLC">
-        <parser-arguments>
-          <response>true</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">36</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">10</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">true</response>
-                      <service dataType="uint" bitLength="7">76</service>
-                      <CipReadResponse>
-                        <reserved dataType="uint" bitLength="8">0</reserved>
-                        <status dataType="uint" bitLength="8">0</status>
-                        <extStatus dataType="uint" bitLength="8">0</extStatus>
-                        <data>
-                          <CIPData>
-                            <dataType>
-                              <CIPDataTypeCode dataType="uint" bitLength="16" stringRepresentation="DINT">196
-                              </CIPDataTypeCode>
-                            </dataType>
-                            <data dataType="byte" bitLength="32">0x2a000000</data>
-                          </CIPData>
-                        </data>
-                      </CipReadResponse>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </incoming-plc-message>
-      <api-response name="Report Read Response to application">
-        <PlcReadResponse>
-          <request>
-            <PlcReadRequest>
-              <PlcTagRequest>
-                <tags isList="true">
-                  <hurz1>
-                    <PlcTagItem>
-                      <tag>
-                        <EipTag>
-                          <node dataType="string" bitLength="32" encoding="UTF8">rate</node>
-                          <type dataType="string" bitLength="32" encoding="UTF8">DINT</type>
-                          <elementNb dataType="uint" bitLength="16">1</elementNb>
-                        </EipTag>
-                      </tag>
-                    </PlcTagItem>
-                  </hurz1>
-                  <hurz2>
-                    <PlcTagItem>
-                      <tag>
-                        <EipTag>
-                          <node dataType="string" bitLength="40" encoding="UTF8">count</node>
-                          <type dataType="string" bitLength="32" encoding="UTF8">DINT</type>
-                          <elementNb dataType="uint" bitLength="16">1</elementNb>
-                        </EipTag>
-                      </tag>
-                    </PlcTagItem>
-                  </hurz2>
-                </tags>
-              </PlcTagRequest>
-            </PlcReadRequest>
-          </request>
-          <values isList="true">
-            <hurz1>
-              <PlcResponseItem>
-                <code dataType="string" bitLength="16" encoding="UTF-8">OK</code>
-                <value>
-                  <PlcDINT dataType="int" bitLength="32">369229824</PlcDINT>
-                </value>
-              </PlcResponseItem>
-            </hurz1>
-            <hurz2>
-              <PlcResponseItem>
-                <code dataType="string" bitLength="16" encoding="UTF-8">OK</code>
-                <value>
-                  <PlcDINT dataType="int" bitLength="32">42</PlcDINT>
-                </value>
-              </PlcResponseItem>
-            </hurz2>
-          </values>
-        </PlcReadResponse>
-      </api-response>
-    </steps>
-  </testcase>
-
-  <testcase>
-    <name>Array read request</name>
-    <steps>
-      <api-request name="Receive Read Request from application">
-        <TestReadRequest>
-          <tags isList="true">
-            <tag className="org.apache.plc4x.test.driver.internal.api.TestTag">
-              <name>hurz</name>
-              <address>%rate:DINT:4</address>
-            </tag>
-          </tags>
-        </TestReadRequest>
-      </api-request>
-      <outgoing-plc-message name="Send CipReadRequest to PLC">
+      <outgoing-plc-message name="Send GetAttributeSingleRequest">
         <parser-arguments>
           <response>false</response>
         </parser-arguments>
         <EipPacket>
           <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">40</packetLength>
+          <packetLength dataType="uint" bitLength="16">22</packetLength>
           <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
           <status dataType="uint" bitLength="32">0</status>
           <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
@@ -819,13 +455,13 @@
               <TypeId>
                 <id dataType="uint" bitLength="16">178</id>
                 <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">24</packetSize>
+                  <packetSize dataType="uint" bitLength="16">8</packetSize>
                   <service>
                     <CipService>
                       <response dataType="bit" bitLength="1">false</response>
-                      <service dataType="uint" bitLength="7">82</service>
-                      <CipUnconnectedRequest>
-                        <requestPathSize dataType="uint" bitLength="8">2</requestPathSize>
+                      <service dataType="uint" bitLength="7">14</service>
+                      <GetAttributeSingleRequest>
+                        <requestPathSize dataType="uint" bitLength="8">3</requestPathSize>
                         <classSegment>
                           <PathSegment>
                             <pathSegment dataType="uint" bitLength="3">1</pathSegment>
@@ -835,7 +471,7 @@
                                   <logicalSegmentType dataType="uint" bitLength="3">0</logicalSegmentType>
                                   <ClassID>
                                     <format dataType="uint" bitLength="2">0</format>
-                                    <segmentClass dataType="uint" bitLength="8">6</segmentClass>
+                                    <segmentClass dataType="uint" bitLength="8">1</segmentClass>
                                   </ClassID>
                                 </LogicalSegmentType>
                               </segmentType>
@@ -858,224 +494,23 @@
                             </LogicalSegment>
                           </PathSegment>
                         </instanceSegment>
-                        <reserved dataType="uint" bitLength="16">40197</reserved>
-                        <messageSize dataType="uint" bitLength="16">10</messageSize>
-                        <unconnectedService>
-                          <CipService>
-                            <response dataType="bit" bitLength="1">false</response>
-                            <service dataType="uint" bitLength="7">76</service>
-                            <CipReadRequest>
-                              <requestPathSize dataType="uint" bitLength="8">3</requestPathSize>
-                              <tag dataType="byte" bitLength="48">0x910472617465</tag>
-                              <elementNb dataType="uint" bitLength="16">4</elementNb>
-                            </CipReadRequest>
-                          </CipService>
-                        </unconnectedService>
-                        <route dataType="uint" bitLength="16">1</route>
-                        <backPlane dataType="int" bitLength="8">1</backPlane>
-                        <slot dataType="int" bitLength="8">0</slot>
-                      </CipUnconnectedRequest>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </outgoing-plc-message>
-      <incoming-plc-message name="Get CipReadResponse from PLC">
-        <parser-arguments>
-          <response>true</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">48</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">22</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">true</response>
-                      <service dataType="uint" bitLength="7">76</service>
-                      <CipReadResponse>
-                        <reserved dataType="uint" bitLength="8">0</reserved>
-                        <status dataType="uint" bitLength="8">0</status>
-                        <extStatus dataType="uint" bitLength="8">0</extStatus>
-                        <data>
-                          <CIPData>
-                            <dataType>
-                              <CIPDataTypeCode dataType="uint" bitLength="16" stringRepresentation="DINT">196
-                              </CIPDataTypeCode>
-                            </dataType>
-                            <data dataType="byte" bitLength="128">0x01000000020000000300000004000000</data>
-                          </CIPData>
-                        </data>
-                      </CipReadResponse>
-                    </CipService>
-                  </service>
-                </UnConnectedDataItem>
-              </TypeId>
-            </typeIds>
-          </CipRRData>
-        </EipPacket>
-      </incoming-plc-message>
-      <api-response name="Report Read Response to application">
-        <PlcReadResponse>
-          <request>
-            <PlcReadRequest>
-              <PlcTagRequest>
-                <tags isList="true">
-                  <hurz>
-                    <PlcTagItem>
-                      <tag>
-                        <EipTag>
-                          <node dataType="string" bitLength="32" encoding="UTF8">rate</node>
-                          <type dataType="string" bitLength="32" encoding="UTF8">DINT</type>
-                          <elementNb dataType="uint" bitLength="16">4</elementNb>
-                        </EipTag>
-                      </tag>
-                    </PlcTagItem>
-                  </hurz>
-                </tags>
-              </PlcTagRequest>
-            </PlcReadRequest>
-          </request>
-          <values isList="true">
-            <hurz>
-              <PlcResponseItem>
-                <code dataType="string" bitLength="16" encoding="UTF-8">OK</code>
-                <value>
-                  <PlcList>
-                    <PlcDINT dataType="int" bitLength="32">1</PlcDINT>
-                    <PlcDINT dataType="int" bitLength="32">2</PlcDINT>
-                    <PlcDINT dataType="int" bitLength="32">3</PlcDINT>
-                    <PlcDINT dataType="int" bitLength="32">4</PlcDINT>
-                  </PlcList>
-                </value>
-              </PlcResponseItem>
-            </hurz>
-          </values>
-        </PlcReadResponse>
-      </api-response>
-    </steps>
-  </testcase>
-
-  <testcase>
-    <name>Single element write request</name>
-    <steps>
-      <api-request name="Receive Write Request from application">
-        <TestWriteRequest>
-          <tags isList="true">
-            <tag className="org.apache.plc4x.test.driver.internal.api.TestValueTag">
-              <name>hurz</name>
-              <address>%rate:DINT</address>
-              <value>369229824</value>
-            </tag>
-          </tags>
-        </TestWriteRequest>
-      </api-request>
-      <outgoing-plc-message name="Send CipWriteRequest to PLC">
-        <parser-arguments>
-          <response>false</response>
-        </parser-arguments>
-        <EipPacket>
-          <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">44</packetLength>
-          <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
-          <status dataType="uint" bitLength="32">0</status>
-          <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
-          <options dataType="uint" bitLength="32">0</options>
-          <CipRRData>
-            <interfaceHandle dataType="uint" bitLength="32">0</interfaceHandle>
-            <timeout dataType="uint" bitLength="16">0</timeout>
-            <typeIdCount dataType="uint" bitLength="16">2</typeIdCount>
-            <typeIds isList="true">
-              <TypeId>
-                <id dataType="uint" bitLength="16">0</id>
-                <NullAddressItem>
-                  <reserved dataType="uint" bitLength="16">0</reserved>
-                </NullAddressItem>
-              </TypeId>
-              <TypeId>
-                <id dataType="uint" bitLength="16">178</id>
-                <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">28</packetSize>
-                  <service>
-                    <CipService>
-                      <response dataType="bit" bitLength="1">false</response>
-                      <service dataType="uint" bitLength="7">82</service>
-                      <CipUnconnectedRequest>
-                        <requestPathSize dataType="uint" bitLength="8">2</requestPathSize>
-                        <classSegment>
-                          <PathSegment>
-                            <pathSegment dataType="uint" bitLength="3">1</pathSegment>
-                            <LogicalSegment>
-                              <segmentType>
-                                <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">0</logicalSegmentType>
-                                  <ClassID>
-                                    <format dataType="uint" bitLength="2">0</format>
-                                    <segmentClass dataType="uint" bitLength="8">6</segmentClass>
-                                  </ClassID>
-                                </LogicalSegmentType>
-                              </segmentType>
-                            </LogicalSegment>
-                          </PathSegment>
-                        </classSegment>
-                        <instanceSegment>
+                        <attributeSegment>
                           <PathSegment>
                             <pathSegment dataType="uint" bitLength="3">1</pathSegment>
                             <LogicalSegment>
                               <segmentType>
                                 <LogicalSegmentType>
-                                  <logicalSegmentType dataType="uint" bitLength="3">1</logicalSegmentType>
-                                  <InstanceID>
+                                  <logicalSegmentType dataType="uint" bitLength="3">4</logicalSegmentType>
+                                  <AttributeID>
                                     <format dataType="uint" bitLength="2">0</format>
-                                    <instance dataType="uint" bitLength="8">1</instance>
-                                  </InstanceID>
+                                    <attribute dataType="uint" bitLength="8">1</attribute>
+                                  </AttributeID>
                                 </LogicalSegmentType>
                               </segmentType>
                             </LogicalSegment>
                           </PathSegment>
-                        </instanceSegment>
-                        <reserved dataType="uint" bitLength="16">40197</reserved>
-                        <messageSize dataType="uint" bitLength="16">14</messageSize>
-                        <unconnectedService>
-                          <CipService>
-                            <response dataType="bit" bitLength="1">false</response>
-                            <service dataType="uint" bitLength="7">77</service>
-                            <CipWriteRequest>
-                              <requestPathSize dataType="uint" bitLength="8">3</requestPathSize>
-                              <tag dataType="byte" bitLength="48">0x910472617465</tag>
-                              <dataType>
-                                <CIPDataTypeCode dataType="uint" bitLength="16" stringRepresentation="DINT">196
-                                </CIPDataTypeCode>
-                              </dataType>
-                              <elementNb dataType="uint" bitLength="16">1</elementNb>
-                              <data dataType="byte" bitLength="32">0x00000216</data>
-                            </CipWriteRequest>
-                          </CipService>
-                        </unconnectedService>
-                        <route dataType="uint" bitLength="16">1</route>
-                        <backPlane dataType="int" bitLength="8">1</backPlane>
-                        <slot dataType="int" bitLength="8">0</slot>
-                      </CipUnconnectedRequest>
+                        </attributeSegment>
+                      </GetAttributeSingleRequest>
                     </CipService>
                   </service>
                 </UnConnectedDataItem>
@@ -1084,13 +519,13 @@
           </CipRRData>
         </EipPacket>
       </outgoing-plc-message>
-      <incoming-plc-message name="Get CipWriteResponse from PLC">
+      <incoming-plc-message name="Receive GetAttributeSingleResponse">
         <parser-arguments>
           <response>true</response>
         </parser-arguments>
         <EipPacket>
           <command dataType="uint" bitLength="16">111</command>
-          <packetLength dataType="uint" bitLength="16">28</packetLength>
+          <packetLength dataType="uint" bitLength="16">22</packetLength>
           <sessionHandle dataType="uint" bitLength="32">1074224669</sessionHandle>
           <status dataType="uint" bitLength="32">0</status>
           <senderContext dataType="byte" bitLength="64">0x504c433458202020</senderContext>
@@ -1109,16 +544,18 @@
               <TypeId>
                 <id dataType="uint" bitLength="16">178</id>
                 <UnConnectedDataItem>
-                  <packetSize dataType="uint" bitLength="16">4</packetSize>
+                  <packetSize dataType="uint" bitLength="16">6</packetSize>
                   <service>
                     <CipService>
                       <response dataType="bit" bitLength="1">true</response>
-                      <service dataType="uint" bitLength="7">77</service>
-                      <CipWriteResponse>
+                      <service dataType="uint" bitLength="7">14</service>
+                      <GetAttributeSingleResponse>
                         <reserved dataType="uint" bitLength="8">0</reserved>
                         <status dataType="uint" bitLength="8">0</status>
-                        <extStatus dataType="uint" bitLength="8">0</extStatus>
-                      </CipWriteResponse>
+                        <extStatusSize dataType="uint" bitLength="16">0</extStatusSize>
+                        <extStatus isList="true"/>
+                        <servicesData dataType="byte" bitLength="16">0x0100</servicesData>
+                      </GetAttributeSingleResponse>
                     </CipService>
                   </service>
                 </UnConnectedDataItem>
@@ -1127,39 +564,6 @@
           </CipRRData>
         </EipPacket>
       </incoming-plc-message>
-      <api-response name="Report Write Response to application">
-        <PlcWriteResponse>
-          <request>
-            <PlcWriteRequest>
-              <PlcTagRequest>
-                <tags isList="true">
-                  <hurz>
-                    <PlcTagItem>
-                      <tag>
-                        <EipTag>
-                          <node dataType="string" bitLength="32" encoding="UTF8">rate</node>
-                          <type dataType="string" bitLength="32" encoding="UTF8">DINT</type>
-                          <elementNb dataType="uint" bitLength="16">1</elementNb>
-                        </EipTag>
-                      </tag>
-                    </PlcTagItem>
-                  </hurz>
-                </tags>
-              </PlcTagRequest>
-              <values isList="true">
-                <hurz>
-                  <PlcDINT dataType="int" bitLength="32">369229824</PlcDINT>
-                </hurz>
-              </values>
-            </PlcWriteRequest>
-          </request>
-          <responseCodes isList="true">
-            <hurz>
-              <ResponseCode dataType="uint" bitLength="8" stringRepresentation="OK">1</ResponseCode>
-            </hurz>
-          </responseCodes>
-        </PlcWriteResponse>
-      </api-response>
     </steps>
   </testcase>