diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
index 877d8b8274..e526218ca0 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/AbEthDriver.java
@@ -84,6 +84,11 @@ protected boolean awaitDisconnectComplete() {
         return false;
     }
 
+    @Override
+    protected boolean canRead() {
+        return true;
+    }
+
     @Override
     protected ProtocolStackConfigurer<CIPEncapsulationPacket> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(CIPEncapsulationPacket.class, CIPEncapsulationPacket::staticParse)
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
index d5c25986a2..0175e4ca13 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/AbEthProtocolLogic.java
@@ -24,7 +24,6 @@
 import org.apache.plc4x.java.abeth.tag.AbEthTagHandler;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.api.messages.PlcResponse;
 import org.apache.plc4x.java.api.model.PlcTag;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
@@ -45,7 +44,6 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -59,7 +57,7 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
 
     private AbEthConfiguration configuration;
 
-    private final AtomicInteger transactionCounterGenerator = new AtomicInteger(10);
+    private final AtomicInteger transactionCounterGenerator = new AtomicInteger(1);
     private RequestTransactionManager tm;
     private long sessionHandle;
 
@@ -97,7 +95,8 @@ public void onConnect(ConversationContext<CIPEncapsulationPacket> context) {
 
     @Override
     public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
-        // TODO: Warning ... we are sending one request per tag ... the result has to be merged back together ...
+        DefaultPlcReadResponse plcReadResponse = new DefaultPlcReadResponse(readRequest, new HashMap<>(readRequest.getNumberOfTags()));
+        CompletableFuture<PlcReadResponse> combinedFuture = CompletableFuture.completedFuture(plcReadResponse);
         for (String tagName : readRequest.getTagNames()) {
             PlcTag tag = readRequest.getTag(tagName);
             if (!(tag instanceof AbEthTag)) {
@@ -122,6 +121,7 @@ public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
                 sessionHandle, 0, emptySenderContext, 0, requestMessage);
 
             CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+            combinedFuture = combinedFuture.thenCombine(future, (r1, r2) -> plcReadResponse);
             RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
             transaction.submit(() -> conversationContext.sendRequest(read)
                 .expectResponse(CIPEncapsulationPacket.class, REQUEST_TIMEOUT)
@@ -130,92 +130,78 @@ public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
                 .only(CIPEncapsulationReadResponse.class)
                 .check(p -> p.getResponse().getTransactionCounter() == transactionCounter)
                 .handle(p -> {
-                    PlcResponse response = decodeReadResponse(p, readRequest);
+                    PlcResponseItem<PlcValue> response = decodeReadResponse(p, abEthTag, tagName);
+                    plcReadResponse.add(tagName, response);
 
-                    // TODO: Not sure how to merge things back together ...
-
-                    //future.complete(response);
+                    future.complete(plcReadResponse);
                     // Finish the request-transaction.
                     transaction.endRequest();
-//                    future.complete(((PlcReadResponse) decodeReadResponse(p, ((InternalPlcReadRequest) readRequest))));
                 }));
-
-            // TODO: This aborts reading other tags after sending the first tags request ... refactor.
-            return future;
         }
-        // TODO: Should return an aggregated future ....
-        return null;
+        return combinedFuture;
     }
 
