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/11/06 15:37:16 UTC

[plc4x] branch feature/cdutz/go-ads-ng updated: refactor(api) PLC4J API refactoring

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

cdutz pushed a commit to branch feature/cdutz/go-ads-ng
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/feature/cdutz/go-ads-ng by this push:
     new 87d81b893a refactor(api) PLC4J API refactoring
87d81b893a is described below

commit 87d81b893a8eeb03e65fdc697e9a5c1376c95086
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Nov 6 16:37:05 2022 +0100

    refactor(api) PLC4J API refactoring
    
    - PlcBrowseItem's getChildren is now a Map
    - PlcBrowseRequest now has a executeWithInterceptor method
    - PlcBrowseResponse now supports multiple queries and therefore has:
        - a getQueryNames() method
        - the getResponseCode method was replaced with a getResponseCode(queryName) method
        - the getValues() method was replaced with a getValues(queryName) method
    - PlcField:
        - Removed the getDefaultJavaType() as PlcValueType provides this
        - replaced String getPlcDataType() with PlcValueType getPlcValueType()
        - replaced int getNumberOfElements() with List<ArrayInfo> getArrayInfo()
    - A new type PlcQuery for being the base of Browse queries
    - PlcValueType now provides a default java type for each constant
    
    Protocols:
    - Extended the data-types of the following protocols to allow mapping to the PlcValueTypes of the API module:
        - canopen
        - genericcan
    
    Adjusted the rest of the codebase accordingly.
---
 plc4go/examples/ads/Browser_test.go                |   2 +-
 plc4go/internal/ads/Browser.go                     |  83 +++++++++++--
 .../api/model/{plc_field.go => plc_array_info.go}  |   8 +-
 plc4go/pkg/api/model/plc_browse.go                 |  28 +++--
 plc4go/pkg/api/model/plc_field.go                  |   6 +-
 .../pkg/api/model/plc_query.go                     |   9 +-
 plc4go/pkg/api/model/plc_read.go                   |   4 +-
 plc4go/pkg/api/model/plc_subscription.go           |   9 +-
 plc4go/pkg/api/model/plc_write.go                  |   4 +-
 .../eip/readwrite/model/CIPDataTypeCode.go         |   2 -
 plc4go/spi/PlcBrowser.go                           |   3 +-
 plc4go/spi/PlcFieldHandler.go                      |   6 +-
 plc4go/spi/model/DefaultPlcBrowseEvent.go          |  10 +-
 plc4go/spi/model/DefaultPlcBrowseEvent_plc4xgen.go |   2 +-
 ...rowseQueryResult.go => DefaultPlcBrowseItem.go} |  51 +++++---
 ...lc4xgen.go => DefaultPlcBrowseItem_plc4xgen.go} |  94 ++++++++++++---
 plc4go/spi/model/DefaultPlcBrowseRequest.go        |  52 ++++----
 .../spi/model/DefaultPlcBrowseRequest_plc4xgen.go  |  39 +++++-
 plc4go/spi/model/DefaultPlcBrowseResponse.go       |   6 +-
 ...DefaultRequest.go => DefaultPlcFieldRequest.go} |  14 +--
 ...4xgen.go => DefaultPlcFieldRequest_plc4xgen.go} |  75 ++++--------
 plc4go/spi/model/DefaultPlcReadRequest.go          |  53 ++++----
 .../model/DefaultPlcReadRequestBuilder_plc4xgen.go |  29 ++---
 plc4go/spi/model/DefaultPlcReadRequest_plc4xgen.go |   2 +-
 .../DefaultPlcRequest.go}                          |  14 ++-
 plc4go/spi/model/DefaultPlcSubscriptionRequest.go  |  48 ++++----
 ...efaultPlcSubscriptionRequestBuilder_plc4xgen.go |  29 ++---
 .../DefaultPlcSubscriptionRequest_plc4xgen.go      |   2 +-
 plc4go/spi/model/DefaultPlcWriteRequest.go         |  42 +++----
 .../DefaultPlcWriteRequestBuilder_plc4xgen.go      |  29 ++---
 .../spi/model/DefaultPlcWriteRequest_plc4xgen.go   |   2 +-
 plc4go/spi/model/DefaultRequest_plc4xgen.go        |   8 +-
 plc4go/spi/model/render_test.go                    |   5 +-
 .../plc4x/java/api/messages/PlcBrowseItem.java     |   2 +-
 .../plc4x/java/api/messages/PlcBrowseRequest.java  |  19 +++
 .../api/messages/PlcBrowseRequestInterceptor.java  |   9 +-
 .../plc4x/java/api/messages/PlcBrowseResponse.java |   7 +-
 .../apache/plc4x/java/api/model/ArrayInfo.java}    |  29 +++--
 .../org/apache/plc4x/java/api/model/PlcField.java  |  39 +++---
 .../org/apache/plc4x/java/api/model/PlcQuery.java  |  42 +++++++
 .../apache/plc4x/java/api/types/PlcValueType.java  | 112 +++++++++--------
 .../plc4x/java/api/messages/mock/MockField.java    |  67 +++++++----
 .../org/apache/plc4x/java/abeth/AbEthDriver.java   |   7 +-
 .../apache/plc4x/java/abeth/field/AbEthField.java  |  25 +++-
 .../plc4x/java/abeth/field/AbEthFieldHandler.java  |   8 +-
 .../java/abeth/protocol/AbEthProtocolLogic.java    |  16 +--
 .../java/abeth/protocol/Plc4xAbEthProtocol.java    |  15 +--
 .../apache/plc4x/java/abeth/types/FileType.java    |  41 ++++---
 .../org/apache/plc4x/java/ads/AdsPlcDriver.java    |   7 +-
 .../plc4x/java/ads/field/AdsFieldHandler.java      |   8 +-
 .../plc4x/java/ads/field/DirectAdsField.java       |  32 ++++-
 .../plc4x/java/ads/field/DirectAdsStringField.java |  13 +-
 .../plc4x/java/ads/field/SymbolicAdsField.java     |  24 +++-
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  | 109 ++++++++++-------
 .../apache/plc4x/java/bacnetip/BacNetIpDriver.java |   7 +-
 .../plc4x/java/bacnetip/field/BacNetIpField.java   |  18 +++
 .../java/bacnetip/field/BacNetIpFieldHandler.java  |   8 +-
 .../bacnetip/protocol/BacNetIpProtocolLogic.java   |   9 +-
 .../plc4x/java/can/generic/GenericCANDriver.java   |   7 +-
 .../java/can/generic/field/GenericCANField.java    |  29 ++++-
 .../can/generic/field/GenericCANFieldHandler.java  |  10 +-
 .../generic/field/GenericCANFieldHandlerTest.java  |   5 +-
 .../plc4x/java/canopen/CANOpenPlcDriver.java       |   7 +-
 .../java/canopen/field/CANOpenFieldHandler.java    |   8 +-
 .../java/canopen/field/CANOpenHeartbeatField.java  |  20 +++-
 .../plc4x/java/canopen/field/CANOpenNMTField.java  |  20 +++-
 .../plc4x/java/canopen/field/CANOpenPDOField.java  |  22 +++-
 .../plc4x/java/canopen/field/CANOpenSDOField.java  |  28 ++++-
 plc4j/drivers/eip/pom.xml                          |   4 +
 .../apache/plc4x/java/eip/readwrite/EIPDriver.java |   7 +-
 .../plc4x/java/eip/readwrite/field/EipField.java   |  85 ++++++-------
 .../java/eip/readwrite/field/EipFieldHandler.java  |   8 +-
 .../eip/readwrite/protocol/EipProtocolLogic.java   |   2 -
 .../java/firmata/readwrite/FirmataDriver.java      |   7 +-
 .../readwrite/field/FirmataFieldAnalog.java        |  25 +++-
 .../readwrite/field/FirmataFieldDigital.java       |  32 ++++-
 .../readwrite/field/FirmataFieldHandler.java       |   8 +-
 .../apache/plc4x/java/knxnetip/KnxNetIpDriver.java |   7 +-
 .../plc4x/java/knxnetip/field/KnxNetIpField.java   |  25 +++-
 .../java/knxnetip/field/KnxNetIpFieldHandler.java  |   8 +-
 .../plc4x/java/mock/connection/MockConnection.java |  27 +++--
 .../apache/plc4x/java/mock/field/MockField.java    |  52 ++++----
 .../plc4x/java/mock/field/MockFieldHandler.java    |   8 +-
 .../apache/plc4x/java/mock/field/MockPlcValue.java |  48 --------
 .../plc4x/java/mock/field/MockValueHandler.java    |  47 --------
 .../plc4x/java/modbus/ascii/ModbusAsciiDriver.java |   7 +-
 .../modbus/base/field/ModbusExtendedRegister.java  |  12 ++
 .../plc4x/java/modbus/base/field/ModbusField.java  |  19 ++-
 .../java/modbus/base/field/ModbusFieldCoil.java    |  12 ++
 .../base/field/ModbusFieldDiscreteInput.java       |  12 ++
 .../java/modbus/base/field/ModbusFieldHandler.java |   8 +-
 .../base/field/ModbusFieldHoldingRegister.java     |  12 ++
 .../base/field/ModbusFieldInputRegister.java       |  12 ++
 .../plc4x/java/modbus/rtu/ModbusRtuDriver.java     |   7 +-
 .../plc4x/java/modbus/tcp/ModbusTcpDriver.java     |   7 +-
 .../apache/plc4x/java/modbus/ModbusEncodeTest.java |  32 ++---
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |   7 +-
 .../apache/plc4x/java/opcua/field/OpcuaField.java  |  21 +++-
 .../java/opcua/field/OpcuaPlcFieldHandler.java     |   8 +-
 .../java/opcua/protocol/OpcuaProtocolLogic.java    | 125 ++++++++-----------
 .../apache/plc4x/java/opcua/ManualPLC4XOpcua.java  |   2 +-
 .../org/apache/plc4x/java/plc4x/Plc4xDriver.java   |   7 +-
 .../apache/plc4x/java/plc4x/field/Plc4xField.java  |  23 ++--
 .../plc4x/java/plc4x/field/Plc4xFieldHandler.java  |  11 +-
 .../java/plc4x/protocol/Plc4xProtocolLogic.java    |   6 +-
 .../apache/plc4x/java/profinet/ProfinetDriver.java |   7 +-
 .../plc4x/java/profinet/field/ProfinetField.java   |  18 +++
 .../java/profinet/field/ProfinetFieldHandler.java  |   8 +-
 .../apache/plc4x/java/s7/readwrite/S7Driver.java   |   7 +-
 .../plc4x/java/s7/readwrite/field/S7Field.java     |  59 ++++-----
 .../java/s7/readwrite/field/S7PlcFieldHandler.java |   8 +-
 .../plc4x/java/s7/readwrite/field/S7SslField.java  |  19 +++
 .../s7/readwrite/field/S7SubscriptionField.java    |  40 +++++--
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |   5 +-
 .../simulated/connection/SimulatedConnection.java  |   4 +-
 .../java/simulated/connection/SimulatedDevice.java |  18 +--
 .../plc4x/java/simulated/field/SimulatedField.java |  68 +++++------
 .../simulated/field/SimulatedFieldHandler.java     |   8 +-
 .../simulated/connection/SimulatedDeviceTest.java  |   4 +-
 .../simulated/field/SimularedFieldHandlerTest.java |   2 +-
 .../java/simulated/field/SimulatedFieldTest.java   |   8 +-
 .../HelloPlc4xDiscoverAndBrowse.java               |   8 +-
 .../apache-calcite/src/test/resources/example.yml  |   4 +-
 .../opcuaserver/backend/Plc4xCommunication.java    |  67 ++++-------
 .../java/opcuaserver/backend/Plc4xNamespace.java   |   7 +-
 .../apache/plc4x/java/spi/Plc4xProtocolBase.java   |   4 +
 .../java/spi/connection/AbstractPlcConnection.java |   7 +-
 .../plc4x/java/spi/connection/PlcFieldHandler.java |   7 +-
 .../spi/messages/DefaultListPlcBrowseItem.java     |   4 +-
 .../java/spi/messages/DefaultPlcBrowseItem.java    |   8 +-
 .../java/spi/messages/DefaultPlcBrowseRequest.java |  45 +++++--
 .../spi/messages/DefaultPlcBrowseResponse.java     |  20 ++--
 .../java/spi/messages/DefaultPlcReadRequest.java   |   3 +-
 .../messages/DefaultPlcSubscriptionRequest.java    |   2 +-
 .../java/spi/messages/DefaultPlcWriteRequest.java  |   3 +-
 .../java/spi/messages/DefaultPlcWriteResponse.java |  10 +-
 .../apache/plc4x/java/spi/messages/PlcBrowser.java |   3 +
 .../plc4x/java/spi/model/DefaultArrayInfo.java}    |  31 +++--
 .../spi/model/DefaultPlcSubscriptionField.java     |  18 +++
 .../org/apache/plc4x/java/spi/values/PlcLDATE.java | 120 +++++++++++++++++++
 .../plc4x/java/spi/values/PlcLDATE_AND_TIME.java   | 133 +++++++++++++++++++++
 .../plc4x/java/spi/values/PlcLTIME_OF_DAY.java     | 106 ++++++++++++++++
 ...61131ValueHandler.java => PlcValueHandler.java} |  72 +++++------
 .../utils/connectionpool2/CachedBrowseRequest.java |  18 +++
 .../utils/connectionpool2/CachedPlcConnection.java |  28 +++++
 .../java/opm/PlcEntityManagerComplexTest.java      |  75 +++++++-----
 .../triggerhandler/TriggerConfiguration.java       |   6 +-
 .../plc4x/java/ui/ConnectionTabController.java     |  15 ++-
 .../org/apache/plc4x/test/manual/ManualTest.java   |   5 +-
 pom.xml                                            |   1 +
 .../src/main/resources/protocols/can/canopen.mspec |  52 ++++----
 .../eip/src/main/resources/protocols/eip/eip.mspec |   2 +-
 .../main/resources/protocols/can/genericcan.mspec  |  42 +++----
 .../plc4x/java/discovery/DiscoveryConnection.java  |   8 +-
 .../java/discovery/DiscoveryFieldHandler.java      |   8 +-
 .../org/apache/plc4x/java/df1/DF1PlcDriver.java    |   7 +-
 .../org/apache/plc4x/java/df1/field/Df1Field.java  |  33 ++++-
 .../plc4x/java/df1/field/Df1FieldHandler.java      |   8 +-
 .../plc4x/java/df1/protocol/Plc4XDf1Protocol.java  |   2 +-
 .../org/apache/plc4x/java/df1/types/DataType.java  |  32 +++--
 160 files changed, 2395 insertions(+), 1261 deletions(-)

diff --git a/plc4go/examples/ads/Browser_test.go b/plc4go/examples/ads/Browser_test.go
index 3c1513f8de..186ad90c7a 100644
--- a/plc4go/examples/ads/Browser_test.go
+++ b/plc4go/examples/ads/Browser_test.go
@@ -31,7 +31,7 @@ func TestBrowserManual(t *testing.T) {
 	drivers.RegisterAdsDriver(driverManager)
 	connectionChan := driverManager.GetConnection("ads:tcp://192.168.23.20?sourceAmsNetId=192.168.23.200.1.1&sourceAmsPort=65534&targetAmsNetId=192.168.23.20.1.1&targetAmsPort=851")
 	connection := <-connectionChan
-	browseRequest, err := connection.GetConnection().BrowseRequestBuilder().AddQuery("all", "*").Build()
+	browseRequest, err := connection.GetConnection().BrowseRequestBuilder().AddQuery("all", "MAIN.rivianTest01.RotationalPosition").Build()
 	if err != nil {
 		panic(err)
 	}
diff --git a/plc4go/internal/ads/Browser.go b/plc4go/internal/ads/Browser.go
index 7dec632bee..7a677309ff 100644
--- a/plc4go/internal/ads/Browser.go
+++ b/plc4go/internal/ads/Browser.go
@@ -94,7 +94,7 @@ func (m *Connection) executeSymbolicAddressQuery(ctx context.Context, field Symb
 	}
 
 	// Process the data type and symbol tables to produce the response.
-	fields := m.filterSymbols("")
+	fields := m.filterSymbols(field.SymbolicAddress)
 	return apiModel.PlcResponseCode_OK, fields
 }
 
@@ -109,8 +109,8 @@ func (m *Connection) filterSymbols(filterExpression string) []apiModel.PlcBrowse
 	symbolName := addressSegments[0]
 	remainingSegments := addressSegments[1:]
 	if len(addressSegments) > 0 {
-		symbolName = symbolName + "." + addressSegments[0]
-		remainingSegments = addressSegments[1:]
+		symbolName = symbolName + "." + remainingSegments[0]
+		remainingSegments = remainingSegments[1:]
 	}
 
 	if symbol, ok := m.symbolTable[symbolName]; !ok {
@@ -125,15 +125,81 @@ func (m *Connection) filterSymbols(filterExpression string) []apiModel.PlcBrowse
 			// Couldn't find data type
 			return nil
 		} else {
-			return m.filterDataTypes(symbolDataType, symbolDataTypeName, remainingSegments)
+			return m.filterDataTypes(symbolName, symbolDataType, symbolDataTypeName, remainingSegments)
 		}
 	}
 }
 
-func (m *Connection) filterDataTypes(currentType model.AdsDataTypeTableEntry, currentPath string, remainingAddressSegments []string) []apiModel.PlcBrowseFoundField {
+/*
+func LALALA(){
+	for (AdsSymbolTableEntry symbol : symbolTable.values()) {
+		// Get the datatype of this entry.
+		AdsDataTypeTableEntry dataType = dataTypeTable.get(symbol.getDataTypeName());
+		if (dataType == null) {
+			System.out.printf("couldn't find datatype: %s%n", symbol.getDataTypeName());
+			continue;
+		}
+		String itemName = (symbol.getComment() == null || symbol.getComment().isEmpty()) ? symbol.getName() : symbol.getComment();
+		// Convert the plc value type from the ADS specific one to the PLC4X global one.
+		org.apache.plc4x.java.api.types.PlcValueType plc4xPlcValueType = org.apache.plc4x.java.api.types.PlcValueType.valueOf(getPlcValueTypeForAdsDataType(dataType).toString());
+
+		// If this type has children, add entries for its children.
+		List<PlcBrowseItem> children = getBrowseItems(symbol.getName(), symbol.getGroup(), symbol.getOffset(), !symbol.getFlagReadOnly(), dataType);
+
+		// Populate a map of protocol-dependent options.
+		Map<String, PlcValue> options = new HashMap<>();
+		options.put("comment", new PlcSTRING(symbol.getComment()));
+		options.put("group-id", new PlcUDINT(symbol.getGroup()));
+		options.put("offset", new PlcUDINT(symbol.getOffset()));
+		options.put("size-in-bytes", new PlcUDINT(symbol.getSize()));
+
+		if(plc4xPlcValueType == org.apache.plc4x.java.api.types.PlcValueType.List) {
+			List<PlcBrowseItemArrayInfo> arrayInfo = new ArrayList<>();
+			for (AdsDataTypeArrayInfo adsDataTypeArrayInfo : dataType.getArrayInfo()) {
+				arrayInfo.add(new DefaultBrowseItemArrayInfo(
+					adsDataTypeArrayInfo.getLowerBound(), adsDataTypeArrayInfo.getUpperBound()));
+			}
+			// Add the type itself.
+			values.add(new DefaultListPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, arrayInfo,
+				true, !symbol.getFlagReadOnly(), true, children, options));
+		} else {
+			// Add the type itself.
+			values.add(new DefaultPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, true,
+				!symbol.getFlagReadOnly(), true, children, options));
+		}
+	}
+	DefaultPlcBrowseResponse response = new DefaultPlcBrowseResponse(browseRequest, PlcResponseCode.OK, values);
+
+}
+*/
+
+func (m *Connection) filterDataTypes(parentName string, currentType model.AdsDataTypeTableEntry, currentPath string, remainingAddressSegments []string) []apiModel.PlcBrowseFoundField {
 	if len(remainingAddressSegments) == 0 {
-		// TODO: Convert the symbol itself into a PlcBrowseField
-		return nil
+		var numElements int32
+		var startElement int32
+		var endElement int32
+		if len(currentType.GetArrayInfo()) > 0 {
+			numElements = int32(currentType.GetArrayInfo()[0].GetNumElements())
+			startElement = int32(currentType.GetArrayInfo()[0].GetLowerBound())
+			endElement = int32(currentType.GetArrayInfo()[0].GetUpperBound())
+		}
+		foundField := &model2.DefaultPlcBrowseQueryResult{
+			Field: SymbolicPlcField{
+				PlcField: PlcField{
+					NumElements:  numElements,
+					StartElement: startElement,
+					EndElement:   endElement,
+				},
+				SymbolicAddress: parentName,
+			},
+			Name:              parentName,
+			Readable:          false,
+			Writable:          false,
+			Subscribable:      false,
+			PossibleDataTypes: nil,
+			Attributes:        nil,
+		}
+		return []apiModel.PlcBrowseFoundField{foundField}
 	}
 
 	currentAddressSegment := remainingAddressSegments[0]
@@ -145,7 +211,8 @@ func (m *Connection) filterDataTypes(currentType model.AdsDataTypeTableEntry, cu
 				// TODO: Couldn't find data type with the name defined in the protperty.
 				return nil
 			} else {
-				return m.filterDataTypes(symbolDataType, currentPath+"."+currentAddressSegment, remainingAddressSegments)
+				return m.filterDataTypes(parentName+"."+child.GetPropertyName(), symbolDataType,
+					currentPath+"."+currentAddressSegment, remainingAddressSegments)
 			}
 		}
 	}
diff --git a/plc4go/pkg/api/model/plc_field.go b/plc4go/pkg/api/model/plc_array_info.go
similarity index 89%
copy from plc4go/pkg/api/model/plc_field.go
copy to plc4go/pkg/api/model/plc_array_info.go
index 91b8caed3f..a9bc95f465 100644
--- a/plc4go/pkg/api/model/plc_field.go
+++ b/plc4go/pkg/api/model/plc_array_info.go
@@ -19,8 +19,8 @@
 
 package model
 
