protected PlcReadResponse processReadResponses(PlcReadRequest readRequest, Map<PlcReadRequest, SubResponse<PlcReadResponse>> readResponses, DriverContext driverContext) {
        S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
        if(!s7DriverContext.isEnableBlockReadOptimizer()) {
            return super.processReadResponses(readRequest, readResponses, driverContext);
        }

        // Create the merged read request so the layer down can correctly process it.
        LinkedHashMap<String, PlcTagItem<PlcTag>> tags = new LinkedHashMap<>();
        for (PlcReadRequest plcReadRequest : readResponses.keySet()) {
            for (String tagName : plcReadRequest.getTagNames()) {
                PlcTag tag = plcReadRequest.getTag(tagName);
                tags.put(tagName, new DefaultPlcTagItem<>(tag));
            }
        }

        // Have the upstream optimizer handle its thing.
        PlcReadResponse rawReadResponse = super.processReadResponses(new DefaultPlcReadRequest(((DefaultPlcReadRequest) readRequest).getReader(), tags), readResponses, driverContext);

        // Merge together split-up chunks.
        LinkedHashMap<String, PlcTagItem<PlcTag>> mergedTagItems = new LinkedHashMap<>();
        Map<String, PlcResponseItem<PlcValue>> mergedValues = new LinkedHashMap<>();
        for (String tagName : rawReadResponse.getTagNames()) {
            PlcTag tag = rawReadResponse.getRequest().getTag(tagName);

            // This indicates it's a chunk that's been split up.
            if((tag instanceof S7TagChunk) && (((S7TagChunk) tag).getTotalPartNumber() > 1)){
                S7TagChunk tagChunk = (S7TagChunk) tag;
                // Only handle the first part
                if(tagChunk.getCurPartIndex() == 0) {
                    String tagBaseName = tagName.substring(0, tagName.indexOf("."));

                    // Allocate a chunk of memory able to store the data of all parts.
                    byte[] chunkData = new byte[tagChunk.getTotalPartSize()];

                    int firstPartOffset = tagChunk.getByteOffset();
                    // Copy the payload of each chunk into the total chunk data.
                    for(int curPartIndex = 0; curPartIndex < tagChunk.getTotalPartNumber(); curPartIndex++) {
                        String curPartTagName = tagBaseName + "." + curPartIndex;
                        S7TagChunk curPartTag = (S7TagChunk) rawReadResponse.getRequest().getTag(curPartTagName);

                        PlcResponseCode responseCode = rawReadResponse.getResponseCode(curPartTagName);
                        // If one of the parts is not OK, all in this chunk will be not OK too.
                        if(responseCode != PlcResponseCode.OK) {
                            mergedValues.put(tagName, new DefaultPlcResponseItem<>(responseCode, new PlcNull()));
                            break;
                        }
                        PlcValue plcValue = rawReadResponse.getPlcValue(curPartTagName);
                        byte[] chunkPartData = plcValue.getRaw();
                        int partDataOffset = curPartTag.getByteOffset() - firstPartOffset;
                        System.arraycopy(chunkPartData, 0, chunkData, partDataOffset, chunkPartData.length);
                    }

                    // Store the merged tag.
                    mergedTagItems.put(tagBaseName, new DefaultPlcTagItem<>(
                        new S7TagChunk(tagChunk.getDataType(), tagChunk.getMemoryArea(), tagChunk.getBlockNumber(),
                            firstPartOffset, (byte) 0, tagChunk.getTotalPartSize(), tagChunk.getChunkTags(),
                            0, 1, tagChunk.getTotalPartSize())));
                    mergedValues.put(tagBaseName, new DefaultPlcResponseItem<>(PlcResponseCode.OK, new PlcRawByteArray(chunkData)));
                }
            }
            // All others are just un-split chunks
            else {
                PlcResponseCode responseCode = rawReadResponse.getResponseCode(tagName);
                PlcValue plcValue = rawReadResponse.getPlcValue(tagName);
                mergedTagItems.put(tagName, new DefaultPlcTagItem<>(tag));
                mergedValues.put(tagName, new DefaultPlcResponseItem<>(responseCode, plcValue));
            }
        }
        PlcReadResponse mergedReadResponse = new DefaultPlcReadResponse(new DefaultPlcReadRequest(((DefaultPlcReadRequest)rawReadResponse.getRequest()).getReader(), mergedTagItems), mergedValues);

        // If a Tag is a normal tag, just copy it over. However, if it's a S7TagChunk, process it.
        Map<String, PlcResponseItem<PlcValue>> values = new HashMap<>();
        for (String tagName : mergedReadResponse.getTagNames()) {
            PlcResponseCode responseCode = mergedReadResponse.getResponseCode(tagName);
            PlcValue plcValue = mergedReadResponse.getPlcValue(tagName);
            // We need to get the request from the response as only this contains the
            // chunk tags and not the original one passed in via readRequest parameter.
            PlcTag tag = mergedReadResponse.getRequest().getTag(tagName);

            // If it's not a tag-chunk, then we just add it to the response.
            if(!(tag instanceof S7TagChunk)) {
                values.put(tagName, new DefaultPlcResponseItem<>(responseCode, plcValue));
                continue;
            }

            // Otherwise it's a tag-chunk and we need to decode the payload.
            // So we decode all the tags that are chunked-together in this.
            ReadBufferByteBased readBuffer = new ReadBufferByteBased(plcValue.getRaw());
            S7TagChunk s7TagChunk = (S7TagChunk) tag;
            int chunkByteOffset = s7TagChunk.getByteOffset();
            for (PlcTag plcTag : s7TagChunk.getChunkTags().keySet()) {
                S7Tag s7Tag = (S7Tag) plcTag;
                String curTagName = s7TagChunk.getChunkTags().get(plcTag);
                int curTagStartPosition = s7Tag.getByteOffset() - chunkByteOffset;
                int curTagDataSize = s7Tag.getDataType().getSizeInBytes() * s7Tag.getNumberOfElements();
                if(s7Tag instanceof S7StringFixedLengthTag) {
                    S7StringFixedLengthTag s7StringFixedLengthTag = (S7StringFixedLengthTag) s7Tag;
                    if(s7Tag.getDataType() == TransportSize.WSTRING) {
                        //curTagStartPosition += 4;
                        curTagDataSize = s7StringFixedLengthTag.getStringLength() * 2;
                    } else {
                        //curTagStartPosition += 2;
                        curTagDataSize = s7StringFixedLengthTag.getStringLength();
                    }
                }
                byte[] curTagData = readBuffer.getBytes(curTagStartPosition, curTagStartPosition + curTagDataSize);
                PlcValue tagValue = parsePlcValue(s7Tag, curTagData, s7DriverContext);
                values.put(curTagName, new DefaultPlcResponseItem<>(responseCode, tagValue));
            }
        }

        return new DefaultPlcReadResponse(readRequest, values);
    }
In contrast to the S7Optimizer, the S7BlockReadOptimizer only looks at the bytes that require being read
and focuses on reading raw blocks of bytes instead of doing individual reads for each item.
plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/optimizer/S7BlockReadOptimizer.java