-    private PlcResponse decodeReadResponse(
-        CIPEncapsulationReadResponse plcReadResponse, PlcReadRequest plcReadRequest) {
-        Map<String, PlcResponseItem<PlcValue>> values = new HashMap<>();
-        for (String tagName : plcReadRequest.getTagNames()) {
-            AbEthTag tag = (AbEthTag) plcReadRequest.getTag(tagName);
-            PlcResponseCode responseCode = decodeResponseCode(plcReadResponse.getResponse().getStatus());
-
-            PlcValue plcValue = null;
-            if (responseCode == PlcResponseCode.OK) {
-                try {
-                    switch (tag.getFileType()) {
-                        case INTEGER: // output as single bytes
-                            if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
-                                DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
-                                List<Short> data = df1PTLR.getData();
-                                if (data.size() == 1) {
-                                    plcValue = new PlcINT(data.get(0));
-                                } else {
-                                    plcValue = DefaultPlcValueHandler.of(tag, data);
-                                }
-                            }
-                            break;
-                        case WORD:
-                            if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
-                                DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
-                                List<Short> data = df1PTLR.getData();
-                                if (((data.get(1) >> 7) & 1) == 0) {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (data.get(1) << 8) + data.get(0));  // positive number
-                                } else {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (((~data.get(1) & 0b01111111) << 8) + (-data.get(0) & 0b11111111)) * -1);  // negative number
-                                }
-                            }
-                            break;
-                        case DWORD:
-                            if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
-                                DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
-                                List<Short> data = df1PTLR.getData();
-                                if (((data.get(3) >> 7) & 1) == 0) {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
-                                } else {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (((~data.get(3) & 0b01111111) << 24) + ((-data.get(2) & 0b11111111) << 16) + ((-data.get(1) & 0b11111111) << 8) + (-data.get(0) & 0b11111111)) * -1);  // negative number
-                                }
-                            }
-                            break;
-                        case SINGLEBIT:
-                            if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
-                                DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
-                                List<Short> data = df1PTLR.getData();
-                                if (tag.getBitNumber() < 8) {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (data.get(0) & (1 << tag.getBitNumber())) != 0);         // read from first byte
-                                } else {
-                                    plcValue = DefaultPlcValueHandler.of(tag, (data.get(1) & (1 << (tag.getBitNumber() - 8))) != 0);   // read from second byte
-                                }
-                            }
-                            break;
-                        default:
-                            logger.warn("Problem during decoding of tag {}: Decoding of file type not implemented; " +
-                                "TagInformation: {}", tagName, tag);
+    private PlcResponseItem<PlcValue> decodeReadResponse(
+        CIPEncapsulationReadResponse plcReadResponse, AbEthTag tag, String tagName) {
+        PlcResponseCode responseCode = decodeResponseCode(plcReadResponse.getResponse().getStatus());
+        PlcValue plcValue = null;
+        if (responseCode != PlcResponseCode.OK) {
+            return new DefaultPlcResponseItem<>(responseCode, plcValue);
+        }
+        try {
+            switch (tag.getFileType()) {
+                case INTEGER: // output as single bytes
+                    if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
+                        DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
+                        List<Short> data = df1PTLR.getData();
+                        if (data.size() == 1) {
+                            plcValue = new PlcINT(data.get(0));
+                        } else {
+                            plcValue = DefaultPlcValueHandler.of(tag, data);
+                        }
+                    }
+                    break;
+                case WORD:
+                    if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
+                        DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
+                        List<Short> data = df1PTLR.getData();
+                        if (((data.get(1) >> 7) & 1) == 0) {
+                            plcValue = DefaultPlcValueHandler.of(tag, (data.get(1) << 8) + data.get(0));  // positive number
+                        } else {
+                            plcValue = DefaultPlcValueHandler.of(tag, (((~data.get(1) & 0b01111111) << 8) + (-data.get(0) & 0b11111111)) * -1);  // negative number
+                        }
                     }
-                } catch (Exception e) {
-                    logger.warn("Some other error occurred casting tag {}, TagInformation: {}", tagName, tag, e);
-                }
+                    break;
+                case DWORD:
+                    if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
+                        DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
+                        List<Short> data = df1PTLR.getData();
+                        if (((data.get(3) >> 7) & 1) == 0) {
+                            plcValue = DefaultPlcValueHandler.of(tag, (data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
+                        } else {
+                            plcValue = DefaultPlcValueHandler.of(tag, (((~data.get(3) & 0b01111111) << 24) + ((-data.get(2) & 0b11111111) << 16) + ((-data.get(1) & 0b11111111) << 8) + (-data.get(0) & 0b11111111)) * -1);  // negative number
+                        }
+                    }
+                    break;
+                case SINGLEBIT:
+                    if (plcReadResponse.getResponse() instanceof DF1CommandResponseMessageProtectedTypedLogicalRead) {
+                        DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
+                        List<Short> data = df1PTLR.getData();
+                        if (tag.getBitNumber() < 8) {
+                            plcValue = DefaultPlcValueHandler.of(tag, (data.get(0) & (1 << tag.getBitNumber())) != 0);         // read from first byte
+                        } else {
+                            plcValue = DefaultPlcValueHandler.of(tag, (data.get(1) & (1 << (tag.getBitNumber() - 8))) != 0);   // read from second byte
+                        }
+                    }
+                    break;
+                default:
+                    logger.warn("Problem during decoding of tag {}: Decoding of file type not implemented; " +
+                        "TagInformation: {}", tagName, tag);
             }
-            PlcResponseItem<PlcValue> result = new DefaultPlcResponseItem<>(responseCode, plcValue);
-            values.put(tagName, result);
+        } catch (Exception e) {
+            logger.warn("Some other error occurred casting tag {}, TagInformation: {}", tagName, tag, e);
         }
-
-        // TODO: Double check if it's really a InternalPlcReadRequest ...
-        return new DefaultPlcReadResponse(plcReadRequest, values);
+        return new DefaultPlcResponseItem<>(responseCode, plcValue);
     }
 
     private PlcResponseCode decodeResponseCode(short status) {