-type PlcField interface {
-	GetAddressString() string
-	GetTypeName() string
-	GetQuantity() uint16
+type ArrayInfo interface {
+	GetSize() uint32
+	GetLowerBound() uint32
+	GetUpperBound() uint32
 }
diff --git a/plc4go/pkg/api/model/plc_browse.go b/plc4go/pkg/api/model/plc_browse.go
index 2f785d572d..5518451bb9 100644
--- a/plc4go/pkg/api/model/plc_browse.go
+++ b/plc4go/pkg/api/model/plc_browse.go
@@ -21,6 +21,7 @@ package model
 
 import (
 	"context"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
@@ -36,19 +37,20 @@ type PlcBrowseRequest interface {
 	// ExecuteWithContext is the same as Execute but handles the Context if implemented for Driver
 	ExecuteWithContext(ctx context.Context) <-chan PlcBrowseRequestResult
 	// ExecuteWithInterceptor Will call the given callback for every found resource
-	ExecuteWithInterceptor(interceptor func(result PlcBrowseEvent) bool) <-chan PlcBrowseRequestResult
+	ExecuteWithInterceptor(interceptor func(result PlcBrowseItem) bool) <-chan PlcBrowseRequestResult
 	// ExecuteWithInterceptorWithContext Will call the given callback for every found resource
-	ExecuteWithInterceptorWithContext(ctx context.Context, interceptor func(result PlcBrowseEvent) bool) <-chan PlcBrowseRequestResult
-	GetFieldNames() []string
-	GetField(name string) PlcField
+	ExecuteWithInterceptorWithContext(ctx context.Context, interceptor func(result PlcBrowseItem) bool) <-chan PlcBrowseRequestResult
+
+	GetQueryNames() []string
+	GetQuery(queryName string) PlcQuery
 }
 
 type PlcBrowseResponse interface {
 	PlcResponse
 	GetRequest() PlcBrowseRequest
-	GetFieldNames() []string
+	GetQueryNames() []string
 	GetResponseCode(name string) PlcResponseCode
-	GetQueryResults(name string) []PlcBrowseFoundField
+	GetQueryResults(name string) []PlcBrowseItem
 }
 
 type PlcBrowseRequestResult interface {
@@ -60,17 +62,21 @@ type PlcBrowseRequestResult interface {
 type PlcBrowseEvent interface {
 	PlcMessage
 	GetRequest() PlcBrowseRequest
-	GetFieldName() string
-	GetResult() PlcBrowseFoundField
+	GetQueryName() string
+	GetResult() PlcBrowseItem
 	GetErr() error
 }
 
-type PlcBrowseFoundField interface {
+type PlcBrowseItem interface {
 	GetField() PlcField
+
+	GetAddress() string
 	GetName() string
+	GetPlcValueType() values.PlcValueType
+	GetArrayInfo() []ArrayInfo
 	IsReadable() bool
 	IsWritable() bool
 	IsSubscribable() bool
-	GetPossibleDataTypes() []string
-	GetAttributes() map[string]values.PlcValue
+	GetChildren() map[string]PlcBrowseItem
+	GetOptions() map[string]values.PlcValue
 }
diff --git a/plc4go/pkg/api/model/plc_field.go b/plc4go/pkg/api/model/plc_field.go
index 91b8caed3f..902dd6e02c 100644
--- a/plc4go/pkg/api/model/plc_field.go
+++ b/plc4go/pkg/api/model/plc_field.go
@@ -19,8 +19,10 @@
 
 package model
 
+import "github.com/apache/plc4x/plc4go/pkg/api/values"
+
 type PlcField interface {
 	GetAddressString() string
-	GetTypeName() string
-	GetQuantity() uint16
+	GetValueType() values.PlcValueType
+	GetArrayInfo() []ArrayInfo
 }
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockType.java b/plc4go/pkg/api/model/plc_query.go
similarity index 89%
rename from plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockType.java
rename to plc4go/pkg/api/model/plc_query.go
index 7c1e1ca097..ef533eab4f 100644
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockType.java
+++ b/plc4go/pkg/api/model/plc_query.go
@@ -16,10 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.mock.field;
 
-public enum MockType {
-    BOOL,
-    INT,
-    REAL
+package model
+
+type PlcQuery interface {
+	GetQueryString() string
 }
diff --git a/plc4go/pkg/api/model/plc_read.go b/plc4go/pkg/api/model/plc_read.go
index 4d4eef150a..8e248a39c7 100644
--- a/plc4go/pkg/api/model/plc_read.go
+++ b/plc4go/pkg/api/model/plc_read.go
@@ -21,11 +21,12 @@ package model
 
 import (
 	"context"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
 type PlcReadRequestBuilder interface {
-	AddQuery(name string, query string) PlcReadRequestBuilder
+	AddFieldQuery(name string, fieldQuery string) PlcReadRequestBuilder
 	AddField(name string, field PlcField) PlcReadRequestBuilder
 	Build() (PlcReadRequest, error)
 }
@@ -40,6 +41,7 @@ type PlcReadRequest interface {
 	PlcRequest
 	Execute() <-chan PlcReadRequestResult
 	ExecuteWithContext(ctx context.Context) <-chan PlcReadRequestResult
+
 	GetFieldNames() []string
 	GetField(name string) PlcField
 }
diff --git a/plc4go/pkg/api/model/plc_subscription.go b/plc4go/pkg/api/model/plc_subscription.go
index 95b9774ae6..9067315a12 100644
--- a/plc4go/pkg/api/model/plc_subscription.go
+++ b/plc4go/pkg/api/model/plc_subscription.go
@@ -21,8 +21,9 @@ package model
 
 import (
 	"context"
-	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	"time"
+
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
 type PlcSubscriptionEvent interface {
@@ -45,11 +46,11 @@ type PlcSubscriptionEvent interface {
 type PlcSubscriptionEventConsumer func(event PlcSubscriptionEvent)
 
 type PlcSubscriptionRequestBuilder interface {
-	AddCyclicQuery(name string, query string, interval time.Duration) PlcSubscriptionRequestBuilder
+	AddCyclicFieldQuery(name string, query string, interval time.Duration) PlcSubscriptionRequestBuilder
 	AddCyclicField(name string, field PlcField, interval time.Duration) PlcSubscriptionRequestBuilder
-	AddChangeOfStateQuery(name string, query string) PlcSubscriptionRequestBuilder
+	AddChangeOfStateFieldQuery(name string, query string) PlcSubscriptionRequestBuilder
 	AddChangeOfStateField(name string, field PlcField) PlcSubscriptionRequestBuilder
-	AddEventQuery(name string, query string) PlcSubscriptionRequestBuilder
+	AddEventFieldQuery(name string, query string) PlcSubscriptionRequestBuilder
 	AddEventField(name string, field PlcField) PlcSubscriptionRequestBuilder
 	AddPreRegisteredConsumer(name string, consumer PlcSubscriptionEventConsumer) PlcSubscriptionRequestBuilder
 	Build() (PlcSubscriptionRequest, error)
diff --git a/plc4go/pkg/api/model/plc_write.go b/plc4go/pkg/api/model/plc_write.go
index 6ed5a6a112..2336b27762 100644
--- a/plc4go/pkg/api/model/plc_write.go
+++ b/plc4go/pkg/api/model/plc_write.go
@@ -21,11 +21,12 @@ package model
 
 import (
 	"context"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
 type PlcWriteRequestBuilder interface {
-	AddQuery(name string, query string, value interface{}) PlcWriteRequestBuilder
+	AddFieldQuery(name string, fieldQuery string, value interface{}) PlcWriteRequestBuilder
 	AddField(name string, field PlcField, value interface{}) PlcWriteRequestBuilder
 	Build() (PlcWriteRequest, error)
 }
@@ -40,6 +41,7 @@ type PlcWriteRequest interface {
 	PlcRequest
 	Execute() <-chan PlcWriteRequestResult
 	ExecuteWithContext(ctx context.Context) <-chan PlcWriteRequestResult
+
 	GetFieldNames() []string
 	GetField(name string) PlcField
 	GetValue(name string) values.PlcValue
diff --git a/plc4go/protocols/eip/readwrite/model/CIPDataTypeCode.go b/plc4go/protocols/eip/readwrite/model/CIPDataTypeCode.go
index 96b37f2c18..be68579d81 100644
--- a/plc4go/protocols/eip/readwrite/model/CIPDataTypeCode.go
+++ b/plc4go/protocols/eip/readwrite/model/CIPDataTypeCode.go
@@ -44,7 +44,6 @@ const (
 	CIPDataTypeCode_DWORD      CIPDataTypeCode = 0x00D3
 	CIPDataTypeCode_STRUCTURED CIPDataTypeCode = 0x02A0
 	CIPDataTypeCode_STRING     CIPDataTypeCode = 0x02A0
-	CIPDataTypeCode_STRING36   CIPDataTypeCode = 0x02A0
 )
 
 var CIPDataTypeCodeValues []CIPDataTypeCode
@@ -61,7 +60,6 @@ func init() {
 		CIPDataTypeCode_DWORD,
 		CIPDataTypeCode_STRUCTURED,
 		CIPDataTypeCode_STRING,
-		CIPDataTypeCode_STRING36,
 	}
 }
 
diff --git a/plc4go/spi/PlcBrowser.go b/plc4go/spi/PlcBrowser.go
index 7b64883012..e9a51234c3 100644
--- a/plc4go/spi/PlcBrowser.go
+++ b/plc4go/spi/PlcBrowser.go
@@ -21,6 +21,7 @@ package spi
 
 import (
 	"context"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 )
 
@@ -34,5 +35,5 @@ type PlcBrowser interface {
 	// and increase throughput. It can also be used for simple filtering.
 	// If the interceptor function returns 'true' the result is added to the overall result
 	// if it's 'false' is is not.
-	BrowseWithInterceptor(ctx context.Context, browseRequest model.PlcBrowseRequest, interceptor func(result model.PlcBrowseEvent) bool) <-chan model.PlcBrowseRequestResult
+	BrowseWithInterceptor(ctx context.Context, browseRequest model.PlcBrowseRequest, interceptor func(result model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult
 }
diff --git a/plc4go/spi/PlcFieldHandler.go b/plc4go/spi/PlcFieldHandler.go
index 4eebbd993d..80ab23a4e1 100644
--- a/plc4go/spi/PlcFieldHandler.go
+++ b/plc4go/spi/PlcFieldHandler.go
@@ -22,6 +22,10 @@ package spi
 import "github.com/apache/plc4x/plc4go/pkg/api/model"
 
 type PlcFieldHandler interface {
+
+	// ParseField Parser function to parse query strings for a given driver and produce PlcField instances from that
+	ParseField(fieldQuery string) (model.PlcField, error)
+
 	// ParseQuery Parser function to parse query strings for a given driver and produce PlcField instances from that
-	ParseQuery(query string) (model.PlcField, error)
+	ParseQuery(query string) (model.PlcQuery, error)
 }
diff --git a/plc4go/spi/model/DefaultPlcBrowseEvent.go b/plc4go/spi/model/DefaultPlcBrowseEvent.go
index fa11d2a5c2..51d55e1905 100644
--- a/plc4go/spi/model/DefaultPlcBrowseEvent.go
+++ b/plc4go/spi/model/DefaultPlcBrowseEvent.go
@@ -26,8 +26,8 @@ import (
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcBrowseEvent
 type DefaultPlcBrowseEvent struct {
 	Request   model.PlcBrowseRequest
-	FieldName string
-	Result    model.PlcBrowseFoundField
+	QueryName string
+	Result    model.PlcBrowseItem
 	Err       error
 }
 
@@ -39,11 +39,11 @@ func (d *DefaultPlcBrowseEvent) GetRequest() model.PlcBrowseRequest {
 	return d.Request
 }
 
-func (d *DefaultPlcBrowseEvent) GetFieldName() string {
-	return d.FieldName
+func (d *DefaultPlcBrowseEvent) GetQueryName() string {
+	return d.QueryName
 }
 
-func (d *DefaultPlcBrowseEvent) GetResult() model.PlcBrowseFoundField {
+func (d *DefaultPlcBrowseEvent) GetResult() model.PlcBrowseItem {
 	return d.Result
 }
 
diff --git a/plc4go/spi/model/DefaultPlcBrowseEvent_plc4xgen.go b/plc4go/spi/model/DefaultPlcBrowseEvent_plc4xgen.go
index e2410addf8..c22818153f 100644
--- a/plc4go/spi/model/DefaultPlcBrowseEvent_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcBrowseEvent_plc4xgen.go
@@ -61,7 +61,7 @@ func (d *DefaultPlcBrowseEvent) SerializeWithWriteBuffer(writeBuffer utils.Write
 		}
 	}
 
-	if err := writeBuffer.WriteString("fieldName", uint32(len(d.FieldName)*8), "UTF-8", d.FieldName); err != nil {
+	if err := writeBuffer.WriteString("queryName", uint32(len(d.QueryName)*8), "UTF-8", d.QueryName); err != nil {
 		return err
 	}
 
diff --git a/plc4go/spi/model/DefaultPlcBrowseQueryResult.go b/plc4go/spi/model/DefaultPlcBrowseItem.go
similarity index 50%
rename from plc4go/spi/model/DefaultPlcBrowseQueryResult.go
rename to plc4go/spi/model/DefaultPlcBrowseItem.go
index 9a78476ddf..31aa4883d8 100644
--- a/plc4go/spi/model/DefaultPlcBrowseQueryResult.go
+++ b/plc4go/spi/model/DefaultPlcBrowseItem.go
@@ -24,41 +24,56 @@ import (
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
-//go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcBrowseQueryResult
-type DefaultPlcBrowseQueryResult struct {
-	Field             model.PlcField
-	Name              string
-	Readable          bool
-	Writable          bool
-	Subscribable      bool
-	PossibleDataTypes []string
-	Attributes        map[string]values.PlcValue
+//go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcBrowseItem
+type DefaultPlcBrowseItem struct {
+	Field        model.PlcField
+	Address      string
+	Name         string
+	PlcValueType values.PlcValueType
+	ArrayInfo    []model.PlcBrowseItemArrayInfo
+	Readable     bool
+	Writable     bool
+	Subscribable bool
+	Children     map[string]model.PlcBrowseItem
+	Options      map[string]values.PlcValue
 }
 
-func (d *DefaultPlcBrowseQueryResult) GetField() model.PlcField {
+func (d *DefaultPlcBrowseItem) GetField() model.PlcField {
 	return d.Field
 }
 
-func (d *DefaultPlcBrowseQueryResult) GetName() string {
+func (d *DefaultPlcBrowseItem) GetAddress() string {
+	return d.Address
+}
+
+func (d *DefaultPlcBrowseItem) GetName() string {
 	return d.Name
 }
 
-func (d *DefaultPlcBrowseQueryResult) IsReadable() bool {
+func (d *DefaultPlcBrowseItem) GetPlcValueType() values.PlcValueType {
+	return d.PlcValueType
+}
+
+func (d *DefaultPlcBrowseItem) GetArrayInfo() []model.PlcBrowseItemArrayInfo {
+	return d.ArrayInfo
+}
+
+func (d *DefaultPlcBrowseItem) IsReadable() bool {
 	return d.Readable
 }
 
-func (d *DefaultPlcBrowseQueryResult) IsWritable() bool {
+func (d *DefaultPlcBrowseItem) IsWritable() bool {
 	return d.Writable
 }
 
-func (d *DefaultPlcBrowseQueryResult) IsSubscribable() bool {
+func (d *DefaultPlcBrowseItem) IsSubscribable() bool {
 	return d.Subscribable
 }
 
-func (d *DefaultPlcBrowseQueryResult) GetPossibleDataTypes() []string {
-	return d.PossibleDataTypes
+func (d *DefaultPlcBrowseItem) GetChildren() map[string]model.PlcBrowseItem {
+	return d.Children
 }
 
-func (d *DefaultPlcBrowseQueryResult) GetAttributes() map[string]values.PlcValue {
-	return d.Attributes
+func (d *DefaultPlcBrowseItem) GetOptions() map[string]values.PlcValue {
+	return d.Options
 }
diff --git a/plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go b/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
similarity index 50%
copy from plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go
copy to plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
index 454b3dd072..8400dede29 100644
--- a/plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xgenerator -type=DefaultPlcBrowseQueryResult"; DO NOT EDIT.
+// Code generated by "plc4xgenerator -type=DefaultPlcBrowseItem"; DO NOT EDIT.
 
 package model
 
@@ -29,7 +29,7 @@ import (
 
 var _ = fmt.Printf
 
-func (d *DefaultPlcBrowseQueryResult) Serialize() ([]byte, error) {
+func (d *DefaultPlcBrowseItem) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := d.SerializeWithWriteBuffer(wb); err != nil {
 		return nil, err
@@ -37,8 +37,8 @@ func (d *DefaultPlcBrowseQueryResult) Serialize() ([]byte, error) {
 	return wb.GetBytes(), nil
 }
 
-func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
-	if err := writeBuffer.PushContext("PlcBrowseQueryResult"); err != nil {
+func (d *DefaultPlcBrowseItem) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+	if err := writeBuffer.PushContext("PlcBrowseItem"); err != nil {
 		return err
 	}
 
@@ -61,10 +61,61 @@ func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils
 		}
 	}
 
+	if err := writeBuffer.WriteString("address", uint32(len(d.Address)*8), "UTF-8", d.Address); err != nil {
+		return err
+	}
+
 	if err := writeBuffer.WriteString("name", uint32(len(d.Name)*8), "UTF-8", d.Name); err != nil {
 		return err
 	}
 
+	if d.PlcValueType != nil {
+		if serializableField, ok := d.PlcValueType.(utils.Serializable); ok {
+			if err := writeBuffer.PushContext("plcValueType"); err != nil {
+				return err
+			}
+			if err := serializableField.SerializeWithWriteBuffer(writeBuffer); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext("plcValueType"); err != nil {
+				return err
+			}
+		} else {
+			stringValue := fmt.Sprintf("%v", d.PlcValueType)
+			if err := writeBuffer.WriteString("plcValueType", uint32(len(stringValue)*8), "UTF-8", stringValue); err != nil {
+				return err
+			}
+		}
+	}
+	if err := writeBuffer.PushContext("arrayInfo", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	for _, elem := range d.ArrayInfo {
+		var elem interface{} = elem
+
+		if elem != nil {
+			if serializableField, ok := elem.(utils.Serializable); ok {
+				if err := writeBuffer.PushContext("value"); err != nil {
+					return err
+				}
+				if err := serializableField.SerializeWithWriteBuffer(writeBuffer); err != nil {
+					return err
+				}
+				if err := writeBuffer.PopContext("value"); err != nil {
+					return err
+				}
+			} else {
+				stringValue := fmt.Sprintf("%v", elem)
+				if err := writeBuffer.WriteString("value", uint32(len(stringValue)*8), "UTF-8", stringValue); err != nil {
+					return err
+				}
+			}
+		}
+	}
+	if err := writeBuffer.PopContext("arrayInfo", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+
 	if err := writeBuffer.WriteBit("readable", d.Readable); err != nil {
 		return err
 	}
@@ -76,21 +127,36 @@ func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils
 	if err := writeBuffer.WriteBit("subscribable", d.Subscribable); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("possibleDataTypes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("children", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for _, elem := range d.PossibleDataTypes {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
-			return err
+	for name, elem := range d.Children {
+
+		var elem interface{} = elem
+		if serializable, ok := elem.(utils.Serializable); ok {
+			if err := writeBuffer.PushContext(name); err != nil {
+				return err
+			}
+			if err := serializable.SerializeWithWriteBuffer(writeBuffer); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext(name); err != nil {
+				return err
+			}
+		} else {
+			elemAsString := fmt.Sprintf("%v", elem)
+			if err := writeBuffer.WriteString(name, uint32(len(elemAsString)*8), "UTF-8", elemAsString); err != nil {
+				return err
+			}
 		}
 	}
-	if err := writeBuffer.PopContext("possibleDataTypes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("children", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("attributes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("options", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for name, elem := range d.Attributes {
+	for name, elem := range d.Options {
 
 		var elem interface{} = elem
 		if serializable, ok := elem.(utils.Serializable); ok {
@@ -110,16 +176,16 @@ func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils
 			}
 		}
 	}
-	if err := writeBuffer.PopContext("attributes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("options", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PopContext("PlcBrowseQueryResult"); err != nil {
+	if err := writeBuffer.PopContext("PlcBrowseItem"); err != nil {
 		return err
 	}
 	return nil
 }
 
-func (d *DefaultPlcBrowseQueryResult) String() string {
+func (d *DefaultPlcBrowseItem) String() string {
 	writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
 	if err := writeBuffer.WriteSerializable(d); err != nil {
 		return err.Error()
diff --git a/plc4go/spi/model/DefaultPlcBrowseRequest.go b/plc4go/spi/model/DefaultPlcBrowseRequest.go
index 1a964c0d7f..436b75b287 100644
--- a/plc4go/spi/model/DefaultPlcBrowseRequest.go
+++ b/plc4go/spi/model/DefaultPlcBrowseRequest.go
@@ -30,55 +30,51 @@ import (
 type DefaultPlcBrowseRequestBuilder struct {
 	fieldHandler spi.PlcFieldHandler
 	browser      spi.PlcBrowser
-	queries      map[string]string
+	// The double structure is in order to preserve the order of elements.
 	queryNames   []string
-	fields       map[string]model.PlcField
-	fieldNames   []string
+	queryStrings map[string]string
 }
 
 func NewDefaultPlcBrowseRequestBuilder(fieldHandler spi.PlcFieldHandler, browser spi.PlcBrowser) *DefaultPlcBrowseRequestBuilder {
 	return &DefaultPlcBrowseRequestBuilder{
 		fieldHandler: fieldHandler,
 		browser:      browser,
-		queries:      map[string]string{},
-		fields:       map[string]model.PlcField{},
+		queryStrings: map[string]string{},
 	}
 }
 
 func (d *DefaultPlcBrowseRequestBuilder) AddQuery(name string, query string) model.PlcBrowseRequestBuilder {
 	d.queryNames = append(d.queryNames, name)
-	d.queries[name] = query
-	return d
-}
-
-func (d *DefaultPlcBrowseRequestBuilder) AddField(name string, field model.PlcField) model.PlcBrowseRequestBuilder {
-	d.fieldNames = append(d.fieldNames, name)
-	d.fields[name] = field
+	d.queryStrings[name] = query
 	return d
 }
 
 func (d *DefaultPlcBrowseRequestBuilder) Build() (model.PlcBrowseRequest, error) {
-	for _, name := range d.queryNames {
-		query := d.queries[name]
-		field, err := d.fieldHandler.ParseQuery(query)
+	queries := map[string]model.PlcQuery{}
+	for name, queryString := range d.queryStrings {
+		query, err := d.fieldHandler.ParseQuery(queryString)
 		if err != nil {
 			return nil, errors.Wrapf(err, "Error parsing query: %s", query)
 		}
-		d.AddField(name, field)
+		queries[name] = query
 	}
-	return NewDefaultPlcBrowseRequest(d.fields, d.fieldNames, d.browser), nil
+	return NewDefaultPlcBrowseRequest(queries, d.queryNames, d.browser), nil
 }
 
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcBrowseRequest
 type DefaultPlcBrowseRequest struct {
-	DefaultRequest
-	browser spi.PlcBrowser
+	DefaultPlcRequest
+	browser    spi.PlcBrowser
+	queryNames []string
+	queries    map[string]model.PlcQuery
 }
 
-func NewDefaultPlcBrowseRequest(fields map[string]model.PlcField, fieldNames []string, browser spi.PlcBrowser) model.PlcBrowseRequest {
+func NewDefaultPlcBrowseRequest(queries map[string]model.PlcQuery, queryNames []string, browser spi.PlcBrowser) model.PlcBrowseRequest {
 	return &DefaultPlcBrowseRequest{
-		DefaultRequest: NewDefaultRequest(fields, fieldNames),
-		browser:        browser,
+		DefaultPlcRequest: DefaultPlcRequest{},
+		browser:           browser,
+		queryNames:        queryNames,
+		queries:           queries,
 	}
 }
 
@@ -90,10 +86,18 @@ func (d *DefaultPlcBrowseRequest) ExecuteWithContext(ctx context.Context) <-chan
 	return d.browser.Browse(ctx, d)
 }
 
-func (d *DefaultPlcBrowseRequest) ExecuteWithInterceptor(interceptor func(result model.PlcBrowseEvent) bool) <-chan model.PlcBrowseRequestResult {
+func (d *DefaultPlcBrowseRequest) ExecuteWithInterceptor(interceptor func(result model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult {
 	return d.ExecuteWithInterceptorWithContext(context.TODO(), interceptor)
 }
 
-func (d *DefaultPlcBrowseRequest) ExecuteWithInterceptorWithContext(ctx context.Context, interceptor func(result model.PlcBrowseEvent) bool) <-chan model.PlcBrowseRequestResult {
+func (d *DefaultPlcBrowseRequest) ExecuteWithInterceptorWithContext(ctx context.Context, interceptor func(result model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult {
 	return d.browser.BrowseWithInterceptor(ctx, d, interceptor)
 }
+
+func (d *DefaultPlcBrowseRequest) GetQueryNames() []string {
+	return d.queryNames
+}
+
+func (d *DefaultPlcBrowseRequest) GetQuery(queryName string) model.PlcQuery {
+	return d.queries[queryName]
+}
diff --git a/plc4go/spi/model/DefaultPlcBrowseRequest_plc4xgen.go b/plc4go/spi/model/DefaultPlcBrowseRequest_plc4xgen.go
index edf5d5931f..7f85349b2e 100644
--- a/plc4go/spi/model/DefaultPlcBrowseRequest_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcBrowseRequest_plc4xgen.go
@@ -41,7 +41,7 @@ func (d *DefaultPlcBrowseRequest) SerializeWithWriteBuffer(writeBuffer utils.Wri
 	if err := writeBuffer.PushContext("PlcBrowseRequest"); err != nil {
 		return err
 	}
-	if err := d.DefaultRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
+	if err := d.DefaultPlcRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
 		return err
 	}
 
@@ -63,6 +63,43 @@ func (d *DefaultPlcBrowseRequest) SerializeWithWriteBuffer(writeBuffer utils.Wri
 			}
 		}
 	}
+	if err := writeBuffer.PushContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	for _, elem := range d.queryNames {
+		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
+			return err
+		}
+	}
+	if err := writeBuffer.PopContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	if err := writeBuffer.PushContext("queries", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	for name, elem := range d.queries {
+
+		var elem interface{} = elem
+		if serializable, ok := elem.(utils.Serializable); ok {
+			if err := writeBuffer.PushContext(name); err != nil {
+				return err
+			}
+			if err := serializable.SerializeWithWriteBuffer(writeBuffer); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext(name); err != nil {
+				return err
+			}
+		} else {
+			elemAsString := fmt.Sprintf("%v", elem)
+			if err := writeBuffer.WriteString(name, uint32(len(elemAsString)*8), "UTF-8", elemAsString); err != nil {
+				return err
+			}
+		}
+	}
+	if err := writeBuffer.PopContext("queries", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
 	if err := writeBuffer.PopContext("PlcBrowseRequest"); err != nil {
 		return err
 	}
diff --git a/plc4go/spi/model/DefaultPlcBrowseResponse.go b/plc4go/spi/model/DefaultPlcBrowseResponse.go
index 0f3a4b7a51..ce1a3c7f79 100644
--- a/plc4go/spi/model/DefaultPlcBrowseResponse.go
+++ b/plc4go/spi/model/DefaultPlcBrowseResponse.go
@@ -21,6 +21,7 @@ package model
 
 import (
 	"encoding/binary"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
@@ -29,8 +30,9 @@ import (
 // TODO: use generator once we figured out how to render results with ast
 type DefaultPlcBrowseResponse struct {
 	DefaultResponse
-	request model.PlcBrowseRequest
-	results map[string][]model.PlcBrowseFoundField
+	request      model.PlcBrowseRequest
+	responseCode model.PlcResponseCode
+	results      map[string][]model.PlcBrowseFoundField
 }
 
 func NewDefaultPlcBrowseResponse(request model.PlcBrowseRequest, results map[string][]model.PlcBrowseFoundField, responseCodes map[string]model.PlcResponseCode) DefaultPlcBrowseResponse {
diff --git a/plc4go/spi/model/DefaultRequest.go b/plc4go/spi/model/DefaultPlcFieldRequest.go
similarity index 72%
rename from plc4go/spi/model/DefaultRequest.go
rename to plc4go/spi/model/DefaultPlcFieldRequest.go
index 032d444932..734020770b 100644
--- a/plc4go/spi/model/DefaultRequest.go
+++ b/plc4go/spi/model/DefaultPlcFieldRequest.go
@@ -23,25 +23,25 @@ import (
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 )
 
-//go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultRequest
-type DefaultRequest struct {
+//go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcFieldRequest
+type DefaultPlcFieldRequest struct {
 	fields     map[string]model.PlcField
 	fieldNames []string
 }
 
-func (d *DefaultRequest) IsAPlcMessage() bool {
+func (d *DefaultPlcFieldRequest) IsAPlcMessage() bool {
 	return true
 }
 
-func NewDefaultRequest(Fields map[string]model.PlcField, FieldNames []string) DefaultRequest {
-	return DefaultRequest{Fields, FieldNames}
+func NewDefaultPlcFieldRequest(fields map[string]model.PlcField, fieldNames []string) DefaultPlcFieldRequest {
+	return DefaultPlcFieldRequest{fields: fields, fieldNames: fieldNames}
 }
 
-func (d *DefaultRequest) GetFieldNames() []string {
+func (d *DefaultPlcFieldRequest) GetFieldNames() []string {
 	return d.fieldNames
 }
 
-func (d *DefaultRequest) GetField(name string) model.PlcField {
+func (d *DefaultPlcFieldRequest) GetField(name string) model.PlcField {
 	if field, ok := d.fields[name]; ok {
 		return field
 	}
diff --git a/plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go b/plc4go/spi/model/DefaultPlcFieldRequest_plc4xgen.go
similarity index 54%
rename from plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go
rename to plc4go/spi/model/DefaultPlcFieldRequest_plc4xgen.go
index 454b3dd072..03a75f4e14 100644
--- a/plc4go/spi/model/DefaultPlcBrowseQueryResult_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcFieldRequest_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xgenerator -type=DefaultPlcBrowseQueryResult"; DO NOT EDIT.
+// Code generated by "plc4xgenerator -type=DefaultPlcFieldRequest"; DO NOT EDIT.
 
 package model
 
@@ -29,7 +29,7 @@ import (
 
 var _ = fmt.Printf
 
-func (d *DefaultPlcBrowseQueryResult) Serialize() ([]byte, error) {
+func (d *DefaultPlcFieldRequest) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := d.SerializeWithWriteBuffer(wb); err != nil {
 		return nil, err
@@ -37,60 +37,14 @@ func (d *DefaultPlcBrowseQueryResult) Serialize() ([]byte, error) {
 	return wb.GetBytes(), nil
 }
 
-func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
-	if err := writeBuffer.PushContext("PlcBrowseQueryResult"); err != nil {
+func (d *DefaultPlcFieldRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+	if err := writeBuffer.PushContext("PlcFieldRequest"); err != nil {
 		return err
 	}
-
-	if d.Field != nil {
-		if serializableField, ok := d.Field.(utils.Serializable); ok {
-			if err := writeBuffer.PushContext("field"); err != nil {
-				return err
-			}
-			if err := serializableField.SerializeWithWriteBuffer(writeBuffer); err != nil {
-				return err
-			}
-			if err := writeBuffer.PopContext("field"); err != nil {
-				return err
-			}
-		} else {
-			stringValue := fmt.Sprintf("%v", d.Field)
-			if err := writeBuffer.WriteString("field", uint32(len(stringValue)*8), "UTF-8", stringValue); err != nil {
-				return err
-			}
-		}
-	}
-
-	if err := writeBuffer.WriteString("name", uint32(len(d.Name)*8), "UTF-8", d.Name); err != nil {
-		return err
-	}
-
-	if err := writeBuffer.WriteBit("readable", d.Readable); err != nil {
-		return err
-	}
-
-	if err := writeBuffer.WriteBit("writable", d.Writable); err != nil {
-		return err
-	}
-
-	if err := writeBuffer.WriteBit("subscribable", d.Subscribable); err != nil {
-		return err
-	}
-	if err := writeBuffer.PushContext("possibleDataTypes", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for _, elem := range d.PossibleDataTypes {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
-			return err
-		}
-	}
-	if err := writeBuffer.PopContext("possibleDataTypes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fields", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("attributes", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for name, elem := range d.Attributes {
+	for name, elem := range d.fields {
 
 		var elem interface{} = elem
 		if serializable, ok := elem.(utils.Serializable); ok {
@@ -110,16 +64,27 @@ func (d *DefaultPlcBrowseQueryResult) SerializeWithWriteBuffer(writeBuffer utils
 			}
 		}
 	}
-	if err := writeBuffer.PopContext("attributes", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fields", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
+		return err
+	}
+	for _, elem := range d.fieldNames {
+		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
+			return err
+		}
+	}
+	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PopContext("PlcBrowseQueryResult"); err != nil {
+	if err := writeBuffer.PopContext("PlcFieldRequest"); err != nil {
 		return err
 	}
 	return nil
 }
 
-func (d *DefaultPlcBrowseQueryResult) String() string {
+func (d *DefaultPlcFieldRequest) String() string {
 	writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
 	if err := writeBuffer.WriteSerializable(d); err != nil {
 		return err.Error()
diff --git a/plc4go/spi/model/DefaultPlcReadRequest.go b/plc4go/spi/model/DefaultPlcReadRequest.go
index 33916349c5..4053167693 100644
--- a/plc4go/spi/model/DefaultPlcReadRequest.go
+++ b/plc4go/spi/model/DefaultPlcReadRequest.go
@@ -21,21 +21,21 @@ package model
 
 import (
 	"context"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi"
 	"github.com/apache/plc4x/plc4go/spi/interceptors"
 	"github.com/pkg/errors"
-	"time"
 )
 
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcReadRequestBuilder
 type DefaultPlcReadRequestBuilder struct {
 	reader                 spi.PlcReader
 	fieldHandler           spi.PlcFieldHandler
-	queries                map[string]string
-	queryNames             []string
-	fields                 map[string]model.PlcField
 	fieldNames             []string
+	fieldQueries           map[string]string
+	fields                 map[string]model.PlcField
 	readRequestInterceptor interceptors.ReadRequestInterceptor
 }
 
@@ -47,48 +47,51 @@ func NewDefaultPlcReadRequestBuilderWithInterceptor(fieldHandler spi.PlcFieldHan
 	return &DefaultPlcReadRequestBuilder{
 		reader:                 reader,
 		fieldHandler:           fieldHandler,
-		queries:                map[string]string{},
-		queryNames:             make([]string, 0),
-		fields:                 map[string]model.PlcField{},
 		fieldNames:             make([]string, 0),
+		fieldQueries:           map[string]string{},
+		fields:                 map[string]model.PlcField{},
 		readRequestInterceptor: readRequestInterceptor,
 	}
 }
 
-func (m *DefaultPlcReadRequestBuilder) AddQuery(name string, query string) model.PlcReadRequestBuilder {
-	m.queryNames = append(m.queryNames, name)
-	m.queries[name] = query
-	return m
+func (d *DefaultPlcReadRequestBuilder) AddFieldQuery(name string, query string) model.PlcReadRequestBuilder {
+	d.fieldNames = append(d.fieldNames, name)
+	d.fieldQueries[name] = query
+	return d
 }
 
-func (m *DefaultPlcReadRequestBuilder) AddField(name string, field model.PlcField) model.PlcReadRequestBuilder {
-	m.fieldNames = append(m.fieldNames, name)
-	m.fields[name] = field
-	return m
+func (d *DefaultPlcReadRequestBuilder) AddField(name string, field model.PlcField) model.PlcReadRequestBuilder {
+	d.fieldNames = append(d.fieldNames, name)
+	d.fields[name] = field
+	return d
 }
 
-func (m *DefaultPlcReadRequestBuilder) Build() (model.PlcReadRequest, error) {
-	for _, name := range m.queryNames {
-		query := m.queries[name]
-		field, err := m.fieldHandler.ParseQuery(query)
-		if err != nil {
-			return nil, errors.Wrapf(err, "Error parsing query: %s", query)
+func (d *DefaultPlcReadRequestBuilder) Build() (model.PlcReadRequest, error) {
+	for _, name := range d.fieldNames {
+		if fieldQuery, ok := d.fieldQueries[name]; ok {
+			field, err := d.fieldHandler.ParseField(fieldQuery)
+			if err != nil {
+				return nil, errors.Wrapf(err, "Error parsing field query: %s", fieldQuery)
+			}
+			d.fields[name] = field
 		}
-		m.AddField(name, field)
 	}
-	return NewDefaultPlcReadRequest(m.fields, m.fieldNames, m.reader, m.readRequestInterceptor), nil
+	// Reset the queries
+	d.fieldQueries = map[string]string{}
+
+	return NewDefaultPlcReadRequest(d.fields, d.fieldNames, d.reader, d.readRequestInterceptor), nil
 }
 
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcReadRequest
 type DefaultPlcReadRequest struct {
-	DefaultRequest
+	DefaultPlcFieldRequest
 	reader                 spi.PlcReader
 	readRequestInterceptor interceptors.ReadRequestInterceptor
 }
 
 func NewDefaultPlcReadRequest(fields map[string]model.PlcField, fieldNames []string, reader spi.PlcReader, readRequestInterceptor interceptors.ReadRequestInterceptor) model.PlcReadRequest {
 	return &DefaultPlcReadRequest{
-		DefaultRequest:         NewDefaultRequest(fields, fieldNames),
+		DefaultPlcFieldRequest: NewDefaultPlcFieldRequest(fields, fieldNames),
 		reader:                 reader,
 		readRequestInterceptor: readRequestInterceptor,
 	}
diff --git a/plc4go/spi/model/DefaultPlcReadRequestBuilder_plc4xgen.go b/plc4go/spi/model/DefaultPlcReadRequestBuilder_plc4xgen.go
index e55dbde894..1a1f6b7625 100644
--- a/plc4go/spi/model/DefaultPlcReadRequestBuilder_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcReadRequestBuilder_plc4xgen.go
@@ -79,27 +79,27 @@ func (d *DefaultPlcReadRequestBuilder) SerializeWithWriteBuffer(writeBuffer util
 			}
 		}
 	}
-	if err := writeBuffer.PushContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for name, elem := range d.queries {
-
-		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for _, elem := range d.fieldNames {
+		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for _, elem := range d.queryNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for name, elem := range d.fieldQueries {
+
+		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
 	if err := writeBuffer.PushContext("fields", utils.WithRenderAsList(true)); err != nil {
@@ -128,17 +128,6 @@ func (d *DefaultPlcReadRequestBuilder) SerializeWithWriteBuffer(writeBuffer util
 	if err := writeBuffer.PopContext("fields", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for _, elem := range d.fieldNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
-			return err
-		}
-	}
-	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
 
 	if d.readRequestInterceptor != nil {
 		if serializableField, ok := d.readRequestInterceptor.(utils.Serializable); ok {
diff --git a/plc4go/spi/model/DefaultPlcReadRequest_plc4xgen.go b/plc4go/spi/model/DefaultPlcReadRequest_plc4xgen.go
index 0a706fb006..d6fed52d48 100644
--- a/plc4go/spi/model/DefaultPlcReadRequest_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcReadRequest_plc4xgen.go
@@ -41,7 +41,7 @@ func (d *DefaultPlcReadRequest) SerializeWithWriteBuffer(writeBuffer utils.Write
 	if err := writeBuffer.PushContext("PlcReadRequest"); err != nil {
 		return err
 	}
-	if err := d.DefaultRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
+	if err := d.DefaultPlcFieldRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
 		return err
 	}
 
diff --git a/plc4go/spi/PlcFieldHandler.go b/plc4go/spi/model/DefaultPlcRequest.go
similarity index 80%
copy from plc4go/spi/PlcFieldHandler.go
copy to plc4go/spi/model/DefaultPlcRequest.go
index 4eebbd993d..ac8b62ad8c 100644
--- a/plc4go/spi/PlcFieldHandler.go
+++ b/plc4go/spi/model/DefaultPlcRequest.go
@@ -17,11 +17,17 @@
  * under the License.
  */
 
-package spi
+package model
 
 import "github.com/apache/plc4x/plc4go/pkg/api/model"
 
-type PlcFieldHandler interface {
-	// ParseQuery Parser function to parse query strings for a given driver and produce PlcField instances from that
-	ParseQuery(query string) (model.PlcField, error)
+type DefaultPlcRequest struct {
+}
+
+func NewDefaultPlcRequest() model.PlcRequest {
+	return &DefaultPlcRequest{}
+}
+
+func (d *DefaultPlcRequest) IsAPlcMessage() bool {
+	return true
 }
diff --git a/plc4go/spi/model/DefaultPlcSubscriptionRequest.go b/plc4go/spi/model/DefaultPlcSubscriptionRequest.go
index cb8cd00195..7140f92bc0 100644
--- a/plc4go/spi/model/DefaultPlcSubscriptionRequest.go
+++ b/plc4go/spi/model/DefaultPlcSubscriptionRequest.go
@@ -21,10 +21,11 @@ package model
 
 import (
 	"context"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi"
 	"github.com/pkg/errors"
-	"time"
 )
 
 type SubscriptionType uint8
@@ -53,10 +54,9 @@ type DefaultPlcSubscriptionRequestBuilder struct {
 	subscriber             spi.PlcSubscriber
 	fieldHandler           spi.PlcFieldHandler
 	valueHandler           spi.PlcValueHandler
-	queries                map[string]string
-	queryNames             []string
-	fields                 map[string]model.PlcField
 	fieldNames             []string
+	fieldQueries           map[string]string
+	fields                 map[string]model.PlcField
 	types                  map[string]SubscriptionType
 	intervals              map[string]time.Duration
 	preRegisteredConsumers map[string][]model.PlcSubscriptionEventConsumer `ignore:"true"`
@@ -67,18 +67,18 @@ func NewDefaultPlcSubscriptionRequestBuilder(fieldHandler spi.PlcFieldHandler, v
 		subscriber:             subscriber,
 		fieldHandler:           fieldHandler,
 		valueHandler:           valueHandler,
-		queries:                map[string]string{},
-		fields:                 map[string]model.PlcField{},
 		fieldNames:             make([]string, 0),
+		fieldQueries:           map[string]string{},
+		fields:                 map[string]model.PlcField{},
 		types:                  map[string]SubscriptionType{},
 		intervals:              map[string]time.Duration{},
 		preRegisteredConsumers: make(map[string][]model.PlcSubscriptionEventConsumer),
 	}
 }
 
-func (d *DefaultPlcSubscriptionRequestBuilder) AddCyclicQuery(name string, query string, interval time.Duration) model.PlcSubscriptionRequestBuilder {
-	d.queryNames = append(d.queryNames, name)
-	d.queries[name] = query
+func (d *DefaultPlcSubscriptionRequestBuilder) AddCyclicFieldQuery(name string, query string, interval time.Duration) model.PlcSubscriptionRequestBuilder {
+	d.fieldNames = append(d.fieldNames, name)
+	d.fieldQueries[name] = query
 	d.types[name] = SubscriptionCyclic
 	d.intervals[name] = interval
 	return d
@@ -92,9 +92,9 @@ func (d *DefaultPlcSubscriptionRequestBuilder) AddCyclicField(name string, field
 	return d
 }
 
-func (d *DefaultPlcSubscriptionRequestBuilder) AddChangeOfStateQuery(name string, query string) model.PlcSubscriptionRequestBuilder {
-	d.queryNames = append(d.queryNames, name)
-	d.queries[name] = query
+func (d *DefaultPlcSubscriptionRequestBuilder) AddChangeOfStateFieldQuery(name string, query string) model.PlcSubscriptionRequestBuilder {
+	d.fieldNames = append(d.fieldNames, name)
+	d.fieldQueries[name] = query
 	d.types[name] = SubscriptionChangeOfState
 	return d
 }
@@ -106,9 +106,9 @@ func (d *DefaultPlcSubscriptionRequestBuilder) AddChangeOfStateField(name string
 	return d
 }
 
-func (d *DefaultPlcSubscriptionRequestBuilder) AddEventQuery(name string, query string) model.PlcSubscriptionRequestBuilder {
-	d.queryNames = append(d.queryNames, name)
-	d.queries[name] = query
+func (d *DefaultPlcSubscriptionRequestBuilder) AddEventFieldQuery(name string, query string) model.PlcSubscriptionRequestBuilder {
+	d.fieldNames = append(d.fieldNames, name)
+	d.fieldQueries[name] = query
 	d.types[name] = SubscriptionEvent
 	return d
 }
@@ -129,21 +129,21 @@ func (d *DefaultPlcSubscriptionRequestBuilder) AddPreRegisteredConsumer(name str
 }
 
 func (d *DefaultPlcSubscriptionRequestBuilder) Build() (model.PlcSubscriptionRequest, error) {
-	for _, name := range d.queryNames {
-		query := d.queries[name]
-		field, err := d.fieldHandler.ParseQuery(query)
-		if err != nil {
-			return nil, errors.Wrapf(err, "Error parsing query: %s", query)
+	for _, name := range d.fieldNames {
+		if fieldQuery, ok := d.fieldQueries[name]; ok {
+			field, err := d.fieldHandler.ParseField(fieldQuery)
+			if err != nil {
+				return nil, errors.Wrapf(err, "Error parsing field query: %s", fieldQuery)
+			}
+			d.fields[name] = field
 		}
-		d.fieldNames = append(d.fieldNames, name)
-		d.fields[name] = field
 	}
 	return NewDefaultPlcSubscriptionRequest(d.fields, d.fieldNames, d.types, d.intervals, d.subscriber, d.preRegisteredConsumers), nil
 }
 
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcSubscriptionRequest
 type DefaultPlcSubscriptionRequest struct {
-	DefaultRequest
+	DefaultPlcFieldRequest
 	types                  map[string]SubscriptionType
 	intervals              map[string]time.Duration
 	subscriber             spi.PlcSubscriber
@@ -151,7 +151,7 @@ type DefaultPlcSubscriptionRequest struct {
 }
 
 func NewDefaultPlcSubscriptionRequest(fields map[string]model.PlcField, fieldNames []string, types map[string]SubscriptionType, intervals map[string]time.Duration, subscriber spi.PlcSubscriber, preRegisteredConsumers map[string][]model.PlcSubscriptionEventConsumer) model.PlcSubscriptionRequest {
-	return &DefaultPlcSubscriptionRequest{NewDefaultRequest(fields, fieldNames), types, intervals, subscriber, preRegisteredConsumers}
+	return &DefaultPlcSubscriptionRequest{NewDefaultPlcFieldRequest(fields, fieldNames), types, intervals, subscriber, preRegisteredConsumers}
 }
 
 func (d *DefaultPlcSubscriptionRequest) Execute() <-chan model.PlcSubscriptionRequestResult {
diff --git a/plc4go/spi/model/DefaultPlcSubscriptionRequestBuilder_plc4xgen.go b/plc4go/spi/model/DefaultPlcSubscriptionRequestBuilder_plc4xgen.go
index 5e5edd8f4d..45c58eea87 100644
--- a/plc4go/spi/model/DefaultPlcSubscriptionRequestBuilder_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcSubscriptionRequestBuilder_plc4xgen.go
@@ -98,27 +98,27 @@ func (d *DefaultPlcSubscriptionRequestBuilder) SerializeWithWriteBuffer(writeBuf
 			}
 		}
 	}
-	if err := writeBuffer.PushContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for name, elem := range d.queries {
-
-		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for _, elem := range d.fieldNames {
+		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for _, elem := range d.queryNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for name, elem := range d.fieldQueries {
+
+		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
 	if err := writeBuffer.PushContext("fields", utils.WithRenderAsList(true)); err != nil {
@@ -147,17 +147,6 @@ func (d *DefaultPlcSubscriptionRequestBuilder) SerializeWithWriteBuffer(writeBuf
 	if err := writeBuffer.PopContext("fields", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for _, elem := range d.fieldNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
-			return err
-		}
-	}
-	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
 	if err := writeBuffer.PushContext("types", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
diff --git a/plc4go/spi/model/DefaultPlcSubscriptionRequest_plc4xgen.go b/plc4go/spi/model/DefaultPlcSubscriptionRequest_plc4xgen.go
index 13fc0801e0..12f4a1000a 100644
--- a/plc4go/spi/model/DefaultPlcSubscriptionRequest_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcSubscriptionRequest_plc4xgen.go
@@ -41,7 +41,7 @@ func (d *DefaultPlcSubscriptionRequest) SerializeWithWriteBuffer(writeBuffer uti
 	if err := writeBuffer.PushContext("PlcSubscriptionRequest"); err != nil {
 		return err
 	}
-	if err := d.DefaultRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
+	if err := d.DefaultPlcFieldRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
 		return err
 	}
 	if err := writeBuffer.PushContext("types", utils.WithRenderAsList(true)); err != nil {
diff --git a/plc4go/spi/model/DefaultPlcWriteRequest.go b/plc4go/spi/model/DefaultPlcWriteRequest.go
index 66f5518167..7a92a4c2d1 100644
--- a/plc4go/spi/model/DefaultPlcWriteRequest.go
+++ b/plc4go/spi/model/DefaultPlcWriteRequest.go
@@ -35,10 +35,9 @@ type DefaultPlcWriteRequestBuilder struct {
 	writer                  spi.PlcWriter
 	fieldHandler            spi.PlcFieldHandler
 	valueHandler            spi.PlcValueHandler
-	queries                 map[string]string
-	queryNames              []string
-	fields                  map[string]model.PlcField
 	fieldNames              []string
+	fieldQueries            map[string]string
+	fields                  map[string]model.PlcField
 	values                  map[string]interface{}
 	writeRequestInterceptor interceptors.WriteRequestInterceptor
 }
@@ -48,10 +47,9 @@ func NewDefaultPlcWriteRequestBuilder(fieldHandler spi.PlcFieldHandler, valueHan
 		writer:       writer,
 		fieldHandler: fieldHandler,
 		valueHandler: valueHandler,
-		queries:      map[string]string{},
-		queryNames:   make([]string, 0),
-		fields:       map[string]model.PlcField{},
 		fieldNames:   make([]string, 0),
+		fieldQueries: map[string]string{},
+		fields:       map[string]model.PlcField{},
 		values:       map[string]interface{}{},
 	}
 }
@@ -61,10 +59,9 @@ func NewDefaultPlcWriteRequestBuilderWithInterceptor(fieldHandler spi.PlcFieldHa
 		writer:                  writer,
 		fieldHandler:            fieldHandler,
 		valueHandler:            valueHandler,
-		queries:                 map[string]string{},
-		queryNames:              make([]string, 0),
-		fields:                  map[string]model.PlcField{},
 		fieldNames:              make([]string, 0),
+		fieldQueries:            map[string]string{},
+		fields:                  map[string]model.PlcField{},
 		values:                  map[string]interface{}{},
 		writeRequestInterceptor: writeRequestInterceptor,
 	}
@@ -78,9 +75,9 @@ func (m *DefaultPlcWriteRequestBuilder) GetWriteRequestInterceptor() interceptor
 	return m.writeRequestInterceptor
 }
 
-func (m *DefaultPlcWriteRequestBuilder) AddQuery(name string, query string, value interface{}) model.PlcWriteRequestBuilder {
-	m.queryNames = append(m.queryNames, name)
-	m.queries[name] = query
+func (m *DefaultPlcWriteRequestBuilder) AddFieldQuery(name string, fieldQuery string, value interface{}) model.PlcWriteRequestBuilder {
+	m.fieldNames = append(m.fieldNames, name)
+	m.fieldQueries[name] = fieldQuery
 	m.values[name] = value
 	return m
 }
@@ -93,15 +90,18 @@ func (m *DefaultPlcWriteRequestBuilder) AddField(name string, field model.PlcFie
 }
 
 func (m *DefaultPlcWriteRequestBuilder) Build() (model.PlcWriteRequest, error) {
-	// Parse the queries as well as pro
-	for _, name := range m.queryNames {
-		query := m.queries[name]
-		field, err := m.fieldHandler.ParseQuery(query)
-		if err != nil {
-			return nil, errors.Wrapf(err, "Error parsing query: %s", query)
+	// Parse any unparsed fieldQueries
+	for _, name := range m.fieldNames {
+		if fieldQuery, ok := m.fieldQueries[name]; ok {
+			field, err := m.fieldHandler.ParseField(fieldQuery)
+			if err != nil {
+				return nil, errors.Wrapf(err, "Error parsing field query: %s", fieldQuery)
+			}
+			m.fields[name] = field
 		}
-		m.AddField(name, field, m.values[name])
 	}
+	// Reset the queries
+	m.fieldQueries = map[string]string{}
 
 	// Process the values for fields.
 	plcValues := make(map[string]values.PlcValue)
@@ -117,14 +117,14 @@ func (m *DefaultPlcWriteRequestBuilder) Build() (model.PlcWriteRequest, error) {
 
 //go:generate go run ../../tools/plc4xgenerator/gen.go -type=DefaultPlcWriteRequest
 type DefaultPlcWriteRequest struct {
-	DefaultRequest
+	DefaultPlcFieldRequest
 	values                  map[string]values.PlcValue
 	writer                  spi.PlcWriter
 	writeRequestInterceptor interceptors.WriteRequestInterceptor
 }
 
 func NewDefaultPlcWriteRequest(fields map[string]model.PlcField, fieldNames []string, values map[string]values.PlcValue, writer spi.PlcWriter, writeRequestInterceptor interceptors.WriteRequestInterceptor) model.PlcWriteRequest {
-	return &DefaultPlcWriteRequest{NewDefaultRequest(fields, fieldNames), values, writer, writeRequestInterceptor}
+	return &DefaultPlcWriteRequest{NewDefaultPlcFieldRequest(fields, fieldNames), values, writer, writeRequestInterceptor}
 }
 
 func (d *DefaultPlcWriteRequest) Execute() <-chan model.PlcWriteRequestResult {
diff --git a/plc4go/spi/model/DefaultPlcWriteRequestBuilder_plc4xgen.go b/plc4go/spi/model/DefaultPlcWriteRequestBuilder_plc4xgen.go
index 30ba71e69b..41499f6b96 100644
--- a/plc4go/spi/model/DefaultPlcWriteRequestBuilder_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcWriteRequestBuilder_plc4xgen.go
@@ -98,27 +98,27 @@ func (d *DefaultPlcWriteRequestBuilder) SerializeWithWriteBuffer(writeBuffer uti
 			}
 		}
 	}
-	if err := writeBuffer.PushContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for name, elem := range d.queries {
-
-		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for _, elem := range d.fieldNames {
+		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queries", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PushContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	for _, elem := range d.queryNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
+	for name, elem := range d.fieldQueries {
+
+		if err := writeBuffer.WriteString(name, uint32(len(elem)*8), "UTF-8", elem); err != nil {
 			return err
 		}
 	}
-	if err := writeBuffer.PopContext("queryNames", utils.WithRenderAsList(true)); err != nil {
+	if err := writeBuffer.PopContext("fieldQueries", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
 	if err := writeBuffer.PushContext("fields", utils.WithRenderAsList(true)); err != nil {
@@ -147,17 +147,6 @@ func (d *DefaultPlcWriteRequestBuilder) SerializeWithWriteBuffer(writeBuffer uti
 	if err := writeBuffer.PopContext("fields", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
-	if err := writeBuffer.PushContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for _, elem := range d.fieldNames {
-		if err := writeBuffer.WriteString("", uint32(len(elem)*8), "UTF-8", elem); err != nil {
-			return err
-		}
-	}
-	if err := writeBuffer.PopContext("fieldNames", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
 	if err := writeBuffer.PushContext("values", utils.WithRenderAsList(true)); err != nil {
 		return err
 	}
diff --git a/plc4go/spi/model/DefaultPlcWriteRequest_plc4xgen.go b/plc4go/spi/model/DefaultPlcWriteRequest_plc4xgen.go
index 9ad7752310..ab248ae87a 100644
--- a/plc4go/spi/model/DefaultPlcWriteRequest_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcWriteRequest_plc4xgen.go
@@ -41,7 +41,7 @@ func (d *DefaultPlcWriteRequest) SerializeWithWriteBuffer(writeBuffer utils.Writ
 	if err := writeBuffer.PushContext("PlcWriteRequest"); err != nil {
 		return err
 	}
-	if err := d.DefaultRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
+	if err := d.DefaultPlcFieldRequest.SerializeWithWriteBuffer(writeBuffer); err != nil {
 		return err
 	}
 	if err := writeBuffer.PushContext("values", utils.WithRenderAsList(true)); err != nil {
diff --git a/plc4go/spi/model/DefaultRequest_plc4xgen.go b/plc4go/spi/model/DefaultRequest_plc4xgen.go
index 5b2ff3f87c..9f3cb10635 100644
--- a/plc4go/spi/model/DefaultRequest_plc4xgen.go
+++ b/plc4go/spi/model/DefaultRequest_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xgenerator -type=DefaultRequest"; DO NOT EDIT.
+// Code generated by "plc4xgenerator -type=DefaultPlcRequest"; DO NOT EDIT.
 
 package model
 
@@ -29,7 +29,7 @@ import (
 
 var _ = fmt.Printf
 
-func (d *DefaultRequest) Serialize() ([]byte, error) {
+func (d *DefaultPlcRequest) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := d.SerializeWithWriteBuffer(wb); err != nil {
 		return nil, err
@@ -37,7 +37,7 @@ func (d *DefaultRequest) Serialize() ([]byte, error) {
 	return wb.GetBytes(), nil
 }
 
-func (d *DefaultRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+func (d *DefaultPlcRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
 	if err := writeBuffer.PushContext("Request"); err != nil {
 		return err
 	}
@@ -84,7 +84,7 @@ func (d *DefaultRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer)
 	return nil
 }
 
-func (d *DefaultRequest) String() string {
+func (d *DefaultPlcRequest) String() string {
 	writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
 	if err := writeBuffer.WriteSerializable(d); err != nil {
 		return err.Error()
diff --git a/plc4go/spi/model/render_test.go b/plc4go/spi/model/render_test.go
index b755054843..566784fd3d 100644
--- a/plc4go/spi/model/render_test.go
+++ b/plc4go/spi/model/render_test.go
@@ -21,8 +21,9 @@ package model
 
 import (
 	"fmt"
-	"github.com/stretchr/testify/assert"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestNonPanickingStrings(t *testing.T) {
@@ -44,7 +45,7 @@ func TestNonPanickingStrings(t *testing.T) {
 		&DefaultPlcWriteRequest{},
 		&DefaultPlcWriteRequestResult{},
 		&DefaultPlcWriteResponse{},
-		&DefaultRequest{},
+		&DefaultPlcRequest{},
 		&DefaultResponse{},
 		&DefaultPlcBrowseRequestResult{},
 		&DefaultPlcBrowseRequest{},
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseItem.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseItem.java
index 194e94d60a..2570fd41d6 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseItem.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseItem.java
@@ -67,7 +67,7 @@ public interface PlcBrowseItem {
     /**
      * @return returns any children this item might have
      */
-    List<PlcBrowseItem> getChildren();
+    Map<String, PlcBrowseItem> getChildren();
 
     /**
      * @return returns a map of additional options the given protocol might provide.
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequest.java
index ccd35fe0ab..11204c623c 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequest.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequest.java
@@ -18,12 +18,31 @@
  */
 package org.apache.plc4x.java.api.messages;
 
+import org.apache.plc4x.java.api.model.PlcQuery;
+
+import java.util.LinkedHashSet;
 import java.util.concurrent.CompletableFuture;
 
 public interface PlcBrowseRequest extends PlcRequest {
 
     CompletableFuture<? extends PlcBrowseResponse> execute();
 
+    /**
+     * In contrast to the default execute method, the executeWithInterceptor allows passing in a so-called
+     * interceptor. This can be used for two different situations:
+     * 1. Filter which items go into the final PlcBrowseResponse (Items are added, if interceptor returns true).
+     * 2. Allow accessing found items on the fly while the system is still processing, hereby allowing a more
+     *    asynchronous consumption of found fields.
+     *
+     * @param interceptor interceptor for intercepting found items
+     * @return future for the final PlcBrowseResponse
+     */
+    CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequestInterceptor interceptor);
+
+    LinkedHashSet<String> getQueryNames();
+
+    PlcQuery getQuery(String name);
+
     interface Builder extends PlcRequestBuilder {
 
         @Override
diff --git a/plc4go/pkg/api/model/plc_field.go b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequestInterceptor.java
similarity index 85%
copy from plc4go/pkg/api/model/plc_field.go
copy to plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequestInterceptor.java
index 91b8caed3f..495a27c5cf 100644
--- a/plc4go/pkg/api/model/plc_field.go
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseRequestInterceptor.java
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.plc4x.java.api.messages;
 
-package model
+public interface PlcBrowseRequestInterceptor {
+
+    boolean intercept(PlcBrowseItem item);
 
-type PlcField interface {
-	GetAddressString() string
-	GetTypeName() string
-	GetQuantity() uint16
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseResponse.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseResponse.java
index f7fae89ae7..6aa36017de 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseResponse.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcBrowseResponse.java
@@ -20,14 +20,17 @@ package org.apache.plc4x.java.api.messages;
 
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 
+import java.util.LinkedHashSet;
 import java.util.List;
 
 public interface PlcBrowseResponse extends PlcResponse {
 
     PlcBrowseRequest getRequest();
 
-    PlcResponseCode getResponseCode();
+    LinkedHashSet<String> getQueryNames();
 
-    List<PlcBrowseItem> getValues();
+    PlcResponseCode getResponseCode(String queryName);
+
+    List<PlcBrowseItem> getValues(String queryName);
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/ArrayInfo.java
similarity index 54%
copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java
copy to plc4j/api/src/main/java/org/apache/plc4x/java/api/model/ArrayInfo.java
index 565f1b2fea..ec32d3ed03 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/ArrayInfo.java
@@ -16,24 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.spi.messages;
+package org.apache.plc4x.java.api.model;
 
-import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
-import org.apache.plc4x.java.api.messages.PlcBrowseResponse;
+public interface ArrayInfo {
 
-import java.util.concurrent.CompletableFuture;
+    /**
+     * @return Number of elements in total
+     */
+    int GetSize();
 
-/**
- * Interface implemented by all PlcConnections that are able to browse remote resources.
- */
-public interface PlcBrowser {
+    /**
+     * As in PLCs not every array starts at 0, we need to be flexible with this.
+     * In the default usage scenario of a simple array [6] this index will be 0 by default.
+     * @return Returns the index of lower bound of the array.
+     */
+    int GetLowerBound();
 
     /**
-     * Reads a requested value from a PLC.
-     *
-     * @param browseRequest object describing the type and location of the value.
-     * @return a {@link CompletableFuture} giving async access to the returned value.
+     * As in PLCs not every array starts at 0, we need to be flexible with this.
+     * In the default usage scenario of a simple array [6] this index will be match the array size.
+     * @return Returns the index of upper bound of the array.
      */
-    CompletableFuture<PlcBrowseResponse> browse(PlcBrowseRequest browseRequest);
+    int GetUpperBound();
 
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
index 78d9fbcb17..7623c75116 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcField.java
@@ -20,10 +20,14 @@ package org.apache.plc4x.java.api.model;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
+
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Base type for all field types.
- * Typically every driver provides an implementation of this interface in order
+ * Typically, every driver provides an implementation of this interface in order
  * to be able to describe the fields of a resource. As this is completely tied to
  * the implemented protocol, this base interface makes absolutely no assumption to
  * any information it should provide.
@@ -31,55 +35,42 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
  * In order to stay platform and protocol independent every driver connection implementation
  * provides a prepareField(String) method that is able to parse a string representation of
  * a resource into it's individual field type. Manually constructing PlcField objects
- * manually makes the solution less independent from the protocol, but might be faster.
+ * manually makes the solution less independent of the protocol, but might be faster.
  */
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
 public interface PlcField {
 
     /**
-     * Returns the "default" type of the response one can expect from this field as java type.
-     * I.e., a call to getXXX for the ResponseItem should succeed.
-     *
-     * The contract is not to return the exact type which is internally hold by PLC4X but to
-     * return a "casteable" type, i.e., a type for which the getXXX method succeeds.
-     * So for example if a type is internally a short, but the getInt() method is implemented, it
-     * is allowed to return Integer.class by this method.
+     * Returns the address string, that this field would be parsed from.
      *
-     * <b>This method should always return the BOXED type for primitives. E.g. not bool.class but Boolean.class</b>
-     * @return Either specific type or Object.class if no specific type is known.
+     * @return Address string representing this Field
      */
-    @JsonIgnore
-    default Class<?> getDefaultJavaType() {
-        return Object.class;
-    }
+    String getAddressString();
 
     /**
      * Returns the "datatype" of the response one can expect from this field.
-     * I.e. The mapping between this string and the PlcValue datatype is handled in the Valuehandler class.
+     * I.e. The mapping between this string and the PlcValue datatype is handled in the ValueHandler class.
      *
      * The contract is to return a String description of the datatype. This doesn't necessarily
      * define the PlcValue type but should be related.
      * i.e. returns "BOOL" -> PlcBOOL, returns "INT16" -> PlcINT
-     * returning an empty string results in the default handler for that dattype to be evaluated.
+     * returning an empty string results in the default handler for that datatype to be evaluated.
      *
      * @return The data type is generally parsed to the PlcField class, if not a default datatype is returned.
      */
     @JsonIgnore
-    default String getPlcDataType() {
-        return "";
+    default PlcValueType getPlcValueType() {
+        return PlcValueType.NULL;
     }
 
     /**
      * Returns the number of elements to expect of the response one can expect from this field.
      *
-     *
      * @return The number of elements to expect.
      */
     @JsonIgnore
-    default int getNumberOfElements() {
-        return 1;
+    default List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
     }
 
-
-
 }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcQuery.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcQuery.java
new file mode 100644
index 0000000000..7a5f011a75
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/model/PlcQuery.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.api.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * Base type for all query types.
+ * Typically, every driver provides an implementation of this interface in order
+ * to be able to describe the queries of a browse request. As this is completely tied to
+ * the implemented protocol, this base interface makes absolutely no assumption to
+ * any information it should provide.
+ *
+ * In order to stay platform and protocol independent every driver connection implementation
+ * provides a prepareQuery(String) method that is able to parse a string representation of
+ * a resource into it's individual query type. Manually constructing PlcQuery objects
+ * manually makes the solution less independent from the protocol, but might be faster.
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public interface PlcQuery {
+
+    @JsonIgnore
+    String getQueryString();
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/types/PlcValueType.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/types/PlcValueType.java
index 04031b70f0..9aa7412882 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/types/PlcValueType.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/types/PlcValueType.java
@@ -18,67 +18,79 @@
  */
 package org.apache.plc4x.java.api.types;
 
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
 // Code generated by code-generation. DO NOT EDIT.
 
 public enum PlcValueType {
-  NULL((short) 0x00),
-  BOOL((short) 0x01),
-  BYTE((short) 0x02),
-  WORD((short) 0x03),
-  DWORD((short) 0x04),
-  LWORD((short) 0x05),
-  USINT((short) 0x11),
-  UINT((short) 0x12),
-  UDINT((short) 0x13),
-  ULINT((short) 0x14),
-  SINT((short) 0x21),
-  INT((short) 0x22),
-  DINT((short) 0x23),
-  LINT((short) 0x24),
-  REAL((short) 0x31),
-  LREAL((short) 0x32),
-  CHAR((short) 0x41),
-  WCHAR((short) 0x42),
-  STRING((short) 0x43),
-  WSTRING((short) 0x44),
-  TIME((short) 0x51),
-  LTIME((short) 0x52),
-  DATE((short) 0x53),
-  LDATE((short) 0x54),
-  TIME_OF_DAY((short) 0x55),
-  LTIME_OF_DAY((short) 0x56),
-  DATE_AND_TIME((short) 0x57),
-  LDATE_AND_TIME((short) 0x58),
-  Struct((short) 0x61),
-  List((short) 0x62),
-  RAW_BYTE_ARRAY((short) 0x71);
-  private static final Map<Short, PlcValueType> map;
+    NULL((short) 0x00, null),
+    BOOL((short) 0x01, Boolean.class),
+    BYTE((short) 0x02, Byte.class),
+    WORD((short) 0x03, Short.class),
+    DWORD((short) 0x04, Integer.class),
+    LWORD((short) 0x05, Long.class),
+    USINT((short) 0x11, Short.class),
+    UINT((short) 0x12, Integer.class),
+    UDINT((short) 0x13, Long.class),
+    ULINT((short) 0x14, BigInteger.class),
+    SINT((short) 0x21, Byte.class),
+    INT((short) 0x22, Short.class),
+    DINT((short) 0x23, Integer.class),
+    LINT((short) 0x24, Long.class),
+    REAL((short) 0x31, Float.class),
+    LREAL((short) 0x32, Double.class),
+    CHAR((short) 0x41, Character.class),
+    WCHAR((short) 0x42, Short.class),
+    STRING((short) 0x43, String.class),
+    WSTRING((short) 0x44, String.class),
+    TIME((short) 0x51, Duration.class),
+    LTIME((short) 0x52, Duration.class),
+    DATE((short) 0x53, LocalDate.class),
+    LDATE((short) 0x54, LocalDate.class),
+    TIME_OF_DAY((short) 0x55, LocalTime.class),
+    LTIME_OF_DAY((short) 0x56, LocalTime.class),
+    DATE_AND_TIME((short) 0x57, LocalDateTime.class),
+    LDATE_AND_TIME((short) 0x58, LocalDateTime.class),
+    Struct((short) 0x61, HashMap.class),
+    List((short) 0x62, ArrayList.class),
+    RAW_BYTE_ARRAY((short) 0x71, Byte.class);
+    private static final Map<Short, PlcValueType> map;
 
-  static {
-    map = new HashMap<>();
-    for (PlcValueType value : PlcValueType.values()) {
-      map.put((short) value.getValue(), value);
+    static {
+        map = new HashMap<>();
+        for (PlcValueType value : PlcValueType.values()) {
+            map.put(value.getValue(), value);
+        }
     }
-  }
 
-  private short value;
+    private short value;
+    private Class<?> defaultJavaType;
 
-  PlcValueType(short value) {
-    this.value = value;
-  }
+    PlcValueType(short value, Class<?> defaultJavaType) {
+        this.value = value;
+        this.defaultJavaType = defaultJavaType;
+    }
+
+    public short getValue() {
+        return value;
+    }
 
-  public short getValue() {
-    return value;
-  }
+    public Class<?> getDefaultJavaType() {
+        return defaultJavaType;
+    }
 
-  public static PlcValueType enumForValue(short value) {
-    return map.get(value);
-  }
+    public static PlcValueType enumForValue(short value) {
+        return map.get(value);
+    }
 
-  public static Boolean isDefined(short value) {
-    return map.containsKey(value);
-  }
+    public static Boolean isDefined(short value) {
+        return map.containsKey(value);
+    }
 }
diff --git a/plc4j/api/src/test/java/org/apache/plc4x/java/api/messages/mock/MockField.java b/plc4j/api/src/test/java/org/apache/plc4x/java/api/messages/mock/MockField.java
index 5bc7536ac4..46f68db284 100644
--- a/plc4j/api/src/test/java/org/apache/plc4x/java/api/messages/mock/MockField.java
+++ b/plc4j/api/src/test/java/org/apache/plc4x/java/api/messages/mock/MockField.java
@@ -18,35 +18,50 @@
  */
 package org.apache.plc4x.java.api.messages.mock;
 
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
+
+import java.util.Collections;
+import java.util.List;
 
 public class MockField implements PlcField {
 
-  private final String field;
-  
-  public MockField(String field) {
-    this.field = field;
-  }
-  
-  public String getField() {
-    return field;
-  }
-  
-  @Override
-  public String toString() {
-    return "mock field: "+ field;
-  }
-  
-  @Override
-  public boolean equals(Object o) {
-    return o != null
-        && o instanceof MockField
-        && ((MockField)o).field.equals(this.field);
-  }
-
-  @Override
-  public int hashCode() {
-    return field.hashCode();
-  }
+    private final String field;
+
+    public MockField(String field) {
+        this.field = field;
+    }
+
+    @Override
+    public String getAddressString() {
+        return field;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.INT;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
+    public String toString() {
+        return "mock field: " + field;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o != null
+            && o instanceof MockField
+            && ((MockField) o).field.equals(this.field);
+    }
+
+    @Override
+    public int hashCode() {
+        return field.hashCode();
+    }
 
 }
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 37310dc8be..dfcce49083 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
@@ -25,8 +25,7 @@ import org.apache.plc4x.java.abeth.field.AbEthFieldHandler;
 import org.apache.plc4x.java.abeth.protocol.AbEthProtocolLogic;
 import org.apache.plc4x.java.abeth.readwrite.CIPEncapsulationPacket;
 import org.apache.plc4x.java.api.model.PlcField;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -65,8 +64,8 @@ public class AbEthDriver extends GeneratedDriverBase<CIPEncapsulationPacket> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     /**
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthField.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthField.java
index ad3b4256c2..13e8adf722 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthField.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthField.java
@@ -20,8 +20,11 @@ package org.apache.plc4x.java.abeth.field;
 
 import org.apache.plc4x.java.abeth.types.FileType;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -66,8 +69,26 @@ public class AbEthField implements PlcField {
     }
 
     @Override
-    public String getPlcDataType() {
-        return fileType.toString();
+    public String getAddressString() {
+        String address = String.format("N%d:%d", fileNumber, elementNumber);
+        if(bitNumber != 0) {
+            address += "/" + bitNumber;
+        }
+        address += ":" + fileType.name();
+        if(byteSize != 1) {
+            address += "[" + byteSize + "]";
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return fileType.getPlcValueType();
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
     }
 
     public short getElementNumber() {
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthFieldHandler.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthFieldHandler.java
index 71549a1361..d7d5133c53 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthFieldHandler.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/field/AbEthFieldHandler.java
@@ -20,16 +20,22 @@ package org.apache.plc4x.java.abeth.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class AbEthFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         if (AbEthField.matches(fieldQuery)) {
             return AbEthField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
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 402edf9d7d..08b87daf1e 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
@@ -33,7 +33,7 @@ import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.values.PlcINT;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -159,7 +159,7 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 if(data.size() == 1) {
                                     plcValue = new PlcINT(data.get(0));
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of(data);
+                                    plcValue = PlcValueHandler.of(data);
                                 }
                             }
                             break;
@@ -168,9 +168,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (((data.get(1)>> 7) & 1) == 0)  {
-                                    plcValue = IEC61131ValueHandler.of((data.get(1) << 8) + data.get(0));  // positive number
+                                    plcValue = PlcValueHandler.of((data.get(1) << 8) + data.get(0));  // positive number
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = PlcValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -179,9 +179,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (((data.get(3)>> 7) & 1) == 0)  {
-                                    plcValue = IEC61131ValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
+                                    plcValue = PlcValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2)-1) & 0b11111111) << 16)+ ((~(data.get(1)-1) & 0b11111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = PlcValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2)-1) & 0b11111111) << 16)+ ((~(data.get(1)-1) & 0b11111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -190,9 +190,9 @@ public class AbEthProtocolLogic extends Plc4xProtocolBase<CIPEncapsulationPacket
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (field.getBitNumber() < 8) {
-                                    plcValue = IEC61131ValueHandler.of((data.get(0) & (1 <<  field.getBitNumber())) != 0);         // read from first byte
+                                    plcValue = PlcValueHandler.of((data.get(0) & (1 <<  field.getBitNumber())) != 0);         // read from first byte
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
+                                    plcValue = PlcValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
                                 }
                             }
                             break;
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
index a1f25e4111..da1820cb54 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/protocol/Plc4xAbEthProtocol.java
@@ -36,6 +36,7 @@ import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.PlcRequestContainer;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.values.*;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -178,7 +179,7 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 if(data.size() == 1) {
                                     plcValue = new PlcINT(data.get(0));
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of(data);
+                                    plcValue = PlcValueHandler.of(data);
                                 }
                             }
                             break;
@@ -187,9 +188,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (((data.get(1)>> 7) & 1) == 0)  {
-                                    plcValue = IEC61131ValueHandler.of((data.get(1) << 8) + data.get(0));  // positive number
+                                    plcValue = PlcValueHandler.of((data.get(1) << 8) + data.get(0));  // positive number
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = PlcValueHandler.of((((~data.get(1) & 0b01111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -198,9 +199,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (((data.get(3)>> 7) & 1) == 0)  {
-                                    plcValue = IEC61131ValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
+                                    plcValue = PlcValueHandler.of((data.get(3) << 24) + (data.get(2) << 16) + (data.get(1) << 8) + data.get(0));  // positive number
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2)-1) & 0b11111111) << 16)+ ((~(data.get(1)-1) & 0b11111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
+                                    plcValue = PlcValueHandler.of((((~data.get(3) & 0b01111111) << 24) + ((~(data.get(2)-1) & 0b11111111) << 16)+ ((~(data.get(1)-1) & 0b11111111) << 8) + (~(data.get(0)-1) & 0b11111111))  * -1);  // negative number
                                 }
                             }
                             break;
@@ -209,9 +210,9 @@ public class Plc4xAbEthProtocol extends PlcMessageToMessageCodec<CIPEncapsulatio
                                 DF1CommandResponseMessageProtectedTypedLogicalRead df1PTLR = (DF1CommandResponseMessageProtectedTypedLogicalRead) plcReadResponse.getResponse();
                                 List<Short> data = df1PTLR.getData();
                                 if (field.getBitNumber() < 8) {
-                                    plcValue = IEC61131ValueHandler.of((data.get(0) & (1 <<  field.getBitNumber())) != 0);         // read from first byte
+                                    plcValue = PlcValueHandler.of((data.get(0) & (1 <<  field.getBitNumber())) != 0);         // read from first byte
                                 } else {
-                                    plcValue = IEC61131ValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
+                                    plcValue = PlcValueHandler.of((data.get(1) & (1 << (field.getBitNumber() - 8) )) != 0);   // read from second byte
                                 }
                             }
                             break;
diff --git a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/types/FileType.java b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/types/FileType.java
index be3fd41574..459c4b013c 100644
--- a/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/types/FileType.java
+++ b/plc4j/drivers/ab-eth/src/main/java/org/apache/plc4x/java/abeth/types/FileType.java
@@ -18,38 +18,45 @@
  */
 package org.apache.plc4x.java.abeth.types;
 
+import org.apache.plc4x.java.api.types.PlcValueType;
+
 import java.util.HashMap;
 import java.util.Map;
 
 public enum FileType {
 
-    HURZ((short) 0x64),
-    STATUS((short) 0x84),
-    BIT((short) 0x85),
-    TIMER((short) 0x86),
-    COUNTER((short) 0x87),
-    CONTROL((short) 0x88),
-    INTEGER((short) 0x89),
-    FLOAT((short) 0x8A),
-    OUTPUT((short) 0x8B),
-    INPUT((short) 0x8C),
-    STRING((short) 0x8D),
-    ASCII((short) 0x8E),
-    BCD((short) 0x8F),
-    WORD((short) 0x89),  // custom 2-byte Integer
-    DWORD((short) 0x89), // custom 4-byte Integer
-    SINGLEBIT((short) 0x89); // custom single bit from Integer file, no official AB type
+    STATUS((short) 0x84, PlcValueType.RAW_BYTE_ARRAY),
+    BIT((short) 0x85, PlcValueType.BOOL),
+    TIMER((short) 0x86, PlcValueType.TIME),
+    COUNTER((short) 0x87, PlcValueType.RAW_BYTE_ARRAY),
+    CONTROL((short) 0x88, PlcValueType.RAW_BYTE_ARRAY),
+    INTEGER((short) 0x89, PlcValueType.INT),
+    FLOAT((short) 0x8A, PlcValueType.REAL),
+    OUTPUT((short) 0x8B, PlcValueType.RAW_BYTE_ARRAY),
+    INPUT((short) 0x8C, PlcValueType.RAW_BYTE_ARRAY),
+    STRING((short) 0x8D, PlcValueType.STRING),
+    ASCII((short) 0x8E, PlcValueType.STRING),
+    BCD((short) 0x8F, PlcValueType.RAW_BYTE_ARRAY),
+    WORD((short) 0x89, PlcValueType.WORD),  // custom 2-byte Integer
+    DWORD((short) 0x89, PlcValueType.DWORD), // custom 4-byte Integer
+    SINGLEBIT((short) 0x89, PlcValueType.WORD); // custom single bit from Integer file, no official AB type
 
     private final short typeCode;
+    private final PlcValueType plcValueType;
 
-    FileType(short typeCode) {
+    FileType(short typeCode, PlcValueType plcValueType) {
         this.typeCode = typeCode;
+        this.plcValueType = plcValueType;
     }
 
     public short getTypeCode() {
         return typeCode;
     }
 
+    public PlcValueType getPlcValueType() {
+        return plcValueType;
+    }
+
     private static final Map<Short, FileType> map;
     static {
         map = new HashMap<>();
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/AdsPlcDriver.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/AdsPlcDriver.java
index 7404ce1e27..e08858938f 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/AdsPlcDriver.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/AdsPlcDriver.java
@@ -27,8 +27,7 @@ import org.apache.plc4x.java.ads.readwrite.AmsTCPPacket;
 import org.apache.plc4x.java.api.messages.PlcDiscoveryRequest;
 import org.apache.plc4x.java.api.metadata.PlcDriverMetadata;
 import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -95,8 +94,8 @@ public class AdsPlcDriver extends GeneratedDriverBase<AmsTCPPacket> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/AdsFieldHandler.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/AdsFieldHandler.java
index 4477556201..1f55d57b1a 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/AdsFieldHandler.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/AdsFieldHandler.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.ads.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class AdsFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         if (DirectAdsStringField.matches(fieldQuery)) {
             return DirectAdsStringField.of(fieldQuery);
         } else if (DirectAdsField.matches(fieldQuery)) {
@@ -36,4 +37,9 @@ public class AdsFieldHandler implements PlcFieldHandler {
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
index 7a689aeb25..0a36816541 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsField.java
@@ -19,10 +19,15 @@
 package org.apache.plc4x.java.ads.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -109,11 +114,36 @@ public class DirectAdsField implements AdsField {
         return adsDataTypeName;
     }
 
-    @Override
     public int getNumberOfElements() {
         return numberOfElements;
     }
 
+    @Override
+    public String getAddressString() {
+        String address = String.format("0x%d/%d:%s", getIndexGroup(), getIndexOffset(), getPlcDataType());
+        if(getNumberOfElements() != 1) {
+            address += "[" + getNumberOfElements() + "]";
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        try {
+            return PlcValueType.valueOf(adsDataTypeName);
+        } catch (Exception e) {
+            return PlcValueType.Struct;
+        }
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(getNumberOfElements() != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, getNumberOfElements()));
+        }
+        return Collections.emptyList();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsStringField.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsStringField.java
index 04d4109cc4..c311c51165 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsStringField.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/DirectAdsStringField.java
@@ -86,6 +86,15 @@ public class DirectAdsStringField extends DirectAdsField implements AdsStringFie
         return RESOURCE_STRING_ADDRESS_PATTERN.matcher(address).matches();
     }
 
+    @Override
+    public String getAddressString() {
+        String address = String.format("0x%d/%d:%s(%d)", getIndexGroup(), getIndexOffset(), getPlcDataType(), getStringLength());
+        if(getNumberOfElements() != 1) {
+            address += "[" + getNumberOfElements() + "]";
+        }
+        return address;
+    }
+
     @Override
     public int getStringLength() {
         return stringLength;
@@ -107,8 +116,8 @@ public class DirectAdsStringField extends DirectAdsField implements AdsStringFie
         writeBuffer.writeUnsignedLong("indexGroup", 32, getIndexGroup());
         writeBuffer.writeUnsignedLong("indexOffset", 32, getIndexOffset());
         writeBuffer.writeUnsignedLong("numberOfElements", 32, getNumberOfElements());
-        String plcDataType = getPlcDataType();
-        writeBuffer.writeString("dataType", plcDataType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), plcDataType);
+        writeBuffer.writeString("dataType", getPlcDataType().getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), getPlcDataType());
+        writeBuffer.writeUnsignedLong("stringLength", 32, getStringLength());
 
         writeBuffer.popContext(getClass().getSimpleName());
     }
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/SymbolicAdsField.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/SymbolicAdsField.java
index 140b1fb602..d14cac5da4 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/SymbolicAdsField.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/field/SymbolicAdsField.java
@@ -19,10 +19,14 @@
 package org.apache.plc4x.java.ads.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -32,6 +36,7 @@ import java.util.regex.Pattern;
  */
 public class SymbolicAdsField implements AdsField {
 
+    // TODO: Model the end of this address to allow usage of multi-dimensional arrays.
     private static final Pattern SYMBOLIC_ADDRESS_PATTERN = Pattern.compile("^(?<symbolicAddress>.+)");
 
     private final String symbolicAddress;
@@ -58,6 +63,21 @@ public class SymbolicAdsField implements AdsField {
         return symbolicAddress;
     }
 
+    @Override
+    public String getAddressString() {
+        return symbolicAddress;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.NULL;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -89,10 +109,6 @@ public class SymbolicAdsField implements AdsField {
         String symbolicAddress = getSymbolicAddress();
         writeBuffer.writeString("symbolicAddress", symbolicAddress.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), symbolicAddress);
 
-        writeBuffer.writeUnsignedLong("numberOfElements", 32, getNumberOfElements());
-
-        String dataType = getPlcDataType();
-        writeBuffer.writeString("dataType", dataType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), dataType);
         writeBuffer.popContext(getClass().getSimpleName());
     }
 }
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 9cd636eccb..74237215c0 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -31,10 +31,7 @@ import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
-import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
-import org.apache.plc4x.java.api.model.PlcField;
-import org.apache.plc4x.java.api.model.PlcSubscriptionField;
-import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
+import org.apache.plc4x.java.api.model.*;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.types.PlcSubscriptionType;
 import org.apache.plc4x.java.api.value.PlcValue;
@@ -464,45 +461,71 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
 
     @Override
     public CompletableFuture<PlcBrowseResponse> browse(PlcBrowseRequest browseRequest) {
+        return browseWithInterceptor(browseRequest, item -> true);
+    }
+
+    public CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor) {
         CompletableFuture<PlcBrowseResponse> future = new CompletableFuture<>();
-        List<PlcBrowseItem> values = new ArrayList<>(symbolTable.size());
-        for (AdsSymbolTableEntry symbol : symbolTable.values()) {
-            // Get the datatype of this entry.
-            AdsDataTypeTableEntry dataType = dataTypeTable.get(symbol.getDataTypeName());
-            if (dataType == null) {
-                System.out.printf("couldn't find datatype: %s%n", symbol.getDataTypeName());
-                continue;
-            }
-            String itemName = (symbol.getComment() == null || symbol.getComment().isEmpty()) ? symbol.getName() : symbol.getComment();
-            // Convert the plc value type from the ADS specific one to the PLC4X global one.
-            org.apache.plc4x.java.api.types.PlcValueType plc4xPlcValueType = org.apache.plc4x.java.api.types.PlcValueType.valueOf(getPlcValueTypeForAdsDataType(dataType).toString());
+        Map<String, PlcResponseCode> responseCodes = new HashMap<>();
+        Map<String, List<PlcBrowseItem>> values = new HashMap<>();
+        for (String queryName : browseRequest.getQueryNames()) {
+            PlcQuery query = browseRequest.getQuery(queryName);
+            List<PlcBrowseItem> resultsForQuery = new ArrayList<>();
+            for (AdsSymbolTableEntry symbol : symbolTable.values()) {
+                // Get the datatype of this entry.
+                AdsDataTypeTableEntry dataType = dataTypeTable.get(symbol.getDataTypeName());
+                if (dataType == null) {
+                    System.out.printf("couldn't find datatype: %s%n", symbol.getDataTypeName());
+                    continue;
+                }
+                String itemName = (symbol.getComment() == null || symbol.getComment().isEmpty()) ? symbol.getName() : symbol.getComment();
+                // Convert the plc value type from the ADS specific one to the PLC4X global one.
+                org.apache.plc4x.java.api.types.PlcValueType plc4xPlcValueType = org.apache.plc4x.java.api.types.PlcValueType.valueOf(getPlcValueTypeForAdsDataType(dataType).toString());
+
+                // If this type has children, add entries for its children.
+                List<PlcBrowseItem> children = getBrowseItems(symbol.getName(), symbol.getGroup(), symbol.getOffset(), !symbol.getFlagReadOnly(), dataType);
+                Map<String, PlcBrowseItem> childMap = new HashMap<>();
+                for (PlcBrowseItem child : children) {
+                    childMap.put(child.getName(), child);
+                }
 
-            // If this type has children, add entries for its children.
-            List<PlcBrowseItem> children = getBrowseItems(symbol.getName(), symbol.getGroup(), symbol.getOffset(), !symbol.getFlagReadOnly(), dataType);
+                // Populate a map of protocol-dependent options.
+                Map<String, PlcValue> options = new HashMap<>();
+                options.put("comment", new PlcSTRING(symbol.getComment()));
+                options.put("group-id", new PlcUDINT(symbol.getGroup()));
+                options.put("offset", new PlcUDINT(symbol.getOffset()));
+                options.put("size-in-bytes", new PlcUDINT(symbol.getSize()));
+
+                if(plc4xPlcValueType == org.apache.plc4x.java.api.types.PlcValueType.List) {
+                    List<PlcBrowseItemArrayInfo> arrayInfo = new ArrayList<>();
+                    for (AdsDataTypeArrayInfo adsDataTypeArrayInfo : dataType.getArrayInfo()) {
+                        arrayInfo.add(new DefaultBrowseItemArrayInfo(
+                            adsDataTypeArrayInfo.getLowerBound(), adsDataTypeArrayInfo.getUpperBound()));
+                    }
+                    DefaultListPlcBrowseItem item = new DefaultListPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, arrayInfo,
+                        true, !symbol.getFlagReadOnly(), true, childMap, options);
 
-            // Populate a map of protocol-dependent options.
-            Map<String, PlcValue> options = new HashMap<>();
-            options.put("comment", new PlcSTRING(symbol.getComment()));
-            options.put("group-id", new PlcUDINT(symbol.getGroup()));
-            options.put("offset", new PlcUDINT(symbol.getOffset()));
-            options.put("size-in-bytes", new PlcUDINT(symbol.getSize()));
+                    // Check if this item should be added to the result
+                    if(interceptor.intercept(item)) {
+                        // Add the type itself.
+                        resultsForQuery.add(item);
+                    }
+                } else {
+                    DefaultPlcBrowseItem item = new DefaultPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, true,
+                        !symbol.getFlagReadOnly(), true, childMap, options);
 
-            if(plc4xPlcValueType == org.apache.plc4x.java.api.types.PlcValueType.List) {
-                List<PlcBrowseItemArrayInfo> arrayInfo = new ArrayList<>();
-                for (AdsDataTypeArrayInfo adsDataTypeArrayInfo : dataType.getArrayInfo()) {
-                    arrayInfo.add(new DefaultBrowseItemArrayInfo(
-                        adsDataTypeArrayInfo.getLowerBound(), adsDataTypeArrayInfo.getUpperBound()));
+                    // Check if this item should be added to the result
+                    if(interceptor.intercept(item)) {
+                        // Add the type itself.
+                        resultsForQuery.add(item);
+                    }
                 }
-                // Add the type itself.
-                values.add(new DefaultListPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, arrayInfo,
-                    true, !symbol.getFlagReadOnly(), true, children, options));
-            } else {
-                // Add the type itself.
-                values.add(new DefaultPlcBrowseItem(symbol.getName(), itemName, plc4xPlcValueType, true,
-                    !symbol.getFlagReadOnly(), true, children, options));
             }
+            responseCodes.put(queryName, PlcResponseCode.OK);
+            values.put(queryName, resultsForQuery);
+            throw new RuntimeException("Gotta implement this ... Currently ignoring all queries.");
         }
-        DefaultPlcBrowseResponse response = new DefaultPlcBrowseResponse(browseRequest, PlcResponseCode.OK, values);
+        DefaultPlcBrowseResponse response = new DefaultPlcBrowseResponse(browseRequest, responseCodes, values);
         future.complete(response);
         return future;
     }
@@ -528,6 +551,10 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
 
             // Recursively add all children of the current datatype.
             List<PlcBrowseItem> children = getBrowseItems(itemAddress, baseGroupId, baseOffset + child.getOffset(), parentWritable, childDataType);
+            Map<String, PlcBrowseItem> childMap = new HashMap<>();
+            for (PlcBrowseItem ch : children) {
+                childMap.put(ch.getName(), ch);
+            }
 
             // Populate a map of protocol-dependent options.
             Map<String, PlcValue> options = new HashMap<>();
@@ -544,11 +571,11 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                 }
                 // Add the type itself.
                 values.add(new DefaultListPlcBrowseItem(basePath + "." + child.getPropertyName(), itemName,
-                    plc4xPlcValueType, arrayInfo,true, parentWritable, true, children, options));
+                    plc4xPlcValueType, arrayInfo,true, parentWritable, true, childMap, options));
             } else {
                 // Add the type itself.
                 values.add(new DefaultPlcBrowseItem(basePath + "." + child.getPropertyName(), itemName,
-                    plc4xPlcValueType,true, parentWritable, true, children, options));
+                    plc4xPlcValueType,true, parentWritable, true, childMap, options));
             }
         }
         return values;
@@ -784,7 +811,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
                     }
                     return null;
                 }).toArray(PlcValue[]::new);
-                return new ResponseItem<>(PlcResponseCode.OK, IEC61131ValueHandler.of(resultItems));
+                return new ResponseItem<>(PlcResponseCode.OK, PlcValueHandler.of(resultItems));
             }
         } catch (Exception e) {
             LOGGER.warn(String.format("Error parsing field item of type: '%s'", field.getPlcDataType()), e);
@@ -1172,12 +1199,14 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
             .map(field -> {
                 AdsDataTypeTableEntry adsDataTypeTableEntry = dataTypeTable.get(resolvedFields.get((AdsField) field.getPlcField()).getPlcDataType());
                 DirectAdsField directAdsField = getDirectAdsFieldForSymbolicName(field.getPlcField());
+                // TODO: We should implement multi-dimensional arrays here ...
+                int numberOfElements = (field.getArrayInfo().size() == 0) ? 1 : field.getArrayInfo().get(0).GetSize();
                 return new AmsTCPPacket(new AdsAddDeviceNotificationRequest(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
                     configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
                     0, getInvokeId(),
                     directAdsField.getIndexGroup(),
                     directAdsField.getIndexOffset(),
-                    adsDataTypeTableEntry.getSize() * field.getNumberOfElements(),
+                    adsDataTypeTableEntry.getSize() * numberOfElements,
                     field.getPlcSubscriptionType() == PlcSubscriptionType.CYCLIC ? AdsTransMode.CYCLIC : AdsTransMode.ON_CHANGE, // if it's not cyclic, it's on change or event
                     0, // there is no api for that yet
                     field.getDuration().orElse(Duration.ZERO).toMillis()));
diff --git a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
index a405103d40..8261bbf885 100644
--- a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
+++ b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/BacNetIpDriver.java
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.bacnetip;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.bacnetip.configuration.BacNetIpConfiguration;
 import org.apache.plc4x.java.bacnetip.field.BacNetIpFieldHandler;
 import org.apache.plc4x.java.bacnetip.protocol.BacNetIpProtocolLogic;
@@ -28,7 +27,7 @@ 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.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 import java.util.function.Consumer;
 import java.util.function.ToIntFunction;
@@ -76,8 +75,8 @@ public class BacNetIpDriver extends GeneratedDriverBase<BVLC> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpField.java b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpField.java
index 19ef9da9b0..f8bea132a8 100644
--- a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpField.java
+++ b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpField.java
@@ -22,8 +22,11 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -63,6 +66,21 @@ public class BacNetIpField implements PlcField {
         this.objectInstance = objectInstance;
     }
 
+    @Override
+    public String getAddressString() {
+        return "TODO: finish me... see golang implementation";
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcField.super.getPlcValueType();
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
+    }
+
     public long getDeviceIdentifier() {
         return deviceIdentifier;
     }
diff --git a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpFieldHandler.java b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpFieldHandler.java
index 81db2d7825..986ae7cf70 100644
--- a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpFieldHandler.java
+++ b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/field/BacNetIpFieldHandler.java
@@ -20,16 +20,22 @@ package org.apache.plc4x.java.bacnetip.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class BacNetIpFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         if (BacNetIpField.matches(fieldQuery)) {
             return BacNetIpField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
index 0cdc6037dd..316cd0829d 100644
--- a/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
+++ b/plc4j/drivers/bacnet/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
@@ -42,6 +42,7 @@ import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
 import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle;
 import org.apache.plc4x.java.spi.values.*;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -162,8 +163,8 @@ public class BacNetIpProtocolLogic extends Plc4xProtocolBase<BVLC> implements Ha
                     enrichedPlcValue.put("address", new PlcSTRING(toString(curField)));
 
                     // From the original BACNet tag
-                    enrichedPlcValue.put("tagNumber", IEC61131ValueHandler.of(propertyValue.getPeekedTagHeader().getActualTagNumber()));
-                    enrichedPlcValue.put("lengthValueType", IEC61131ValueHandler.of(propertyValue.getPeekedTagHeader().getActualLength()));
+                    enrichedPlcValue.put("tagNumber", PlcValueHandler.of(propertyValue.getPeekedTagHeader().getActualTagNumber()));
+                    enrichedPlcValue.put("lengthValueType", PlcValueHandler.of(propertyValue.getPeekedTagHeader().getActualLength()));
 
                     // Use the information in the edeModel to enrich the information.
                     if (edeModel != null) {
@@ -213,8 +214,8 @@ public class BacNetIpProtocolLogic extends Plc4xProtocolBase<BVLC> implements Ha
                     enrichedPlcValue.put("address", new PlcSTRING(toString(curField)));
 
                     // From the original BACNet tag
-                    enrichedPlcValue.put("tagNumber", IEC61131ValueHandler.of(baCnetTag.getActualTagNumber()));
-                    enrichedPlcValue.put("lengthValueType", IEC61131ValueHandler.of(baCnetTag.getActualLength()));
+                    enrichedPlcValue.put("tagNumber", PlcValueHandler.of(baCnetTag.getActualTagNumber()));
+                    enrichedPlcValue.put("lengthValueType", PlcValueHandler.of(baCnetTag.getActualLength()));
 
                     // Use the information in the edeModel to enrich the information.
                     if (edeModel != null) {
diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/GenericCANDriver.java b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/GenericCANDriver.java
index 2fe35c386b..576a864ad0 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/GenericCANDriver.java
+++ b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/GenericCANDriver.java
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.can.generic;
 
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.can.adapter.CANDriverAdapter;
 import org.apache.plc4x.java.can.generic.configuration.GenericCANConfiguration;
 import org.apache.plc4x.java.can.generic.context.GenericCANDriverContext;
@@ -34,7 +33,7 @@ import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.generation.Message;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.transport.Transport;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.transport.can.CANTransport;
 
 /**
@@ -85,8 +84,8 @@ public class GenericCANDriver extends GeneratedDriverBase<Message> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     /**
diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANField.java b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANField.java
index e1cda54df1..5e795aff73 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANField.java
+++ b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANField.java
@@ -19,12 +19,18 @@
 package org.apache.plc4x.java.can.generic.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.genericcan.readwrite.GenericCANDataType;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
 public class GenericCANField implements PlcField {
 
@@ -44,8 +50,25 @@ public class GenericCANField implements PlcField {
     }
 
     @Override
-    public String getPlcDataType() {
-        return dataType.name();
+    public String getAddressString() {
+        String address = nodeId + ":" + dataType.name();
+        if(arraySize != 1) {
+            address += "[" + arraySize + "]";
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(dataType.getPlcValueName());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(arraySize != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, arraySize));
+        }
+        return Collections.emptyList();
     }
 
     public int getArraySize() {
@@ -58,7 +81,7 @@ public class GenericCANField implements PlcField {
 
     public static Optional<GenericCANField> matches(String fieldQuery) {
         Matcher matcher = ADDRESS_PATTERN.matcher(fieldQuery);
-        return matcher.matches() ? Optional.ofNullable(GenericCANField.create(matcher)) : Optional.empty();
+        return matcher.matches() ? Optional.of(GenericCANField.create(matcher)) : Optional.empty();
     }
 
     static GenericCANField create(Matcher fieldQuery) {
diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java
index e3ed78b630..4adc831f63 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java
+++ b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java
@@ -18,14 +18,22 @@
  */
 package org.apache.plc4x.java.can.generic.field;
 
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 import java.util.Optional;
 
 public class GenericCANFieldHandler implements PlcFieldHandler {
+
     @Override
-    public GenericCANField createField(String fieldQuery) {
+    public GenericCANField parseField(String fieldQuery) {
         Optional<GenericCANField> field = GenericCANField.matches(fieldQuery);
         return field.orElse(null);
     }
+
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandlerTest.java b/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandlerTest.java
index b110c0d74e..c0d574c7ae 100644
--- a/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandlerTest.java
+++ b/plc4j/drivers/can/src/test/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandlerTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.plc4x.java.can.generic.field;
 
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -26,10 +27,10 @@ class GenericCANFieldHandlerTest {
 
     @Test
     void checkFieldSyntax() {
-        GenericCANField field = new GenericCANFieldHandler().createField("200:BYTE[8]");
+        GenericCANField field = new GenericCANFieldHandler().parseField("200:BYTE[8]");
 
         assertEquals(200, field.getNodeId());
-        assertEquals("BYTE", field.getPlcDataType());
+        assertEquals(PlcValueType.BYTE, field.getPlcValueType());
         assertEquals(8, field.getArraySize());
     }
 
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/CANOpenPlcDriver.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/CANOpenPlcDriver.java
index 8af0784f3c..9d1898ed2a 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/CANOpenPlcDriver.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/CANOpenPlcDriver.java
@@ -21,7 +21,6 @@ package org.apache.plc4x.java.canopen;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.can.adapter.CANDriverAdapter;
 import org.apache.plc4x.java.canopen.configuration.CANOpenConfiguration;
 import org.apache.plc4x.java.canopen.context.CANOpenDriverContext;
@@ -37,7 +36,7 @@ import org.apache.plc4x.java.spi.generation.Message;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.apache.plc4x.java.spi.optimizer.SingleFieldOptimizer;
 import org.apache.plc4x.java.spi.transport.Transport;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.values.PlcList;
 import org.apache.plc4x.java.transport.can.CANTransport;
 
@@ -86,8 +85,8 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<Message> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler() {
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler() {
             @Override
             public PlcValue newPlcValue(PlcField field, Object[] values) {
                 if (values[0] instanceof PlcList) {
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenFieldHandler.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenFieldHandler.java
index a69bc18501..4cc64db259 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenFieldHandler.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenFieldHandler.java
@@ -20,13 +20,19 @@ package org.apache.plc4x.java.canopen.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class CANOpenFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         return CANOpenField.of(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenHeartbeatField.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenHeartbeatField.java
index df3d991a0a..699a2b6c69 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenHeartbeatField.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenHeartbeatField.java
@@ -19,12 +19,15 @@
 package org.apache.plc4x.java.canopen.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenService;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -45,6 +48,21 @@ public class CANOpenHeartbeatField extends CANOpenField implements CANOpenSubscr
         return getNodeId() == 0;
     }
 
+    @Override
+    public String getAddressString() {
+        return "HEARTBEAT:" + getNodeId();
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.NULL;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches();
     }
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenNMTField.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenNMTField.java
index b23601de53..9ecb79cce9 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenNMTField.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenNMTField.java
@@ -19,12 +19,15 @@
 package org.apache.plc4x.java.canopen.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenService;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -45,6 +48,21 @@ public class CANOpenNMTField extends CANOpenField implements CANOpenSubscription
         return getNodeId() == 0;
     }
 
+    @Override
+    public String getAddressString() {
+        return "NMT:" + getNodeId();
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.NULL;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches();
     }
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenPDOField.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenPDOField.java
index 8e967537fc..624ecbab42 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenPDOField.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenPDOField.java
@@ -19,13 +19,16 @@
 package org.apache.plc4x.java.canopen.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenDataType;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenService;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -45,6 +48,23 @@ public class CANOpenPDOField extends CANOpenField implements CANOpenSubscription
         return canOpenDataType;
     }
 
+    @Override
+    public String getAddressString() {
+        // Number of Elements not implemented.
+        return service.name() + ":" + canOpenDataType.name();
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(canOpenDataType.getPlcValueName());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        // Number of elements not implemented.
+        return Collections.emptyList();
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches();
     }
diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenSDOField.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenSDOField.java
index 18a7a9fd4a..c323fb4ca6 100644
--- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenSDOField.java
+++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/field/CANOpenSDOField.java
@@ -19,12 +19,15 @@
 package org.apache.plc4x.java.canopen.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenDataType;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -48,6 +51,29 @@ public class CANOpenSDOField extends CANOpenField {
         this.canOpenDataType = canOpenDataType;
     }
 
+    @Override
+    public String getAddressString() {
+       // "SDO:" + NODE_PATTERN + "(?:/(?<answerNodeId>\\d+))?:" + CANOpenField.ADDRESS_PATTERN;
+        String address = "SDO:" + getNodeId();
+        if(answerNode != 0) {
+            address += ":/" + answerNode;
+        }
+
+        address += ":" + index + "/" + subIndex + ":" + canOpenDataType.name();
+        // Number of Elements is commented out.
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(canOpenDataType.getPlcValueName());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     public int getAnswerNodeId() {
         return answerNode;
     }
diff --git a/plc4j/drivers/eip/pom.xml b/plc4j/drivers/eip/pom.xml
index 99ae30577b..05a482e0d0 100644
--- a/plc4j/drivers/eip/pom.xml
+++ b/plc4j/drivers/eip/pom.xml
@@ -134,6 +134,10 @@
       <groupId>io.netty</groupId>
       <artifactId>netty-buffer</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.plc4x</groupId>
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
index 38b13f3102..1a7fd2391a 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/EIPDriver.java
@@ -23,8 +23,7 @@ import org.apache.plc4x.java.eip.readwrite.configuration.EIPConfiguration;
 import org.apache.plc4x.java.eip.readwrite.field.EipField;
 import org.apache.plc4x.java.eip.readwrite.field.EipFieldHandler;
 import org.apache.plc4x.java.eip.readwrite.protocol.EipProtocolLogic;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
@@ -57,8 +56,8 @@ public class EIPDriver extends GeneratedDriverBase<EipPacket> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     /**
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipField.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipField.java
index ec9cd6644b..5f55fc93dd 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipField.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipField.java
@@ -18,13 +18,17 @@
  */
 package org.apache.plc4x.java.eip.readwrite.field;
 
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.eip.readwrite.CIPDataTypeCode;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
 
 import java.nio.charset.StandardCharsets;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -42,44 +46,59 @@ public class EipField implements PlcField, Serializable {
     private CIPDataTypeCode type;
     private int elementNb;
 
-    public CIPDataTypeCode getType() {
-        return type;
+    public EipField(String tag) {
+        this.tag = tag;
     }
 
-    public void setType(CIPDataTypeCode type) {
+    public EipField(String tag, int elementNb) {
+        this.tag = tag;
+        this.elementNb = elementNb;
+    }
+
+    public EipField(String tag, CIPDataTypeCode type, int elementNb) {
+        this.tag = tag;
         this.type = type;
+        this.elementNb = elementNb;
     }
 
-    public int getElementNb() {
-        return elementNb;
+    public EipField(String tag, CIPDataTypeCode type) {
+        this.tag = tag;
+        this.type = type;
     }
 
-    public void setElementNb(int elementNb) {
-        this.elementNb = elementNb;
+    @Override
+    public String getAddressString() {
+        throw new NotImplementedException("Need to implement this");
     }
 
-    public String getTag() {
-        return tag;
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(type.name());
     }
 
-    public EipField(String tag) {
-        this.tag = tag;
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
     }
 
-    public EipField(String tag, int elementNb) {
-        this.tag = tag;
-        this.elementNb = elementNb;
+    public CIPDataTypeCode getType() {
+        return type;
     }
 
-    public EipField(String tag, CIPDataTypeCode type, int elementNb) {
-        this.tag = tag;
+    public void setType(CIPDataTypeCode type) {
         this.type = type;
+    }
+
+    public int getElementNb() {
+        return elementNb;
+    }
+
+    public void setElementNb(int elementNb) {
         this.elementNb = elementNb;
     }
 
-    public EipField(String tag, CIPDataTypeCode type) {
-        this.tag = tag;
-        this.type = type;
+    public String getTag() {
+        return tag;
     }
 
     public static boolean matches(String fieldQuery) {
@@ -113,32 +132,6 @@ public class EipField implements PlcField, Serializable {
         return null;
     }
 
-    @Override
-    public String getPlcDataType() {
-        return type.toString();
-    }
-
-    @Override
-    public Class<?> getDefaultJavaType() {
-        switch (type) {
-            //ToDo differenciate Short, Integer and Long
-            case INT:
-            case DINT:
-            case SINT:
-            case LINT:
-                return java.lang.Integer.class;
-            case STRING:
-            case STRING36:
-                return java.lang.String.class;
-            case REAL:
-                return java.lang.Double.class;
-            case BOOL:
-                return java.lang.Boolean.class;
-            default:
-                return Object.class;
-        }
-    }
-
     @Override
     public void serialize(WriteBuffer writeBuffer) throws SerializationException {
         writeBuffer.pushContext(getClass().getSimpleName());
@@ -149,7 +142,7 @@ public class EipField implements PlcField, Serializable {
         }
         writeBuffer.writeUnsignedInt("elementNb", 16, elementNb);
         // TODO: remove this (not language agnostic)
-        String defaultJavaType = (type == null ? Object.class : getDefaultJavaType()).getName();
+        String defaultJavaType = (type == null ? Object.class : getPlcValueType().getDefaultJavaType()).getName();
         writeBuffer.writeString("defaultJavaType", defaultJavaType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), defaultJavaType);
 
         writeBuffer.popContext(getClass().getSimpleName());
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipFieldHandler.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipFieldHandler.java
index 9ffe1829fc..d71343aef7 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipFieldHandler.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/field/EipFieldHandler.java
@@ -20,16 +20,22 @@ package org.apache.plc4x.java.eip.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class EipFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
        if(EipField.matches(fieldQuery)){
            return EipField.of(fieldQuery);
        }
        else throw new PlcInvalidFieldException("Invalid field "+fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
index 52fd41cdc4..9a87a5a80b 100644
--- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
+++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
@@ -401,7 +401,6 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha
                     return new PlcREAL(swap(data.getFloat(0)));
                 case BOOL:
                     return new PlcBOOL(data.getBoolean(0));
-                case STRING36:
                 case STRING:
                 case STRUCTURED: {
                     Short structuredType = Short.reverseBytes(data.getShort(0));
@@ -615,7 +614,6 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha
                 buffer.putLong(value.getLong());
                 break;
             case STRING:
-            case STRING36:
                 buffer.putInt(value.getString().length());
                 buffer.put(value.getString().getBytes(), 0, value.getString().length());
                 break;
diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
index 424eff71a8..187fe389da 100644
--- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
+++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java
@@ -25,8 +25,7 @@ import org.apache.plc4x.java.firmata.readwrite.context.FirmataDriverContext;
 import org.apache.plc4x.java.firmata.readwrite.field.FirmataField;
 import org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldHandler;
 import org.apache.plc4x.java.firmata.readwrite.protocol.FirmataProtocolLogic;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
@@ -74,8 +73,8 @@ public class FirmataDriver extends GeneratedDriverBase<FirmataMessage> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     /**
diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldAnalog.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldAnalog.java
index ef5f488949..6102a9557c 100644
--- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldAnalog.java
+++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldAnalog.java
@@ -19,7 +19,12 @@
 package org.apache.plc4x.java.firmata.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -32,10 +37,26 @@ public class FirmataFieldAnalog extends FirmataField {
     }
 
     @Override
-    public String getPlcDataType() {
-        return "INT";
+    public String getAddressString() {
+        String address = "analog:" + getAddress();
+        if(getNumberOfElements() != 1) {
+            address += "[" + getNumberOfElements() + "]";
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.INT;
     }
 
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(getNumberOfElements() != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, getNumberOfElements()));
+        }
+        return Collections.emptyList();    }
+
     public static FirmataFieldAnalog of(String addressString) throws PlcInvalidFieldException {
         Matcher matcher = ADDRESS_PATTERN.matcher(addressString);
         if (!matcher.matches()) {
diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldDigital.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldDigital.java
index 9814a1bd14..6ef8792dad 100644
--- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldDigital.java
+++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldDigital.java
@@ -19,9 +19,14 @@
 package org.apache.plc4x.java.firmata.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.firmata.readwrite.PinMode;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
 import java.util.BitSet;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -43,6 +48,28 @@ public class FirmataFieldDigital extends FirmataField {
         this.pinMode = pinMode;
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "digital:" + getAddress();
+        if(getNumberOfElements() != 1) {
+            address += "[" + getNumberOfElements() + "]";
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.BOOL;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(getNumberOfElements() != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, getNumberOfElements()));
+        }
+        return Collections.emptyList();
+    }
+
     public BitSet getBitSet() {
         return bitSet;
     }
@@ -51,11 +78,6 @@ public class FirmataFieldDigital extends FirmataField {
         return pinMode;
     }
 
-    @Override
-    public String getPlcDataType() {
-        return "BOOL";
-    }
-
     public static FirmataFieldDigital of(String addressString) {
         Matcher matcher = ADDRESS_PATTERN.matcher(addressString);
         if (!matcher.matches()) {
diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldHandler.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldHandler.java
index 3cb9c54d58..c9fc6f87b5 100644
--- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldHandler.java
+++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/field/FirmataFieldHandler.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.firmata.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class FirmataFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if (FirmataFieldDigital.ADDRESS_PATTERN.matcher(fieldQuery).matches()) {
             return FirmataFieldDigital.of(fieldQuery);
         } else if (FirmataFieldAnalog.ADDRESS_PATTERN.matcher(fieldQuery).matches()) {
@@ -34,4 +35,9 @@ public class FirmataFieldHandler implements PlcFieldHandler {
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
index a2a86a3cee..48e83ac22c 100644
--- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
+++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
@@ -26,8 +26,7 @@ import org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpMessage;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.knxnetip.field.KnxNetIpFieldHandler;
 import org.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocolLogic;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -87,8 +86,8 @@ public class KnxNetIpDriver extends GeneratedDriverBase<KnxNetIpMessage> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpField.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpField.java
index a1630cceae..0459e1e8de 100644
--- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpField.java
+++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpField.java
@@ -19,9 +19,12 @@
 package org.apache.plc4x.java.knxnetip.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.knxnetip.ets.model.GroupAddress;
 
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -85,9 +88,27 @@ public class KnxNetIpField implements PlcField {
         return subGroup;
     }
 
+
+    @Override
+    public String getAddressString() {
+        String address = mainGroup;
+        if(middleGroup != null) {
+            address += "/" + middleGroup;
+        }
+        if(subGroup != null) {
+            address += "/" + subGroup;
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.NULL;
+    }
+
     @Override
-    public String getPlcDataType() {
-        return "";
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
     }
 
     // As our fields can contain wildcards and complex matching logic,
diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpFieldHandler.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpFieldHandler.java
index d4a291d877..499f41f7e4 100644
--- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpFieldHandler.java
+++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/field/KnxNetIpFieldHandler.java
@@ -20,16 +20,22 @@ package org.apache.plc4x.java.knxnetip.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class KnxNetIpFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if (KnxNetIpField.matches(fieldQuery)) {
             return KnxNetIpField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/connection/MockConnection.java b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/connection/MockConnection.java
index e693264642..185f485470 100644
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/connection/MockConnection.java
+++ b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/connection/MockConnection.java
@@ -27,11 +27,10 @@ import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
 import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.mock.field.MockField;
 import org.apache.plc4x.java.mock.field.MockFieldHandler;
-import org.apache.plc4x.java.mock.field.MockValueHandler;
 import org.apache.plc4x.java.spi.messages.*;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -113,7 +112,7 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
 
     @Override
     public PlcBrowseRequest.Builder browseRequestBuilder() {
-        return new DefaultPlcBrowseRequest.Builder(this);
+        return new DefaultPlcBrowseRequest.Builder(this, new MockFieldHandler());
     }
 
     @Override
@@ -121,7 +120,16 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
         return CompletableFuture.supplyAsync(() -> {
             Validate.notNull(device, "No device is set in the mock connection!");
             LOGGER.debug("Sending browse request to MockDevice");
-            return new DefaultPlcBrowseResponse(browseRequest, PlcResponseCode.OK, Collections.emptyList());
+            return new DefaultPlcBrowseResponse(browseRequest, Collections.emptyMap(), Collections.emptyMap());
+        });
+    }
+
+    @Override
+    public CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor) {
+        return CompletableFuture.supplyAsync(() -> {
+            Validate.notNull(device, "No device is set in the mock connection!");
+            LOGGER.debug("Sending browse request to MockDevice");
+            return new DefaultPlcBrowseResponse(browseRequest, Collections.emptyMap(), Collections.emptyMap());
         });
     }
 
@@ -138,10 +146,10 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
             Map<String, ResponseItem<PlcValue>> response = readRequest.getFieldNames().stream()
                 .collect(Collectors.toMap(
                         Function.identity(),
-                        name -> device.read(((MockField) readRequest.getField(name)).getAddress())
+                        name -> device.read(readRequest.getField(name).getAddressString())
                     )
                 );
-            return new DefaultPlcReadResponse((DefaultPlcReadRequest) readRequest, response);
+            return new DefaultPlcReadResponse(readRequest, response);
         });
     }
 
@@ -153,8 +161,7 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
             Map<String, PlcResponseCode> response = writeRequest.getFieldNames().stream()
                 .collect(Collectors.toMap(
                         Function.identity(),
-                        name -> device.write(((MockField) writeRequest.getField(name)).getAddress(),
-                            ((MockField) writeRequest.getField(name)).getPlcValue())
+                        name -> device.write(writeRequest.getField(name).getAddressString(), writeRequest.getPlcValue(name))
                     )
                 );
             return new DefaultPlcWriteResponse((DefaultPlcWriteRequest) writeRequest, response);
@@ -169,7 +176,7 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
             Map<String, ResponseItem<PlcSubscriptionHandle>> response = subscriptionRequest.getFieldNames().stream()
                 .collect(Collectors.toMap(
                         Function.identity(),
-                        name -> device.subscribe(((MockField) subscriptionRequest.getField(name)).getAddress())
+                        name -> device.subscribe(subscriptionRequest.getField(name).getAddressString())
                     )
                 );
             return new DefaultPlcSubscriptionResponse(subscriptionRequest, response);
@@ -198,7 +205,7 @@ public class MockConnection implements PlcConnection, PlcReader, PlcWriter, PlcS
 
     @Override
     public PlcWriteRequest.Builder writeRequestBuilder() {
-        return new DefaultPlcWriteRequest.Builder(this, new MockFieldHandler(), new MockValueHandler());
+        return new DefaultPlcWriteRequest.Builder(this, new MockFieldHandler(), new PlcValueHandler());
     }
 
     @Override
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockField.java b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockField.java
index f887dc14f4..1c1bf3f7ca 100644
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockField.java
+++ b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockField.java
@@ -19,56 +19,62 @@
 package org.apache.plc4x.java.mock.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class MockField implements PlcField {
 
     private final String address;
-    private MockPlcValue plcValue;
-    private MockType type;
-
+    private final PlcValueType type;
     private static final Pattern PATTERN =
-        Pattern.compile("%(?<name>[a-zA-Z_.0-9]+(?:\\[[0-9]*])?):?(?<type>[A-Z]*)");
+        Pattern.compile("%(?<address>[a-zA-Z_.0-9]+(?:\\[[0-9]*])?):?(?<type>[A-Z]*)");
 
     public static MockField of(String addressString) throws PlcInvalidFieldException {
         Matcher matcher = PATTERN.matcher(addressString);
         if (matcher.matches()) {
-            String addr = matcher.group("name");
-            MockType type = MockType.valueOf(matcher.group("type"));
-            return new MockField(addr, type);
+            String address = matcher.group("address");
+            PlcValueType type = PlcValueType.valueOf(matcher.group("type"));
+            return new MockField(address, type);
         }
         return null;
     }
 
     public MockField(String address) {
         this.address = address;
-        this.plcValue = null;
+        this.type = null;
     }
 
-    public MockField(String address, MockType type) {
+    public MockField(String address, PlcValueType type) {
         this.address = address;
         this.type = type;
     }
 
-    public MockField(String address, MockPlcValue plcValue) {
+    public MockField(String address, PlcValue plcValue) {
         this.address = address;
-        this.plcValue = plcValue;
+        this.type = plcValue.getPlcValueType();
     }
 
-    public String getAddress() {
+    @Override
+    public String getAddressString() {
         return address;
     }
 
-    public MockPlcValue getPlcValue() {
-        return plcValue;
+    @Override
+    public PlcValueType getPlcValueType() {
+        return type;
     }
 
     @Override
-    public String getPlcDataType() {
-        return type.toString();
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
     }
 
     @Override
@@ -87,18 +93,4 @@ public class MockField implements PlcField {
         return address.hashCode();
     }
 
-
-    @Override
-    public Class<?> getDefaultJavaType() {
-        switch (type) {
-            case BOOL:
-                return Boolean.class;
-            case INT:
-                return Integer.class;
-            case REAL:
-                return Double.class;
-            default:
-                return null;
-        }
-    }
 }
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockFieldHandler.java b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockFieldHandler.java
index 29bf8379b8..8d3dc13d90 100644
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockFieldHandler.java
+++ b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockFieldHandler.java
@@ -19,13 +19,19 @@
 package org.apache.plc4x.java.mock.field;
 
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class MockFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         return new MockField(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockPlcValue.java b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockPlcValue.java
deleted file mode 100644
index b3017f0205..0000000000
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockPlcValue.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.mock.field;
-
-import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException;
-import org.apache.plc4x.java.api.types.PlcValueType;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
-import org.apache.plc4x.java.spi.values.PlcValueAdapter;
-
-public class MockPlcValue extends PlcValueAdapter {
-
-    final Object[] values;
-
-    public MockPlcValue(Object... values) {
-        this.values = values;
-    }
-
-    @Override
-    public PlcValueType getPlcValueType() {
-        return null;
-    }
-
-    public Object getObject(int index) {
-        return values[index];
-    }
-
-    @Override
-    public void serialize(WriteBuffer writeBuffer) {
-        throw new PlcNotImplementedException("Not implemented");
-    }
-
-}
diff --git a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockValueHandler.java b/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockValueHandler.java
deleted file mode 100644
index d91952ded0..0000000000
--- a/plc4j/drivers/mock/src/main/java/org/apache/plc4x/java/mock/field/MockValueHandler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.mock.field;
-
-import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.api.model.PlcField;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
-
-public class MockValueHandler implements PlcValueHandler {
-
-    @Override
-    public PlcValue newPlcValue(Object value) {
-        return new MockPlcValue(value);
-    }
-
-    @Override
-    public PlcValue newPlcValue(Object[] values) {
-        return new MockPlcValue(values);
-    }
-
-    @Override
-    public PlcValue newPlcValue(PlcField field, Object value) {
-        return newPlcValue(value);
-    }
-
-    @Override
-    public PlcValue newPlcValue(PlcField field, Object[] values) {
-        return newPlcValue(values);
-    }
-
-}
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 42c3f8ba2a..8ecd09a227 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
@@ -21,7 +21,6 @@ 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;
 import org.apache.plc4x.java.modbus.base.field.ModbusField;
@@ -35,7 +34,7 @@ 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 org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 import java.nio.charset.StandardCharsets;
 import java.util.function.ToIntFunction;
@@ -101,8 +100,8 @@ public class ModbusAsciiDriver extends GeneratedDriverBase<ModbusAsciiADU> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
index 64306cb8d7..9dfa4f06ed 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusExtendedRegister.java
@@ -36,6 +36,18 @@ public class ModbusExtendedRegister extends ModbusField {
         super(address, quantity, dataType);
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "6x" + getAddress();
+        if(getDataType() != null) {
+            address += ":" + getDataType().name();
+        }
+        if(getArrayInfo().size() > 0) {
+            address += "[" + getArrayInfo().get(0).GetUpperBound() + "]";
+        }
+        return address;
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches() ||
             ADDRESS_SHORTER_PATTERN.matcher(addressString).matches() ||
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
index 950915ed06..8db5f8fbe9 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusField.java
@@ -20,13 +20,18 @@ package org.apache.plc4x.java.modbus.base.field;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.modbus.readwrite.*;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 import org.apache.plc4x.java.spi.utils.Serializable;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.regex.Pattern;
 
@@ -96,8 +101,16 @@ public abstract class ModbusField implements PlcField, Serializable {
     }
 
     @Override
-    public String getPlcDataType() {
-        return dataType.name();
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(dataType.name());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(quantity != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, quantity));
+        }
+        return Collections.emptyList();
     }
 
     @Override
@@ -132,7 +145,7 @@ public abstract class ModbusField implements PlcField, Serializable {
 
         writeBuffer.writeUnsignedInt("address", 16, address);
         writeBuffer.writeUnsignedInt("numberOfElements", 16, getNumberOfElements());
-        String dataType = getPlcDataType();
+        String dataType = getDataType().name();
         writeBuffer.writeString("dataType", dataType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), dataType);
 
         writeBuffer.popContext(getClass().getSimpleName());
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
index ec91bbbd3d..92e7484015 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldCoil.java
@@ -36,6 +36,18 @@ public class ModbusFieldCoil extends ModbusField {
         super(address, quantity, dataType);
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "0x" + getAddress();
+        if(getDataType() != null) {
+            address += ":" + getDataType().name();
+        }
+        if(getArrayInfo().size() > 0) {
+            address += "[" + getArrayInfo().get(0).GetUpperBound() + "]";
+        }
+        return address;
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches() ||
             ADDRESS_SHORTER_PATTERN.matcher(addressString).matches() ||
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
index 1d4647a855..a1d6ca7665 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldDiscreteInput.java
@@ -36,6 +36,18 @@ public class ModbusFieldDiscreteInput extends ModbusField {
         super(address, quantity, dataType);
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "1x" + getAddress();
+        if(getDataType() != null) {
+            address += ":" + getDataType().name();
+        }
+        if(getArrayInfo().size() > 0) {
+            address += "[" + getArrayInfo().get(0).GetUpperBound() + "]";
+        }
+        return address;
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches() ||
             ADDRESS_SHORTER_PATTERN.matcher(addressString).matches() ||
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
index 7a5f5f0a6a..a187491921 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHandler.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.modbus.base.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class ModbusFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if (ModbusFieldDiscreteInput.matches(fieldQuery)) {
             return ModbusFieldDiscreteInput.of(fieldQuery);
         } else if (ModbusFieldHoldingRegister.matches(fieldQuery)) {
@@ -40,4 +41,9 @@ public class ModbusFieldHandler implements PlcFieldHandler {
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
index 7e184bb36f..97169d16de 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldHoldingRegister.java
@@ -36,6 +36,18 @@ public class ModbusFieldHoldingRegister extends ModbusField {
         super(address, quantity, dataType);
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "4x" + getAddress();
+        if(getDataType() != null) {
+            address += ":" + getDataType().name();
+        }
+        if(getArrayInfo().size() > 0) {
+            address += "[" + getArrayInfo().get(0).GetUpperBound() + "]";
+        }
+        return address;
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches() ||
             ADDRESS_SHORTER_PATTERN.matcher(addressString).matches() ||
diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
index 5ced1fae92..4300251add 100644
--- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
+++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/base/field/ModbusFieldInputRegister.java
@@ -36,6 +36,18 @@ public class ModbusFieldInputRegister extends ModbusField {
         super(address, quantity, dataType);
     }
 
+    @Override
+    public String getAddressString() {
+        String address = "3x" + getAddress();
+        if(getDataType() != null) {
+            address += ":" + getDataType().name();
+        }
+        if(getArrayInfo().size() > 0) {
+            address += "[" + getArrayInfo().get(0).GetUpperBound() + "]";
+        }
+        return address;
+    }
+
     public static boolean matches(String addressString) {
         return ADDRESS_PATTERN.matcher(addressString).matches() ||
             ADDRESS_SHORTER_PATTERN.matcher(addressString).matches() ||
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 265b07f703..093740a2bc 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
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.modbus.rtu;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.modbus.base.field.ModbusField;
 import org.apache.plc4x.java.modbus.base.field.ModbusFieldHandler;
 import org.apache.plc4x.java.modbus.readwrite.DriverType;
@@ -32,7 +31,7 @@ import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 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 org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 import java.util.function.ToIntFunction;
 
@@ -97,8 +96,8 @@ public class ModbusRtuDriver extends GeneratedDriverBase<ModbusRtuADU> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
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 7528c6eb08..f9f5968ab6 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
@@ -29,8 +29,7 @@ import org.apache.plc4x.java.modbus.base.field.ModbusFieldHandler;
 import org.apache.plc4x.java.modbus.readwrite.ModbusTcpADU;
 import org.apache.plc4x.java.modbus.tcp.protocol.ModbusTcpProtocolLogic;
 import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
@@ -116,8 +115,8 @@ public class ModbusTcpDriver extends GeneratedDriverBase<ModbusTcpADU> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
index 7c509b7b62..b8b829a8d8 100644
--- a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
+++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
@@ -21,7 +21,7 @@ package org.apache.plc4x.java.modbus;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.modbus.base.field.ModbusFieldHoldingRegister;
 import org.apache.plc4x.java.modbus.base.field.ModbusFieldCoil;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.values.PlcList;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -33,7 +33,7 @@ public class ModbusEncodeTest {
     public void testEncodeBooleanBOOL() {
         Boolean[] object = {true,false,true,false,true,false,true,true,false};
         ModbusFieldCoil coils = ModbusFieldCoil.of("coil:8:BOOL");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(coils, object);
+        PlcList list = (PlcList) PlcValueHandler.of(coils, object);
         Assertions.assertEquals("[true,false,true,false,true,false,true,true,false]", list.toString());
     }
 
@@ -41,7 +41,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerSINT() {
         Integer[] object = {1,-1,127,-128,5,6,7,8};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:8:SINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,-1,127,-128,5,6,7,8]", list.toString());
     }
 
@@ -49,7 +49,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerUSINT() {
         Integer[] object = {1,255,0,4,5,6,7,8};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:8:USINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,255,0,4,5,6,7,8]", list.toString());
     }
 
@@ -57,7 +57,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerBYTE() {
         Integer[] object = {1,255,0,4,5,6,7,8};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:8:BYTE");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,255,0,4,5,6,7,8]", list.toString());
     }
 
@@ -65,7 +65,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerINT() {
         Integer[] object = {1,-1,32000,-32000,5,6,7};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:INT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,-1,32000,-32000,5,6,7]", list.toString());
     }
 
@@ -73,7 +73,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerUINT() {
         Integer[] object = {1,65535,10,55000,5,6,7};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:UINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,65535,10,55000,5,6,7]", list.toString());
     }
 
@@ -81,7 +81,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerWORD() {
         Integer[] object = {1,65535,10,55000,5,6,7};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:WORD");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,65535,10,55000,5,6,7]", list.toString());
     }
 
@@ -89,7 +89,7 @@ public class ModbusEncodeTest {
     public void testEncodeIntegerDINT() {
         Integer[] object = {1,655354775,-2147483648,2147483647,5,6,7};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:DINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,-2147483648,2147483647,5,6,7]", list.toString());
     }
 
@@ -97,7 +97,7 @@ public class ModbusEncodeTest {
     public void testEncodeLongUDINT() {
         Long[] object = {1L,655354775L,0L,4294967295L,5L,6L,7L};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:UDINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,0,4294967295,5,6,7]", list.toString());
     }
 
@@ -105,7 +105,7 @@ public class ModbusEncodeTest {
     public void testEncodeLongDWORD() {
         Long[] object = {1L,655354775L,0L,4294967295L,5L,6L,7L};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:DWORD");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,0,4294967295,5,6,7]", list.toString());
     }
 
@@ -113,7 +113,7 @@ public class ModbusEncodeTest {
     public void testEncodeLongLINT() {
         Long[] object = {1L,655354775L,-9223372036854775808L,9223372036854775807L,5L,6L,7L};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:LINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,-9223372036854775808,9223372036854775807,5,6,7]", list.toString());
     }
 
@@ -121,7 +121,7 @@ public class ModbusEncodeTest {
     public void testEncodeBigIntegerULINT() {
         BigInteger[] object = {BigInteger.valueOf(1L),BigInteger.valueOf(655354775L),BigInteger.valueOf(0),new BigInteger("18446744073709551615"),BigInteger.valueOf(5L),BigInteger.valueOf(6L),BigInteger.valueOf(7L)};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:ULINT");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,0,18446744073709551615,5,6,7]", list.toString());
     }
 
@@ -129,7 +129,7 @@ public class ModbusEncodeTest {
     public void testEncodeBigIntegerLWORD() {
         BigInteger[] object = {BigInteger.valueOf(1L),BigInteger.valueOf(655354775L),BigInteger.valueOf(0),new BigInteger("18446744073709551615"),BigInteger.valueOf(5L),BigInteger.valueOf(6L),BigInteger.valueOf(7L)};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:LWORD");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1,655354775,0,18446744073709551615,5,6,7]", list.toString());
     }
 
@@ -137,7 +137,7 @@ public class ModbusEncodeTest {
     public void testEncodeFloatREAL() {
         Float[] object = {1.1f,1000.1f,100000.1f,3.4028232E38f,-3.4028232E38f,-1f,10384759934840.0f};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:REAL");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         //! When using Java 19 it seems the toString method uses a different precision than the previous versions,
         //! so we need to check differently in this case.
         for (int i = 0; i < list.getLength(); i++) {
@@ -151,7 +151,7 @@ public class ModbusEncodeTest {
     public void testEncodeDoubleLREAL() {
         Double[] object = {1.1,1000.1,100000.1,1.7E308,-1.7E308,-1d,10384759934840.0};
         ModbusFieldHoldingRegister holdingregister = ModbusFieldHoldingRegister.of("holding-register:7:LREAL");
-        PlcList list = (PlcList) IEC61131ValueHandler.of(holdingregister, object);
+        PlcList list = (PlcList) PlcValueHandler.of(holdingregister, object);
         Assertions.assertEquals("[1.1,1000.1,100000.1,1.7E308,-1.7E308,-1.0,1.038475993484E13]", list.toString());
     }
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 11b436cd1e..706c9a5903 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -29,8 +29,7 @@ import org.apache.plc4x.java.opcua.readwrite.*;
 import org.apache.plc4x.java.spi.configuration.ConfigurationFactory;
 import org.apache.plc4x.java.spi.connection.*;
 import org.apache.plc4x.java.spi.transport.Transport;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import io.netty.buffer.ByteBuf;
@@ -118,8 +117,8 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     protected boolean awaitDisconnectComplete() {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaField.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaField.java
index be87423c0b..5d69d4841a 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaField.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaField.java
@@ -21,12 +21,15 @@ package org.apache.plc4x.java.opcua.field;
 import org.apache.commons.lang3.EnumUtils;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcSubscriptionField;
 import org.apache.plc4x.java.api.types.PlcSubscriptionType;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaIdentifierType;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaDataType;
 
 import java.time.Duration;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.regex.Matcher;
@@ -97,8 +100,22 @@ public class OpcuaField implements PlcSubscriptionField {
     }
 
     @Override
-    public String getPlcDataType() {
-        return dataType.name();
+    public String getAddressString() {
+        String address = String.format("ns=%d;%s=%s", namespace, identifierType.getValue(), identifier);
+        if (dataType != null) {
+            address += ";" + dataType.name();
+        }
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(dataType.name());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcSubscriptionField.super.getArrayInfo();
     }
 
     @Override
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaPlcFieldHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaPlcFieldHandler.java
index 86b8dfdf3c..7b09bdce4f 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaPlcFieldHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/field/OpcuaPlcFieldHandler.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.opcua.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 /**
@@ -26,11 +27,16 @@ import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 public class OpcuaPlcFieldHandler implements PlcFieldHandler {
 
     @Override
-    public OpcuaField createField(String fieldQuery) {
+    public OpcuaField parseField(String fieldQuery) {
         if (OpcuaField.matches(fieldQuery)) {
             return OpcuaField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
index 1af628a412..5ca1b1cd4c 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
@@ -23,6 +23,7 @@ import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
 import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.opcua.config.OpcuaConfiguration;
 import org.apache.plc4x.java.opcua.context.SecureChannel;
@@ -37,7 +38,7 @@ import org.apache.plc4x.java.spi.messages.*;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
 import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.values.PlcList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -256,44 +257,44 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = array[i] != 0;
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantSByte) {
                     byte[] array = ((VariantSByte) variant).getValue();
-                    value = IEC61131ValueHandler.of(array);
+                    value = PlcValueHandler.of(array);
                 } else if (variant instanceof VariantByte) {
                     List<Short> array = ((VariantByte) variant).getValue();
                     Short[] tmpValue = array.toArray(new Short[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantInt16) {
                     List<Short> array = ((VariantInt16) variant).getValue();
                     Short[] tmpValue = array.toArray(new Short[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantUInt16) {
                     List<Integer> array = ((VariantUInt16) variant).getValue();
                     Integer[] tmpValue = array.toArray(new Integer[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantInt32) {
                     List<Integer> array = ((VariantInt32) variant).getValue();
                     Integer[] tmpValue = array.toArray(new Integer[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantUInt32) {
                     List<Long> array = ((VariantUInt32) variant).getValue();
                     Long[] tmpValue = array.toArray(new Long[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantInt64) {
                     List<Long> array = ((VariantInt64) variant).getValue();
                     Long[] tmpValue = array.toArray(new Long[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantUInt64) {
-                    value = IEC61131ValueHandler.of(((VariantUInt64) variant).getValue());
+                    value = PlcValueHandler.of(((VariantUInt64) variant).getValue());
                 } else if (variant instanceof VariantFloat) {
                     List<Float> array = ((VariantFloat) variant).getValue();
                     Float[] tmpValue = array.toArray(new Float[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantDouble) {
                     List<Double> array = ((VariantDouble) variant).getValue();
                     Double[] tmpValue = array.toArray(new Double[0]);
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantString) {
                     int length = ((VariantString) variant).getValue().size();
                     List<PascalString> stringArray = ((VariantString) variant).getValue();
@@ -301,7 +302,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = stringArray.get(i).getStringValue();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantDateTime) {
                     List<Long> array = ((VariantDateTime) variant).getValue();
                     int length = array.size();
@@ -309,7 +310,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = LocalDateTime.ofInstant(Instant.ofEpochMilli(getDateTime(array.get(i))), ZoneOffset.UTC);
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantGuid) {
                     List<GuidValue> array = ((VariantGuid) variant).getValue();
                     int length = array.size();
@@ -328,7 +329,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                         }
                         tmpValue[i] = Long.toHexString(array.get(i).getData1()) + "-" + Integer.toHexString(array.get(i).getData2()) + "-" + Integer.toHexString(array.get(i).getData3()) + "-" + Integer.toHexString(data4) + "-" + Long.toHexString(data5);
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantXmlElement) {
                     int length = ((VariantXmlElement) variant).getValue().size();
                     List<PascalString> strings = ((VariantXmlElement) variant).getValue();
@@ -336,7 +337,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = strings.get(i).getStringValue();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantLocalizedText) {
                     int length = ((VariantLocalizedText) variant).getValue().size();
                     List<LocalizedText> strings = ((VariantLocalizedText) variant).getValue();
@@ -346,7 +347,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                         tmpValue[i] += strings.get(i).getLocaleSpecified() ? strings.get(i).getLocale().getStringValue() + "|" : "";
                         tmpValue[i] += strings.get(i).getTextSpecified() ? strings.get(i).getText().getStringValue() : "";
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantQualifiedName) {
                     int length = ((VariantQualifiedName) variant).getValue().size();
                     List<QualifiedName> strings = ((VariantQualifiedName) variant).getValue();
@@ -354,7 +355,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = "ns=" + strings.get(i).getNamespaceIndex() + ";s=" + strings.get(i).getName().getStringValue();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantExtensionObject) {
                     int length = ((VariantExtensionObject) variant).getValue().size();
                     List<ExtensionObject> strings = ((VariantExtensionObject) variant).getValue();
@@ -362,7 +363,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = strings.get(i).toString();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantNodeId) {
                     int length = ((VariantNodeId) variant).getValue().size();
                     List<NodeId> strings = ((VariantNodeId) variant).getValue();
@@ -370,7 +371,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = strings.get(i).toString();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantStatusCode) {
                     int length = ((VariantStatusCode) variant).getValue().size();
                     List<StatusCode> strings = ((VariantStatusCode) variant).getValue();
@@ -378,7 +379,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     for (int i = 0; i < length; i++) {
                         tmpValue[i] = strings.get(i).toString();
                     }
-                    value = IEC61131ValueHandler.of(tmpValue);
+                    value = PlcValueHandler.of(tmpValue);
                 } else if (variant instanceof VariantByteString) {
                     PlcList plcList = new PlcList();
                     List<ByteStringArray> array = ((VariantByteString) variant).getValue();
@@ -388,7 +389,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                         for (int i = 0; i < length; i++) {
                             tmpValue[i] = array.get(k).getValue().get(i);
                         }
-                        plcList.add(IEC61131ValueHandler.of(tmpValue));
+                        plcList.add(PlcValueHandler.of(tmpValue));
                     }
                     value = plcList;
                 } else {
@@ -420,31 +421,30 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
         }
 
         List<PlcValue> plcValueList = valueObject.getList();
-        String dataType = field.getPlcDataType();
-        if (dataType.equals("NULL")) {
+        PlcValueType dataType = field.getPlcValueType();
+        if (dataType.equals(PlcValueType.NULL)) {
             if (plcValueList.get(0).getObject() instanceof Boolean) {
-                dataType = "BOOL";
+                dataType = PlcValueType.BOOL;
             } else if (plcValueList.get(0).getObject() instanceof Byte) {
-                dataType = "SINT";
+                dataType = PlcValueType.SINT;
             } else if (plcValueList.get(0).getObject() instanceof Short) {
-                dataType = "INT";
+                dataType = PlcValueType.INT;
             } else if (plcValueList.get(0).getObject() instanceof Integer) {
-                dataType = "DINT";
+                dataType = PlcValueType.DINT;
             } else if (plcValueList.get(0).getObject() instanceof Long) {
-                dataType = "LINT";
+                dataType = PlcValueType.LINT;
             } else if (plcValueList.get(0).getObject() instanceof Float) {
-                dataType = "REAL";
+                dataType = PlcValueType.REAL;
             } else if (plcValueList.get(0).getObject() instanceof Double) {
-                dataType = "LREAL";
+                dataType = PlcValueType.LREAL;
             } else if (plcValueList.get(0).getObject() instanceof String) {
-                dataType = "STRING";
+                dataType = PlcValueType.STRING;
             }
         }
         int length = valueObject.getLength();
         switch (dataType) {
             // Simple boolean values
-            case "BOOL":
-            case "BIT":
+            case BOOL:
                 byte[] tmpBOOL = new byte[length];
                 for (int i = 0; i < length; i++) {
                     tmpBOOL[i] = valueObject.getIndex(i).getByte();
@@ -457,9 +457,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpBOOL);
 
             // 8-Bit Bit-Strings (Groups of Boolean Values)
-            case "BYTE":
-            case "BIT8":
-            case "BITARR8":
+            case BYTE:
                 List<Short> tmpBYTE = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpBYTE.add(valueObject.getIndex(i).getShort());
@@ -472,9 +470,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpBYTE);
 
             // 16-Bit Bit-Strings (Groups of Boolean Values)
-            case "WORD":
-            case "BIT16":
-            case "BITARR16":
+            case WORD:
                 List<Integer> tmpWORD = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpWORD.add(valueObject.getIndex(i).getInteger());
@@ -487,9 +483,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpWORD);
 
             // 32-Bit Bit-Strings (Groups of Boolean Values)
-            case "DWORD":
-            case "BIT32":
-            case "BITARR32":
+            case DWORD:
                 List<Long> tmpDWORD = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpDWORD.add(valueObject.getIndex(i).getLong());
@@ -502,9 +496,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpDWORD);
 
             // 64-Bit Bit-Strings (Groups of Boolean Values)
-            case "LWORD":
-            case "BIT64":
-            case "BITARR64":
+            case LWORD:
                 List<BigInteger> tmpLWORD = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpLWORD.add(valueObject.getIndex(i).getBigInteger());
@@ -517,8 +509,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpLWORD);
 
             // 8-Bit Unsigned Integers
-            case "USINT":
-            case "UINT8":
+            case USINT:
                 List<Short> tmpUSINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpUSINT.add(valueObject.getIndex(i).getShort());
@@ -531,8 +522,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpUSINT);
 
             // 8-Bit Signed Integers
-            case "SINT":
-            case "INT8":
+            case SINT:
                 byte[] tmpSINT = new byte[length];
                 for (int i = 0; i < length; i++) {
                     tmpSINT[i] = valueObject.getIndex(i).getByte();
@@ -545,8 +535,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpSINT);
 
             // 16-Bit Unsigned Integers
-            case "UINT":
-            case "UINT16":
+            case UINT:
                 List<Integer> tmpUINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpUINT.add(valueObject.getIndex(i).getInt());
@@ -559,8 +548,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpUINT);
 
             // 16-Bit Signed Integers
-            case "INT":
-            case "INT16":
+            case INT:
                 List<Short> tmpINT16 = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpINT16.add(valueObject.getIndex(i).getShort());
@@ -573,8 +561,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpINT16);
 
             // 32-Bit Unsigned Integers
-            case "UDINT":
-            case "UINT32":
+            case UDINT:
                 List<Long> tmpUDINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpUDINT.add(valueObject.getIndex(i).getLong());
@@ -587,8 +574,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpUDINT);
 
             // 32-Bit Signed Integers
-            case "DINT":
-            case "INT32":
+            case DINT:
                 List<Integer> tmpDINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpDINT.add(valueObject.getIndex(i).getInt());
@@ -601,8 +587,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpDINT);
 
             // 64-Bit Unsigned Integers
-            case "ULINT":
-            case "UINT64":
+            case ULINT:
                 List<BigInteger> tmpULINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpULINT.add(valueObject.getIndex(i).getBigInteger());
@@ -615,8 +600,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpULINT);
 
             // 64-Bit Signed Integers
-            case "LINT":
-            case "INT64":
+            case LINT:
                 List<Long> tmpLINT = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpLINT.add(valueObject.getIndex(i).getLong());
@@ -629,8 +613,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpLINT);
 
             // 32-Bit Floating Point Values
-            case "REAL":
-            case "FLOAT":
+            case REAL:
                 List<Float> tmpREAL = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpREAL.add(valueObject.getIndex(i).getFloat());
@@ -643,8 +626,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpREAL);
 
             // 64-Bit Floating Point Values
-            case "LREAL":
-            case "DOUBLE":
+            case LREAL:
                 List<Double> tmpLREAL = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpLREAL.add(valueObject.getIndex(i).getDouble());
@@ -657,13 +639,12 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     tmpLREAL);
 
             // UTF-8 Characters and Strings
-            case "CHAR":
-            case "STRING":
+            case CHAR:
+            case STRING:
 
                 // UTF-16 Characters and Strings
-            case "WCHAR":
-            case "WSTRING":
-            case "STRING16":
+            case WCHAR:
+            case WSTRING:
                 List<PascalString> tmpString = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     String s = valueObject.getIndex(i).getString();
@@ -676,7 +657,7 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
                     length == 1 ? null : length,
                     tmpString);
 
-            case "DATE_AND_TIME":
+            case DATE_AND_TIME:
                 List<Long> tmpDateTime = new ArrayList<>(length);
                 for (int i = 0; i < length; i++) {
                     tmpDateTime.add(valueObject.getIndex(i).getDateTime().toEpochSecond(ZoneOffset.UTC));
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
index 7d8f6766e4..e1c80b6bc8 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
@@ -99,7 +99,7 @@ public class ManualPLC4XOpcua {
         }
         PlcConnection opcuaConnection = null;
         OpcuaPlcFieldHandler fieldH = new OpcuaPlcFieldHandler();
-        PlcField field = fieldH.createField(BOOL_IDENTIFIER);
+        PlcField field = fieldH.parseField(BOOL_IDENTIFIER);
         try {
             opcuaConnection = new PlcDriverManager().getConnection("opcua:tcp://127.0.0.1:12686/milo?discovery=false");
 
diff --git a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/Plc4xDriver.java b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/Plc4xDriver.java
index 5296015a5f..94c1c20bc5 100644
--- a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/Plc4xDriver.java
+++ b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/Plc4xDriver.java
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.plc4x;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.plc4x.config.Plc4xConfiguration;
 import org.apache.plc4x.java.plc4x.field.Plc4xFieldHandler;
 import org.apache.plc4x.java.plc4x.protocol.Plc4xProtocolLogic;
@@ -29,7 +28,7 @@ import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 import java.util.function.ToIntFunction;
 
@@ -56,8 +55,8 @@ public class Plc4xDriver extends GeneratedDriverBase<Plc4xMessage> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xField.java b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xField.java
index 30c92eb270..41fad959f2 100644
--- a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xField.java
+++ b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xField.java
@@ -18,38 +18,39 @@
  */
 package org.apache.plc4x.java.plc4x.field;
 
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.plc4x.readwrite.Plc4xValueType;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
 
+import java.util.List;
+
 public class Plc4xField implements PlcField, Serializable {
 
     private final String address;
-    private final Plc4xValueType valueType;
+    private final PlcValueType valueType;
 
-    public Plc4xField(String address, Plc4xValueType valueType) {
+    public Plc4xField(String address, PlcValueType valueType) {
         this.address = address;
         this.valueType = valueType;
     }
 
-    public String getAddress() {
+    @Override
+    public String getAddressString() {
         return address;
     }
 
-    public Plc4xValueType getValueType() {
-        return valueType;
-    }
-
     @Override
-    public String getPlcDataType() {
-        return valueType.name();
+    public PlcValueType getPlcValueType() {
+        return valueType;
     }
 
     @Override
-    public int getNumberOfElements() {
-        return PlcField.super.getNumberOfElements();
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
     }
 
     @Override
diff --git a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xFieldHandler.java b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xFieldHandler.java
index d3cc1fe961..cace917e41 100644
--- a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xFieldHandler.java
+++ b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/field/Plc4xFieldHandler.java
@@ -20,19 +20,26 @@ package org.apache.plc4x.java.plc4x.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.plc4x.readwrite.Plc4xValueType;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class Plc4xFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if(!fieldQuery.contains(":")) {
             throw new PlcInvalidFieldException(fieldQuery);
         }
         String address = fieldQuery.substring(0, fieldQuery.lastIndexOf(":"));
         String dataType = fieldQuery.substring(fieldQuery.lastIndexOf(":") + 1);
-        return new Plc4xField(address, Plc4xValueType.valueOf(dataType));
+        return new Plc4xField(address, PlcValueType.valueOf(dataType));
+    }
+
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
     }
 
 }
diff --git a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/protocol/Plc4xProtocolLogic.java b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/protocol/Plc4xProtocolLogic.java
index f7e77b93e1..62abfdbee8 100644
--- a/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/protocol/Plc4xProtocolLogic.java
+++ b/plc4j/drivers/plc4x/src/main/java/org/apache/plc4x/java/plc4x/protocol/Plc4xProtocolLogic.java
@@ -95,7 +95,7 @@ public class Plc4xProtocolLogic extends Plc4xProtocolBase<Plc4xMessage> implemen
             final org.apache.plc4x.java.plc4x.field.Plc4xField plc4xField =
                 (org.apache.plc4x.java.plc4x.field.Plc4xField) apiReadRequest.getField(fieldName);
             Plc4xFieldRequest plc4xFieldRequest = new Plc4xFieldRequest(
-                new Plc4xField(fieldName, plc4xField.getAddress() + ":" + plc4xField.getPlcDataType()));
+                new Plc4xField(fieldName, plc4xField.getAddressString() + ":" + plc4xField.getPlcValueType().name()));
             plc4xFields.add(plc4xFieldRequest);
         }
         final int requestId = txIdGenerator.getAndIncrement();
@@ -136,10 +136,10 @@ public class Plc4xProtocolLogic extends Plc4xProtocolBase<Plc4xMessage> implemen
         List<Plc4xFieldValueRequest> fields = new ArrayList<>(writeRequest.getNumberOfFields());
         for (String fieldName : writeRequest.getFieldNames()) {
             final org.apache.plc4x.java.plc4x.field.Plc4xField plc4xField = (org.apache.plc4x.java.plc4x.field.Plc4xField) writeRequest.getField(fieldName);
-            final Plc4xValueType plc4xValueType = plc4xField.getValueType();
+            final Plc4xValueType plc4xValueType = Plc4xValueType.valueOf(plc4xField.getPlcValueType().name());
             final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
             Plc4xFieldValueRequest fieldRequest = new Plc4xFieldValueRequest(
-                new Plc4xField(fieldName, plc4xField.getAddress() + ":" + plc4xField.getPlcDataType()), plc4xValueType, plcValue);
+                new Plc4xField(fieldName, plc4xField.getAddressString() + ":" + plc4xField.getPlcValueType().name()), plc4xValueType, plcValue);
             fields.add(fieldRequest);
         }
         final int requestId = txIdGenerator.getAndIncrement();
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
index 1fec4f741a..ef85487227 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java
@@ -31,8 +31,7 @@ import org.apache.plc4x.java.profinet.readwrite.Ethernet_Frame;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.messages.DefaultPlcDiscoveryRequest;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
@@ -118,8 +117,8 @@ public class ProfinetDriver extends GeneratedDriverBase<Ethernet_Frame> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetField.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetField.java
index 937db28780..771a5408fa 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetField.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetField.java
@@ -19,7 +19,11 @@
 package org.apache.plc4x.java.profinet.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
+
+import java.util.List;
 
 public class ProfinetField implements PlcField {
 
@@ -27,4 +31,18 @@ public class ProfinetField implements PlcField {
         throw new PlcInvalidFieldException("Unable to parse address: " + addressString);
     }
 
+    @Override
+    public String getAddressString() {
+        return null;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcField.super.getPlcValueType();
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return PlcField.super.getArrayInfo();
+    }
 }
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetFieldHandler.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetFieldHandler.java
index 77bc7392a7..8998f015ff 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetFieldHandler.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/field/ProfinetFieldHandler.java
@@ -19,13 +19,19 @@
 package org.apache.plc4x.java.profinet.field;
 
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class ProfinetFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         return null;
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
index ddfc54434b..a130d2d466 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
@@ -25,13 +25,12 @@ import org.apache.plc4x.java.s7.readwrite.field.S7Field;
 import org.apache.plc4x.java.s7.readwrite.optimizer.S7Optimizer;
 import org.apache.plc4x.java.s7.readwrite.protocol.S7ProtocolLogic;
 import org.apache.plc4x.java.s7.readwrite.field.S7PlcFieldHandler;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 import java.util.function.Consumer;
 import java.util.function.ToIntFunction;
@@ -87,8 +86,8 @@ public class S7Driver extends GeneratedDriverBase<TPKTPacket> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     /**
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
index 5da1ca1279..bff96fca07 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
@@ -25,18 +25,23 @@ import org.apache.commons.codec.DecoderException;
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.s7.readwrite.S7Address;
 import org.apache.plc4x.java.s7.readwrite.S7AddressAny;
 import org.apache.plc4x.java.s7.readwrite.MemoryArea;
 import org.apache.plc4x.java.s7.readwrite.TransportSize;
 import org.apache.plc4x.java.spi.generation.*;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 import org.apache.plc4x.java.spi.utils.Serializable;
 
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -91,6 +96,24 @@ public class S7Field implements PlcField, Serializable {
         this.numElements = numElements;
     }
 
+    @Override
+    public String getAddressString() {
+        return null;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.valueOf(dataType.name());
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        if(numElements != 1) {
+            return Collections.singletonList(new DefaultArrayInfo(0, numElements));
+        }
+        return Collections.emptyList();
+    }
+
     public TransportSize getDataType() {
         return dataType;
     }
@@ -129,42 +152,6 @@ public class S7Field implements PlcField, Serializable {
                 ADDRESS_PATTERN.matcher(fieldString).matches();
     }
 
-    /**
-     * @return Java type of expected response.
-     * <p>
-     * TODO validate all Methods existing are implemented
-     */
-    @Override
-    public Class<?> getDefaultJavaType() {
-        switch (dataType) {
-            case STRING:
-                return String.class;
-            case USINT:
-            case SINT:
-            case UINT:
-            case INT:
-            case DINT:
-                return Integer.class;
-            case UDINT:
-            case ULINT:
-            case LINT:
-                return Long.class;
-            case BOOL:
-                return Boolean.class;
-            case REAL:
-            case LREAL:
-                return Double.class;
-            case DATE_AND_TIME:
-                return LocalDateTime.class;
-            case DATE:
-                return LocalDate.class;
-            case TIME_OF_DAY:
-                return LocalTime.class;
-            default:
-                throw new NotImplementedException("The response type for datatype " + dataType + " is not yet implemented");
-        }
-    }
-
     public static S7Field of(String fieldString) {
         Matcher matcher;
         if ((matcher = DATA_BLOCK_STRING_ADDRESS_PATTERN.matcher(fieldString)).matches()) {
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7PlcFieldHandler.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7PlcFieldHandler.java
index f686499ad5..e78ca4ece9 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7PlcFieldHandler.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7PlcFieldHandler.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.s7.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class S7PlcFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if (S7Field.matches(fieldQuery)) {
             return S7Field.of(fieldQuery);
         } else if (S7SubscriptionField.matches(fieldQuery)){
@@ -36,4 +37,9 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SslField.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SslField.java
index 22479758c0..dda85c15e2 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SslField.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SslField.java
@@ -18,10 +18,14 @@
  */
 package org.apache.plc4x.java.s7.readwrite.field;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 
 public class S7SslField  implements PlcField {
     
@@ -40,6 +44,21 @@ public class S7SslField  implements PlcField {
         this.index = index;
     }
 
+    @Override
+    public String getAddressString() {
+        return String.format("SSL_ID=%s;INDEX=16#%d", szlId, index);
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.RAW_BYTE_ARRAY;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     public int getSslId() {
         return szlId;
     }
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SubscriptionField.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SubscriptionField.java
index e5e1a0ca13..d1b714966e 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SubscriptionField.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7SubscriptionField.java
@@ -19,12 +19,16 @@
 package org.apache.plc4x.java.s7.readwrite.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.s7.readwrite.AlarmType;
 import org.apache.plc4x.java.s7.readwrite.EventType;
 import org.apache.plc4x.java.s7.readwrite.types.S7SubscriptionFieldType;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -43,13 +47,15 @@ public class S7SubscriptionField implements PlcField {
     private static final Pattern EVENT_ALARM_QUERY_PATTERN =
         Pattern.compile("(^QUERY:)((ALARM_S)|(ALARM_8))");
 
+    private final String address;
     private final S7SubscriptionFieldType fieldType;
     private final EventType eventtype;
     private final S7Field s7field;
     private final ArrayList<Integer> ackAlarms;
     private final AlarmType alarmQueryType;
 
-    public S7SubscriptionField(S7SubscriptionFieldType fieldType, EventType eventtype) {
+    public S7SubscriptionField(String address, S7SubscriptionFieldType fieldType, EventType eventtype) {
+        this.address = address;
         this.fieldType = fieldType;
         this.eventtype = eventtype;
         this.s7field = null;
@@ -57,7 +63,8 @@ public class S7SubscriptionField implements PlcField {
         this.alarmQueryType = null;
     }
 
-    public S7SubscriptionField(S7SubscriptionFieldType fieldType, ArrayList<Integer> ackAlarms) {
+    public S7SubscriptionField(String address, S7SubscriptionFieldType fieldType, ArrayList<Integer> ackAlarms) {
+        this.address = address;
         this.fieldType = fieldType;
         this.eventtype = null;
         this.s7field = null;
@@ -65,7 +72,8 @@ public class S7SubscriptionField implements PlcField {
         this.alarmQueryType = null;
     }
 
-    public S7SubscriptionField(S7SubscriptionFieldType fieldType, AlarmType alarmQueryType) {
+    public S7SubscriptionField(String address, S7SubscriptionFieldType fieldType, AlarmType alarmQueryType) {
+        this.address = address;
         this.fieldType = fieldType;
         this.eventtype = null;
         this.s7field = null;
@@ -73,7 +81,8 @@ public class S7SubscriptionField implements PlcField {
         this.alarmQueryType = alarmQueryType;
     }
 
-    public S7SubscriptionField(S7SubscriptionFieldType fieldType, S7Field s7field) {
+    public S7SubscriptionField(String address, S7SubscriptionFieldType fieldType, S7Field s7field) {
+        this.address = address;
         this.fieldType = fieldType;
         this.eventtype = null;
         this.s7field = s7field;
@@ -81,6 +90,21 @@ public class S7SubscriptionField implements PlcField {
         this.alarmQueryType = null;
     }
 
+    @Override
+    public String getAddressString() {
+        return address;
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.RAW_BYTE_ARRAY;
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.emptyList();
+    }
+
     public S7SubscriptionFieldType getFieldType() {
         return fieldType;
     }
@@ -112,7 +136,7 @@ public class S7SubscriptionField implements PlcField {
         {
             Matcher matcher = EVENT_SUBSCRIPTION_TYPE_PATTERN.matcher(fieldString);
             if (matcher.matches()) {
-                return new S7SubscriptionField(S7SubscriptionFieldType.EVENT_SUBSCRIPTION,
+                return new S7SubscriptionField(fieldString, S7SubscriptionFieldType.EVENT_SUBSCRIPTION,
                     EventType.valueOf(fieldString));
             }
         }
@@ -128,7 +152,7 @@ public class S7SubscriptionField implements PlcField {
                     EventId = EventId.replaceAll("16#", "");
                     arrEventId.add(Integer.parseInt(EventId, 16));
                 }
-                return new S7SubscriptionField(S7SubscriptionFieldType.ALARM_ACK, arrEventId);
+                return new S7SubscriptionField(fieldString, S7SubscriptionFieldType.ALARM_ACK, arrEventId);
             }
         }
 
@@ -136,7 +160,7 @@ public class S7SubscriptionField implements PlcField {
             //TODO: Support for ALARM_8            
             Matcher matcher = EVENT_ALARM_QUERY_PATTERN.matcher(fieldString);
             if (matcher.matches()) {
-                return new S7SubscriptionField(S7SubscriptionFieldType.ALARM_QUERY, AlarmType.ALARM_S);
+                return new S7SubscriptionField(fieldString, S7SubscriptionFieldType.ALARM_QUERY, AlarmType.ALARM_S);
             }
         }
 
@@ -149,7 +173,7 @@ public class S7SubscriptionField implements PlcField {
                     default:
 
                 }
-                return new S7SubscriptionField(S7SubscriptionFieldType.CYCLIC_SUBSCRIPTION,
+                return new S7SubscriptionField(fieldString, S7SubscriptionFieldType.CYCLIC_SUBSCRIPTION,
                     s7field);
             }
         }
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index 1e61095ae3..84f530c401 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -33,7 +33,7 @@ import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.values.PlcNull;
 import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.s7.readwrite.*;
 import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
 import org.apache.plc4x.java.s7.readwrite.field.S7StringField;
@@ -51,7 +51,6 @@ import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.reflect.InvocationTargetException;
 import java.nio.ByteBuffer;
 import java.time.Duration;
 import java.util.*;
@@ -897,7 +896,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
                     }
                     return null;
                 }).toArray(PlcValue[]::new);
-                return IEC61131ValueHandler.of(resultItems);
+                return PlcValueHandler.of(resultItems);
             }
         } catch (ParseException e) {
             logger.warn("Error parsing field item of type: '{}'", field.getDataType().name(), e);
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
index 7f429ded33..d632d45d2d 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
@@ -46,7 +46,7 @@ import org.apache.plc4x.java.spi.messages.PlcWriter;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
 import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -79,7 +79,7 @@ public class SimulatedConnection extends AbstractPlcConnection implements PlcRea
 
     public SimulatedConnection(SimulatedDevice device) {
         super(true, true, true, false,
-            new SimulatedFieldHandler(), new IEC61131ValueHandler(), null, null);
+            new SimulatedFieldHandler(), new PlcValueHandler(), null, null);
         this.device = device;
     }
 
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
index 174878efe6..9b335fcbba 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
@@ -25,6 +25,7 @@ import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
 import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.simulated.field.SimulatedField;
 import org.apache.plc4x.java.simulated.readwrite.DataItem;
+import org.apache.plc4x.java.simulated.readwrite.SimulatedDataTypeSizes;
 import org.apache.plc4x.java.spi.generation.*;
 
 import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField;
@@ -96,15 +97,15 @@ public class SimulatedDevice {
                 LOGGER.info("TEST PLC STDOUT [{}]: {}", field.getName(), value.toString());
                 return;
             case RANDOM:
-                switch (field.getPlcDataType()) {
-                    case "STRING":
-                    case "WSTRING":
+                switch (field.getPlcValueType()) {
+                    case STRING:
+                    case WSTRING:
                         break;
                     default:
                         try {
-                            final int lengthInBits = DataItem.getLengthInBits(value, field.getPlcDataType(), field.getNumberOfElements());
+                            final int lengthInBits = DataItem.getLengthInBits(value, field.getPlcValueType().name(), field.getArrayInfo().get(0).GetSize());
                             final WriteBufferByteBased writeBuffer = new WriteBufferByteBased((int) Math.ceil(((float) lengthInBits) / 8.0f));
-                            DataItem.staticSerialize(writeBuffer, value, field.getPlcDataType(), field.getNumberOfElements(), ByteOrder.BIG_ENDIAN);
+                            DataItem.staticSerialize(writeBuffer, value, field.getPlcValueType().name(), field.getArrayInfo().get(0).GetSize(), ByteOrder.BIG_ENDIAN);
                         } catch (SerializationException e) {
                             LOGGER.info("Write failed");
                         }
@@ -116,14 +117,15 @@ public class SimulatedDevice {
     }
 
     private PlcValue randomValue(SimulatedField field) {
-        short fieldDataTypeSize = field.getDataType().getDataTypeSize();
 
-        byte[] b = new byte[fieldDataTypeSize * field.getNumberOfElements()];
+        short fieldDataTypeSize = SimulatedDataTypeSizes.valueOf(field.getPlcValueType().name()).getDataTypeSize();
+
+        byte[] b = new byte[fieldDataTypeSize * field.getArrayInfo().get(0).GetSize()];
         random.nextBytes(b);
 
         ReadBuffer io = new ReadBufferByteBased(b);
         try {
-            return DataItem.staticParse(io, field.getPlcDataType(), field.getNumberOfElements());
+            return DataItem.staticParse(io, field.getPlcValueType().name(), field.getArrayInfo().get(0).GetSize());
         } catch (ParseException e) {
             return null;
         }
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedField.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedField.java
index a1de31319d..294d5c79f5 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedField.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedField.java
@@ -20,10 +20,15 @@ package org.apache.plc4x.java.simulated.field;
 
 import org.apache.commons.lang3.EnumUtils;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.simulated.readwrite.SimulatedDataTypeSizes;
 import org.apache.plc4x.java.simulated.types.SimulatedFieldType;
+import org.apache.plc4x.java.spi.model.DefaultArrayInfo;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -42,10 +47,10 @@ public class SimulatedField implements PlcField {
 
     private final SimulatedFieldType type;
     private final String name;
-    private final SimulatedDataTypeSizes dataType;
+    private final PlcValueType dataType;
     private final int numElements;
 
-    private SimulatedField(SimulatedFieldType type, String name, SimulatedDataTypeSizes dataType, int numElements) {
+    private SimulatedField(SimulatedFieldType type, String name, PlcValueType dataType, int numElements) {
         this.type = type;
         this.name = name;
         this.dataType = dataType;
@@ -57,41 +62,19 @@ public class SimulatedField implements PlcField {
         if (matcher.matches()) {
             SimulatedFieldType type = SimulatedFieldType.valueOf(matcher.group("type"));
             String name = matcher.group("name");
-            String dataType;
-            switch (matcher.group("dataType").toUpperCase()) {
-                case "INTEGER":
-                    dataType = "DINT";
-                    break;
-                case "BYTE":
-                    dataType = "BYTE";
-                    break;
-                case "SHORT":
-                    dataType = "INT";
-                    break;
-                case "LONG":
-                    dataType = "LINT";
-                    break;
-                case "FLOAT":
-                    dataType = "REAL";
-                    break;
-                case "DOUBLE":
-                    dataType = "LREAL";
-                    break;
-                case "BOOLEAN":
-                    dataType = "BOOL";
-                    break;
-                default:
-                    dataType = matcher.group("dataType").toUpperCase();
-            }
-            if (!EnumUtils.isValidEnum(SimulatedDataTypeSizes.class, dataType)) {
-                throw new PlcInvalidFieldException("Invalid data type: " + dataType);
+
+            PlcValueType dataType;
+            try {
+                dataType = PlcValueType.valueOf(matcher.group("dataType").toUpperCase());
+            } catch (Exception e) {
+                throw new PlcInvalidFieldException("Invalid data type: " + matcher.group("dataType"));
             }
 
             int numElements = 1;
             if (matcher.group("numElements") != null) {
                 numElements = Integer.parseInt(matcher.group("numElements"));
             }
-            return new SimulatedField(type, name, SimulatedDataTypeSizes.valueOf(dataType), numElements);
+            return new SimulatedField(type, name, dataType, numElements);
         }
         throw new PlcInvalidFieldException("Unable to parse address: " + fieldString);
     }
@@ -100,24 +83,27 @@ public class SimulatedField implements PlcField {
         return ADDRESS_PATTERN.matcher(fieldString).matches();
     }
 
-    public SimulatedFieldType getType() {
-        return type;
+    @Override
+    public String getAddressString() {
+        return String.format("%s/%s:%s[%d]", type.name(), name, dataType.name(), numElements);
     }
 
-    public String getPlcDataType() {
-        return dataType.name();
+    @Override
+    public PlcValueType getPlcValueType() {
+        return dataType;
     }
 
-    public String getName() {
-        return name;
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return Collections.singletonList(new DefaultArrayInfo(0, numElements));
     }
 
-    public SimulatedDataTypeSizes getDataType() {
-        return dataType;
+    public SimulatedFieldType getType() {
+        return type;
     }
 
-    public int getNumberOfElements() {
-        return numElements;
+    public String getName() {
+        return name;
     }
 
     @Override
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedFieldHandler.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedFieldHandler.java
index 7d0059d7cd..45bc24aba7 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedFieldHandler.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/field/SimulatedFieldHandler.java
@@ -20,16 +20,22 @@ package org.apache.plc4x.java.simulated.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class SimulatedFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) {
+    public PlcField parseField(String fieldQuery) {
         if (SimulatedField.matches(fieldQuery)) {
             return SimulatedField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java
index c0573e8fd9..00c018f6fb 100644
--- a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java
+++ b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/connection/SimulatedDeviceTest.java
@@ -32,7 +32,7 @@ public class SimulatedDeviceTest {
     @Test
     public void random() {
         SimulatedDevice device = new SimulatedDevice("foobar");
-        SimulatedField field = SimulatedField.of("RANDOM/foo:Integer");
+        SimulatedField field = SimulatedField.of("RANDOM/foo:DINT");
 
         Optional<PlcValue> value = device.get(field);
 
@@ -42,7 +42,7 @@ public class SimulatedDeviceTest {
     @Test
     public void read() {
         SimulatedDevice device = new SimulatedDevice("foobar");
-        SimulatedField field = SimulatedField.of("STATE/bar:Integer");
+        SimulatedField field = SimulatedField.of("STATE/bar:DINT");
 
         Optional<PlcValue> value = device.get(field);
         assertFalse(value.isPresent());
diff --git a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimularedFieldHandlerTest.java b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimularedFieldHandlerTest.java
index 128172c16c..05ad118b04 100644
--- a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimularedFieldHandlerTest.java
+++ b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimularedFieldHandlerTest.java
@@ -34,7 +34,7 @@ class SimularedFieldHandlerTest implements WithAssertions {
 
     @Test
     void createField() {
-        assertThat(SUT.createField("STATE/bar:Integer")).isNotNull();
+        assertThat(SUT.parseField("STATE/bar:DINT")).isNotNull();
     }
 
     /*@Test
diff --git a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimulatedFieldTest.java b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimulatedFieldTest.java
index 657e259ea8..ab2949ab7c 100644
--- a/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimulatedFieldTest.java
+++ b/plc4j/drivers/simulated/src/test/java/org/apache/plc4x/java/simulated/field/SimulatedFieldTest.java
@@ -31,12 +31,12 @@ public class SimulatedFieldTest {
 
     @Test
     public void constructor() {
-        assertThat(SimulatedField.matches("RANDOM/test:Integer[2]"), equalTo(true));
-        SimulatedField field = SimulatedField.of("RANDOM/test:Integer[2]");
+        assertThat(SimulatedField.matches("RANDOM/test:DINT[2]"), equalTo(true));
+        SimulatedField field = SimulatedField.of("RANDOM/test:DINT[2]");
         assertThat(field.getType(), equalTo(SimulatedFieldType.RANDOM));
         assertThat(field.getName(), equalTo("test"));
-        assertThat(field.getPlcDataType(), equalTo("DINT"));
-        assertThat(field.getNumberOfElements(), equalTo(2));
+        assertThat(field.getPlcValueType().name(), equalTo("DINT"));
+        assertThat(field.getArrayInfo().get(0).GetSize(), equalTo(2));
         assertThat(field.toString(),
             equalTo("TestField{type=RANDOM, name='test', dataType='DINT', numElements=2}"));
     }
diff --git a/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java b/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
index 9b8418dfcd..5e698405b9 100644
--- a/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
+++ b/plc4j/examples/hello-world-plc4x-discover-and-browse/src/main/java/org/apache/plc4x/java/examples/helloplc4x/discoverandbrowse/HelloPlc4xDiscoverAndBrowse.java
@@ -51,8 +51,10 @@ public class HelloPlc4xDiscoverAndBrowse {
                                 if (throwable != null) {
                                     throwable.printStackTrace();
                                 } else {
-                                    for (PlcBrowseItem value : browseResponse.getValues()) {
-                                        outputBrowseItem(value, 0);
+                                    for (String queryName : browseResponse.getQueryNames()) {
+                                        for (PlcBrowseItem value : browseResponse.getValues(queryName)) {
+                                            outputBrowseItem(value, 0);
+                                        }
                                     }
                                 }
                             });
@@ -74,7 +76,7 @@ public class HelloPlc4xDiscoverAndBrowse {
             browseItem.isWritable() ? "W" : " ",
             browseItem.isSubscribable() ? "S" : " ");
         if (!browseItem.getChildren().isEmpty()) {
-            for (PlcBrowseItem child : browseItem.getChildren()) {
+            for (PlcBrowseItem child : browseItem.getChildren().values()) {
                 outputBrowseItem(child, indent + 1);
             }
         }
diff --git a/plc4j/integrations/apache-calcite/src/test/resources/example.yml b/plc4j/integrations/apache-calcite/src/test/resources/example.yml
index 1fff2ce155..f9a67715b5 100644
--- a/plc4j/integrations/apache-calcite/src/test/resources/example.yml
+++ b/plc4j/integrations/apache-calcite/src/test/resources/example.yml
@@ -28,5 +28,5 @@ jobs:
     - test
     - test2
     fields:
-      test: 'RANDOM/test:Integer'
-      test2: 'RANDOM/test:String'
+      test: 'RANDOM/test:DINT'
+      test2: 'RANDOM/test:STRING'
diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
index 77f15b95c3..bb12b17f5a 100644
--- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
+++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.opcuaserver.backend;
 import java.lang.reflect.Array;
 import java.util.Arrays;
 
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.eclipse.milo.opcua.sdk.server.AbstractLifecycle;
 import org.eclipse.milo.opcua.sdk.server.api.DataItem;
 import org.eclipse.milo.opcua.sdk.server.nodes.filters.AttributeFilterContext;
@@ -106,62 +107,38 @@ public class Plc4xCommunication extends AbstractLifecycle {
         monitoredList.remove(item.getReadValueId().getNodeId());
     }
 
-    public static NodeId getNodeId(String plcValue) {
-        switch (plcValue) {
-            case "BOOL":
-            case "BIT":
+    public static NodeId getNodeId(PlcValueType plcValueType) {
+        switch (plcValueType) {
+            case BOOL:
                 return Identifiers.Boolean;
-            case "BYTE":
-            case "BITARR8":
+            case BYTE:
+            case USINT:
                 return Identifiers.Byte;
-            case "SINT":
-            case "INT8":
+            case SINT:
                 return Identifiers.SByte;
-            case "USINT":
-            case "UINT8":
-            case "BIT8":
-                return Identifiers.Byte;
-            case "INT":
-            case "INT16":
+            case INT:
                 return Identifiers.Int16;
-            case "UINT":
-            case "UINT16":
-                return Identifiers.UInt16;
-            case "WORD":
-            case "BITARR16":
+            case WORD:
+            case UINT:
                 return Identifiers.UInt16;
-            case "DINT":
-            case "INT32":
+            case DINT:
                 return Identifiers.Int32;
-            case "UDINT":
-            case "UINT32":
+            case DWORD:
+            case UDINT:
                 return Identifiers.UInt32;
-            case "DWORD":
-            case "BITARR32":
-                return Identifiers.UInt32;
-            case "LINT":
-            case "INT64":
+            case LINT:
                 return Identifiers.Int64;
-            case "ULINT":
-            case "UINT64":
-                return Identifiers.UInt64;
-            case "LWORD":
-            case "BITARR64":
+            case ULINT:
+            case LWORD:
                 return Identifiers.UInt64;
-            case "REAL":
-            case "FLOAT":
+            case REAL:
                 return Identifiers.Float;
-            case "LREAL":
-            case "DOUBLE":
+            case LREAL:
                 return Identifiers.Double;
-            case "CHAR":
-                return Identifiers.String;
-            case "WCHAR":
-                return Identifiers.String;
-            case "STRING":
-                return Identifiers.String;
-            case "WSTRING":
-            case "STRING16":
+            case CHAR:
+            case WCHAR:
+            case STRING:
+            case WSTRING:
                 return Identifiers.String;
             default:
                 return Identifiers.BaseDataType;
diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
index 073b933af2..690026e356 100644
--- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
+++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java
@@ -110,9 +110,10 @@ public class Plc4xNamespace extends ManagedNamespaceWithLifecycle {
             UaVariableNode node = null;
             Variant variant = null;
             try {
-                datatype = plc4xServer.getField(tag, connectionString).getDefaultJavaType();
-                final int length = plc4xServer.getField(tag, connectionString).getNumberOfElements();
-                typeId = Plc4xCommunication.getNodeId(plc4xServer.getField(tag, connectionString).getPlcDataType());
+                datatype = plc4xServer.getField(tag, connectionString).getPlcValueType().getDefaultJavaType();
+                final int length = (plc4xServer.getField(tag, connectionString).getArrayInfo().isEmpty()) ? 1 :
+                    plc4xServer.getField(tag, connectionString).getArrayInfo().get(0).GetSize();
+                typeId = Plc4xCommunication.getNodeId(plc4xServer.getField(tag, connectionString).getPlcValueType());
 
 
                 if (length > 1) {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
index 9db99a7ac7..dbbabb51e8 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
@@ -86,6 +86,10 @@ public abstract class Plc4xProtocolBase<T> {
         throw new NotImplementedException("");
     }
 
+    public CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor) {
+        throw new NotImplementedException("");
+    }
+
     public abstract void close(ConversationContext<T> context);
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
index bf94518185..2dc980eb32 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
@@ -158,7 +158,7 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         if (!canBrowse) {
             throw new PlcUnsupportedOperationException("The connection does not support browsing");
         }
-        return new DefaultPlcBrowseRequest.Builder(this);
+        return new DefaultPlcBrowseRequest.Builder(this, getPlcFieldHandler());
     }
 
     @Override
@@ -208,4 +208,9 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         return protocol.browse(browseRequest);
     }
 
+    @Override
+    public CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor) {
+        return protocol.browseWithInterceptor(browseRequest, interceptor);
+    }
+
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
index da2214c8e8..842cb1265b 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/PlcFieldHandler.java
@@ -19,12 +19,15 @@
 package org.apache.plc4x.java.spi.connection;
 
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 
 /**
- * Field Handler which handles the parsing of string to {@link PlcField} and the encoding of retrieved plc values.
+ * Field Handler which handles the parsing of string to {@link PlcField} or {@link PlcQuery}.
  */
 public interface PlcFieldHandler {
 
-    PlcField createField(String fieldQuery);
+    PlcField parseField(String fieldQuery);
+
+    PlcQuery parseQuery(String query);
 
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultListPlcBrowseItem.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultListPlcBrowseItem.java
index ee40de8237..4e4279a9cd 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultListPlcBrowseItem.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultListPlcBrowseItem.java
@@ -45,7 +45,7 @@ public class DefaultListPlcBrowseItem extends DefaultPlcBrowseItem {
                                     @JsonProperty("readable") boolean readable,
                                     @JsonProperty("writable") boolean writable,
                                     @JsonProperty("subscribable") boolean subscribable,
-                                    @JsonProperty("children") List<PlcBrowseItem> children,
+                                    @JsonProperty("children") Map<String, PlcBrowseItem> children,
                                     @JsonProperty("options") Map<String, PlcValue> options) {
         super(address, name, dataType, readable, writable, subscribable, children, options);
         this.arrayInfo = arrayInfo;
@@ -65,7 +65,7 @@ public class DefaultListPlcBrowseItem extends DefaultPlcBrowseItem {
         //writeBuffer.writeString("dataType", dataType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), dataType);
         if(getChildren() != null && !getChildren().isEmpty()) {
             writeBuffer.pushContext("children");
-            for (PlcBrowseItem child : getChildren()) {
+            for (PlcBrowseItem child : getChildren().values()) {
                 writeBuffer.pushContext("child");
                 ((DefaultListPlcBrowseItem) child).serialize(writeBuffer);
                 writeBuffer.popContext("child");
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseItem.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseItem.java
index 233b48bc54..26aed5f790 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseItem.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseItem.java
@@ -45,7 +45,7 @@ public class DefaultPlcBrowseItem implements PlcBrowseItem, Serializable {
     private final boolean writable;
     private final boolean subscribable;
 
-    private final List<PlcBrowseItem> children;
+    private final Map<String, PlcBrowseItem> children;
 
     private final Map<String, PlcValue> options;
 
@@ -56,7 +56,7 @@ public class DefaultPlcBrowseItem implements PlcBrowseItem, Serializable {
                                 @JsonProperty("readable") boolean readable,
                                 @JsonProperty("writable") boolean writable,
                                 @JsonProperty("subscribable") boolean subscribable,
-                                @JsonProperty("children") List<PlcBrowseItem> children,
+                                @JsonProperty("children") Map<String, PlcBrowseItem> children,
                                 @JsonProperty("options") Map<String, PlcValue> options) {
         this.address = address;
         this.name = name;
@@ -96,7 +96,7 @@ public class DefaultPlcBrowseItem implements PlcBrowseItem, Serializable {
     }
 
     @Override
-    public List<PlcBrowseItem> getChildren() {
+    public Map<String, PlcBrowseItem> getChildren() {
         return children;
     }
 
@@ -114,7 +114,7 @@ public class DefaultPlcBrowseItem implements PlcBrowseItem, Serializable {
         //writeBuffer.writeString("dataType", dataType.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), dataType);
         if(children != null && !children.isEmpty()) {
             writeBuffer.pushContext("children");
-            for (PlcBrowseItem child : children) {
+            for (PlcBrowseItem child : children.values()) {
                 writeBuffer.pushContext("child");
                 ((DefaultPlcBrowseItem) child).serialize(writeBuffer);
                 writeBuffer.popContext("child");
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseRequest.java
index 3be0554478..3dba103c3e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseRequest.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseRequest.java
@@ -19,25 +19,29 @@
 package org.apache.plc4x.java.spi.messages;
 
 import com.fasterxml.jackson.annotation.*;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.model.PlcQuery;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
 
 import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.LinkedHashSet;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
 
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
 public class DefaultPlcBrowseRequest implements PlcBrowseRequest, Serializable {
 
     private final PlcBrowser browser;
 
-    private final LinkedHashMap<String, String> queries;
+    private final LinkedHashMap<String, PlcQuery> queries;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public DefaultPlcBrowseRequest(@JsonProperty("browser") PlcBrowser browser,
-                                   @JsonProperty("queries") LinkedHashMap<String, String> queries) {
+                                   @JsonProperty("queries") LinkedHashMap<String, PlcQuery> queries) {
         this.browser = browser;
         this.queries = queries;
     }
@@ -48,14 +52,25 @@ public class DefaultPlcBrowseRequest implements PlcBrowseRequest, Serializable {
         return browser.browse(this);
     }
 
+    @Override
+    @JsonIgnore
+    public CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequestInterceptor interceptor) {
+        return browser.browseWithInterceptor(this, interceptor);
+    }
+
     @JsonIgnore
     public PlcBrowser getBrowser() {
         return browser;
     }
 
-    @JsonIgnore
-    public Map<String, String> getQueries() {
-        return queries;
+    @Override
+    public LinkedHashSet<String> getQueryNames() {
+        return new LinkedHashSet<>(queries.keySet());
+    }
+
+    @Override
+    public PlcQuery getQuery(String name) {
+        return queries.get(name);
     }
 
     @Override
@@ -67,23 +82,31 @@ public class DefaultPlcBrowseRequest implements PlcBrowseRequest, Serializable {
     public static class Builder implements PlcBrowseRequest.Builder {
 
         private final PlcBrowser browser;
+        private final PlcFieldHandler fieldHandler;
+        private final LinkedHashMap<String, Supplier<PlcQuery>> queries;
 
-        private final LinkedHashMap<String, String> queries;
-
-        public Builder(PlcBrowser browser) {
+        public Builder(PlcBrowser browser, PlcFieldHandler fieldHandler) {
             this.browser = browser;
+            this.fieldHandler = fieldHandler;
             queries = new LinkedHashMap<>();
         }
 
         @Override
         public Builder addQuery(String name, String query) {
-            queries.put(name, query);
+            if (queries.containsKey(name)) {
+                throw new PlcRuntimeException("Duplicate query definition '" + name + "'");
+            }
+            queries.put(name, () -> fieldHandler.parseQuery(query));
             return this;
         }
 
         @Override
         public PlcBrowseRequest build() {
-            return new DefaultPlcBrowseRequest(browser, queries);
+            LinkedHashMap<String, PlcQuery> parsedQueries = new LinkedHashMap<>();
+            queries.forEach((name, fieldQuery) -> {
+                parsedQueries.put(name, fieldQuery.get());
+            });
+            return new DefaultPlcBrowseRequest(browser, parsedQueries);
         }
 
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseResponse.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseResponse.java
index 7eaf855050..d84b2956bb 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseResponse.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcBrowseResponse.java
@@ -44,14 +44,14 @@ public class DefaultPlcBrowseResponse implements PlcBrowseResponse, Serializable
 
     private final PlcBrowseRequest request;
 
-    private final PlcResponseCode responseCode;
+    private final Map<String, PlcResponseCode> responseCodes;
 
-    private final List<PlcBrowseItem> values;
+    private final Map<String, List<PlcBrowseItem>> values;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-    public DefaultPlcBrowseResponse(@JsonProperty("request") PlcBrowseRequest request, @JsonProperty("responseCode") PlcResponseCode responseCode, @JsonProperty("values") List<PlcBrowseItem> values) {
+    public DefaultPlcBrowseResponse(@JsonProperty("request") PlcBrowseRequest request, @JsonProperty("responseCodes") Map<String, PlcResponseCode> responseCodes, @JsonProperty("values") Map<String, List<PlcBrowseItem>> values) {
         this.request = request;
-        this.responseCode = responseCode;
+        this.responseCodes = responseCodes;
         this.values = values;
     }
 
@@ -60,14 +60,18 @@ public class DefaultPlcBrowseResponse implements PlcBrowseResponse, Serializable
         return request;
     }
 
+    public LinkedHashSet<String> getQueryNames() {
+        return request.getQueryNames();
+    }
+
     @Override
-    public PlcResponseCode getResponseCode() {
-        return responseCode;
+    public PlcResponseCode getResponseCode(String queryName) {
+        return responseCodes.get(queryName);
     }
 
     @Override
-    public List<PlcBrowseItem> getValues() {
-        return values;
+    public List<PlcBrowseItem> getValues(String queryName) {
+        return values.get(queryName);
     }
 
     @Override
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcReadRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcReadRequest.java
index 25a1743cf9..6babbb61b5 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcReadRequest.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcReadRequest.java
@@ -26,7 +26,6 @@ import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
@@ -145,7 +144,7 @@ public class DefaultPlcReadRequest implements PlcReadRequest, PlcFieldRequest, S
             if (fields.containsKey(name)) {
                 throw new PlcRuntimeException("Duplicate field definition '" + name + "'");
             }
-            fields.put(name, () -> fieldHandler.createField(fieldQuery));
+            fields.put(name, () -> fieldHandler.parseField(fieldQuery));
             return this;
         }
 
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcSubscriptionRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcSubscriptionRequest.java
index f3d648f5a8..0c231b5700 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcSubscriptionRequest.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcSubscriptionRequest.java
@@ -175,7 +175,7 @@ public class DefaultPlcSubscriptionRequest implements PlcSubscriptionRequest, Se
             LinkedHashMap<String, PlcSubscriptionField> parsedFields = new LinkedHashMap<>();
 
             fields.forEach((name, builderItem) -> {
-                PlcField parsedField = fieldHandler.createField(builderItem.fieldQuery);
+                PlcField parsedField = fieldHandler.parseField(builderItem.fieldQuery);
                 parsedFields.put(name, new DefaultPlcSubscriptionField(builderItem.plcSubscriptionType, parsedField, builderItem.duration));
             });
             preRegisteredConsumers.forEach((fieldName, ignored) -> {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
index f2e51a9e09..0300a18468 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteRequest.java
@@ -27,7 +27,6 @@ import org.apache.commons.lang3.tuple.Triple;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.model.PlcField;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.SerializationException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.utils.Serializable;
@@ -200,7 +199,7 @@ public class DefaultPlcWriteRequest implements PlcWriteRequest, Serializable {
             fields.forEach((name, fieldValues) -> {
                 // Compile the query string.
                 String fieldQuery = fieldValues.getLeft();
-                PlcField field = fieldHandler.createField(fieldQuery);
+                PlcField field = fieldHandler.parseField(fieldQuery);
                 Object[] value = fieldValues.getRight();
                 PlcValue plcValue = valueHandler.newPlcValue(field, value);
                 parsedFields.put(name, new FieldValueItem(field, plcValue));
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteResponse.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteResponse.java
index a9f05f1e1b..0c42fa6a7d 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteResponse.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/DefaultPlcWriteResponse.java
@@ -38,13 +38,13 @@ import java.util.Map;
 public class DefaultPlcWriteResponse implements PlcWriteResponse, Serializable {
 
     private final PlcWriteRequest request;
-    private final Map<String, PlcResponseCode> responses;
+    private final Map<String, PlcResponseCode> responseCodes;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public DefaultPlcWriteResponse(@JsonProperty("request") PlcWriteRequest request,
-                                   @JsonProperty("values") Map<String, PlcResponseCode> responses) {
+                                   @JsonProperty("responseCodes") Map<String, PlcResponseCode> responseCodes) {
         this.request = request;
-        this.responses = responses;
+        this.responseCodes = responseCodes;
     }
 
     @Override
@@ -67,7 +67,7 @@ public class DefaultPlcWriteResponse implements PlcWriteResponse, Serializable {
     @Override
     @JsonIgnore
     public PlcResponseCode getResponseCode(String name) {
-        return responses.get(name);
+        return responseCodes.get(name);
     }
 
     @Override
@@ -78,7 +78,7 @@ public class DefaultPlcWriteResponse implements PlcWriteResponse, Serializable {
             ((Serializable) request).serialize(writeBuffer);
         }
         writeBuffer.pushContext("fields");
-        for (Map.Entry<String, PlcResponseCode> fieldEntry : responses.entrySet()) {
+        for (Map.Entry<String, PlcResponseCode> fieldEntry : responseCodes.entrySet()) {
             String fieldName = fieldEntry.getKey();
             final PlcResponseCode fieldResponseCode = fieldEntry.getValue();
             String result = fieldResponseCode.name();
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java
index 565f1b2fea..d07dad60f0 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/messages/PlcBrowser.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.spi.messages;
 
 import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
+import org.apache.plc4x.java.api.messages.PlcBrowseRequestInterceptor;
 import org.apache.plc4x.java.api.messages.PlcBrowseResponse;
 
 import java.util.concurrent.CompletableFuture;
@@ -36,4 +37,6 @@ public interface PlcBrowser {
      */
     CompletableFuture<PlcBrowseResponse> browse(PlcBrowseRequest browseRequest);
 
+    CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor);
+
 }
diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultArrayInfo.java
similarity index 58%
copy from plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java
copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultArrayInfo.java
index e3ed78b630..57c467f528 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/generic/field/GenericCANFieldHandler.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultArrayInfo.java
@@ -16,16 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.plc4x.java.can.generic.field;
+package org.apache.plc4x.java.spi.model;
 
-import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+import org.apache.plc4x.java.api.model.ArrayInfo;
 
-import java.util.Optional;
+public class DefaultArrayInfo implements ArrayInfo {
+
+    private final int lowerBound;
+    private final int upperBound;
+
+    public DefaultArrayInfo(int lowerBound, int upperBound) {
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+    }
+
+    @Override
+    public int GetSize() {
+        return upperBound - lowerBound;
+    }
 
-public class GenericCANFieldHandler implements PlcFieldHandler {
     @Override
-    public GenericCANField createField(String fieldQuery) {
-        Optional<GenericCANField> field = GenericCANField.matches(fieldQuery);
-        return field.orElse(null);
+    public int GetLowerBound() {
+        return lowerBound;
     }
+
+    @Override
+    public int GetUpperBound() {
+        return upperBound;
+    }
+
 }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultPlcSubscriptionField.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultPlcSubscriptionField.java
index 98671d85ae..fe8c22b1e7 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultPlcSubscriptionField.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/model/DefaultPlcSubscriptionField.java
@@ -18,11 +18,14 @@
  */
 package org.apache.plc4x.java.spi.model;
 
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.model.PlcSubscriptionField;
 import org.apache.plc4x.java.api.types.PlcSubscriptionType;
+import org.apache.plc4x.java.api.types.PlcValueType;
 
 import java.time.Duration;
+import java.util.List;
 import java.util.Optional;
 
 /**
@@ -42,6 +45,21 @@ public class DefaultPlcSubscriptionField implements PlcSubscriptionField {
         this.duration = duration;
     }
 
+    @Override
+    public String getAddressString() {
+        return plcField.getAddressString();
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return plcField.getPlcValueType();
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        return plcField.getArrayInfo();
+    }
+
     public PlcSubscriptionType getPlcSubscriptionType() {
         return plcSubscriptionType;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE.java
new file mode 100644
index 0000000000..d1fd652f46
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.values;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class PlcLDATE extends PlcSimpleValue<LocalDate> {
+
+    public static PlcLDATE of(Object value) {
+        if (value instanceof LocalDate) {
+            return new PlcLDATE((LocalDate) value);
+        } else if (value instanceof Long) {
+            return new PlcLDATE(LocalDateTime.ofInstant(
+                Instant.ofEpochSecond((long) value), ZoneId.systemDefault()).toLocalDate());
+        }
+        throw new PlcRuntimeException("Invalid value type");
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLDATE(@JsonProperty("value") LocalDate value) {
+        super(value, true);
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLDATE(@JsonProperty("value") Integer value) {
+        // In this case the date is the number of days since 1990-01-01
+        // So we gotta add 7305 days to the value to have it relative to epoch
+        // Then we also need to transform it from days to seconds by multiplying by 86400
+        super(LocalDateTime.ofInstant(Instant.ofEpochSecond((value + 7305L) * 86400L),
+            ZoneId.systemDefault()).toLocalDate(), true);
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLDATE(@JsonProperty("value") Long value) {
+        super(LocalDateTime.ofInstant(Instant.ofEpochSecond(value), ZoneId.systemDefault()).toLocalDate(), true);
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.DATE;
+    }
+
+    @Override
+    public boolean isLong() {
+        return true;
+    }
+
+    @Override
+    public long getLong() {
+        Instant instant = value.atStartOfDay(ZoneId.systemDefault()).toInstant();
+        return (instant.toEpochMilli() / 1000);
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isString() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public String getString() {
+        return value.toString();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isDate() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public LocalDate getDate() {
+        return value;
+    }
+
+    @Override
+    @JsonIgnore
+    public String toString() {
+        return String.valueOf(value);
+    }
+
+    @Override
+    public void serialize(WriteBuffer writeBuffer) throws SerializationException {
+        String valueString = value.toString();
+        writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_8).length * 8, StandardCharsets.UTF_8.name(), valueString);
+    }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE_AND_TIME.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE_AND_TIME.java
new file mode 100644
index 0000000000..e8318e4cd9
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLDATE_AND_TIME.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.values;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.nio.charset.StandardCharsets;
+import java.time.*;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class PlcLDATE_AND_TIME extends PlcSimpleValue<LocalDateTime> {
+
+    public static PlcLDATE_AND_TIME of(Object value) {
+        if (value instanceof LocalDateTime) {
+            return new PlcLDATE_AND_TIME((LocalDateTime) value);
+        } else if (value instanceof Long) {
+            return new PlcLDATE_AND_TIME(LocalDateTime.ofInstant(
+                Instant.ofEpochSecond((long) value), ZoneId.systemDefault()));
+        }
+        throw new PlcRuntimeException("Invalid value type");
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLDATE_AND_TIME(@JsonProperty("value") LocalDateTime value) {
+        super(value, true);
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLDATE_AND_TIME(@JsonProperty("value") Long value) {
+        super(LocalDateTime.ofInstant(
+            Instant.ofEpochSecond(value), ZoneId.of("UTC")), true);
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.DATE_AND_TIME;
+    }
+
+    @Override
+    public boolean isLong() {
+        return true;
+    }
+
+    @Override
+    public long getLong() {
+        Instant instant = value.atZone(ZoneId.systemDefault()).toInstant();
+        return instant.getEpochSecond();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isString() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public String getString() {
+        return value.toString();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isTime() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public LocalTime getTime() {
+        return value.toLocalTime();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isDate() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public LocalDate getDate() {
+        return value.toLocalDate();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isDateTime() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public LocalDateTime getDateTime() {
+        return value;
+    }
+
+    @Override
+    @JsonIgnore
+    public String toString() {
+        return String.valueOf(value);
+    }
+
+    @Override
+    public void serialize(WriteBuffer writeBuffer) throws SerializationException {
+        String valueString = value.toString();
+        writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_8).length*8,StandardCharsets.UTF_8.name(),valueString);
+    }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME_OF_DAY.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME_OF_DAY.java
new file mode 100644
index 0000000000..5a455c89b6
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcLTIME_OF_DAY.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.java.spi.values;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.types.PlcValueType;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.nio.charset.StandardCharsets;
+import java.time.LocalTime;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
+public class PlcLTIME_OF_DAY extends PlcSimpleValue<LocalTime> {
+
+    public static PlcLTIME_OF_DAY of(Object value) {
+        if (value instanceof LocalTime) {
+            return new PlcLTIME_OF_DAY((LocalTime) value);
+        } else if (value instanceof Long) {
+            return new PlcLTIME_OF_DAY(LocalTime.ofSecondOfDay(((long) value) / 1000));
+        }
+        throw new PlcRuntimeException("Invalid value type");
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLTIME_OF_DAY(@JsonProperty("value") LocalTime value) {
+        super(value, true);
+    }
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public PlcLTIME_OF_DAY(@JsonProperty("value") Long value) {
+        super(LocalTime.ofNanoOfDay(value * 1000000), true);
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return PlcValueType.TIME_OF_DAY;
+    }
+
+    @Override
+    public boolean isLong() {
+        return true;
+    }
+
+    @Override
+    public long getLong() {
+        return ((long) value.toSecondOfDay()) * 1000;
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isString() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public String getString() {
+        return value.toString();
+    }
+
+    @Override
+    @JsonIgnore
+    public boolean isTime() {
+        return true;
+    }
+
+    @Override
+    @JsonIgnore
+    public LocalTime getTime() {
+        return value;
+    }
+
+    @Override
+    @JsonIgnore
+    public String toString() {
+        return String.valueOf(value);
+    }
+
+    @Override
+    public void serialize(WriteBuffer writeBuffer) throws SerializationException {
+        String valueString = value.toString();
+        writeBuffer.writeString(getClass().getSimpleName(), valueString.getBytes(StandardCharsets.UTF_8).length*8,StandardCharsets.UTF_8.name(),valueString);
+    }
+
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/IEC61131ValueHandler.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValueHandler.java
similarity index 84%
rename from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/IEC61131ValueHandler.java
rename to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValueHandler.java
index 9318da1086..27ab4d442c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/IEC61131ValueHandler.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/values/PlcValueHandler.java
@@ -22,7 +22,6 @@ import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.value.PlcValue;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 
 import java.math.BigInteger;
 import java.time.Duration;
@@ -31,8 +30,7 @@ import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.List;
 
-public class IEC61131ValueHandler implements PlcValueHandler {
-
+public class PlcValueHandler implements org.apache.plc4x.java.api.value.PlcValueHandler {
 
     public PlcValue newPlcValue(Object value) {
         return of(new Object[]{value});
@@ -122,12 +120,13 @@ public class IEC61131ValueHandler implements PlcValueHandler {
     public static PlcValue of(PlcField field, Object[] values) {
         if (values.length == 1) {
             Object value = values[0];
-            switch (field.getPlcDataType().toUpperCase()) {
-                case "BOOL":
-                case "BIT":
+            if(field.getPlcValueType() == null) {
+                return new PlcNull();
+            }
+            switch (field.getPlcValueType()) {
+                case BOOL:
                     return PlcBOOL.of(value);
-                case "BYTE":
-                case "BITARR8":
+                case BYTE:
                     if(value instanceof Short) {
                         return new PlcBYTE((short) value);
                     } else if(value instanceof Integer) {
@@ -138,21 +137,15 @@ public class IEC61131ValueHandler implements PlcValueHandler {
                         return new PlcBYTE(((BigInteger) value).shortValue());
                     }
                     throw new PlcRuntimeException("BYTE requires short");
-                case "SINT":
-                case "INT8":
+                case SINT:
                     return PlcSINT.of(value);
-                case "USINT":
-                case "UINT8":
-                case "BIT8":
+                case USINT:
                     return PlcUSINT.of(value);
-                case "INT":
-                case "INT16":
+                case INT:
                     return PlcINT.of(value);
-                case "UINT":
-                case "UINT16":
+                case UINT:
                     return PlcUINT.of(value);
-                case "WORD":
-                case "BITARR16":
+                case WORD:
                     if(value instanceof Short) {
                         return new PlcWORD((int) value);
                     } else if(value instanceof Integer) {
@@ -163,14 +156,11 @@ public class IEC61131ValueHandler implements PlcValueHandler {
                         return new PlcWORD(((BigInteger) value).intValue());
                     }
                     throw new PlcRuntimeException("WORD requires int");
-                case "DINT":
-                case "INT32":
+                case DINT:
                     return PlcDINT.of(value);
-                case "UDINT":
-                case "UINT32":
+                case UDINT:
                     return PlcUDINT.of(value);
-                case "DWORD":
-                case "BITARR32":
+                case DWORD:
                     if(value instanceof Short) {
                         return new PlcDWORD((long) value);
                     } else if(value instanceof Integer) {
@@ -181,14 +171,11 @@ public class IEC61131ValueHandler implements PlcValueHandler {
                         return new PlcDWORD(((BigInteger) value).longValue());
                     }
                     throw new PlcRuntimeException("DWORD requires long");
-                case "LINT":
-                case "INT64":
+                case LINT:
                     return PlcLINT.of(value);
-                case "ULINT":
-                case "UINT64":
+                case ULINT:
                     return PlcULINT.of(value);
-                case "LWORD":
-                case "BITARR64":
+                case LWORD:
                     if(value instanceof Short) {
                         return new PlcLWORD(BigInteger.valueOf((long) value));
                     } else if(value instanceof Integer) {
@@ -199,28 +186,25 @@ public class IEC61131ValueHandler implements PlcValueHandler {
                         return new PlcLWORD((BigInteger) value);
                     }
                     throw new PlcRuntimeException("LWORD requires BigInteger");
-                case "REAL":
-                case "FLOAT":
+                case REAL:
                     return PlcREAL.of(value);
-                case "LREAL":
-                case "DOUBLE":
+                case LREAL:
                     return PlcLREAL.of(value);
-                case "CHAR":
+                case CHAR:
                     return PlcCHAR.of(value);
-                case "WCHAR":
+                case WCHAR:
                     return PlcWCHAR.of(value);
-                case "STRING":
+                case STRING:
                     return PlcSTRING.of(value);
-                case "WSTRING":
-                case "STRING16":
+                case WSTRING:
                     return PlcWSTRING.of(value);
-                case "TIME":
+                case TIME:
                     return PlcTIME.of(value);
-                case "DATE":
+                case DATE:
                     return PlcDATE.of(value);
-                case "TIME_OF_DAY":
+                case TIME_OF_DAY:
                     return PlcTIME_OF_DAY.of(value);
-                case "DATE_AND_TIME":
+                case DATE_AND_TIME:
                     return PlcDATE_AND_TIME.of(value);
                 default:
                     return customDataType(new Object[]{value});
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java
index 2952b395de..f69f05caa0 100644
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java
+++ b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedBrowseRequest.java
@@ -19,8 +19,11 @@
 package org.apache.plc4x.java.utils.connectionpool2;
 
 import org.apache.plc4x.java.api.messages.PlcBrowseRequest;
+import org.apache.plc4x.java.api.messages.PlcBrowseRequestInterceptor;
 import org.apache.plc4x.java.api.messages.PlcBrowseResponse;
+import org.apache.plc4x.java.api.model.PlcQuery;
 
+import java.util.LinkedHashSet;
 import java.util.concurrent.CompletableFuture;
 
 public class CachedBrowseRequest implements PlcBrowseRequest {
@@ -39,4 +42,19 @@ public class CachedBrowseRequest implements PlcBrowseRequest {
         return parent.execute(innerRequest);
     }
 
+    @Override
+    public CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequestInterceptor interceptor) {
+        return parent.executeWithInterceptor(innerRequest, interceptor);
+    }
+
+    @Override
+    public LinkedHashSet<String> getQueryNames() {
+        return innerRequest.getQueryNames();
+    }
+
+    @Override
+    public PlcQuery getQuery(String name) {
+        return innerRequest.getQuery(name);
+    }
+
 }
diff --git a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
index 462fc33588..7c2b9005d4 100644
--- a/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
+++ b/plc4j/tools/connection-cache/src/main/java/org/apache/plc4x/java/utils/connectionpool2/CachedPlcConnection.java
@@ -180,6 +180,34 @@ public class CachedPlcConnection implements PlcConnection, PlcConnectionMetadata
         }
     }
 
+    public CompletableFuture<? extends PlcBrowseResponse> executeWithInterceptor(PlcBrowseRequest request, PlcBrowseRequestInterceptor interceptor) {
+        logger.trace("Trying to executing Request with interceptor {}", request);
+        if (closed) {
+            throw new IllegalStateException("Trying to execute a Request on a closed Connection!");
+        }
+        try {
+            logger.trace("Executing Request {}", request);
+            final CompletableFuture<? extends PlcBrowseResponse> responseFuture = wrapBrowseWithTimeout(request.executeWithInterceptor(interceptor), 5_000);
+            // The following code handles the case, that a read fails (which is handled async and thus not really connected
+            // to the connection, yet
+            // Thus, we register our own listener who gets the notification and reports the connection as broken
+            final CompletableFuture<PlcBrowseResponse> handledResponseFuture = responseFuture.handleAsync(new BiFunction<PlcBrowseResponse, Throwable, PlcBrowseResponse>() {
+                @Override
+                public PlcBrowseResponse apply(PlcBrowseResponse plcBrowseResponse, Throwable throwable) {
+                    if (throwable != null) {
+                        // Do something here...
+                        logger.warn("Request finished with exception. Reporting Connection as Broken", throwable);
+                        closeConnectionExceptionally(null);
+                    }
+                    return plcBrowseResponse;
+                }
+            });
+            return handledResponseFuture;
+        } catch (Exception e) {
+            return (CompletableFuture<? extends PlcBrowseResponse>) closeConnectionExceptionally(e);
+        }
+    }
+
     /**
      * Executes the Request.
      */
diff --git a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
index d039f16aa4..e48b1aa4f0 100644
--- a/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
+++ b/plc4j/tools/opm/src/test/java/org/apache/plc4x/java/opm/PlcEntityManagerComplexTest.java
@@ -24,7 +24,10 @@ import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
+import org.apache.plc4x.java.api.model.ArrayInfo;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
@@ -34,7 +37,7 @@ import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
 import org.apache.plc4x.java.spi.messages.PlcReader;
 import org.apache.plc4x.java.spi.messages.PlcWriter;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
-import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 import org.apache.plc4x.java.spi.values.PlcDINT;
 import org.apache.plc4x.java.spi.values.PlcLINT;
 import org.assertj.core.api.WithAssertions;
@@ -48,10 +51,7 @@ import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -127,26 +127,26 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
     private PlcEntityManager getInitializedEntityManager() throws PlcConnectionException {
         Map<String, PlcValue> map = new HashMap<>();
         String prefix = ConnectedEntity.class.getName() + ".";
-        map.put(prefix + "boolVar", IEC61131ValueHandler.of(true));
-        map.put(prefix + "byteVar", IEC61131ValueHandler.of((byte) 1));
-        map.put(prefix + "shortVar", IEC61131ValueHandler.of((short) 1));
-        map.put(prefix + "intVar", IEC61131ValueHandler.of(1));
-        map.put(prefix + "longVar", IEC61131ValueHandler.of(1L));
-        map.put(prefix + "boxedBoolVar", IEC61131ValueHandler.of(1L));
-        map.put(prefix + "boxedByteVar", IEC61131ValueHandler.of((byte) 1));
-        map.put(prefix + "boxedShortVar", IEC61131ValueHandler.of((short) 1));
-        map.put(prefix + "boxedIntegerVar", IEC61131ValueHandler.of(1));
-        map.put(prefix + "boxedLongVar", IEC61131ValueHandler.of(1L));
-        map.put(prefix + "bigIntegerVar", IEC61131ValueHandler.of(BigInteger.ONE));
-        map.put(prefix + "floatVar", IEC61131ValueHandler.of(1f));
-        map.put(prefix + "doubleVar", IEC61131ValueHandler.of(1d));
-        map.put(prefix + "bigDecimalVar", IEC61131ValueHandler.of(BigDecimal.ONE));
-        map.put(prefix + "localTimeVar", IEC61131ValueHandler.of(LocalTime.of(1, 1)));
-        map.put(prefix + "localDateVar", IEC61131ValueHandler.of(LocalDate.of(1, 1, 1)));
-        map.put(prefix + "localDateTimeVar", IEC61131ValueHandler.of(LocalDateTime.of(1, 1, 1, 1, 1)));
-        map.put(prefix + "byteArrayVar", IEC61131ValueHandler.of(new Byte[]{0x0, 0x1}));
-        map.put(prefix + "bigByteArrayVar", IEC61131ValueHandler.of(new Byte[]{0x0, 0x1}));
-        map.put(prefix + "stringVar", IEC61131ValueHandler.of("Hallo"));
+        map.put(prefix + "boolVar", PlcValueHandler.of(true));
+        map.put(prefix + "byteVar", PlcValueHandler.of((byte) 1));
+        map.put(prefix + "shortVar", PlcValueHandler.of((short) 1));
+        map.put(prefix + "intVar", PlcValueHandler.of(1));
+        map.put(prefix + "longVar", PlcValueHandler.of(1L));
+        map.put(prefix + "boxedBoolVar", PlcValueHandler.of(1L));
+        map.put(prefix + "boxedByteVar", PlcValueHandler.of((byte) 1));
+        map.put(prefix + "boxedShortVar", PlcValueHandler.of((short) 1));
+        map.put(prefix + "boxedIntegerVar", PlcValueHandler.of(1));
+        map.put(prefix + "boxedLongVar", PlcValueHandler.of(1L));
+        map.put(prefix + "bigIntegerVar", PlcValueHandler.of(BigInteger.ONE));
+        map.put(prefix + "floatVar", PlcValueHandler.of(1f));
+        map.put(prefix + "doubleVar", PlcValueHandler.of(1d));
+        map.put(prefix + "bigDecimalVar", PlcValueHandler.of(BigDecimal.ONE));
+        map.put(prefix + "localTimeVar", PlcValueHandler.of(LocalTime.of(1, 1)));
+        map.put(prefix + "localDateVar", PlcValueHandler.of(LocalDate.of(1, 1, 1)));
+        map.put(prefix + "localDateTimeVar", PlcValueHandler.of(LocalDateTime.of(1, 1, 1, 1, 1)));
+        map.put(prefix + "byteArrayVar", PlcValueHandler.of(new Byte[]{0x0, 0x1}));
+        map.put(prefix + "bigByteArrayVar", PlcValueHandler.of(new Byte[]{0x0, 0x1}));
+        map.put(prefix + "stringVar", PlcValueHandler.of("Hallo"));
         return getPlcEntityManager(map);
     }
 
@@ -251,19 +251,38 @@ public class PlcEntityManagerComplexTest implements WithAssertions {
         return new NoOpPlcFieldHandler();
     }
 
-    private PlcValueHandler getValueHandler() {
+    private org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
         return new NoOpPlcValueHandler();
     }
 
     private static class NoOpPlcFieldHandler implements PlcFieldHandler {
         @Override
-        public org.apache.plc4x.java.api.model.PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+        public org.apache.plc4x.java.api.model.PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
             return new org.apache.plc4x.java.api.model.PlcField() {
+                @Override
+                public String getAddressString() {
+                    return "address";
+                }
+
+                @Override
+                public PlcValueType getPlcValueType() {
+                    return org.apache.plc4x.java.api.model.PlcField.super.getPlcValueType();
+                }
+
+                @Override
+                public List<ArrayInfo> getArrayInfo() {
+                    return org.apache.plc4x.java.api.model.PlcField.super.getArrayInfo();
+                }
             };
         }
+
+        @Override
+        public PlcQuery parseQuery(String query) {
+            throw new UnsupportedOperationException("This driver doesn't support browsing");
+        }
     }
 
-    private static class NoOpPlcValueHandler implements PlcValueHandler {
+    private static class NoOpPlcValueHandler implements org.apache.plc4x.java.api.value.PlcValueHandler {
         @Override
         public PlcValue newPlcValue(Object value) {
             throw new RuntimeException("Data Type " + value.getClass().getSimpleName() + "Is not supported");
diff --git a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
index eac63f291b..8ebacfe08c 100644
--- a/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
+++ b/plc4j/tools/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
@@ -153,13 +153,13 @@ public class TriggerConfiguration{
      */
     private static Class<?> validateDataType(PlcField plcField) throws ScraperConfigurationException {
         if(plcField!=null){
-            Class<?> javaDataType = plcField.getDefaultJavaType();
+            Class<?> javaDataType = plcField.getPlcValueType().getDefaultJavaType();
             if(!javaDataType.equals(Boolean.class)
                 && !javaDataType.equals(Integer.class)
                 && !javaDataType.equals(Long.class)
                 && !javaDataType.equals(Double.class)
             ){
-                String exceptionMessage = String.format("Unsupported plc-trigger variable %s with converted data-type %s used",plcField,plcField.getDefaultJavaType());
+                String exceptionMessage = String.format("Unsupported plc-trigger variable %s with converted data-type %s used",plcField,plcField.getPlcValueType().getDefaultJavaType());
                 throw new ScraperConfigurationException(exceptionMessage);
             }
             return javaDataType;
@@ -656,7 +656,7 @@ public class TriggerConfiguration{
         private void matchTypeAndComparator() throws ScraperConfigurationException {
             if(validateDataType(this.plcField).equals(Boolean.class)
                 && !(this.comparatorType.equals(Comparator.EQUAL) || this.comparatorType.equals(Comparator.UNEQUAL))){
-                String exceptionMessage = String.format("Trigger-Data-Type (%s) and Comparator (%s) do not match",this.plcField.getDefaultJavaType(),this.comparatorType);
+                String exceptionMessage = String.format("Trigger-Data-Type (%s) and Comparator (%s) do not match",this.plcField.getPlcValueType().getDefaultJavaType(),this.comparatorType);
                 throw new ScraperConfigurationException(exceptionMessage);
             }
             //all other combinations are valid
diff --git a/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/ConnectionTabController.java b/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/ConnectionTabController.java
index 85f06bc5b5..21a32f50bf 100644
--- a/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/ConnectionTabController.java
+++ b/plc4j/tools/ui/src/main/java/org/apache/plc4x/java/ui/ConnectionTabController.java
@@ -30,6 +30,7 @@ import org.apache.plc4x.java.api.types.PlcValueType;
 import org.kordamp.ikonli.javafx.FontIcon;
 import org.kordamp.ikonli.materialdesign.MaterialDesign;
 
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
@@ -87,11 +88,13 @@ public class ConnectionTabController {
                 rootItem.setExpanded(true);
 
                 // Sort the entries first.
-                List<PlcBrowseItem> values = browseResponse.getValues();
-                values.sort(new PlcBrowseItemComparator());
-                // Then add the elements to the tree.
-                for (PlcBrowseItem value : values) {
-                    rootItem.getChildren().add(getTreeItemForBrowseItem(value));
+                for (String queryName : browseResponse.getQueryNames()) {
+                    List<PlcBrowseItem> values = browseResponse.getValues(queryName);
+                    values.sort(new PlcBrowseItemComparator());
+                    // Then add the elements to the tree.
+                    for (PlcBrowseItem value : values) {
+                        rootItem.getChildren().add(getTreeItemForBrowseItem(value));
+                    }
                 }
 
                 resourceTreeView.setRoot(rootItem);
@@ -114,7 +117,7 @@ public class ConnectionTabController {
             browseItem.isReadable(), browseItem.isWritable(), browseItem.isSubscribable()));
         if(!browseItem.getChildren().isEmpty()) {
             // Sort the entries first.
-            List<PlcBrowseItem> values = browseItem.getChildren();
+            List<PlcBrowseItem> values = new ArrayList<>(browseItem.getChildren().values());
             // Then add the elements to the tree.
             values.sort(new PlcBrowseItemComparator());
             for (PlcBrowseItem child : values) {
diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
index 494da6bcf8..99c03d2dba 100644
--- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
+++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/manual/ManualTest.java
@@ -27,6 +27,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.spi.values.PlcList;
+import org.apache.plc4x.java.spi.values.PlcStruct;
 import org.apache.plc4x.java.spi.values.PlcValues;
 import org.junit.jupiter.api.Assertions;
 
@@ -91,7 +92,9 @@ public abstract class ManualTest {
                         }
                     }
                 } else {
-                    if (testCase.expectedReadValue instanceof PlcValue) {
+                    if (testCase.expectedReadValue instanceof PlcStruct) {
+                        Assertions.assertEquals(testCase.expectedReadValue.toString(), readResponse.getPlcValue(fieldName).toString(), fieldName);
+                    } else if (testCase.expectedReadValue instanceof PlcValue) {
                         Assertions.assertEquals(
                             ((PlcValue) testCase.expectedReadValue).getObject(), readResponse.getPlcValue(fieldName).getObject(), fieldName);
                     } else {
diff --git a/pom.xml b/pom.xml
index ed3e679dce..b09ae3cbe6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -799,6 +799,7 @@
             <!-- Temporarily exclude generated code from thrift in python modules -->
             <!--exclude>generated/**</exclude-->
             <!-- Temporary Python files -->
+            <exclude>**/.eggs/**</exclude>
             <exclude>**/plc4py.egg-info/**</exclude>
 
             <!-- Temporary Python virtualenv files-->
diff --git a/protocols/canopen/src/main/resources/protocols/can/canopen.mspec b/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
index a23cedb0e6..d10f26d58a 100644
--- a/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/canopen/src/main/resources/protocols/can/canopen.mspec
@@ -240,34 +240,34 @@
     [simple uint 16 days]
 ]
 
-[enum CANOpenDataType (uint 8 numBits)
-    [BOOLEAN     [ '1'] ]
-    [UNSIGNED8   [ '8'] ]
-    [UNSIGNED16  ['16'] ]
-    [UNSIGNED24  ['24'] ]
-    [UNSIGNED32  ['32'] ]
-    [UNSIGNED40  ['40'] ]
-    [UNSIGNED48  ['48'] ]
-    [UNSIGNED56  ['56'] ]
-    [UNSIGNED64  ['64'] ]
-    [INTEGER8    [ '8'] ]
-    [INTEGER16   ['16'] ]
-    [INTEGER24   ['24'] ]
-    [INTEGER32   ['32'] ]
-    [INTEGER40   ['40'] ]
-    [INTEGER48   ['48'] ]
-    [INTEGER56   ['56'] ]
-    [INTEGER64   ['64'] ]
-    [REAL32      ['32'] ]
-    [REAL64      ['64'] ]
+[enum CANOpenDataType (uint 8 numBits, vstring plcValueName)
+    [BOOLEAN     [ '1', '"BIT"'           ] ]
+    [UNSIGNED8   [ '8', '"USINT"'         ] ]
+    [UNSIGNED16  ['16', '"UINT"'          ] ]
+    [UNSIGNED24  ['24', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED32  ['32', '"UDINT"'         ] ]
+    [UNSIGNED40  ['40', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED48  ['48', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED56  ['56', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED64  ['64', '"ULINT"'         ] ]
+    [INTEGER8    [ '8', '"SINT"'          ] ]
+    [INTEGER16   ['16', '"INT"'           ] ]
+    [INTEGER24   ['24', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER32   ['32', '"DINT"'          ] ]
+    [INTEGER40   ['40', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER48   ['48', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER56   ['56', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER64   ['64', '"LINT"'          ] ]
+    [REAL32      ['32', '"REAL"'          ] ]
+    [REAL64      ['64', '"LREAL"'         ] ]
 
     // compound/complex types
-    [RECORD           [ '8'] ]
-    [OCTET_STRING     [ '8'] ]
-    [VISIBLE_STRING   [ '8'] ]
-    [UNICODE_STRING   ['16'] ]
-    [TIME_OF_DAY      ['48'] ]
-    [TIME_DIFFERENCE  ['48'] ]
+    [RECORD           [ '8', '"BYTE"'       ] ]
+    [OCTET_STRING     [ '8', '"BYTE"'       ] ]
+    [VISIBLE_STRING   [ '8', '"CHAR"'       ] ]
+    [UNICODE_STRING   ['16', '"WCHAR"'      ] ]
+    [TIME_OF_DAY      ['48', '"TIME_OF_DAY"'] ]
+    [TIME_DIFFERENCE  ['48', '"TIME"'       ] ]
 ]
 
 [dataIo DataItem(CANOpenDataType dataType, int 32 size)
diff --git a/protocols/eip/src/main/resources/protocols/eip/eip.mspec b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
index 5e3092e708..27f1023267 100644
--- a/protocols/eip/src/main/resources/protocols/eip/eip.mspec
+++ b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
@@ -124,7 +124,7 @@
     ['0X00D3'   DWORD           ['4']]
     ['0X02A0'   STRUCTURED      ['88']]
     ['0X02A0'   STRING          ['88']]
-    ['0X02A0'   STRING36        ['40']]
+    //['0X02A0'   STRING36        ['40']]
     //TODO: -1 is not a valid value for uint
     //['-1'       UNKNOWN         ['-1']]
 ]
diff --git a/protocols/genericcan/src/main/resources/protocols/can/genericcan.mspec b/protocols/genericcan/src/main/resources/protocols/can/genericcan.mspec
index 6d9cd761b5..99b3a187fe 100644
--- a/protocols/genericcan/src/main/resources/protocols/can/genericcan.mspec
+++ b/protocols/genericcan/src/main/resources/protocols/can/genericcan.mspec
@@ -17,27 +17,27 @@
  * under the License.
  */
 
-[enum GenericCANDataType(uint 8 numBits)
-    [BYTE        [ '8'] ]
-    [BOOLEAN     [ '1'] ]
-    [UNSIGNED8   [ '8'] ]
-    [UNSIGNED16  ['16'] ]
-    [UNSIGNED24  ['24'] ]
-    [UNSIGNED32  ['32'] ]
-    [UNSIGNED40  ['40'] ]
-    [UNSIGNED48  ['48'] ]
-    [UNSIGNED56  ['56'] ]
-    [UNSIGNED64  ['64'] ]
-    [INTEGER8    [ '8'] ]
-    [INTEGER16   ['16'] ]
-    [INTEGER24   ['24'] ]
-    [INTEGER32   ['32'] ]
-    [INTEGER40   ['40'] ]
-    [INTEGER48   ['48'] ]
-    [INTEGER56   ['56'] ]
-    [INTEGER64   ['64'] ]
-    [REAL32      ['32'] ]
-    [REAL64      ['64'] ]
+[enum GenericCANDataType(uint 8 numBits, vstring plcValueName)
+    [BYTE        [ '8', '"BYTE"'          ] ]
+    [BOOLEAN     [ '1', '"BIT"'           ] ]
+    [UNSIGNED8   [ '8', '"BYTE"'          ] ]
+    [UNSIGNED16  ['16', '"WORD"'          ] ]
+    [UNSIGNED24  ['24', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED32  ['32', '"DWORD"'         ] ]
+    [UNSIGNED40  ['40', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED48  ['48', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED56  ['56', '"RAW_BYTE_ARRAY"'] ]
+    [UNSIGNED64  ['64', '"LWORD"'         ] ]
+    [INTEGER8    [ '8', '"SINT"'          ] ]
+    [INTEGER16   ['16', '"INT"'           ] ]
+    [INTEGER24   ['24', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER32   ['32', '"DINT"'          ] ]
+    [INTEGER40   ['40', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER48   ['48', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER56   ['56', '"RAW_BYTE_ARRAY"'] ]
+    [INTEGER64   ['64', '"LINT"'          ] ]
+    [REAL32      ['32', '"REAL"'          ] ]
+    [REAL64      ['64', '"LREAL"'         ] ]
 ]
 
 [dataIo DataItem(GenericCANDataType dataType) byteOrder='LITTLE_ENDIAN'
diff --git a/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryConnection.java b/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryConnection.java
index f886606cfd..44b270cdfa 100644
--- a/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryConnection.java
+++ b/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryConnection.java
@@ -145,7 +145,7 @@ public class DiscoveryConnection implements PlcConnection, PlcSubscriber, PlcBro
 
     @Override
     public PlcBrowseRequest.Builder browseRequestBuilder() {
-        return new DefaultPlcBrowseRequest.Builder(this);
+        return new DefaultPlcBrowseRequest.Builder(this, new DiscoveryFieldHandler());
     }
 
     @Override
@@ -177,4 +177,10 @@ public class DiscoveryConnection implements PlcConnection, PlcSubscriber, PlcBro
         return null;
     }
 
+    @Override
+    public CompletableFuture<PlcBrowseResponse> browseWithInterceptor(PlcBrowseRequest browseRequest, PlcBrowseRequestInterceptor interceptor) {
+        // TODO: Implement ...
+        return null;
+    }
+
 }
diff --git a/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryFieldHandler.java b/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryFieldHandler.java
index 5ee869734b..bf0acc1be7 100644
--- a/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryFieldHandler.java
+++ b/sandbox/discovery/src/main/java/org/apache/plc4x/java/discovery/DiscoveryFieldHandler.java
@@ -20,14 +20,20 @@ package org.apache.plc4x.java.discovery;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class DiscoveryFieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         // TODO: Implement ...
         return null;
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
index 2f1baded9b..3f40869ca7 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
@@ -18,7 +18,6 @@
  */
 package org.apache.plc4x.java.df1;
 
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.df1.configuration.Df1Configuration;
 import org.apache.plc4x.java.df1.field.Df1FieldHandler;
 import org.apache.plc4x.java.df1.protocol.Df1ProtocolLogic;
@@ -27,7 +26,7 @@ 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.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.spi.values.PlcValueHandler;
 
 public class DF1PlcDriver extends GeneratedDriverBase<DF1Command> {
 
@@ -57,8 +56,8 @@ public class DF1PlcDriver extends GeneratedDriverBase<DF1Command> {
     }
 
     @Override
-    protected PlcValueHandler getValueHandler() {
-        return new IEC61131ValueHandler();
+    protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() {
+        return new PlcValueHandler();
     }
 
     @Override
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1Field.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1Field.java
index 5c01f4b67f..8824c38ef0 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1Field.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1Field.java
@@ -18,21 +18,42 @@
  */
 package org.apache.plc4x.java.df1.field;
 
+import org.apache.plc4x.java.api.model.ArrayInfo;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcValueType;
 import org.apache.plc4x.java.df1.types.DataType;
 
+import java.util.Collections;
+import java.util.List;
+
 public class Df1Field implements PlcField {
 
     private final int address;
     private final int size;
     private final DataType dataType;
-    private final addressType address_type;
+    private final AddressType addressType;
 
-    public Df1Field(int address, int size, DataType dataType, addressType address_type) {
+    public Df1Field(int address, int size, DataType dataType, AddressType addressType) {
         this.address = address;
         this.size = size;
         this.dataType = dataType;
-        this.address_type = address_type;
+        this.addressType = addressType;
+    }
+
+    @Override
+    public String getAddressString() {
+        return String.format("%d:%s", address, addressType.toString());
+    }
+
+    @Override
+    public PlcValueType getPlcValueType() {
+        return dataType.getPlcValueType();
+    }
+
+    @Override
+    public List<ArrayInfo> getArrayInfo() {
+        // TODO: This might need some work...
+        return Collections.emptyList();
     }
 
     public int getAddress() {
@@ -47,14 +68,14 @@ public class Df1Field implements PlcField {
         return dataType;
     }
 
-    public addressType getAddress_type() { return address_type; }
+    public AddressType getAddressType() { return addressType; }
 
     public static PlcField of(String fieldQuery) {
         String[] tmp = fieldQuery.split(":");
-        return new Df1Field(Integer.parseInt(tmp[0]), DataType.valueOf(tmp[1]).getLength(),DataType.valueOf(tmp[1]), addressType.OFFSET);
+        return new Df1Field(Integer.parseInt(tmp[0]), DataType.valueOf(tmp[1]).getLength(),DataType.valueOf(tmp[1]), AddressType.OFFSET);
     }
 
-    public enum addressType {
+    public enum AddressType {
         OFFSET,
         LOGICAL
     }
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
index d0780c70f7..6c8d422476 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/field/Df1FieldHandler.java
@@ -20,13 +20,19 @@ package org.apache.plc4x.java.df1.field;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcQuery;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
 public class Df1FieldHandler implements PlcFieldHandler {
 
     @Override
-    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+    public PlcField parseField(String fieldQuery) throws PlcInvalidFieldException {
         return Df1Field.of(fieldQuery);
     }
 
+    @Override
+    public PlcQuery parseQuery(String query) {
+        throw new UnsupportedOperationException("This driver doesn't support browsing");
+    }
+
 }
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Plc4XDf1Protocol.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Plc4XDf1Protocol.java
index f962ae1ebc..11d9abf507 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Plc4XDf1Protocol.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/protocol/Plc4XDf1Protocol.java
@@ -71,7 +71,7 @@ public class Plc4XDf1Protocol extends PlcMessageToMessageCodec<DF1Symbol, PlcReq
 
                 requests.put(transactionId, msg);
 
-                switch (((Df1Field) field).getAddress_type()) {
+                switch (((Df1Field) field).getAddressType()) {
                     case OFFSET:
                         out.add(new DF1UnprotectedReadRequest((short) 0x00, (short)transactionId, address, size));
                         break;
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/types/DataType.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/types/DataType.java
index d486f6e3f3..f8b54a9e9b 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/types/DataType.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/types/DataType.java
@@ -18,27 +18,35 @@
  */
 package org.apache.plc4x.java.df1.types;
 
+import org.apache.plc4x.java.api.types.PlcValueType;
+
 public enum DataType {
-    BIT((short)1),
-    BIT_STRING((short)-1),
-    BYTE_STRING((short)-1),
-    INTEGER((short)2),
-    TIMER((short)-1),
-    COUNTER((short)-1),
-    GENERAL_COUNT_STRUCTURE((short)-1),
-    FLOAT((short)-1),
-    ARRAY((short)-1),
-    ADDRESS((short)-1),
-    BINARY_CODED_DECIMAL((short)-1);
+    BIT((short)1, PlcValueType.BOOL),
+    BIT_STRING((short)-1, PlcValueType.List),
+    BYTE_STRING((short)-1, PlcValueType.BYTE),
+    INTEGER((short)2, PlcValueType.INT),
+    TIMER((short)-1, PlcValueType.TIME),
+    COUNTER((short)-1, PlcValueType.LINT),
+    GENERAL_COUNT_STRUCTURE((short)-1, PlcValueType.Struct),
+    FLOAT((short)-1, PlcValueType.REAL),
+    ARRAY((short)-1, PlcValueType.List),
+    ADDRESS((short)-1, PlcValueType.STRING),
+    BINARY_CODED_DECIMAL((short)-1, PlcValueType.LINT);
 
     private final short length;
+    private final PlcValueType plcValueType;
 
-    DataType(short length) {
+    DataType(short length, PlcValueType plcValueType) {
         this.length = length;
+        this.plcValueType = plcValueType;
     }
 
     public short getLength() {
         return length;
     }
 
+    public PlcValueType getPlcValueType() {
+        return plcValueType;
+    }
+
 }