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 22:11:23 UTC

[plc4x] branch feature/cdutz/go-ads-ng updated: refactor(api) PLC4Go 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 e4527f578d refactor(api) PLC4Go API refactoring
e4527f578d is described below

commit e4527f578d7ca569614fdd94fafd9aed8782de0f
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Nov 6 23:11:15 2022 +0100

    refactor(api) PLC4Go API refactoring
    
    - Continued porting the PLC4Go API to be on par with the updated PLC4J API
    - Started porting most of the existing code, but espeically the Browse parts still need quite some work.
---
 plc4go/internal/ads/Browser.go                     |  61 +--
 plc4go/internal/ads/Field.go                       | 102 +++-
 plc4go/internal/ads/FieldHandler.go                |   8 +-
 .../DefaultPlcRequest.go => internal/ads/Query.go} |  15 +-
 plc4go/internal/ads/Reader.go                      |   4 +-
 plc4go/internal/bacnetip/Field.go                  |  15 +-
 plc4go/internal/bacnetip/FieldHandler.go           |  18 +-
 plc4go/internal/cbus/Browser.go                    |  28 +-
 plc4go/internal/cbus/Field.go                      | 217 ++++++--
 plc4go/internal/cbus/FieldHandler.go               |  27 +-
 plc4go/internal/cbus/ValueHandler.go               | 601 +++++++++++----------
 plc4go/internal/eip/Field.go                       |  34 +-
 plc4go/internal/eip/FieldHandler.go                |  12 +-
 plc4go/internal/knxnetip/Browser.go                |   3 +-
 plc4go/internal/knxnetip/Field.go                  |  87 ++-
 plc4go/internal/knxnetip/FieldHandler.go           |  28 +-
 plc4go/internal/knxnetip/SubscriptionEvent.go      |   3 +-
 plc4go/internal/knxnetip/Utils.go                  |   3 +-
 plc4go/internal/modbus/Field.go                    |  53 +-
 plc4go/internal/modbus/FieldHandler.go             |  31 +-
 plc4go/internal/s7/Field.go                        |  23 +-
 plc4go/internal/s7/FieldHandler.go                 |  14 +-
 plc4go/internal/simulated/Device.go                |  13 +-
 plc4go/internal/simulated/Device_test.go           |  35 +-
 plc4go/internal/simulated/Field.go                 |  39 +-
 plc4go/internal/simulated/FieldHandler.go          |  12 +-
 plc4go/internal/simulated/Field_test.go            |  19 +-
 plc4go/internal/simulated/Reader.go                |   7 +-
 plc4go/internal/simulated/Reader_test.go           |  15 +-
 plc4go/internal/simulated/Writer.go                |   7 +-
 plc4go/internal/simulated/Writer_test.go           |  25 +-
 plc4go/pkg/api/model/plc_browse.go                 |  11 -
 plc4go/pkg/api/values/plc_value.go                 | 221 +++++---
 plc4go/spi/default/DefaultBrowser.go               |  18 +-
 plc4go/spi/default/DefaultConnection.go            |   3 +-
 .../{DefaultPlcRequest.go => DefaultArrayInfo.go}  |  16 +-
 plc4go/spi/model/DefaultPlcBrowseItem.go           |  16 +-
 plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go  |  49 +-
 plc4go/spi/model/DefaultPlcBrowseResponse.go       |  17 +-
 plc4go/spi/model/DefaultPlcRequest.go              |  33 +-
 plc4go/spi/model/DefaultRequest_plc4xgen.go        |  93 ----
 plc4go/spi/values/BINT.go                          | 174 ------
 plc4go/spi/values/BREAL.go                         | 203 -------
 plc4go/spi/values/{BOOL.go => PlcBOOL.go}          |   1 +
 plc4go/spi/values/{BYTE.go => PlcBYTE.go}          |   1 +
 plc4go/spi/values/PlcBitString.go                  |  83 ---
 plc4go/spi/values/{CHAR.go => PlcCHAR.go}          |   1 +
 plc4go/spi/values/{DATE.go => PlcDATE.go}          |   3 +-
 .../{DATE_AND_TIME.go => PlcDATE_AND_TIME.go}      |   3 +-
 plc4go/spi/values/{DINT.go => PlcDINT.go}          |   5 +-
 plc4go/spi/values/{DWORD.go => PlcDWORD.go}        |   1 +
 plc4go/spi/values/{INT.go => PlcINT.go}            |   5 +-
 plc4go/spi/values/PlcLDATE.go                      |   1 +
 plc4go/spi/values/PlcLDATE_AND_TIME.go             |   1 +
 plc4go/spi/values/{LINT.go => PlcLINT.go}          |   5 +-
 plc4go/spi/values/{LREAL.go => PlcLREAL.go}        |   3 +-
 plc4go/spi/values/{LTIME.go => PlcLTIME.go}        |   3 +-
 plc4go/spi/values/PlcLTIME_OF_DAY.go               |   1 +
 plc4go/spi/values/{LWORD.go => PlcLWORD.go}        |   1 +
 plc4go/spi/values/PlcList.go                       |   7 +-
 plc4go/spi/values/{NULL.go => PlcNull.go}          |  13 +-
 plc4go/spi/values/{REAL.go => PlcREAL.go}          |   3 +-
 .../values/{PlcByteArray.go => PlcRawByteArray.go} |   3 +-
 plc4go/spi/values/{SINT.go => PlcSINT.go}          |   3 +-
 plc4go/spi/values/{STRING.go => PlcSTRING.go}      |   1 +
 plc4go/spi/values/PlcStruct.go                     |   5 +-
 plc4go/spi/values/{TIME.go => PlcTIME.go}          |   3 +-
 .../values/{TIME_OF_DAY.go => PlcTIME_OF_DAY.go}   |   3 +-
 plc4go/spi/values/{UDINT.go => PlcUDINT.go}        |   5 +-
 plc4go/spi/values/{UINT.go => PlcUINT.go}          |   5 +-
 plc4go/spi/values/{ULINT.go => PlcULINT.go}        |   5 +-
 plc4go/spi/values/{USINT.go => PlcUSINT.go}        |   5 +-
 ...{IEC61131ValueHandler.go => PlcValueHandler.go} |   0
 plc4go/spi/values/{WCHAR.go => PlcWCHAR.go}        |   1 +
 plc4go/spi/values/{WORD.go => PlcWORD.go}          |   1 +
 plc4go/spi/values/{WSTRING.go => PlcWSTRING.go}    |   1 +
 plc4go/spi/values/RawPlcValue.go                   |  92 ----
 plc4go/spi/values/value_combination_test.go        |  22 +-
 .../eip/src/main/resources/protocols/eip/eip.mspec |   2 +-
 79 files changed, 1195 insertions(+), 1516 deletions(-)

diff --git a/plc4go/internal/ads/Browser.go b/plc4go/internal/ads/Browser.go
index 7a677309ff..965eefd117 100644
--- a/plc4go/internal/ads/Browser.go
+++ b/plc4go/internal/ads/Browser.go
@@ -32,19 +32,19 @@ import (
 )
 
 func (m *Connection) Browse(ctx context.Context, browseRequest apiModel.PlcBrowseRequest) <-chan apiModel.PlcBrowseRequestResult {
-	return m.BrowseWithInterceptor(ctx, browseRequest, func(result apiModel.PlcBrowseEvent) bool {
+	return m.BrowseWithInterceptor(ctx, browseRequest, func(result apiModel.PlcBrowseItem) bool {
 		return true
 	})
 }
 
-func (m *Connection) BrowseWithInterceptor(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseEvent) bool) <-chan apiModel.PlcBrowseRequestResult {
+func (m *Connection) BrowseWithInterceptor(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool) <-chan apiModel.PlcBrowseRequestResult {
 	result := make(chan apiModel.PlcBrowseRequestResult)
 	go func() {
 		responseCodes := map[string]apiModel.PlcResponseCode{}
-		results := map[string][]apiModel.PlcBrowseFoundField{}
-		for _, fieldName := range browseRequest.GetFieldNames() {
-			field := browseRequest.GetField(fieldName)
-			responseCodes[fieldName], results[fieldName] = m.BrowseField(ctx, browseRequest, interceptor, fieldName, field)
+		results := map[string][]apiModel.PlcBrowseItem{}
+		for _, queryName := range browseRequest.GetQueryNames() {
+			query := browseRequest.GetQuery(queryName)
+			responseCodes[queryName], results[queryName] = m.BrowseQuery(ctx, browseRequest, interceptor, queryName, query)
 		}
 		browseResponse := model2.NewDefaultPlcBrowseResponse(browseRequest, results, responseCodes)
 		result <- &model2.DefaultPlcBrowseRequestResult{
@@ -56,16 +56,16 @@ func (m *Connection) BrowseWithInterceptor(ctx context.Context, browseRequest ap
 	return result
 }
 
-func (m *Connection) BrowseField(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseEvent) bool, fieldName string, field apiModel.PlcField) (apiModel.PlcResponseCode, []apiModel.PlcBrowseFoundField) {
-	switch field.(type) {
-	case SymbolicPlcField:
-		return m.executeSymbolicAddressQuery(ctx, field.(SymbolicPlcField))
+func (m *Connection) BrowseQuery(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool, queryName string, query apiModel.PlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem) {
+	switch query.(type) {
+	case SymbolicPlcQuery:
+		return m.executeSymbolicAddressQuery(ctx, query.(SymbolicPlcQuery))
 	default:
 		return apiModel.PlcResponseCode_INTERNAL_ERROR, nil
 	}
 }
 
-func (m *Connection) executeSymbolicAddressQuery(ctx context.Context, field SymbolicPlcField) (apiModel.PlcResponseCode, []apiModel.PlcBrowseFoundField) {
+func (m *Connection) executeSymbolicAddressQuery(ctx context.Context, query SymbolicPlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem) {
 	var err error
 
 	// First read the sizes of the data type and symbol table, if needed.
@@ -94,11 +94,11 @@ func (m *Connection) executeSymbolicAddressQuery(ctx context.Context, field Symb
 	}
 
 	// Process the data type and symbol tables to produce the response.
-	fields := m.filterSymbols(field.SymbolicAddress)
+	fields := m.filterSymbols(query.GetSymbolicAddressPattern())
 	return apiModel.PlcResponseCode_OK, fields
 }
 
-func (m *Connection) filterSymbols(filterExpression string) []apiModel.PlcBrowseFoundField {
+func (m *Connection) filterSymbols(filterExpression string) []apiModel.PlcBrowseItem {
 	if len(filterExpression) == 0 {
 		return nil
 	}
@@ -173,33 +173,30 @@ func LALALA(){
 }
 */
 
-func (m *Connection) filterDataTypes(parentName string, currentType model.AdsDataTypeTableEntry, currentPath string, remainingAddressSegments []string) []apiModel.PlcBrowseFoundField {
+func (m *Connection) filterDataTypes(parentName string, currentType model.AdsDataTypeTableEntry, currentPath string, remainingAddressSegments []string) []apiModel.PlcBrowseItem {
 	if len(remainingAddressSegments) == 0 {
-		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())
+		arrayInfo := []apiModel.ArrayInfo{}
+		for _, ai := range currentType.GetArrayInfo() {
+			arrayInfo = append(arrayInfo, model2.DefaultArrayInfo{
+				LowerBound: ai.GetLowerBound(),
+				UpperBound: ai.GetUpperBound(),
+			})
 		}
-		foundField := &model2.DefaultPlcBrowseQueryResult{
+		foundField := &model2.DefaultPlcBrowseItem{
 			Field: SymbolicPlcField{
 				PlcField: PlcField{
-					NumElements:  numElements,
-					StartElement: startElement,
-					EndElement:   endElement,
+					arrayInfo: arrayInfo,
 				},
 				SymbolicAddress: parentName,
 			},
-			Name:              parentName,
-			Readable:          false,
-			Writable:          false,
-			Subscribable:      false,
-			PossibleDataTypes: nil,
-			Attributes:        nil,
+			Name:         parentName,
+			DataTypeName: currentType.GetDataTypeName(),
+			Readable:     false,
+			Writable:     false,
+			Subscribable: false,
+			Options:      nil,
 		}
-		return []apiModel.PlcBrowseFoundField{foundField}
+		return []apiModel.PlcBrowseItem{foundField}
 	}
 
 	currentAddressSegment := remainingAddressSegments[0]
diff --git a/plc4go/internal/ads/Field.go b/plc4go/internal/ads/Field.go
index 299078246c..98eafacfd0 100644
--- a/plc4go/internal/ads/Field.go
+++ b/plc4go/internal/ads/Field.go
@@ -22,8 +22,11 @@ package ads
 import (
 	"encoding/binary"
 	"encoding/xml"
+	"fmt"
+	"strconv"
 
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	adsModel "github.com/apache/plc4x/plc4go/protocols/ads/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
@@ -34,9 +37,7 @@ const NONE = int32(-1)
 type PlcField struct {
 	model.PlcField
 
-	NumElements  int32
-	StartElement int32
-	EndElement   int32
+	arrayInfo []model.ArrayInfo
 }
 
 func needsResolving(plcField model.PlcField) bool {
@@ -59,16 +60,14 @@ type DirectPlcField struct {
 	StringLength int32
 }
 
-func newDirectAdsPlcField(indexGroup uint32, indexOffset uint32, adsDatatype adsModel.AdsDataType, stringLength int32, numElements int32, startElement int32, endElement int32) (model.PlcField, error) {
+func newDirectAdsPlcField(indexGroup uint32, indexOffset uint32, adsDatatype adsModel.AdsDataType, stringLength int32, arrayInfo []model.ArrayInfo) (model.PlcField, error) {
 	return DirectPlcField{
 		IndexGroup:   indexGroup,
 		IndexOffset:  indexOffset,
 		AdsDatatype:  adsDatatype,
 		StringLength: stringLength,
 		PlcField: PlcField{
-			NumElements:  numElements,
-			StartElement: startElement,
-			EndElement:   endElement,
+			arrayInfo: arrayInfo,
 		},
 	}, nil
 }
@@ -80,6 +79,31 @@ func castToDirectAdsFieldFromPlcField(plcField model.PlcField) (DirectPlcField,
 	return DirectPlcField{}, errors.Errorf("couldn't %T cast to DirectPlcField", plcField)
 }
 
+func (m DirectPlcField) GetAddressString() string {
+	address := fmt.Sprintf("0x%d/%d:%s", m.IndexGroup, m.IndexOffset, m.AdsDatatype.String())
+	if m.AdsDatatype == adsModel.AdsDataType_STRING || m.AdsDatatype == adsModel.AdsDataType_WSTRING {
+		address = address + "(" + strconv.Itoa(int(m.StringLength)) + ")"
+	}
+	if len(m.arrayInfo) > 0 {
+		for _, ai := range m.arrayInfo {
+			address = address + "[" + strconv.Itoa(int(ai.GetLowerBound())) + ".." + strconv.Itoa(int(ai.GetUpperBound())) + "]"
+		}
+	}
+	return address
+}
+
+func (m DirectPlcField) GetValueType() values.PlcValueType {
+	if plcValueType, ok := values.PlcValueByName(m.AdsDatatype.PlcValueType().String()); !ok {
+		return values.NULL
+	} else {
+		return plcValueType
+	}
+}
+
+func (m DirectPlcField) GetArrayInfo() []model.ArrayInfo {
+	return []model.ArrayInfo{}
+}
+
 func (m DirectPlcField) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := m.SerializeWithWriteBuffer(wb); err != nil {
@@ -107,16 +131,25 @@ func (m DirectPlcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer)
 			return err
 		}
 	}
-	if m.NumElements != NONE {
-		if err := writeBuffer.WriteInt32("numElements", 32, m.NumElements); err != nil {
+	if len(m.arrayInfo) > 0 {
+		if err := writeBuffer.PushContext("ArrayInfo"); err != nil {
 			return err
 		}
-	}
-	if m.StartElement != NONE && m.EndElement != NONE {
-		if err := writeBuffer.WriteInt32("startElement", 32, m.StartElement); err != nil {
-			return err
+		for _, ai := range m.arrayInfo {
+			if err := writeBuffer.PushContext("ArrayInfo"); err != nil {
+				return err
+			}
+			if err := writeBuffer.WriteInt32("lowerBound", 32, int32(ai.GetLowerBound())); err != nil {
+				return err
+			}
+			if err := writeBuffer.WriteInt32("upperBound", 32, int32(ai.GetUpperBound())); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext("ArrayInfo"); err != nil {
+				return err
+			}
 		}
-		if err := writeBuffer.WriteInt32("endElement", 32, m.EndElement); err != nil {
+		if err := writeBuffer.PopContext("ArrayInfo"); err != nil {
 			return err
 		}
 	}
@@ -137,13 +170,11 @@ type SymbolicPlcField struct {
 	SymbolicAddress string
 }
 
-func newAdsSymbolicPlcField(symbolicAddress string, numElements int32, startElement int32, endElement int32) (model.PlcField, error) {
+func newAdsSymbolicPlcField(symbolicAddress string, arrayInfo []model.ArrayInfo) (model.PlcField, error) {
 	return SymbolicPlcField{
 		SymbolicAddress: symbolicAddress,
 		PlcField: PlcField{
-			NumElements:  numElements,
-			StartElement: startElement,
-			EndElement:   endElement,
+			arrayInfo: arrayInfo,
 		},
 	}, nil
 }
@@ -155,6 +186,18 @@ func castToSymbolicPlcFieldFromPlcField(plcField model.PlcField) (SymbolicPlcFie
 	return SymbolicPlcField{}, errors.Errorf("couldn't cast %T to SymbolicPlcField", plcField)
 }
 
+func (m SymbolicPlcField) GetAddressString() string {
+	return m.SymbolicAddress
+}
+
+func (m SymbolicPlcField) GetValueType() values.PlcValueType {
+	return values.NULL
+}
+
+func (m SymbolicPlcField) GetArrayInfo() []model.ArrayInfo {
+	return []model.ArrayInfo{}
+}
+
 func (m SymbolicPlcField) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := m.SerializeWithWriteBuffer(wb); err != nil {
@@ -171,16 +214,25 @@ func (m SymbolicPlcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer
 	if err := writeBuffer.WriteString("symbolicAddress", uint32(len([]rune(m.SymbolicAddress))*8), "UTF-8", m.SymbolicAddress); err != nil {
 		return err
 	}
-	if m.NumElements != NONE {
-		if err := writeBuffer.WriteInt32("numElements", 32, m.NumElements); err != nil {
+	if len(m.arrayInfo) > 0 {
+		if err := writeBuffer.PushContext("ArrayInfo"); err != nil {
 			return err
 		}
-	}
-	if m.StartElement != NONE && m.EndElement != NONE {
-		if err := writeBuffer.WriteInt32("startElement", 32, m.StartElement); err != nil {
-			return err
+		for _, ai := range m.arrayInfo {
+			if err := writeBuffer.PushContext("ArrayInfo"); err != nil {
+				return err
+			}
+			if err := writeBuffer.WriteInt32("lowerBound", 32, int32(ai.GetLowerBound())); err != nil {
+				return err
+			}
+			if err := writeBuffer.WriteInt32("upperBound", 32, int32(ai.GetUpperBound())); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext("ArrayInfo"); err != nil {
+				return err
+			}
 		}
-		if err := writeBuffer.WriteInt32("endElement", 32, m.EndElement); err != nil {
+		if err := writeBuffer.PopContext("ArrayInfo"); err != nil {
 			return err
 		}
 	}
diff --git a/plc4go/internal/ads/FieldHandler.go b/plc4go/internal/ads/FieldHandler.go
index ab71fd87a2..2cc0c82dad 100644
--- a/plc4go/internal/ads/FieldHandler.go
+++ b/plc4go/internal/ads/FieldHandler.go
@@ -46,7 +46,7 @@ func NewFieldHandler() FieldHandler {
 	}
 }
 
-func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
+func (m FieldHandler) ParseField(query string) (apiModel.PlcField, error) {
 	if match := utils.GetSubgroupMatches(m.directAdsStringField, query); match != nil {
 		var indexGroup uint32
 		if indexGroupHexString := match["indexGroupHex"]; indexGroupHexString != "" {
@@ -266,8 +266,12 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 			}
 		}
 
-		return newAdsSymbolicPlcField(match["symbolicAddress"], numElements, startElement, endElement)
+		return newAdsSymbolicPlcField(match["symbolicAddress"])
 	} else {
 		return nil, errors.Errorf("Invalid address format for address '%s'", query)
 	}
 }
+
+func (m FieldHandler) ParseQuery(_ string) (apiModel.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
+}
diff --git a/plc4go/spi/model/DefaultPlcRequest.go b/plc4go/internal/ads/Query.go
similarity index 76%
copy from plc4go/spi/model/DefaultPlcRequest.go
copy to plc4go/internal/ads/Query.go
index ac8b62ad8c..d719f7ac6f 100644
--- a/plc4go/spi/model/DefaultPlcRequest.go
+++ b/plc4go/internal/ads/Query.go
@@ -17,17 +17,12 @@
  * under the License.
  */
 
-package model
+package ads
 
-import "github.com/apache/plc4x/plc4go/pkg/api/model"
+import apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 
-type DefaultPlcRequest struct {
-}
-
-func NewDefaultPlcRequest() model.PlcRequest {
-	return &DefaultPlcRequest{}
-}
+type SymbolicPlcQuery interface {
+	apiModel.PlcQuery
 
-func (d *DefaultPlcRequest) IsAPlcMessage() bool {
-	return true
+	GetSymbolicAddressPattern() string
 }
diff --git a/plc4go/internal/ads/Reader.go b/plc4go/internal/ads/Reader.go
index aef515c1fb..3d4bf7230d 100644
--- a/plc4go/internal/ads/Reader.go
+++ b/plc4go/internal/ads/Reader.go
@@ -41,7 +41,7 @@ type Reader struct {
 	sourceAmsNetId        readWriteModel.AmsNetId
 	sourceAmsPort         uint16
 	messageCodec          spi.MessageCodec
-	fieldMapping          map[SymbolicPlcField]DirectPlcField
+	fieldMapping          map[string]DirectPlcField
 	mappingLock           sync.Mutex
 }
 
@@ -53,7 +53,7 @@ func NewReader(messageCodec spi.MessageCodec, targetAmsNetId readWriteModel.AmsN
 		sourceAmsNetId:        sourceAmsNetId,
 		sourceAmsPort:         sourceAmsPort,
 		messageCodec:          messageCodec,
-		fieldMapping:          make(map[SymbolicPlcField]DirectPlcField),
+		fieldMapping:          make(map[string]DirectPlcField),
 	}
 }
 
diff --git a/plc4go/internal/bacnetip/Field.go b/plc4go/internal/bacnetip/Field.go
index 47c2163e34..805fb06805 100644
--- a/plc4go/internal/bacnetip/Field.go
+++ b/plc4go/internal/bacnetip/Field.go
@@ -22,12 +22,17 @@ package bacnetip
 import (
 	"encoding/binary"
 	"fmt"
+	"strings"
+
+	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"strings"
 )
 
 type BacNetPlcField interface {
+	model.PlcField
+
 	GetObjectId() objectId
 	GetProperties() []property
 }
@@ -105,12 +110,12 @@ func (m plcField) GetAddressString() string {
 	return fmt.Sprintf("%v/%s", m.ObjectId, propertiesString)
 }
 
-func (m plcField) GetTypeName() string {
-	return m.ObjectId.String()
+func (m plcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (m plcField) GetQuantity() uint16 {
-	return uint16(len(m.Properties))
+func (m plcField) GetArrayInfo() []model.ArrayInfo {
+	return []model.ArrayInfo{}
 }
 
 func (m plcField) GetObjectId() objectId {
diff --git a/plc4go/internal/bacnetip/FieldHandler.go b/plc4go/internal/bacnetip/FieldHandler.go
index 3eb9718572..d150116d3d 100644
--- a/plc4go/internal/bacnetip/FieldHandler.go
+++ b/plc4go/internal/bacnetip/FieldHandler.go
@@ -20,13 +20,15 @@
 package bacnetip
 
 import (
+	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
-	"strconv"
-	"strings"
 )
 
 type FieldHandler struct {
@@ -49,8 +51,8 @@ const (
 	ARRAY_INDEX          = "arrayIndex"
 )
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
-	if addressMatch := utils.GetSubgroupMatches(m.addressPattern, query); addressMatch != nil {
+func (m FieldHandler) ParseField(fieldString string) (model.PlcField, error) {
+	if addressMatch := utils.GetSubgroupMatches(m.addressPattern, fieldString); addressMatch != nil {
 		var result plcField
 		{
 			objectTypeMatch := addressMatch[OBJECT_TYPE]
@@ -102,5 +104,9 @@ func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
 		}
 		return result, nil
 	}
-	return nil, errors.Errorf("Unable to parse %s", query)
+	return nil, errors.Errorf("Unable to parse %s", fieldString)
+}
+
+func (m FieldHandler) ParseQuery(_ string) (model.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
 }
diff --git a/plc4go/internal/cbus/Browser.go b/plc4go/internal/cbus/Browser.go
index ea554108cb..c35a799715 100644
--- a/plc4go/internal/cbus/Browser.go
+++ b/plc4go/internal/cbus/Browser.go
@@ -22,6 +22,8 @@ package cbus
 import (
 	"context"
 	"fmt"
+	"time"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
@@ -30,7 +32,6 @@ import (
 	"github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
-	"time"
 )
 
 type Browser struct {
@@ -50,15 +51,15 @@ func NewBrowser(connection *Connection, messageCodec spi.MessageCodec) *Browser
 	return &browser
 }
 
-func (m Browser) BrowseField(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseEvent) bool, fieldName string, field apiModel.PlcField) (apiModel.PlcResponseCode, []apiModel.PlcBrowseFoundField) {
-	var queryResults []apiModel.PlcBrowseFoundField
-	switch field := field.(type) {
+func (m Browser) InternalBrowse(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool, queryName string, query apiModel.PlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem) {
+	var queryResults []apiModel.PlcBrowseItem
+	switch query := query.(type) {
 	case *unitInfoField:
 		allUnits := false
 		var units []readWriteModel.UnitAddress
 		allAttributes := false
 		var attributes []readWriteModel.Attribute
-		if unitAddress := field.unitAddress; unitAddress != nil {
+		if unitAddress := query.unitAddress; unitAddress != nil {
 			units = append(units, *unitAddress)
 		} else {
 			// TODO: check if we still want the option to brute force all addresses
@@ -76,7 +77,7 @@ func (m Browser) BrowseField(ctx context.Context, browseRequest apiModel.PlcBrow
 				}
 			}
 		}
-		if attribute := field.attribute; attribute != nil {
+		if attribute := query.attribute; attribute != nil {
 			attributes = append(attributes, *attribute)
 		} else {
 			allAttributes = true
@@ -113,7 +114,7 @@ func (m Browser) BrowseField(ctx context.Context, browseRequest apiModel.PlcBrow
 				} else {
 					event.Msgf("unit %d: Query %s", unitAddress, attribute)
 				}
-				readFieldName := fmt.Sprintf("%s/%d/%s", fieldName, unitAddress, attribute)
+				readFieldName := fmt.Sprintf("%s/%d/%s", queryName, unitAddress, attribute)
 				readRequest, _ := m.connection.ReadRequestBuilder().
 					AddField(readFieldName, NewCALIdentifyField(unit, attribute, 1)).
 					Build()
@@ -131,23 +132,18 @@ func (m Browser) BrowseField(ctx context.Context, browseRequest apiModel.PlcBrow
 					event.Msgf("unit %d: error reading field %s. Code %s", unitAddress, attribute, code)
 					continue unitLoop
 				}
-				queryResult := &model.DefaultPlcBrowseQueryResult{
+				queryResult := &model.DefaultPlcBrowseItem{
 					Field:        NewCALIdentifyField(unit, attribute, 1),
-					Name:         fieldName,
+					Name:         queryName,
 					Readable:     true,
 					Writable:     false,
 					Subscribable: false,
-					Attributes: map[string]values.PlcValue{
+					Options: map[string]values.PlcValue{
 						"CurrentValue": response.GetValue(readFieldName),
 					},
 				}
 				if interceptor != nil {
-					interceptor(&model.DefaultPlcBrowseEvent{
-						Request:   browseRequest,
-						FieldName: readFieldName,
-						Result:    queryResult,
-						Err:       nil,
-					})
+					interceptor(queryResult)
 				}
 				queryResults = append(queryResults, queryResult)
 			}
diff --git a/plc4go/internal/cbus/Field.go b/plc4go/internal/cbus/Field.go
index 911b7b9926..56d2f2b9fb 100644
--- a/plc4go/internal/cbus/Field.go
+++ b/plc4go/internal/cbus/Field.go
@@ -22,8 +22,11 @@ package cbus
 import (
 	"encoding/binary"
 	"fmt"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
+	model2 "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
@@ -44,9 +47,16 @@ func (s StatusRequestType) String() string {
 	return ""
 }
 
+type CbusField interface {
+	model.PlcField
+
+	GetFieldType() FieldType
+}
+
 // StatusField can be used to query status using a P-to-MP-StatusRequest command
 type StatusField interface {
-	model.PlcField
+	CbusField
+
 	GetStatusRequestType() StatusRequestType
 	GetStartingGroupAddressLabel() *byte
 	GetApplication() readWriteModel.ApplicationIdContainer
@@ -68,8 +78,9 @@ type CalField interface {
 
 // CALRecallField can be used to get device/network management fields
 type CALRecallField interface {
-	model.PlcField
+	CbusField
 	CalField
+
 	GetParameter() readWriteModel.Parameter
 	GetCount() uint8
 }
@@ -86,8 +97,9 @@ func NewCALRecallField(unitAddress readWriteModel.UnitAddress, parameter readWri
 
 // CALIdentifyField can be used to get device/network management fields
 type CALIdentifyField interface {
-	model.PlcField
+	CbusField
 	CalField
+
 	GetAttribute() readWriteModel.Attribute
 }
 
@@ -102,8 +114,9 @@ func NewCALIdentifyField(unitAddress readWriteModel.UnitAddress, attribute readW
 
 // CALGetstatusField can be used to get device/network management fields
 type CALGetstatusField interface {
-	model.PlcField
+	CbusField
 	CalField
+
 	GetParameter() readWriteModel.Parameter
 	GetCount() uint8
 }
@@ -120,7 +133,8 @@ func NewCALGetstatusField(unitAddress readWriteModel.UnitAddress, parameter read
 
 // SALField can be used to send SAL commands
 type SALField interface {
-	model.PlcField
+	CbusField
+
 	GetApplication() readWriteModel.ApplicationIdContainer
 	GetSALCommand() string
 }
@@ -136,7 +150,8 @@ func NewSALField(application readWriteModel.ApplicationIdContainer, salCommand s
 
 // SALMonitorField can be used to monitor sal fields
 type SALMonitorField interface {
-	model.PlcField
+	CbusField
+
 	GetUnitAddress() *readWriteModel.UnitAddress
 	GetApplication() *readWriteModel.ApplicationIdContainer
 }
@@ -152,7 +167,8 @@ func NewSALMonitorField(unitAddress *readWriteModel.UnitAddress, application *re
 
 // MMIMonitorField can be used to monitor mmi fields
 type MMIMonitorField interface {
-	model.PlcField
+	CbusField
+
 	GetUnitAddress() *readWriteModel.UnitAddress
 	GetApplication() *readWriteModel.ApplicationIdContainer
 }
@@ -168,7 +184,8 @@ func NewMMIMonitorField(unitAddress *readWriteModel.UnitAddress, application *re
 
 // UnitInfoField can be used to get information about unit(s)
 type UnitInfoField interface {
-	model.PlcField
+	CbusField
+
 	GetUnitAddress() *readWriteModel.UnitAddress
 	GetAttribute() *readWriteModel.Attribute
 }
@@ -268,6 +285,26 @@ func (s statusField) GetAddressString() string {
 	return fmt.Sprintf("status/%s/%s", statusRequestType, s.application)
 }
 
+func (s statusField) GetValueType() values.PlcValueType {
+	return values.NULL
+}
+
+func (s statusField) GetArrayInfo() []model.ArrayInfo {
+	if s.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(s.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s statusField) GetFieldType() FieldType {
+	return s.fieldType
+}
+
 func (s statusField) GetStatusRequestType() StatusRequestType {
 	return s.statusRequestType
 }
@@ -280,14 +317,6 @@ func (s statusField) GetApplication() readWriteModel.ApplicationIdContainer {
 	return s.application
 }
 
-func (s statusField) GetTypeName() string {
-	return STATUS.GetName()
-}
-
-func (s statusField) GetQuantity() uint16 {
-	return s.numElements
-}
-
 func (s statusField) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := s.SerializeWithWriteBuffer(wb); err != nil {
@@ -366,12 +395,24 @@ func (c calRecallField) GetAddressString() string {
 	return fmt.Sprintf("cal/%d/recall=%s", c.unitAddress.GetAddress(), c.parameter)
 }
 
-func (c calRecallField) GetTypeName() string {
-	return c.fieldType.GetName()
+func (c calRecallField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (c calRecallField) GetQuantity() uint16 {
-	return c.numElements
+func (c calRecallField) GetArrayInfo() []model.ArrayInfo {
+	if c.count != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(c.count),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s calRecallField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (c calRecallField) Serialize() ([]byte, error) {
@@ -421,12 +462,24 @@ func (c calIdentifyField) GetAddressString() string {
 	return fmt.Sprintf("cal/%d/identify=%s", c.unitAddress.GetAddress(), c.GetAttribute())
 }
 
-func (c calIdentifyField) GetTypeName() string {
-	return c.fieldType.GetName()
+func (c calIdentifyField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (c calIdentifyField) GetQuantity() uint16 {
-	return c.numElements
+func (c calIdentifyField) GetArrayInfo() []model.ArrayInfo {
+	if c.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(c.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s calIdentifyField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (c calIdentifyField) Serialize() ([]byte, error) {
@@ -476,12 +529,24 @@ func (c calGetstatusField) GetAddressString() string {
 	return fmt.Sprintf("cal/getstatus=%s, %d", c.parameter, c.GetCount())
 }
 
-func (c calGetstatusField) GetTypeName() string {
-	return c.fieldType.GetName()
+func (c calGetstatusField) GetValueType() values.PlcValueType {
+	return values.Struct
+}
+
+func (c calGetstatusField) GetArrayInfo() []model.ArrayInfo {
+	if c.count != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(c.count),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
 }
 
-func (c calGetstatusField) GetQuantity() uint16 {
-	return c.numElements
+func (s calGetstatusField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (c calGetstatusField) Serialize() ([]byte, error) {
@@ -535,12 +600,24 @@ func (s salField) GetAddressString() string {
 	return fmt.Sprintf("sal/%s/%s", s.application, s.salCommand)
 }
 
-func (s salField) GetTypeName() string {
-	return s.fieldType.GetName()
+func (s salField) GetValueType() values.PlcValueType {
+	return values.Struct
+}
+
+func (s salField) GetArrayInfo() []model.ArrayInfo {
+	if s.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(s.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
 }
 
-func (s salField) GetQuantity() uint16 {
-	return s.numElements
+func (s salField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (s salField) Serialize() ([]byte, error) {
@@ -590,12 +667,24 @@ func (s salMonitorField) GetAddressString() string {
 	return fmt.Sprintf("salmonitor/%s/%s", unitAddress, application)
 }
 
-func (s salMonitorField) GetTypeName() string {
-	return s.fieldType.GetName()
+func (s salMonitorField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (s salMonitorField) GetQuantity() uint16 {
-	return s.numElements
+func (s salMonitorField) GetArrayInfo() []model.ArrayInfo {
+	if s.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(s.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s salMonitorField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (s salMonitorField) GetUnitAddress() *readWriteModel.UnitAddress {
@@ -656,12 +745,24 @@ func (m mmiMonitorField) GetAddressString() string {
 	return fmt.Sprintf("mmimonitor/%s/%s", unitAddress, application)
 }
 
-func (m mmiMonitorField) GetTypeName() string {
-	return m.fieldType.GetName()
+func (m mmiMonitorField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (m mmiMonitorField) GetQuantity() uint16 {
-	return m.numElements
+func (m mmiMonitorField) GetArrayInfo() []model.ArrayInfo {
+	if m.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(m.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s mmiMonitorField) GetFieldType() FieldType {
+	return s.fieldType
 }
 
 func (m mmiMonitorField) GetUnitAddress() *readWriteModel.UnitAddress {
@@ -710,14 +811,6 @@ func (m mmiMonitorField) String() string {
 	return writeBuffer.GetBox().String()
 }
 
-func (u unitInfoField) GetUnitAddress() *readWriteModel.UnitAddress {
-	return u.unitAddress
-}
-
-func (u unitInfoField) GetAttribute() *readWriteModel.Attribute {
-	return u.attribute
-}
-
 func (u unitInfoField) GetAddressString() string {
 	unitAddressString := "*"
 	if u.unitAddress != nil {
@@ -730,12 +823,32 @@ func (u unitInfoField) GetAddressString() string {
 	return fmt.Sprintf("cal/%s/identify=%s", unitAddressString, attributeString)
 }
 
-func (u unitInfoField) GetTypeName() string {
-	return u.fieldType.GetName()
+func (u unitInfoField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (u unitInfoField) GetQuantity() uint16 {
-	return u.numElements
+func (u unitInfoField) GetArrayInfo() []model.ArrayInfo {
+	if u.numElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(u.numElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
+}
+
+func (s unitInfoField) GetFieldType() FieldType {
+	return s.fieldType
+}
+
+func (u unitInfoField) GetUnitAddress() *readWriteModel.UnitAddress {
+	return u.unitAddress
+}
+
+func (u unitInfoField) GetAttribute() *readWriteModel.Attribute {
+	return u.attribute
 }
 
 func (u unitInfoField) Serialize() ([]byte, error) {
diff --git a/plc4go/internal/cbus/FieldHandler.go b/plc4go/internal/cbus/FieldHandler.go
index 7480d3cfe0..aacfbfca5e 100644
--- a/plc4go/internal/cbus/FieldHandler.go
+++ b/plc4go/internal/cbus/FieldHandler.go
@@ -22,13 +22,14 @@ package cbus
 import (
 	"encoding/hex"
 	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
-	"strconv"
-	"strings"
 )
 
 type FieldType uint8
@@ -111,24 +112,28 @@ var PossibleSalCommands = map[readWriteModel.ApplicationId][]CommandAndArguments
 	readWriteModel.ApplicationId_HVAC_ACTUATOR:                      c2nl(readWriteModel.LightingCommandTypeValues),
 }
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
-	if match := utils.GetSubgroupMatches(m.statusRequestPattern, query); match != nil {
+func (m FieldHandler) ParseField(fieldQuery string) (model.PlcField, error) {
+	if match := utils.GetSubgroupMatches(m.statusRequestPattern, fieldQuery); match != nil {
 		return m.handleStatusRequestPattern(match)
-	} else if match := utils.GetSubgroupMatches(m.calPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.calPattern, fieldQuery); match != nil {
 		return m.handleCalPattern(match)
-	} else if match := utils.GetSubgroupMatches(m.salPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.salPattern, fieldQuery); match != nil {
 		return m.handleSALPattern(match)
-	} else if match := utils.GetSubgroupMatches(m.salMonitorPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.salMonitorPattern, fieldQuery); match != nil {
 		return m.handleSALMonitorPattern(match)
-	} else if match := utils.GetSubgroupMatches(m.mmiMonitorPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.mmiMonitorPattern, fieldQuery); match != nil {
 		return m.handleMMIMonitorPattern(match)
-	} else if match := utils.GetSubgroupMatches(m.unityQuery, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.unityQuery, fieldQuery); match != nil {
 		return m.handleUnitQuery(match)
 	} else {
-		return nil, errors.Errorf("Unable to parse %s", query)
+		return nil, errors.Errorf("Unable to parse %s", fieldQuery)
 	}
 }
 
+func (m FieldHandler) ParseQuery(_ string) (model.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
+}
+
 func (m FieldHandler) handleStatusRequestPattern(match map[string]string) (model.PlcField, error) {
 	var startingGroupAddressLabel *byte
 	var statusRequestType StatusRequestType
diff --git a/plc4go/internal/cbus/ValueHandler.go b/plc4go/internal/cbus/ValueHandler.go
index ba999cc88b..1b6b612d6c 100644
--- a/plc4go/internal/cbus/ValueHandler.go
+++ b/plc4go/internal/cbus/ValueHandler.go
@@ -20,12 +20,13 @@
 package cbus
 
 import (
+	"reflect"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
 	spiValues "github.com/apache/plc4x/plc4go/spi/values"
 	"github.com/pkg/errors"
-	"reflect"
 )
 
 type ValueHandler struct {
@@ -37,323 +38,325 @@ func NewValueHandler() ValueHandler {
 }
 
 func (m ValueHandler) NewPlcValue(field apiModel.PlcField, value interface{}) (apiValues.PlcValue, error) {
-	switch field.GetTypeName() {
-	case
-		CAL_WRITE.GetName(),
-		CAL_IDENTIFY_REPLY.GetName(),
-		CAL_STATUS.GetName(),
-		CAL_STATUS_EXTENDED.GetName():
-		panic("Implement me") //TODO: implement me
-	case SAL.GetName():
-		var curValues []any
-		if field.GetQuantity() > 1 {
-			s := reflect.ValueOf(value)
-			if s.Kind() != reflect.Slice {
-				return nil, errors.New("couldn't cast value to []interface{}")
-			}
-			curValues = make([]interface{}, s.Len())
-			for i := 0; i < s.Len(); i++ {
-				curValues[i] = s.Index(i).Interface()
+	if cbusField, ok := field.(CbusField); ok {
+		switch cbusField.GetFieldType() {
+		case
+			CAL_WRITE,
+			CAL_IDENTIFY_REPLY,
+			CAL_STATUS,
+			CAL_STATUS_EXTENDED:
+			panic("Implement me") //TODO: implement me
+		case SAL:
+			var curValues []any
+			if len(field.GetArrayInfo()) > 0 && field.GetArrayInfo()[0].GetSize() > 1 {
+				s := reflect.ValueOf(value)
+				if s.Kind() != reflect.Slice {
+					return nil, errors.New("couldn't cast value to []interface{}")
+				}
+				curValues = make([]interface{}, s.Len())
+				for i := 0; i < s.Len(); i++ {
+					curValues[i] = s.Index(i).Interface()
+				}
+			} else {
+				curValues = append(curValues, value)
 			}
-		} else {
-			curValues = append(curValues, value)
-		}
 
-		field := field.(*salField)
-		salCommand := field.salCommand
-		switch field.application.ApplicationId() {
-		case readWriteModel.ApplicationId_FREE_USAGE:
-			switch salCommand {
-			// TODO:implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_TEMPERATURE_BROADCAST:
-			switch salCommand {
-			case readWriteModel.TemperatureBroadcastCommandType_BROADCAST_EVENT.PLC4XEnumName():
-				if len(curValues) != 2 {
-					return nil, errors.Errorf("%s requires exactly 2 arguments [temperatureGroup,temperatureByte]", salCommand)
+			field := field.(*salField)
+			salCommand := field.salCommand
+			switch field.application.ApplicationId() {
+			case readWriteModel.ApplicationId_FREE_USAGE:
+				switch salCommand {
+				// TODO:implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				temperatureGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for temperatureGroup")
+			case readWriteModel.ApplicationId_TEMPERATURE_BROADCAST:
+				switch salCommand {
+				case readWriteModel.TemperatureBroadcastCommandType_BROADCAST_EVENT.PLC4XEnumName():
+					if len(curValues) != 2 {
+						return nil, errors.Errorf("%s requires exactly 2 arguments [temperatureGroup,temperatureByte]", salCommand)
+					}
+					temperatureGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for temperatureGroup")
+					}
+					temperatureByte, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[1])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for temperatureByte")
+					}
+					return spiValues.NewPlcList([]apiValues.PlcValue{temperatureGroup, temperatureByte}), nil
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				temperatureByte, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[1])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for temperatureByte")
+			case readWriteModel.ApplicationId_ROOM_CONTROL_SYSTEM:
+				switch salCommand {
+				// TODO:implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return spiValues.NewPlcList([]apiValues.PlcValue{temperatureGroup, temperatureByte}), nil
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_ROOM_CONTROL_SYSTEM:
-			switch salCommand {
-			// TODO:implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_LIGHTING,
-			readWriteModel.ApplicationId_VENTILATION,
-			readWriteModel.ApplicationId_IRRIGATION_CONTROL,
-			readWriteModel.ApplicationId_POOLS_SPAS_PONDS_FOUNTAINS_CONTROL,
-			readWriteModel.ApplicationId_HEATING,
-			readWriteModel.ApplicationId_AUDIO_AND_VIDEO,
-			readWriteModel.ApplicationId_HVAC_ACTUATOR:
-			switch salCommand {
-			case readWriteModel.LightingCommandType_OFF.PLC4XEnumName():
-				if len(curValues) != 1 {
-					return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+			case readWriteModel.ApplicationId_LIGHTING,
+				readWriteModel.ApplicationId_VENTILATION,
+				readWriteModel.ApplicationId_IRRIGATION_CONTROL,
+				readWriteModel.ApplicationId_POOLS_SPAS_PONDS_FOUNTAINS_CONTROL,
+				readWriteModel.ApplicationId_HEATING,
+				readWriteModel.ApplicationId_AUDIO_AND_VIDEO,
+				readWriteModel.ApplicationId_HVAC_ACTUATOR:
+				switch salCommand {
+				case readWriteModel.LightingCommandType_OFF.PLC4XEnumName():
+					if len(curValues) != 1 {
+						return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+					}
+					group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for group")
+					}
+					return group, nil
+				case readWriteModel.LightingCommandType_ON.PLC4XEnumName():
+					if len(curValues) != 1 {
+						return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+					}
+					group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for group")
+					}
+					return group, nil
+				case readWriteModel.LightingCommandType_RAMP_TO_LEVEL.PLC4XEnumName():
+					if len(curValues) != 2 {
+						return nil, errors.Errorf("%s requires exactly 2 arguments [group,level]", salCommand)
+					}
+					group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for group")
+					}
+					level, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for level")
+					}
+					return spiValues.NewPlcList([]apiValues.PlcValue{group, level}), nil
+				case readWriteModel.LightingCommandType_TERMINATE_RAMP.PLC4XEnumName():
+					if len(curValues) != 1 {
+						return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+					}
+					group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for group")
+					}
+					return group, nil
+				case readWriteModel.LightingCommandType_LABEL.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for group")
+			case readWriteModel.ApplicationId_AIR_CONDITIONING:
+				switch salCommand {
+				case readWriteModel.AirConditioningCommandType_SET_ZONE_GROUP_OFF.PLC4XEnumName():
+					zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for zoneGroup")
+					}
+					return zoneGroup, nil
+				case readWriteModel.AirConditioningCommandType_ZONE_HVAC_PLANT_STATUS.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_ZONE_HUMIDITY_PLANT_STATUS.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_ZONE_TEMPERATURE.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_ZONE_HUMIDITY.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_REFRESH.PLC4XEnumName():
+					zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for zoneGroup")
+					}
+					return zoneGroup, nil
+				case readWriteModel.AirConditioningCommandType_SET_ZONE_HVAC_MODE.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_PLANT_HVAC_LEVEL.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_ZONE_HUMIDITY_MODE.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_PLANT_HUMIDITY_LEVEL.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_HVAC_UPPER_GUARD_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_HVAC_LOWER_GUARD_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_HVAC_SETBACK_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_UPPER_GUARD_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_LOWER_GUARD_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_SET_ZONE_GROUP_ON.PLC4XEnumName():
+					zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
+					if err != nil {
+						return nil, errors.Wrap(err, "error creating value for zoneGroup")
+					}
+					return zoneGroup, nil
+				case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_SETBACK_LIMIT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_HVAC_SCHEDULE_ENTRY.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.AirConditioningCommandType_HUMIDITY_SCHEDULE_ENTRY.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return group, nil
-			case readWriteModel.LightingCommandType_ON.PLC4XEnumName():
-				if len(curValues) != 1 {
-					return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+			case readWriteModel.ApplicationId_TRIGGER_CONTROL:
+				switch salCommand {
+				case readWriteModel.TriggerControlCommandType_TRIGGER_EVENT.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.TriggerControlCommandType_TRIGGER_MIN.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.TriggerControlCommandType_TRIGGER_MAX.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.TriggerControlCommandType_INDICATOR_KILL.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				case readWriteModel.TriggerControlCommandType_LABEL.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for group")
+			case readWriteModel.ApplicationId_ENABLE_CONTROL:
+				switch salCommand {
+				case readWriteModel.EnableControlCommandType_SET_NETWORK_VARIABLE.PLC4XEnumName():
+					panic("Implement me") //TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return group, nil
-			case readWriteModel.LightingCommandType_RAMP_TO_LEVEL.PLC4XEnumName():
-				if len(curValues) != 2 {
-					return nil, errors.Errorf("%s requires exactly 2 arguments [group,level]", salCommand)
+			case readWriteModel.ApplicationId_SECURITY:
+				switch salCommand {
+				case readWriteModel.SecurityCommandType_OFF.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.SecurityCommandType_ON.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.SecurityCommandType_EVENT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for group")
+			case readWriteModel.ApplicationId_METERING:
+				switch salCommand {
+				case readWriteModel.MeteringCommandType_EVENT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				level, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for level")
+			case readWriteModel.ApplicationId_ACCESS_CONTROL:
+				switch salCommand {
+				case readWriteModel.AccessControlCommandType_CLOSE_ACCESS_POINT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_LOCK_ACCESS_POINT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_ACCESS_POINT_LEFT_OPEN.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_ACCESS_POINT_FORCED_OPEN.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_ACCESS_POINT_CLOSED.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_REQUEST_TO_EXIT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_VALID_ACCESS.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.AccessControlCommandType_INVALID_ACCESS.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return spiValues.NewPlcList([]apiValues.PlcValue{group, level}), nil
-			case readWriteModel.LightingCommandType_TERMINATE_RAMP.PLC4XEnumName():
-				if len(curValues) != 1 {
-					return nil, errors.Errorf("%s requires exactly 1 arguments [groupe]", salCommand)
+			case readWriteModel.ApplicationId_CLOCK_AND_TIMEKEEPING:
+				switch salCommand {
+				case readWriteModel.ClockAndTimekeepingCommandType_UPDATE_NETWORK_VARIABLE.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				case readWriteModel.ClockAndTimekeepingCommandType_REQUEST_REFRESH.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				group, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for group")
+			case readWriteModel.ApplicationId_TELEPHONY_STATUS_AND_CONTROL:
+				switch salCommand {
+				case readWriteModel.TelephonyCommandType_EVENT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return group, nil
-			case readWriteModel.LightingCommandType_LABEL.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_AIR_CONDITIONING:
-			switch salCommand {
-			case readWriteModel.AirConditioningCommandType_SET_ZONE_GROUP_OFF.PLC4XEnumName():
-				zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for zoneGroup")
+			case readWriteModel.ApplicationId_MEASUREMENT:
+				switch salCommand {
+				case readWriteModel.MeasurementCommandType_MEASUREMENT_EVENT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return zoneGroup, nil
-			case readWriteModel.AirConditioningCommandType_ZONE_HVAC_PLANT_STATUS.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_ZONE_HUMIDITY_PLANT_STATUS.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_ZONE_TEMPERATURE.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_ZONE_HUMIDITY.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_REFRESH.PLC4XEnumName():
-				zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for zoneGroup")
+			case readWriteModel.ApplicationId_TESTING:
+				switch salCommand {
+				// TODO:implement
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return zoneGroup, nil
-			case readWriteModel.AirConditioningCommandType_SET_ZONE_HVAC_MODE.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_PLANT_HVAC_LEVEL.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_ZONE_HUMIDITY_MODE.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_PLANT_HUMIDITY_LEVEL.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_HVAC_UPPER_GUARD_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_HVAC_LOWER_GUARD_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_HVAC_SETBACK_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_UPPER_GUARD_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_LOWER_GUARD_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_SET_ZONE_GROUP_ON.PLC4XEnumName():
-				zoneGroup, err := m.IEC61131ValueHandler.NewPlcValueFromType(spiValues.IEC61131_BYTE, curValues[0])
-				if err != nil {
-					return nil, errors.Wrap(err, "error creating value for zoneGroup")
+			case readWriteModel.ApplicationId_MEDIA_TRANSPORT_CONTROL:
+				switch salCommand {
+				case readWriteModel.MediaTransportControlCommandType_STOP.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_PLAY.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_PAUSE_RESUME.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SELECT_CATEGORY.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SELECT_SELECTION.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SELECT_TRACK.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SHUFFLE_ON_OFF.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_REPEAT_ON_OFF.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_CATEGORY.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_SELECTION.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_TRACK.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_FAST_FORWARD.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_REWIND.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SOURCE_POWER_CONTROL.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_TOTAL_TRACKS.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_STATUS_REQUEST.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_ENUMERATE_CATEGORIES_SELECTIONS_TRACKS.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_ENUMERATION_SIZE.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_TRACK_NAME.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_SELECTION_NAME.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_CATEGORY_NAME.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.MediaTransportControlCommandType_FAST_FORWARD.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
+				}
+			case readWriteModel.ApplicationId_ERROR_REPORTING:
+				switch salCommand {
+				case readWriteModel.ErrorReportingCommandType_DEPRECATED.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.ErrorReportingCommandType_ERROR_REPORT.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.ErrorReportingCommandType_ACKNOWLEDGE.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				case readWriteModel.ErrorReportingCommandType_CLEAR_MOST_SEVERE.PLC4XEnumName():
+					panic("Implement me") // TODO: implement me
+				default:
+					return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 				}
-				return zoneGroup, nil
-			case readWriteModel.AirConditioningCommandType_SET_HUMIDITY_SETBACK_LIMIT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_HVAC_SCHEDULE_ENTRY.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.AirConditioningCommandType_HUMIDITY_SCHEDULE_ENTRY.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_TRIGGER_CONTROL:
-			switch salCommand {
-			case readWriteModel.TriggerControlCommandType_TRIGGER_EVENT.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.TriggerControlCommandType_TRIGGER_MIN.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.TriggerControlCommandType_TRIGGER_MAX.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.TriggerControlCommandType_INDICATOR_KILL.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			case readWriteModel.TriggerControlCommandType_LABEL.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_ENABLE_CONTROL:
-			switch salCommand {
-			case readWriteModel.EnableControlCommandType_SET_NETWORK_VARIABLE.PLC4XEnumName():
-				panic("Implement me") //TODO: implement me
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_SECURITY:
-			switch salCommand {
-			case readWriteModel.SecurityCommandType_OFF.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.SecurityCommandType_ON.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.SecurityCommandType_EVENT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_METERING:
-			switch salCommand {
-			case readWriteModel.MeteringCommandType_EVENT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_ACCESS_CONTROL:
-			switch salCommand {
-			case readWriteModel.AccessControlCommandType_CLOSE_ACCESS_POINT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_LOCK_ACCESS_POINT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_ACCESS_POINT_LEFT_OPEN.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_ACCESS_POINT_FORCED_OPEN.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_ACCESS_POINT_CLOSED.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_REQUEST_TO_EXIT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_VALID_ACCESS.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.AccessControlCommandType_INVALID_ACCESS.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_CLOCK_AND_TIMEKEEPING:
-			switch salCommand {
-			case readWriteModel.ClockAndTimekeepingCommandType_UPDATE_NETWORK_VARIABLE.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			case readWriteModel.ClockAndTimekeepingCommandType_REQUEST_REFRESH.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_TELEPHONY_STATUS_AND_CONTROL:
-			switch salCommand {
-			case readWriteModel.TelephonyCommandType_EVENT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_MEASUREMENT:
-			switch salCommand {
-			case readWriteModel.MeasurementCommandType_MEASUREMENT_EVENT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_TESTING:
-			switch salCommand {
-			// TODO:implement
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_MEDIA_TRANSPORT_CONTROL:
-			switch salCommand {
-			case readWriteModel.MediaTransportControlCommandType_STOP.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_PLAY.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_PAUSE_RESUME.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SELECT_CATEGORY.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SELECT_SELECTION.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SELECT_TRACK.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SHUFFLE_ON_OFF.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_REPEAT_ON_OFF.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_CATEGORY.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_SELECTION.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_NEXT_PREVIOUS_TRACK.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_FAST_FORWARD.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_REWIND.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SOURCE_POWER_CONTROL.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_TOTAL_TRACKS.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_STATUS_REQUEST.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_ENUMERATE_CATEGORIES_SELECTIONS_TRACKS.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_ENUMERATION_SIZE.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_TRACK_NAME.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_SELECTION_NAME.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_CATEGORY_NAME.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.MediaTransportControlCommandType_FAST_FORWARD.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
-			}
-		case readWriteModel.ApplicationId_ERROR_REPORTING:
-			switch salCommand {
-			case readWriteModel.ErrorReportingCommandType_DEPRECATED.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.ErrorReportingCommandType_ERROR_REPORT.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.ErrorReportingCommandType_ACKNOWLEDGE.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
-			case readWriteModel.ErrorReportingCommandType_CLEAR_MOST_SEVERE.PLC4XEnumName():
-				panic("Implement me") // TODO: implement me
 			default:
-				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
+				return nil, errors.Errorf("No support for %s", field.application)
 			}
-		default:
-			return nil, errors.Errorf("No support for %s", field.application)
 		}
 	}
 	return m.IEC61131ValueHandler.NewPlcValue(field, value)
diff --git a/plc4go/internal/eip/Field.go b/plc4go/internal/eip/Field.go
index fab04f815a..6ae26631ad 100644
--- a/plc4go/internal/eip/Field.go
+++ b/plc4go/internal/eip/Field.go
@@ -22,55 +22,63 @@ package eip
 import (
 	"encoding/binary"
 
+	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWrite "github.com/apache/plc4x/plc4go/protocols/eip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type EIPPlcField interface {
+	model.PlcField
+
 	GetTag() string
 	GetType() readWrite.CIPDataTypeCode
 	GetElementNb() uint16
 }
 
-type PlcField struct {
+type plcField struct {
 	Tag       string
 	Type      readWrite.CIPDataTypeCode
 	ElementNb uint16
 }
 
-func (m PlcField) GetAddressString() string {
+func (m plcField) GetAddressString() string {
 	return m.GetTag()
 }
 
-func (m PlcField) GetTypeName() string {
-	return m.GetType().String()
+func (m plcField) GetValueType() values.PlcValueType {
+	if plcValueType, ok := values.PlcValueByName(m.GetType().String()); !ok {
+		return values.NULL
+	} else {
+		return plcValueType
+	}
 }
 
-func (m PlcField) GetQuantity() uint16 {
-	return 1
+func (m plcField) GetArrayInfo() []model.ArrayInfo {
+	return []model.ArrayInfo{}
 }
 
-func NewField(tag string, _type readWrite.CIPDataTypeCode, elementNb uint16) PlcField {
-	return PlcField{
+func NewField(tag string, _type readWrite.CIPDataTypeCode, elementNb uint16) plcField {
+	return plcField{
 		Tag:       tag,
 		Type:      _type,
 		ElementNb: elementNb,
 	}
 }
 
-func (m PlcField) GetTag() string {
+func (m plcField) GetTag() string {
 	return m.Tag
 }
 
-func (m PlcField) GetType() readWrite.CIPDataTypeCode {
+func (m plcField) GetType() readWrite.CIPDataTypeCode {
 	return m.Type
 }
 
-func (m PlcField) GetElementNb() uint16 {
+func (m plcField) GetElementNb() uint16 {
 	return m.ElementNb
 }
 
-func (m PlcField) Serialize() ([]byte, error) {
+func (m plcField) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := m.SerializeWithWriteBuffer(wb); err != nil {
 		return nil, err
@@ -78,7 +86,7 @@ func (m PlcField) Serialize() ([]byte, error) {
 	return wb.GetBytes(), nil
 }
 
-func (m PlcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+func (m plcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
 	if err := writeBuffer.PushContext("EipField"); err != nil {
 		return err
 	}
diff --git a/plc4go/internal/eip/FieldHandler.go b/plc4go/internal/eip/FieldHandler.go
index 5ead14d815..563c8f76db 100644
--- a/plc4go/internal/eip/FieldHandler.go
+++ b/plc4go/internal/eip/FieldHandler.go
@@ -20,12 +20,14 @@
 package eip
 
 import (
+	"fmt"
+	"regexp"
+	"strconv"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/eip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
-	"strconv"
 )
 
 type FieldHandler struct {
@@ -44,7 +46,7 @@ const (
 	ELEMENT_NB = "elementNb"
 )
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
+func (m FieldHandler) ParseField(query string) (model.PlcField, error) {
 	if match := utils.GetSubgroupMatches(m.addressPattern, query); match != nil {
 		tag := match[TAG]
 		_type, ok := readWriteModel.CIPDataTypeCodeByName(match[DATA_TYPE])
@@ -57,3 +59,7 @@ func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
 	}
 	return nil, errors.Errorf("Unable to parse %s", query)
 }
+
+func (m FieldHandler) ParseQuery(query string) (model.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
+}
diff --git a/plc4go/internal/knxnetip/Browser.go b/plc4go/internal/knxnetip/Browser.go
index d7d967a4ab..8caa1b0d0e 100644
--- a/plc4go/internal/knxnetip/Browser.go
+++ b/plc4go/internal/knxnetip/Browser.go
@@ -23,11 +23,12 @@ import (
 	"context"
 	"encoding/hex"
 	"fmt"
-	_default "github.com/apache/plc4x/plc4go/spi/default"
 	"strconv"
 	"strings"
 	"time"
 
+	_default "github.com/apache/plc4x/plc4go/spi/default"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
diff --git a/plc4go/internal/knxnetip/Field.go b/plc4go/internal/knxnetip/Field.go
index 02db0567b9..960ac677de 100644
--- a/plc4go/internal/knxnetip/Field.go
+++ b/plc4go/internal/knxnetip/Field.go
@@ -22,10 +22,12 @@ package knxnetip
 import (
 	"errors"
 	"fmt"
-	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
-	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 	"strconv"
 	"strings"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
+	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 )
 
 type Field interface {
@@ -33,16 +35,18 @@ type Field interface {
 }
 
 type GroupAddressField interface {
+	Field
+
 	GetFieldType() *driverModel.KnxDatapointType
 	IsPatternField() bool
 	matches(knxGroupAddress driverModel.KnxGroupAddress) bool
 	toGroupAddress() driverModel.KnxGroupAddress
-	Field
 }
 
 type DeviceField interface {
-	toKnxAddress() driverModel.KnxAddress
 	Field
+
+	toKnxAddress() driverModel.KnxAddress
 }
 
 type GroupAddress3LevelPlcField struct {
@@ -65,16 +69,16 @@ func (k GroupAddress3LevelPlcField) GetAddressString() string {
 	return fmt.Sprintf("%s/%s/%s:%s", k.MainGroup, k.MiddleGroup, k.SubGroup, k.FieldType.String())
 }
 
-func (k GroupAddress3LevelPlcField) GetTypeName() string {
-	return k.FieldType.Name()
+func (k GroupAddress3LevelPlcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k GroupAddress3LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
-	return k.FieldType
+func (k GroupAddress3LevelPlcField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
-func (k GroupAddress3LevelPlcField) GetQuantity() uint16 {
-	return 1
+func (k GroupAddress3LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
+	return k.FieldType
 }
 
 func (k GroupAddress3LevelPlcField) IsPatternField() bool {
@@ -136,16 +140,16 @@ func (k GroupAddress2LevelPlcField) GetAddressString() string {
 	return fmt.Sprintf("%s/%s:%s", k.MainGroup, k.SubGroup, k.FieldType.String())
 }
 
-func (k GroupAddress2LevelPlcField) GetTypeName() string {
-	return k.FieldType.Name()
+func (k GroupAddress2LevelPlcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k GroupAddress2LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
-	return k.FieldType
+func (k GroupAddress2LevelPlcField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
-func (k GroupAddress2LevelPlcField) GetQuantity() uint16 {
-	return 1
+func (k GroupAddress2LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
+	return k.FieldType
 }
 
 func (k GroupAddress2LevelPlcField) IsPatternField() bool {
@@ -197,16 +201,16 @@ func (k GroupAddress1LevelPlcField) GetAddressString() string {
 	return fmt.Sprintf("%s:%s", k.MainGroup, k.FieldType.String())
 }
 
-func (k GroupAddress1LevelPlcField) GetTypeName() string {
-	return k.FieldType.Name()
+func (k GroupAddress1LevelPlcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k GroupAddress1LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
-	return k.FieldType
+func (k GroupAddress1LevelPlcField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
-func (k GroupAddress1LevelPlcField) GetQuantity() uint16 {
-	return 1
+func (k GroupAddress1LevelPlcField) GetFieldType() *driverModel.KnxDatapointType {
+	return k.FieldType
 }
 
 func (k GroupAddress1LevelPlcField) IsPatternField() bool {
@@ -252,12 +256,12 @@ func (k DeviceQueryField) GetAddressString() string {
 	return fmt.Sprintf("%s.%s.%s", k.MainGroup, k.MiddleGroup, k.SubGroup)
 }
 
-func (k DeviceQueryField) GetTypeName() string {
-	return ""
+func (k DeviceQueryField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k DeviceQueryField) GetQuantity() uint16 {
-	return 1
+func (k DeviceQueryField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
 func (k DeviceQueryField) toKnxAddress() driverModel.KnxAddress {
@@ -292,12 +296,12 @@ func (k DevicePropertyAddressPlcField) GetAddressString() string {
 		k.MainGroup, k.MiddleGroup, k.SubGroup, k.ObjectId, k.PropertyId, k.PropertyIndex, k.NumElements)
 }
 
-func (k DevicePropertyAddressPlcField) GetTypeName() string {
-	return ""
+func (k DevicePropertyAddressPlcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k DevicePropertyAddressPlcField) GetQuantity() uint16 {
-	return 1
+func (k DevicePropertyAddressPlcField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
 func (k DevicePropertyAddressPlcField) toKnxAddress() driverModel.KnxAddress {
@@ -334,19 +338,12 @@ func (k DeviceMemoryAddressPlcField) GetAddressString() string {
 		k.MainGroup, k.MiddleGroup, k.SubGroup, k.Address, k.FieldType.String(), k.NumElements)
 }
 
-func (k DeviceMemoryAddressPlcField) GetTypeName() string {
-	if k.FieldType != nil {
-		return k.FieldType.Name()
-	}
-	return ""
-}
-
-func (k DeviceMemoryAddressPlcField) GetFieldType() *driverModel.KnxDatapointType {
-	return k.FieldType
+func (k DeviceMemoryAddressPlcField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k DeviceMemoryAddressPlcField) GetQuantity() uint16 {
-	return uint16(k.NumElements)
+func (k DeviceMemoryAddressPlcField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
 func (k DeviceMemoryAddressPlcField) toKnxAddress() driverModel.KnxAddress {
@@ -378,12 +375,12 @@ func (k CommunicationObjectQueryField) GetAddressString() string {
 		k.MainGroup, k.MiddleGroup, k.SubGroup)
 }
 
-func (k CommunicationObjectQueryField) GetTypeName() string {
-	return ""
+func (k CommunicationObjectQueryField) GetValueType() values.PlcValueType {
+	return values.Struct
 }
 
-func (k CommunicationObjectQueryField) GetQuantity() uint16 {
-	return 1
+func (k CommunicationObjectQueryField) GetArrayInfo() []apiModel.ArrayInfo {
+	return []apiModel.ArrayInfo{}
 }
 
 func (k CommunicationObjectQueryField) toKnxAddress() driverModel.KnxAddress {
diff --git a/plc4go/internal/knxnetip/FieldHandler.go b/plc4go/internal/knxnetip/FieldHandler.go
index da7a7ba4c6..e39d0cc639 100644
--- a/plc4go/internal/knxnetip/FieldHandler.go
+++ b/plc4go/internal/knxnetip/FieldHandler.go
@@ -21,12 +21,14 @@ package knxnetip
 
 import (
 	"encoding/hex"
+	"fmt"
+	"regexp"
+	"strconv"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
-	"strconv"
 )
 
 type FieldHandler struct {
@@ -52,8 +54,8 @@ func NewFieldHandler() FieldHandler {
 	}
 }
 
-func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
-	if match := utils.GetSubgroupMatches(m.groupAddress1Level, query); match != nil {
+func (m FieldHandler) ParseField(fieldQuery string) (apiModel.PlcField, error) {
+	if match := utils.GetSubgroupMatches(m.groupAddress1Level, fieldQuery); match != nil {
 		fieldTypeName, ok := match["datatype"]
 		var fieldType driverModel.KnxDatapointType
 		if ok {
@@ -63,7 +65,7 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 			}
 		}
 		return NewGroupAddress1LevelPlcField(match["mainGroup"], &fieldType), nil
-	} else if match := utils.GetSubgroupMatches(m.groupAddress2Level, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.groupAddress2Level, fieldQuery); match != nil {
 		fieldTypeName, ok := match["datatype"]
 		var fieldType driverModel.KnxDatapointType
 		if ok {
@@ -73,7 +75,7 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 			}
 		}
 		return NewGroupAddress2LevelPlcField(match["mainGroup"], match["subGroup"], &fieldType), nil
-	} else if match := utils.GetSubgroupMatches(m.groupAddress3Level, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.groupAddress3Level, fieldQuery); match != nil {
 		fieldTypeName, ok := match["datatype"]
 		var fieldType driverModel.KnxDatapointType
 		if ok {
@@ -83,10 +85,10 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 			}
 		}
 		return NewGroupAddress3LevelPlcField(match["mainGroup"], match["middleGroup"], match["subGroup"], &fieldType), nil
-	} else if match := utils.GetSubgroupMatches(m.deviceQuery, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.deviceQuery, fieldQuery); match != nil {
 		return NewDeviceQueryField(
 			match["mainGroup"], match["middleGroup"], match["subGroup"]), nil
-	} else if match := utils.GetSubgroupMatches(m.devicePropertyAddress, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.devicePropertyAddress, fieldQuery); match != nil {
 		mainGroup, _ := strconv.ParseUint(match["mainGroup"], 10, 8)
 		middleGroup, _ := strconv.ParseUint(match["middleGroup"], 10, 8)
 		subGroup, _ := strconv.ParseUint(match["subGroup"], 10, 8)
@@ -105,7 +107,7 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 		return NewDevicePropertyAddressPlcField(
 			uint8(mainGroup), uint8(middleGroup), uint8(subGroup), uint8(objectId), uint8(propertyId),
 			uint16(propertyIndex), uint8(numberOfElements)), nil
-	} else if match := utils.GetSubgroupMatches(m.deviceMemoryAddress, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.deviceMemoryAddress, fieldQuery); match != nil {
 		fieldTypeName, ok := match["datatype"]
 		// This is a 0-255 valued 1-byte value.
 		fieldType := driverModel.KnxDatapointType_DPT_DecimalFactor
@@ -130,12 +132,16 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 			numberOfElements, _ = strconv.ParseUint(numElements, 10, 8)
 		}
 		return NewDeviceMemoryAddressPlcField(uint8(mainGroup), uint8(middleGroup), uint8(subGroup), address, uint8(numberOfElements), &fieldType), nil
-	} else if match := utils.GetSubgroupMatches(m.deviceCommunicationObjectQuery, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.deviceCommunicationObjectQuery, fieldQuery); match != nil {
 		mainGroup, _ := strconv.ParseUint(match["mainGroup"], 10, 8)
 		middleGroup, _ := strconv.ParseUint(match["middleGroup"], 10, 8)
 		subGroup, _ := strconv.ParseUint(match["subGroup"], 10, 8)
 		return NewCommunicationObjectQueryField(
 			uint8(mainGroup), uint8(middleGroup), uint8(subGroup)), nil
 	}
-	return nil, errors.New("Invalid address format for address '" + query + "'")
+	return nil, errors.New("Invalid address format for address '" + fieldQuery + "'")
+}
+
+func (m FieldHandler) ParseQuery(query string) (apiModel.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
 }
diff --git a/plc4go/internal/knxnetip/SubscriptionEvent.go b/plc4go/internal/knxnetip/SubscriptionEvent.go
index 091f2031d1..2579fbecbd 100644
--- a/plc4go/internal/knxnetip/SubscriptionEvent.go
+++ b/plc4go/internal/knxnetip/SubscriptionEvent.go
@@ -20,11 +20,12 @@
 package knxnetip
 
 import (
+	"time"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 	internalMode "github.com/apache/plc4x/plc4go/spi/model"
-	"time"
 )
 
 type SubscriptionEvent struct {
diff --git a/plc4go/internal/knxnetip/Utils.go b/plc4go/internal/knxnetip/Utils.go
index 66280ce237..11b42df2c0 100644
--- a/plc4go/internal/knxnetip/Utils.go
+++ b/plc4go/internal/knxnetip/Utils.go
@@ -21,8 +21,9 @@ package knxnetip
 
 import (
 	"fmt"
-	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 	"strconv"
+
+	driverModel "github.com/apache/plc4x/plc4go/protocols/knxnetip/readwrite/model"
 )
 
 func NumericGroupAddressToString(numericAddress uint16, groupAddress GroupAddressField) string {
diff --git a/plc4go/internal/modbus/Field.go b/plc4go/internal/modbus/Field.go
index f4206c0c0c..68ebe8503c 100644
--- a/plc4go/internal/modbus/Field.go
+++ b/plc4go/internal/modbus/Field.go
@@ -22,27 +22,32 @@ package modbus
 import (
 	"encoding/binary"
 	"fmt"
+	"strconv"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	model2 "github.com/apache/plc4x/plc4go/protocols/modbus/readwrite/model"
+	model3 "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
-	"strconv"
 )
 
 const (
 	AddressOffset = 1
 )
 
-type PlcField struct {
+type modbusField struct {
+	model.PlcField
+
 	FieldType FieldType
 	Address   uint16
 	Quantity  uint16
 	Datatype  model2.ModbusDataType
 }
 
-func NewField(fieldType FieldType, address uint16, quantity uint16, datatype model2.ModbusDataType) PlcField {
-	return PlcField{
+func NewField(fieldType FieldType, address uint16, quantity uint16, datatype model2.ModbusDataType) modbusField {
+	return modbusField{
 		FieldType: fieldType,
 		Address:   address - AddressOffset,
 		Quantity:  quantity,
@@ -67,30 +72,38 @@ func NewModbusPlcFieldFromStrings(fieldType FieldType, addressString string, qua
 	return NewField(fieldType, uint16(address), uint16(quantity), datatype), nil
 }
 
-func (m PlcField) GetAddressString() string {
+func (m modbusField) GetAddressString() string {
 	return fmt.Sprintf("%dx%05d:%s[%d]", m.FieldType, m.Address, m.Datatype.String(), m.Quantity)
 }
 
-func (m PlcField) GetTypeName() string {
-	return m.Datatype.String()
-}
-
-func (m PlcField) GetDataType() model2.ModbusDataType {
-	return m.Datatype
+func (m modbusField) GetValueType() values.PlcValueType {
+	if plcValueType, ok := values.PlcValueByName(m.Datatype.String()); !ok {
+		return values.NULL
+	} else {
+		return plcValueType
+	}
 }
 
-func (m PlcField) GetQuantity() uint16 {
-	return m.Quantity
+func (m modbusField) GetArrayInfo() []model.ArrayInfo {
+	if m.Quantity != 1 {
+		return []model.ArrayInfo{
+			model3.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(m.Quantity),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
 }
 
-func CastToModbusFieldFromPlcField(plcField model.PlcField) (PlcField, error) {
-	if modbusField, ok := plcField.(PlcField); ok {
+func CastToModbusFieldFromPlcField(plcField model.PlcField) (modbusField, error) {
+	if modbusField, ok := plcField.(modbusField); ok {
 		return modbusField, nil
 	}
-	return PlcField{}, errors.New("couldn't cast to ModbusPlcField")
+	return modbusField{}, errors.New("couldn't cast to ModbusPlcField")
 }
 
-func (m PlcField) Serialize() ([]byte, error) {
+func (m modbusField) Serialize() ([]byte, error) {
 	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
 	if err := m.SerializeWithWriteBuffer(wb); err != nil {
 		return nil, err
@@ -98,7 +111,7 @@ func (m PlcField) Serialize() ([]byte, error) {
 	return wb.GetBytes(), nil
 }
 
-func (m PlcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+func (m modbusField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
 	if err := writeBuffer.PushContext(m.FieldType.GetName()); err != nil {
 		return err
 	}
@@ -106,10 +119,10 @@ func (m PlcField) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error
 	if err := writeBuffer.WriteUint16("address", 16, m.Address); err != nil {
 		return err
 	}
-	if err := writeBuffer.WriteUint16("numberOfElements", 16, m.GetQuantity()); err != nil {
+	if err := writeBuffer.WriteUint16("numberOfElements", 16, m.Quantity); err != nil {
 		return err
 	}
-	dataType := m.GetDataType().String()
+	dataType := m.Datatype.String()
 	if err := writeBuffer.WriteString("dataType", uint32(len([]rune(dataType))*8), "UTF-8", dataType); err != nil {
 		return err
 	}
diff --git a/plc4go/internal/modbus/FieldHandler.go b/plc4go/internal/modbus/FieldHandler.go
index e391b575a1..1fb35759c2 100644
--- a/plc4go/internal/modbus/FieldHandler.go
+++ b/plc4go/internal/modbus/FieldHandler.go
@@ -21,11 +21,12 @@ package modbus
 
 import (
 	"fmt"
+	"regexp"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	model2 "github.com/apache/plc4x/plc4go/protocols/modbus/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
 )
 
 type FieldType uint8
@@ -73,67 +74,71 @@ func NewFieldHandler() FieldHandler {
 	}
 }
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
-	if match := utils.GetSubgroupMatches(m.plc4xCoilPattern, query); match != nil {
+func (m FieldHandler) ParseField(fieldQuery string) (model.PlcField, error) {
+	if match := utils.GetSubgroupMatches(m.plc4xCoilPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(Coil, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.numericCoilPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.numericCoilPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(Coil, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.plc4xDiscreteInputPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.plc4xDiscreteInputPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(DiscreteInput, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.numericDiscreteInputPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.numericDiscreteInputPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(DiscreteInput, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.plc4xInputRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.plc4xInputRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(InputRegister, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.numericInputRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.numericInputRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(InputRegister, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.plc4xHoldingRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.plc4xHoldingRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(HoldingRegister, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.numericHoldingRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.numericHoldingRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(HoldingRegister, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.plc4xExtendedRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.plc4xExtendedRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(ExtendedRegister, match["address"], match["quantity"], typeByName)
-	} else if match := utils.GetSubgroupMatches(m.numericExtendedRegisterPattern, query); match != nil {
+	} else if match := utils.GetSubgroupMatches(m.numericExtendedRegisterPattern, fieldQuery); match != nil {
 		typeByName, ok := model2.ModbusDataTypeByName(match["datatype"])
 		if !ok {
 			return nil, errors.Errorf("Unknown type %s", match["datatype"])
 		}
 		return NewModbusPlcFieldFromStrings(ExtendedRegister, match["address"], match["quantity"], typeByName)
 	}
-	return nil, errors.Errorf("Invalid address format for address '%s'", query)
+	return nil, errors.Errorf("Invalid address format for address '%s'", fieldQuery)
+}
+
+func (m FieldHandler) ParseQuery(query string) (model.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
 }
diff --git a/plc4go/internal/s7/Field.go b/plc4go/internal/s7/Field.go
index 6620363197..3abc7edfb2 100644
--- a/plc4go/internal/s7/Field.go
+++ b/plc4go/internal/s7/Field.go
@@ -22,13 +22,17 @@ package s7
 import (
 	"encoding/binary"
 	"fmt"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/s7/readwrite/model"
+	model2 "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcField interface {
 	model.PlcField
+
 	GetDataType() readWriteModel.TransportSize
 	GetNumElements() uint16
 	GetBlockNumber() uint16
@@ -84,8 +88,23 @@ func (m plcField) GetAddressString() string {
 	return fmt.Sprintf("%d:%s[%d]", m.FieldType, m.Datatype, m.NumElements)
 }
 
-func (m plcField) GetTypeName() string {
-	return m.Datatype.String()
+func (m plcField) GetValueType() values.PlcValueType {
+	if plcValueByName, ok := values.PlcValueByName(m.Datatype.String()); ok {
+		return plcValueByName
+	}
+	return values.NULL
+}
+
+func (m plcField) GetArrayInfo() []model.ArrayInfo {
+	if m.NumElements != 1 {
+		return []model.ArrayInfo{
+			model2.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(m.NumElements),
+			},
+		}
+	}
+	return []model.ArrayInfo{}
 }
 
 func (m plcField) GetDataType() readWriteModel.TransportSize {
diff --git a/plc4go/internal/s7/FieldHandler.go b/plc4go/internal/s7/FieldHandler.go
index d7d22a84e4..c4e704adfc 100644
--- a/plc4go/internal/s7/FieldHandler.go
+++ b/plc4go/internal/s7/FieldHandler.go
@@ -21,13 +21,15 @@ package s7
 
 import (
 	"encoding/hex"
+	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/s7/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"regexp"
-	"strconv"
-	"strings"
 )
 
 type FieldType uint8
@@ -74,7 +76,7 @@ const (
 	MEMORY_AREA        = "memoryArea"
 )
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
+func (m FieldHandler) ParseField(query string) (model.PlcField, error) {
 	if match := utils.GetSubgroupMatches(m.dataBlockStringAddressPattern, query); match != nil {
 		dataType, ok := readWriteModel.TransportSizeByName(match[DATA_TYPE])
 		if !ok {
@@ -317,6 +319,10 @@ func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
 	return nil, errors.Errorf("Unable to parse %s", query)
 }
 
+func (m FieldHandler) ParseQuery(query string) (model.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
+}
+
 func checkDatablockNumber(blockNumber uint64) (uint16, error) {
 	//ToDo check the value or add reference - limit eventually depending on active S7 --> make a case selection
 	if blockNumber > 64000 || blockNumber < 1 {
diff --git a/plc4go/internal/simulated/Device.go b/plc4go/internal/simulated/Device.go
index b89acdb0bd..c4b6cbbff2 100644
--- a/plc4go/internal/simulated/Device.go
+++ b/plc4go/internal/simulated/Device.go
@@ -20,25 +20,26 @@
 package simulated
 
 import (
+	"math/rand"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
 	"github.com/rs/zerolog/log"
-	"math/rand"
 )
 
 type Device struct {
 	Name  string
-	State map[SimulatedField]*values.PlcValue
+	State map[simulatedField]*values.PlcValue
 }
 
 func NewDevice(name string) *Device {
 	return &Device{
 		Name:  name,
-		State: make(map[SimulatedField]*values.PlcValue),
+		State: make(map[simulatedField]*values.PlcValue),
 	}
 }
 
-func (t *Device) Get(field SimulatedField) *values.PlcValue {
+func (t *Device) Get(field simulatedField) *values.PlcValue {
 	switch field.FieldType {
 	case FieldState:
 		return t.State[field]
@@ -48,7 +49,7 @@ func (t *Device) Get(field SimulatedField) *values.PlcValue {
 	return nil
 }
 
-func (t *Device) Set(field SimulatedField, value *values.PlcValue) {
+func (t *Device) Set(field simulatedField, value *values.PlcValue) {
 	switch field.FieldType {
 	case FieldState:
 		t.State[field] = value
@@ -62,7 +63,7 @@ func (t *Device) Set(field SimulatedField, value *values.PlcValue) {
 	}
 }
 
-func (t *Device) getRandomValue(field SimulatedField) *values.PlcValue {
+func (t *Device) getRandomValue(field simulatedField) *values.PlcValue {
 	size := field.GetDataTypeSize().DataTypeSize()
 	data := make([]byte, uint16(size)*field.Quantity)
 	rand.Read(data)
diff --git a/plc4go/internal/simulated/Device_test.go b/plc4go/internal/simulated/Device_test.go
index c951c1d5cc..73f2a2863c 100644
--- a/plc4go/internal/simulated/Device_test.go
+++ b/plc4go/internal/simulated/Device_test.go
@@ -20,21 +20,22 @@
 package simulated
 
 import (
+	"reflect"
+	"testing"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
 	values2 "github.com/apache/plc4x/plc4go/spi/values"
 	"github.com/rs/zerolog/log"
-	"reflect"
-	"testing"
 )
 
 func TestDevice_Get(t1 *testing.T) {
 	type fields struct {
 		Name  string
-		State map[SimulatedField]*values.PlcValue
+		State map[simulatedField]*values.PlcValue
 	}
 	type args struct {
-		field        SimulatedField
+		field        simulatedField
 		verifyOutput bool
 	}
 	tests := []struct {
@@ -47,7 +48,7 @@ func TestDevice_Get(t1 *testing.T) {
 			name: "simple state",
 			fields: fields{
 				Name: "hurz",
-				State: map[SimulatedField]*values.PlcValue{
+				State: map[simulatedField]*values.PlcValue{
 					NewSimulatedField(FieldState, "boolField", model.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 				},
 			},
@@ -61,7 +62,7 @@ func TestDevice_Get(t1 *testing.T) {
 			name: "simple random",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:        NewSimulatedField(FieldRandom, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -73,7 +74,7 @@ func TestDevice_Get(t1 *testing.T) {
 			name: "simple stdout",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:        NewSimulatedField(FieldStdOut, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -108,10 +109,10 @@ func TestDevice_Get(t1 *testing.T) {
 func TestDevice_Random(t1 *testing.T) {
 	type fields struct {
 		Name  string
-		State map[SimulatedField]*values.PlcValue
+		State map[simulatedField]*values.PlcValue
 	}
 	type args struct {
-		field   SimulatedField
+		field   simulatedField
 		numRuns int
 	}
 	tests := []struct {
@@ -124,7 +125,7 @@ func TestDevice_Random(t1 *testing.T) {
 			name: "simple random",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:   NewSimulatedField(FieldRandom, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -162,10 +163,10 @@ func TestDevice_Random(t1 *testing.T) {
 func TestDevice_Set(t1 *testing.T) {
 	type fields struct {
 		Name  string
-		State map[SimulatedField]*values.PlcValue
+		State map[simulatedField]*values.PlcValue
 	}
 	type args struct {
-		field         SimulatedField
+		field         simulatedField
 		value         *values.PlcValue
 		shouldBeSaved bool
 	}
@@ -178,7 +179,7 @@ func TestDevice_Set(t1 *testing.T) {
 			name: "simple state",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:         NewSimulatedField(FieldState, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -190,7 +191,7 @@ func TestDevice_Set(t1 *testing.T) {
 			name: "simple random",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:         NewSimulatedField(FieldRandom, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -202,7 +203,7 @@ func TestDevice_Set(t1 *testing.T) {
 			name: "simple stdout",
 			fields: fields{
 				Name:  "hurz",
-				State: map[SimulatedField]*values.PlcValue{},
+				State: map[simulatedField]*values.PlcValue{},
 			},
 			args: args{
 				field:         NewSimulatedField(FieldStdOut, "boolField", model.SimulatedDataTypeSizes_BOOL, 1),
@@ -237,10 +238,10 @@ func TestDevice_Set(t1 *testing.T) {
 func TestDevice_getRandomValue(t1 *testing.T) {
 	type fields struct {
 		Name  string
-		State map[SimulatedField]*values.PlcValue
+		State map[simulatedField]*values.PlcValue
 	}
 	type args struct {
-		field SimulatedField
+		field simulatedField
 	}
 	tests := []struct {
 		name   string
diff --git a/plc4go/internal/simulated/Field.go b/plc4go/internal/simulated/Field.go
index b75b1bdad6..40ea0a3ef8 100644
--- a/plc4go/internal/simulated/Field.go
+++ b/plc4go/internal/simulated/Field.go
@@ -21,24 +21,30 @@ package simulated
 
 import (
 	"fmt"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
 )
 
 type Field interface {
+	apiModel.PlcField
+
 	GetFieldType() *FieldType
 	GetName() string
 	GetDataTypeSize() *model.SimulatedDataTypeSizes
 }
 
-type SimulatedField struct {
+type simulatedField struct {
 	FieldType    FieldType
 	Name         string
 	DataTypeSize model.SimulatedDataTypeSizes
 	Quantity     uint16
 }
 
-func NewSimulatedField(fieldType FieldType, name string, dataTypeSize model.SimulatedDataTypeSizes, quantity uint16) SimulatedField {
-	return SimulatedField{
+func NewSimulatedField(fieldType FieldType, name string, dataTypeSize model.SimulatedDataTypeSizes, quantity uint16) apiModel.PlcField {
+	return simulatedField{
 		FieldType:    fieldType,
 		Name:         name,
 		DataTypeSize: dataTypeSize,
@@ -46,26 +52,37 @@ func NewSimulatedField(fieldType FieldType, name string, dataTypeSize model.Simu
 	}
 }
 
-func (t SimulatedField) GetFieldType() FieldType {
+func (t simulatedField) GetFieldType() FieldType {
 	return t.FieldType
 }
 
-func (t SimulatedField) GetName() string {
+func (t simulatedField) GetName() string {
 	return t.Name
 }
 
-func (t SimulatedField) GetDataTypeSize() model.SimulatedDataTypeSizes {
+func (t simulatedField) GetDataTypeSize() model.SimulatedDataTypeSizes {
 	return t.DataTypeSize
 }
 
-func (t SimulatedField) GetAddressString() string {
+func (t simulatedField) GetAddressString() string {
 	return fmt.Sprintf("%s/%s:%s[%d]", t.FieldType.Name(), t.Name, t.DataTypeSize.String(), t.Quantity)
 }
 
-func (t SimulatedField) GetTypeName() string {
-	return t.DataTypeSize.String()
+func (t simulatedField) GetValueType() values.PlcValueType {
+	if plcValueType, ok := values.PlcValueByName(t.DataTypeSize.String()); ok {
+		return plcValueType
+	}
+	return values.NULL
 }
 
-func (t SimulatedField) GetQuantity() uint16 {
-	return t.Quantity
+func (t simulatedField) GetArrayInfo() []apiModel.ArrayInfo {
+	if t.Quantity != 1 {
+		return []apiModel.ArrayInfo{
+			spiModel.DefaultArrayInfo{
+				LowerBound: 0,
+				UpperBound: uint32(t.Quantity),
+			},
+		}
+	}
+	return []apiModel.ArrayInfo{}
 }
diff --git a/plc4go/internal/simulated/FieldHandler.go b/plc4go/internal/simulated/FieldHandler.go
index ccf546833c..a1495c92e8 100644
--- a/plc4go/internal/simulated/FieldHandler.go
+++ b/plc4go/internal/simulated/FieldHandler.go
@@ -21,11 +21,13 @@ package simulated
 
 import (
 	"errors"
+	"fmt"
+	"regexp"
+	"strconv"
+
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"regexp"
-	"strconv"
 )
 
 type FieldType uint8
@@ -59,7 +61,7 @@ func NewFieldHandler() FieldHandler {
 	}
 }
 
-func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
+func (m FieldHandler) ParseField(query string) (apiModel.PlcField, error) {
 	if match := utils.GetSubgroupMatches(m.simulatedQuery, query); match != nil {
 		fieldTypeName, ok := match["type"]
 		var fieldType FieldType
@@ -101,3 +103,7 @@ func (m FieldHandler) ParseQuery(query string) (apiModel.PlcField, error) {
 	}
 	return nil, errors.New("Invalid address format for address '" + query + "'")
 }
+
+func (m FieldHandler) ParseQuery(query string) (apiModel.PlcQuery, error) {
+	return nil, fmt.Errorf("queries not supported")
+}
diff --git a/plc4go/internal/simulated/Field_test.go b/plc4go/internal/simulated/Field_test.go
index e2cb3f52e9..5ab613cfd5 100644
--- a/plc4go/internal/simulated/Field_test.go
+++ b/plc4go/internal/simulated/Field_test.go
@@ -20,9 +20,10 @@
 package simulated
 
 import (
-	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
 	"reflect"
 	"testing"
+
+	"github.com/apache/plc4x/plc4go/protocols/simulated/readwrite/model"
 )
 
 func TestNewSimulatedField(t *testing.T) {
@@ -35,7 +36,7 @@ func TestNewSimulatedField(t *testing.T) {
 	tests := []struct {
 		name string
 		args args
-		want SimulatedField
+		want simulatedField
 	}{
 		{
 			name: "simple",
@@ -45,7 +46,7 @@ func TestNewSimulatedField(t *testing.T) {
 				dataTypeSize: model.SimulatedDataTypeSizes_BOOL,
 				quantity:     1,
 			},
-			want: SimulatedField{
+			want: simulatedField{
 				FieldType:    FieldRandom,
 				Name:         "test",
 				DataTypeSize: model.SimulatedDataTypeSizes_BOOL,
@@ -87,7 +88,7 @@ func TestSimulatedField_GetAddressString(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
@@ -125,7 +126,7 @@ func TestSimulatedField_GetDataTypeSize(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
@@ -163,7 +164,7 @@ func TestSimulatedField_GetFieldType(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
@@ -201,7 +202,7 @@ func TestSimulatedField_GetName(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
@@ -239,7 +240,7 @@ func TestSimulatedField_GetQuantity(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
@@ -277,7 +278,7 @@ func TestSimulatedField_GetTypeName(t1 *testing.T) {
 	}
 	for _, tt := range tests {
 		t1.Run(tt.name, func(t1 *testing.T) {
-			t := SimulatedField{
+			t := simulatedField{
 				FieldType:    tt.fields.FieldType,
 				Name:         tt.fields.Name,
 				DataTypeSize: tt.fields.DataTypeSize,
diff --git a/plc4go/internal/simulated/Reader.go b/plc4go/internal/simulated/Reader.go
index 9520cefa02..a75703ae67 100644
--- a/plc4go/internal/simulated/Reader.go
+++ b/plc4go/internal/simulated/Reader.go
@@ -21,12 +21,13 @@ package simulated
 
 import (
 	"context"
+	"strconv"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi"
 	model2 "github.com/apache/plc4x/plc4go/spi/model"
-	"strconv"
-	"time"
 )
 
 type Reader struct {
@@ -66,7 +67,7 @@ func (r Reader) Read(ctx context.Context, readRequest model.PlcReadRequest) <-ch
 		responseValues := make(map[string]values.PlcValue)
 		for _, fieldName := range readRequest.GetFieldNames() {
 			field := readRequest.GetField(fieldName)
-			simulatedField, ok := field.(SimulatedField)
+			simulatedField, ok := field.(simulatedField)
 			if !ok {
 				responseCodes[fieldName] = model.PlcResponseCode_INVALID_ADDRESS
 				responseValues[fieldName] = nil
diff --git a/plc4go/internal/simulated/Reader_test.go b/plc4go/internal/simulated/Reader_test.go
index b5f08d20e5..5bc241eacc 100644
--- a/plc4go/internal/simulated/Reader_test.go
+++ b/plc4go/internal/simulated/Reader_test.go
@@ -21,6 +21,10 @@ package simulated
 
 import (
 	"context"
+	"reflect"
+	"testing"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/internal/s7"
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
@@ -29,9 +33,6 @@ import (
 	model3 "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	values2 "github.com/apache/plc4x/plc4go/spi/values"
-	"reflect"
-	"testing"
-	"time"
 )
 
 func TestReader_Read(t *testing.T) {
@@ -55,7 +56,7 @@ func TestReader_Read(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -81,7 +82,7 @@ func TestReader_Read(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -109,7 +110,7 @@ func TestReader_Read(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -136,7 +137,7 @@ func TestReader_Read(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
diff --git a/plc4go/internal/simulated/Writer.go b/plc4go/internal/simulated/Writer.go
index 0317f48c5b..21d9a19fb1 100644
--- a/plc4go/internal/simulated/Writer.go
+++ b/plc4go/internal/simulated/Writer.go
@@ -21,11 +21,12 @@ package simulated
 
 import (
 	"context"
+	"strconv"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi"
 	model2 "github.com/apache/plc4x/plc4go/spi/model"
-	"strconv"
-	"time"
 )
 
 type Writer struct {
@@ -64,7 +65,7 @@ func (w Writer) Write(ctx context.Context, writeRequest model.PlcWriteRequest) <
 		responseCodes := map[string]model.PlcResponseCode{}
 		for _, fieldName := range writeRequest.GetFieldNames() {
 			field := writeRequest.GetField(fieldName)
-			simulatedField, ok := field.(SimulatedField)
+			simulatedField, ok := field.(simulatedField)
 			if !ok {
 				responseCodes[fieldName] = model.PlcResponseCode_INVALID_ADDRESS
 			} else {
diff --git a/plc4go/internal/simulated/Writer_test.go b/plc4go/internal/simulated/Writer_test.go
index 086651c6be..ead21125de 100644
--- a/plc4go/internal/simulated/Writer_test.go
+++ b/plc4go/internal/simulated/Writer_test.go
@@ -21,6 +21,10 @@ package simulated
 
 import (
 	"context"
+	"reflect"
+	"testing"
+	"time"
+
 	"github.com/apache/plc4x/plc4go/internal/s7"
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/pkg/api/values"
@@ -29,9 +33,6 @@ import (
 	model3 "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	values2 "github.com/apache/plc4x/plc4go/spi/values"
-	"reflect"
-	"testing"
-	"time"
 )
 
 func TestWriter_Write(t *testing.T) {
@@ -49,7 +50,7 @@ func TestWriter_Write(t *testing.T) {
 		fields       fields
 		args         args
 		want         model.PlcWriteResponse
-		newState     map[SimulatedField]*values.PlcValue
+		newState     map[simulatedField]*values.PlcValue
 		delayAtLeast time.Duration
 	}{
 		{
@@ -57,7 +58,7 @@ func TestWriter_Write(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name:  "hurz",
-					State: map[SimulatedField]*values.PlcValue{},
+					State: map[simulatedField]*values.PlcValue{},
 				},
 				options: map[string][]string{},
 			},
@@ -74,7 +75,7 @@ func TestWriter_Write(t *testing.T) {
 				map[string]model.PlcResponseCode{
 					"test": model.PlcResponseCode_OK,
 				}),
-			newState: map[SimulatedField]*values.PlcValue{
+			newState: map[simulatedField]*values.PlcValue{
 				NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 			},
 			delayAtLeast: 0,
@@ -84,7 +85,7 @@ func TestWriter_Write(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -103,7 +104,7 @@ func TestWriter_Write(t *testing.T) {
 				map[string]model.PlcResponseCode{
 					"test": model.PlcResponseCode_OK,
 				}),
-			newState: map[SimulatedField]*values.PlcValue{
+			newState: map[simulatedField]*values.PlcValue{
 				NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(false)),
 			},
 			delayAtLeast: 0,
@@ -113,7 +114,7 @@ func TestWriter_Write(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -134,7 +135,7 @@ func TestWriter_Write(t *testing.T) {
 				map[string]model.PlcResponseCode{
 					"test": model.PlcResponseCode_OK,
 				}),
-			newState: map[SimulatedField]*values.PlcValue{
+			newState: map[simulatedField]*values.PlcValue{
 				NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(false)),
 			},
 			delayAtLeast: 1000,
@@ -145,7 +146,7 @@ func TestWriter_Write(t *testing.T) {
 			fields: fields{
 				device: &Device{
 					Name: "hurz",
-					State: map[SimulatedField]*values.PlcValue{
+					State: map[simulatedField]*values.PlcValue{
 						NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 					},
 				},
@@ -164,7 +165,7 @@ func TestWriter_Write(t *testing.T) {
 				map[string]model.PlcResponseCode{
 					"test": model.PlcResponseCode_INVALID_ADDRESS,
 				}),
-			newState: map[SimulatedField]*values.PlcValue{
+			newState: map[simulatedField]*values.PlcValue{
 				NewSimulatedField(FieldState, "test", model2.SimulatedDataTypeSizes_BOOL, 1): ToReference(values2.NewPlcBOOL(true)),
 			},
 			delayAtLeast: 0,
diff --git a/plc4go/pkg/api/model/plc_browse.go b/plc4go/pkg/api/model/plc_browse.go
index 5518451bb9..eee0b86719 100644
--- a/plc4go/pkg/api/model/plc_browse.go
+++ b/plc4go/pkg/api/model/plc_browse.go
@@ -59,21 +59,10 @@ type PlcBrowseRequestResult interface {
 	GetErr() error
 }
 
-type PlcBrowseEvent interface {
-	PlcMessage
-	GetRequest() PlcBrowseRequest
-	GetQueryName() string
-	GetResult() PlcBrowseItem
-	GetErr() error
-}
-
 type PlcBrowseItem interface {
 	GetField() PlcField
 
-	GetAddress() string
 	GetName() string
-	GetPlcValueType() values.PlcValueType
-	GetArrayInfo() []ArrayInfo
 	IsReadable() bool
 	IsWritable() bool
 	IsSubscribable() bool
diff --git a/plc4go/pkg/api/values/plc_value.go b/plc4go/pkg/api/values/plc_value.go
index 8b157ac0ee..bc938b6b16 100644
--- a/plc4go/pkg/api/values/plc_value.go
+++ b/plc4go/pkg/api/values/plc_value.go
@@ -157,106 +157,171 @@ type RawPlcValue interface {
 type PlcValueType uint8
 
 const (
-	BINT PlcValueType = iota
-	BIT_STRING
-	BOOL
-	BREAL
-	BYTE
-	BYTE_ARRAY
-	CHAR
-	DATE
-	DATE_AND_TIME
-	DINT
-	DWORD
-	INT
-	LINT
-	LIST
-	LREAL
-	LTIME
-	LWORD
-	NULL
-	RAW_PLC_VALUE
-	REAL
-	STRUCT
-	SINT
-	STRING
-	TIME
-	TIME_OF_DAY
-	UDINT
-	UINT
-	ULINT
-	USINT
-	WCHAR
-	WORD
-	WSTRING
+	NULL           PlcValueType = 0x00
+	BOOL           PlcValueType = 0x01
+	BYTE           PlcValueType = 0x02
+	WORD           PlcValueType = 0x03
+	DWORD          PlcValueType = 0x04
+	LWORD          PlcValueType = 0x05
+	USINT          PlcValueType = 0x11
+	UINT           PlcValueType = 0x12
+	UDINT          PlcValueType = 0x13
+	ULINT          PlcValueType = 0x14
+	SINT           PlcValueType = 0x21
+	INT            PlcValueType = 0x22
+	DINT           PlcValueType = 0x23
+	LINT           PlcValueType = 0x24
+	REAL           PlcValueType = 0x31
+	LREAL          PlcValueType = 0x32
+	CHAR           PlcValueType = 0x41
+	WCHAR          PlcValueType = 0x42
+	STRING         PlcValueType = 0x43
+	WSTRING        PlcValueType = 0x44
+	TIME           PlcValueType = 0x51
+	LTIME          PlcValueType = 0x52
+	DATE           PlcValueType = 0x53
+	LDATE          PlcValueType = 0x54
+	TIME_OF_DAY    PlcValueType = 0x55
+	LTIME_OF_DAY   PlcValueType = 0x56
+	DATE_AND_TIME  PlcValueType = 0x57
+	LDATE_AND_TIME PlcValueType = 0x58
+	Struct         PlcValueType = 0x61
+	List           PlcValueType = 0x62
+	RAW_BYTE_ARRAY PlcValueType = 0x71
 )
 
 func (p PlcValueType) String() string {
 	switch {
-	case p == BINT:
-		return "BINT"
-	case p == BIT_STRING:
-		return "BIT_STRING"
+	case p == NULL:
+		return "NULL"
 	case p == BOOL:
 		return "BOOL"
-	case p == BREAL:
-		return "BREAL"
 	case p == BYTE:
 		return "BYTE"
-	case p == BYTE_ARRAY:
-		return "BYTE_ARRAY"
-	case p == CHAR:
-		return "CHAR"
-	case p == DATE:
-		return "DATE"
-	case p == DATE_AND_TIME:
-		return "DATE_AND_TIME"
-	case p == DINT:
-		return "DINT"
+	case p == WORD:
+		return "WORD"
 	case p == DWORD:
 		return "DWORD"
+	case p == LWORD:
+		return "LWORD"
+	case p == USINT:
+		return "USINT"
+	case p == UINT:
+		return "UINT"
+	case p == UDINT:
+		return "UDINT"
+	case p == ULINT:
+		return "ULINT"
+	case p == SINT:
+		return "SINT"
 	case p == INT:
 		return "INT"
+	case p == DINT:
+		return "DINT"
 	case p == LINT:
 		return "LINT"
-	case p == LIST:
-		return "LIST"
-	case p == LREAL:
-		return "LREAL"
-	case p == LTIME:
-		return "LTIME"
-	case p == LWORD:
-		return "LWORD"
-	case p == NULL:
-		return "NULL"
-	case p == RAW_PLC_VALUE:
-		return "RAW_PLC_VALUE"
 	case p == REAL:
 		return "REAL"
-	case p == STRUCT:
-		return "STRUCT"
-	case p == SINT:
-		return "SINT"
+	case p == LREAL:
+		return "LREAL"
+	case p == CHAR:
+		return "CHAR"
+	case p == WCHAR:
+		return "WCHAR"
 	case p == STRING:
 		return "STRING"
+	case p == WSTRING:
+		return "WSTRING"
 	case p == TIME:
 		return "TIME"
+	case p == LTIME:
+		return "LTIME"
+	case p == DATE:
+		return "DATE"
+	case p == LDATE:
+		return "LDATE"
 	case p == TIME_OF_DAY:
 		return "TIME_OF_DAY"
-	case p == UDINT:
-		return "UDINT"
-	case p == UINT:
-		return "UINT"
-	case p == ULINT:
-		return "ULINT"
-	case p == USINT:
-		return "USINT"
-	case p == WCHAR:
-		return "WCHAR"
-	case p == WORD:
-		return "WORD"
-	case p == WSTRING:
-		return "WSTRING"
+	case p == LTIME_OF_DAY:
+		return "LTIME_OF_DAY"
+	case p == DATE_AND_TIME:
+		return "DATE_AND_TIME"
+	case p == LDATE_AND_TIME:
+		return "LDATE_AND_TIME"
+	case p == Struct:
+		return "Struct"
+	case p == List:
+		return "List"
+	case p == RAW_BYTE_ARRAY:
+		return "RAW_BYTE_ARRAY"
 	}
 	return "Unknown"
 }
+
+func PlcValueByName(value string) (PlcValueType, bool) {
+	switch value {
+	case "NULL":
+		return NULL, true
+	case "BOOL":
+		return BOOL, true
+	case "BYTE":
+		return BYTE, true
+	case "WORD":
+		return WORD, true
+	case "DWORD":
+		return DWORD, true
+	case "LWORD":
+		return LWORD, true
+	case "USINT":
+		return USINT, true
+	case "UINT":
+		return UINT, true
+	case "UDINT":
+		return UDINT, true
+	case "ULINT":
+		return ULINT, true
+	case "SINT":
+		return SINT, true
+	case "INT":
+		return INT, true
+	case "DINT":
+		return DINT, true
+	case "LINT":
+		return LINT, true
+	case "REAL":
+		return REAL, true
+	case "LREAL":
+		return LREAL, true
+	case "CHAR":
+		return CHAR, true
+	case "WCHAR":
+		return WCHAR, true
+	case "STRING":
+		return STRING, true
+	case "WSTRING":
+		return WSTRING, true
+	case "TIME":
+		return TIME, true
+	case "LTIME":
+		return LTIME, true
+	case "DATE":
+		return DATE, true
+	case "LDATE":
+		return LDATE, true
+	case "TIME_OF_DAY":
+		return TIME_OF_DAY, true
+	case "LTIME_OF_DAY":
+		return LTIME_OF_DAY, true
+	case "DATE_AND_TIME":
+		return DATE_AND_TIME, true
+	case "LDATE_AND_TIME":
+		return LDATE_AND_TIME, true
+	case "Struct":
+		return Struct, true
+	case "List":
+		return List, true
+	case "RAW_BYTE_ARRAY":
+		return RAW_BYTE_ARRAY, true
+	}
+	return NULL, false
+}
diff --git a/plc4go/spi/default/DefaultBrowser.go b/plc4go/spi/default/DefaultBrowser.go
index 8ff7c097c7..5b65b739db 100644
--- a/plc4go/spi/default/DefaultBrowser.go
+++ b/plc4go/spi/default/DefaultBrowser.go
@@ -29,7 +29,7 @@ import (
 
 // DefaultBrowserRequirements adds required methods to Browser that are needed when using DefaultBrowser
 type DefaultBrowserRequirements interface {
-	BrowseField(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseEvent) bool, fieldName string, field apiModel.PlcField) (apiModel.PlcResponseCode, []apiModel.PlcBrowseFoundField)
+	InternalBrowse(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool, queryName string, query apiModel.PlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem)
 }
 
 type DefaultBrowser interface {
@@ -37,7 +37,9 @@ type DefaultBrowser interface {
 }
 
 func NewDefaultBrowser(defaultBrowserRequirements DefaultBrowserRequirements) DefaultBrowser {
-	return &defaultBrowser{defaultBrowserRequirements}
+	return &defaultBrowser{
+		defaultBrowserRequirements,
+	}
 }
 
 ///////////////////////////////////////
@@ -57,19 +59,19 @@ type defaultBrowser struct {
 ///////////////////////////////////////
 
 func (m *defaultBrowser) Browse(ctx context.Context, browseRequest apiModel.PlcBrowseRequest) <-chan apiModel.PlcBrowseRequestResult {
-	return m.BrowseWithInterceptor(ctx, browseRequest, func(result apiModel.PlcBrowseEvent) bool {
+	return m.BrowseWithInterceptor(ctx, browseRequest, func(result apiModel.PlcBrowseItem) bool {
 		return true
 	})
 }
 
-func (m *defaultBrowser) BrowseWithInterceptor(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseEvent) bool) <-chan apiModel.PlcBrowseRequestResult {
+func (m *defaultBrowser) BrowseWithInterceptor(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool) <-chan apiModel.PlcBrowseRequestResult {
 	result := make(chan apiModel.PlcBrowseRequestResult)
 	go func() {
 		responseCodes := map[string]apiModel.PlcResponseCode{}
-		results := map[string][]apiModel.PlcBrowseFoundField{}
-		for _, fieldName := range browseRequest.GetFieldNames() {
-			field := browseRequest.GetField(fieldName)
-			responseCodes[fieldName], results[fieldName] = m.BrowseField(ctx, browseRequest, interceptor, fieldName, field)
+		results := map[string][]apiModel.PlcBrowseItem{}
+		for _, queryName := range browseRequest.GetQueryNames() {
+			query := browseRequest.GetQuery(queryName)
+			responseCodes[queryName], results[queryName] = m.InternalBrowse(ctx, browseRequest, interceptor, queryName, query)
 		}
 		browseResponse := model.NewDefaultPlcBrowseResponse(browseRequest, results, responseCodes)
 		result <- &model.DefaultPlcBrowseRequestResult{
diff --git a/plc4go/spi/default/DefaultConnection.go b/plc4go/spi/default/DefaultConnection.go
index 3ed9d8d7e9..aaa88195ab 100644
--- a/plc4go/spi/default/DefaultConnection.go
+++ b/plc4go/spi/default/DefaultConnection.go
@@ -20,9 +20,10 @@
 package _default
 
 import (
-	"github.com/apache/plc4x/plc4go/spi/options"
 	"time"
 
+	"github.com/apache/plc4x/plc4go/spi/options"
+
 	"github.com/apache/plc4x/plc4go/pkg/api"
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi"
diff --git a/plc4go/spi/model/DefaultPlcRequest.go b/plc4go/spi/model/DefaultArrayInfo.go
similarity index 73%
copy from plc4go/spi/model/DefaultPlcRequest.go
copy to plc4go/spi/model/DefaultArrayInfo.go
index ac8b62ad8c..fcc4927d53 100644
--- a/plc4go/spi/model/DefaultPlcRequest.go
+++ b/plc4go/spi/model/DefaultArrayInfo.go
@@ -19,15 +19,19 @@
 
 package model
 
-import "github.com/apache/plc4x/plc4go/pkg/api/model"
+type DefaultArrayInfo struct {
+	LowerBound uint32
+	UpperBound uint32
+}
 
-type DefaultPlcRequest struct {
+func (t DefaultArrayInfo) GetSize() uint32 {
+	return t.UpperBound - t.LowerBound
 }
 
-func NewDefaultPlcRequest() model.PlcRequest {
-	return &DefaultPlcRequest{}
+func (t DefaultArrayInfo) GetLowerBound() uint32 {
+	return t.LowerBound
 }
 
-func (d *DefaultPlcRequest) IsAPlcMessage() bool {
-	return true
+func (t DefaultArrayInfo) GetUpperBound() uint32 {
+	return t.UpperBound
 }
diff --git a/plc4go/spi/model/DefaultPlcBrowseItem.go b/plc4go/spi/model/DefaultPlcBrowseItem.go
index 31aa4883d8..c1c80d6b80 100644
--- a/plc4go/spi/model/DefaultPlcBrowseItem.go
+++ b/plc4go/spi/model/DefaultPlcBrowseItem.go
@@ -27,10 +27,8 @@ import (
 //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
+	DataTypeName string
 	Readable     bool
 	Writable     bool
 	Subscribable bool
@@ -42,20 +40,12 @@ func (d *DefaultPlcBrowseItem) GetField() model.PlcField {
 	return d.Field
 }
 
-func (d *DefaultPlcBrowseItem) GetAddress() string {
-	return d.Address
-}
-
 func (d *DefaultPlcBrowseItem) GetName() string {
 	return d.Name
 }
 
-func (d *DefaultPlcBrowseItem) GetPlcValueType() values.PlcValueType {
-	return d.PlcValueType
-}
-
-func (d *DefaultPlcBrowseItem) GetArrayInfo() []model.PlcBrowseItemArrayInfo {
-	return d.ArrayInfo
+func (d *DefaultPlcBrowseItem) GetDataTypeName() string {
+	return d.DataTypeName
 }
 
 func (d *DefaultPlcBrowseItem) IsReadable() bool {
diff --git a/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go b/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
index 8400dede29..60da6c7a50 100644
--- a/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
+++ b/plc4go/spi/model/DefaultPlcBrowseItem_plc4xgen.go
@@ -61,58 +61,11 @@ func (d *DefaultPlcBrowseItem) SerializeWithWriteBuffer(writeBuffer utils.WriteB
 		}
 	}
 
-	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 {
+	if err := writeBuffer.WriteString("dataTypeName", uint32(len(d.DataTypeName)*8), "UTF-8", d.DataTypeName); err != nil {
 		return err
 	}
 
diff --git a/plc4go/spi/model/DefaultPlcBrowseResponse.go b/plc4go/spi/model/DefaultPlcBrowseResponse.go
index ce1a3c7f79..e621404ceb 100644
--- a/plc4go/spi/model/DefaultPlcBrowseResponse.go
+++ b/plc4go/spi/model/DefaultPlcBrowseResponse.go
@@ -32,10 +32,10 @@ type DefaultPlcBrowseResponse struct {
 	DefaultResponse
 	request      model.PlcBrowseRequest
 	responseCode model.PlcResponseCode
-	results      map[string][]model.PlcBrowseFoundField
+	results      map[string][]model.PlcBrowseItem
 }
 
-func NewDefaultPlcBrowseResponse(request model.PlcBrowseRequest, results map[string][]model.PlcBrowseFoundField, responseCodes map[string]model.PlcResponseCode) DefaultPlcBrowseResponse {
+func NewDefaultPlcBrowseResponse(request model.PlcBrowseRequest, results map[string][]model.PlcBrowseItem, responseCodes map[string]model.PlcResponseCode) DefaultPlcBrowseResponse {
 	return DefaultPlcBrowseResponse{
 		DefaultResponse: DefaultResponse{responseCodes: responseCodes},
 		request:         request,
@@ -43,17 +43,6 @@ func NewDefaultPlcBrowseResponse(request model.PlcBrowseRequest, results map[str
 	}
 }
 
-func (d DefaultPlcBrowseResponse) GetFieldNames() []string {
-	var fieldNames []string
-	// We take the field names from the request to keep order as map is not ordered
-	for _, name := range d.request.GetFieldNames() {
-		if _, ok := d.results[name]; ok {
-			fieldNames = append(fieldNames, name)
-		}
-	}
-	return fieldNames
-}
-
 func (d DefaultPlcBrowseResponse) GetRequest() model.PlcBrowseRequest {
 	return d.request
 }
@@ -66,7 +55,7 @@ func (d DefaultPlcBrowseResponse) GetQueryNames() []string {
 	return queryNames
 }
 
-func (d DefaultPlcBrowseResponse) GetQueryResults(queryName string) []model.PlcBrowseFoundField {
+func (d DefaultPlcBrowseResponse) GetQueryResults(queryName string) []model.PlcBrowseItem {
 	return d.results[queryName]
 }
 
diff --git a/plc4go/spi/model/DefaultPlcRequest.go b/plc4go/spi/model/DefaultPlcRequest.go
index ac8b62ad8c..9f6391aee4 100644
--- a/plc4go/spi/model/DefaultPlcRequest.go
+++ b/plc4go/spi/model/DefaultPlcRequest.go
@@ -19,7 +19,12 @@
 
 package model
 
-import "github.com/apache/plc4x/plc4go/pkg/api/model"
+import (
+	"encoding/binary"
+
+	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/spi/utils"
+)
 
 type DefaultPlcRequest struct {
 }
@@ -31,3 +36,29 @@ func NewDefaultPlcRequest() model.PlcRequest {
 func (d *DefaultPlcRequest) IsAPlcMessage() bool {
 	return true
 }
+
+func (d *DefaultPlcRequest) Serialize() ([]byte, error) {
+	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
+	if err := d.SerializeWithWriteBuffer(wb); err != nil {
+		return nil, err
+	}
+	return wb.GetBytes(), nil
+}
+
+func (d *DefaultPlcRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
+	if err := writeBuffer.PushContext("DefaultPlcRequest"); err != nil {
+		return err
+	}
+	if err := writeBuffer.PopContext("DefaultPlcRequest"); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d *DefaultPlcRequest) String() string {
+	writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(d); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/spi/model/DefaultRequest_plc4xgen.go b/plc4go/spi/model/DefaultRequest_plc4xgen.go
deleted file mode 100644
index 9f3cb10635..0000000000
--- a/plc4go/spi/model/DefaultRequest_plc4xgen.go
+++ /dev/null
@@ -1,93 +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.
- */
-
-// Code generated by "plc4xgenerator -type=DefaultPlcRequest"; DO NOT EDIT.
-
-package model
-
-import (
-	"encoding/binary"
-	"fmt"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-)
-
-var _ = fmt.Printf
-
-func (d *DefaultPlcRequest) Serialize() ([]byte, error) {
-	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
-	if err := d.SerializeWithWriteBuffer(wb); err != nil {
-		return nil, err
-	}
-	return wb.GetBytes(), nil
-}
-
-func (d *DefaultPlcRequest) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
-	if err := writeBuffer.PushContext("Request"); err != nil {
-		return err
-	}
-	if err := writeBuffer.PushContext("fields", utils.WithRenderAsList(true)); err != nil {
-		return err
-	}
-	for name, elem := range d.fields {
-
-		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("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("Request"); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (d *DefaultPlcRequest) String() string {
-	writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
-	if err := writeBuffer.WriteSerializable(d); err != nil {
-		return err.Error()
-	}
-	return writeBuffer.GetBox().String()
-}
diff --git a/plc4go/spi/values/BINT.go b/plc4go/spi/values/BINT.go
deleted file mode 100644
index dc203d6e13..0000000000
--- a/plc4go/spi/values/BINT.go
+++ /dev/null
@@ -1,174 +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 values
-
-import (
-	"encoding/binary"
-	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-	"math"
-	"math/big"
-	"strconv"
-)
-
-type PlcBINT struct {
-	PlcSimpleNumericValueAdapter
-	value *big.Int
-}
-
-func NewPlcBINT(value *big.Int) PlcBINT {
-	return PlcBINT{
-		value: value,
-	}
-}
-
-func (m PlcBINT) GetRaw() []byte {
-	return m.value.Bytes()
-}
-
-func (m PlcBINT) GetBoolean() bool {
-	if m.isZero() {
-		return false
-	}
-	return true
-}
-
-func (m PlcBINT) IsByte() bool {
-	return m.IsUint8()
-}
-
-func (m PlcBINT) GetByte() byte {
-	return m.GetUint8()
-}
-
-func (m PlcBINT) IsUint8() bool {
-	return m.isEqualsOrGreaterZero() && m.value.Cmp(big.NewInt(math.MaxUint8)) <= 0
-}
-
-func (m PlcBINT) GetUint8() uint8 {
-	if m.IsUint8() {
-		return uint8(m.GetInt16())
-	}
-	return 0
-}
-
-func (m PlcBINT) IsUint16() bool {
-	return m.isEqualsOrGreaterZero()
-}
-
-func (m PlcBINT) GetUint16() uint16 {
-	if m.IsUint16() {
-		return uint16(m.GetInt16())
-	}
-	return 0
-}
-
-func (m PlcBINT) IsUint32() bool {
-	return m.isEqualsOrGreaterZero()
-}
-
-func (m PlcBINT) GetUint32() uint32 {
-	if m.IsUint32() {
-		return uint32(m.GetInt32())
-	}
-	return 0
-}
-
-func (m PlcBINT) IsUint64() bool {
-	return m.isEqualsOrGreaterZero()
-}
-
-func (m PlcBINT) GetUint64() uint64 {
-	if m.IsUint64() {
-		return uint64(m.value.Int64())
-	}
-	return 0
-}
-
-func (m PlcBINT) IsInt8() bool {
-	return m.isGreaterOrEqual(math.MinInt8) && m.isLowerOrEqual(math.MaxInt8)
-}
-
-func (m PlcBINT) GetInt8() int8 {
-	return int8(m.value.Int64())
-}
-
-func (m PlcBINT) GetInt16() int16 {
-	return int16(m.value.Int64())
-}
-
-func (m PlcBINT) GetInt32() int32 {
-	return int32(m.value.Int64())
-}
-
-func (m PlcBINT) GetInt64() int64 {
-	return m.value.Int64()
-}
-
-func (m PlcBINT) GetFloat32() float32 {
-	//TODO: Check if this is ok
-	return float32(m.value.Int64())
-}
-
-func (m PlcBINT) GetFloat64() float64 {
-	//TODO: Check if this is ok
-	return float64(m.value.Int64())
-}
-
-func (m PlcBINT) GetString() string {
-	return strconv.Itoa(int(m.GetInt64()))
-}
-
-func (m PlcBINT) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.BINT
-}
-
-func (m PlcBINT) isZero() bool {
-	return m.value.Cmp(big.NewInt(0)) == 0
-}
-
-func (m PlcBINT) isEqualsOrGreaterZero() bool {
-	return m.isGreaterOrEqual(0)
-}
-
-func (m PlcBINT) isGreaterOrEqual(other int64) bool {
-	return m.value.Cmp(big.NewInt(other)) >= 0
-}
-
-func (m PlcBINT) isLowerOrEqual(other int64) bool {
-	return m.value.Cmp(big.NewInt(other)) <= 0
-}
-
-func (m PlcBINT) Serialize() ([]byte, error) {
-	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
-	if err := m.SerializeWithWriteBuffer(wb); err != nil {
-		return nil, err
-	}
-	return wb.GetBytes(), nil
-}
-
-func (m PlcBINT) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
-	return writeBuffer.WriteBigInt("PlcBINT", uint8(m.value.BitLen()), m.value)
-}
-
-func (m PlcBINT) String() string {
-	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), m.value.BitLen(), m.value)
-}
diff --git a/plc4go/spi/values/BREAL.go b/plc4go/spi/values/BREAL.go
deleted file mode 100644
index 96dfc6f0db..0000000000
--- a/plc4go/spi/values/BREAL.go
+++ /dev/null
@@ -1,203 +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 values
-
-import (
-	"encoding/binary"
-	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-	"math"
-	"math/big"
-)
-
-type PlcBREAL struct {
-	value *big.Float
-	PlcSimpleNumericValueAdapter
-}
-
-func NewPlcBREAL(value *big.Float) PlcBREAL {
-	return PlcBREAL{
-		value: value,
-	}
-}
-
-func (m PlcBREAL) GetRaw() []byte {
-	theBytes, _ := m.Serialize()
-	return theBytes
-}
-
-func (m PlcBREAL) GetBoolean() bool {
-	if m.isZero() {
-		return false
-	}
-	return true
-}
-
-func (m PlcBREAL) IsUint8() bool {
-	return m.isGreaterOrEqual(0.0) && m.isLowerOrEqual(math.MaxUint8)
-}
-
-func (m PlcBREAL) GetUint8() uint8 {
-	if m.IsUint8() {
-		return uint8(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsUint16() bool {
-	return m.isGreaterOrEqual(0.0) && m.isLowerOrEqual(math.MaxUint16)
-}
-
-func (m PlcBREAL) GetUint16() uint16 {
-	if m.IsUint16() {
-		return uint16(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsUint32() bool {
-	return m.isGreaterOrEqual(0.0) && m.isLowerOrEqual(math.MaxUint32)
-}
-
-func (m PlcBREAL) GetUint32() uint32 {
-	if m.IsUint32() {
-		return uint32(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsUint64() bool {
-	return m.isGreaterOrEqual(0.0) && m.isLowerOrEqual(math.MaxUint64)
-}
-
-func (m PlcBREAL) GetUint64() uint64 {
-	if m.IsUint64() {
-		return uint64(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsByte() bool {
-	return m.IsUint8()
-}
-
-func (m PlcBREAL) GetByte() byte {
-	return m.GetUint8()
-}
-
-func (m PlcBREAL) IsInt8() bool {
-	return m.isGreaterOrEqual(math.MinInt8) && m.isLowerOrEqual(math.MaxInt8)
-}
-
-func (m PlcBREAL) GetInt8() int8 {
-	if m.IsInt8() {
-		return int8(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsInt16() bool {
-	return m.isGreaterOrEqual(math.MinInt16) && m.isLowerOrEqual(math.MaxInt16)
-}
-
-func (m PlcBREAL) GetInt16() int16 {
-	if m.IsInt16() {
-		return int16(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsInt32() bool {
-	return m.isGreaterOrEqual(math.MinInt32) && m.isLowerOrEqual(math.MaxInt32)
-}
-
-func (m PlcBREAL) GetInt32() int32 {
-	if m.IsInt32() {
-		return int32(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) IsInt64() bool {
-	return m.isGreaterOrEqual(math.MinInt64) && m.isLowerOrEqual(math.MaxInt64)
-}
-
-func (m PlcBREAL) GetInt64() int64 {
-	if m.IsInt64() {
-		return int64(m.GetFloat32())
-	}
-	return 0
-}
-
-func (m PlcBREAL) GetFloat32() float32 {
-	f, _ := m.value.Float32()
-	return f
-}
-
-func (m PlcBREAL) GetFloat64() float64 {
-	f, _ := m.value.Float64()
-	return f
-}
-
-func (m PlcBREAL) IsString() bool {
-	return true
-}
-
-func (m PlcBREAL) GetString() string {
-	return fmt.Sprintf("%g", m.GetFloat64())
-}
-
-func (m PlcBREAL) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.BREAL
-}
-
-func (m PlcBREAL) isZero() bool {
-	return m.value.Cmp(big.NewFloat(0.0)) == 0.0
-}
-
-func (m PlcBREAL) isEqualsOrGreaterZero() bool {
-	return m.isGreaterOrEqual(0)
-}
-
-func (m PlcBREAL) isGreaterOrEqual(other float64) bool {
-	return m.value.Cmp(big.NewFloat(other)) >= 0
-}
-
-func (m PlcBREAL) isLowerOrEqual(other float64) bool {
-	return m.value.Cmp(big.NewFloat(other)) <= 0
-}
-
-func (m PlcBREAL) Serialize() ([]byte, error) {
-	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
-	if err := m.SerializeWithWriteBuffer(wb); err != nil {
-		return nil, err
-	}
-	return wb.GetBytes(), nil
-}
-
-func (m PlcBREAL) SerializeWithWriteBuffer(writeBuffer utils.WriteBuffer) error {
-	// TODO: fix this a insert a valid bit length calculation
-	return writeBuffer.WriteBigFloat("PlcBREAL", uint8(m.value.MinPrec()), m.value)
-}
-
-func (m PlcBREAL) String() string {
-	return fmt.Sprintf("%s(%dbit):%v", m.GetPlcValueType(), m.value.MinPrec(), m.value)
-}
diff --git a/plc4go/spi/values/BOOL.go b/plc4go/spi/values/PlcBOOL.go
similarity index 99%
rename from plc4go/spi/values/BOOL.go
rename to plc4go/spi/values/PlcBOOL.go
index 3eb4e7e9d3..0a4707702f 100644
--- a/plc4go/spi/values/BOOL.go
+++ b/plc4go/spi/values/PlcBOOL.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/BYTE.go b/plc4go/spi/values/PlcBYTE.go
similarity index 99%
rename from plc4go/spi/values/BYTE.go
rename to plc4go/spi/values/PlcBYTE.go
index 89880ee72a..9b0a80fc96 100644
--- a/plc4go/spi/values/BYTE.go
+++ b/plc4go/spi/values/PlcBYTE.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/PlcBitString.go b/plc4go/spi/values/PlcBitString.go
deleted file mode 100644
index 4c25733c31..0000000000
--- a/plc4go/spi/values/PlcBitString.go
+++ /dev/null
@@ -1,83 +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 values
-
-import (
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-)
-
-type PlcBitString struct {
-	PlcList
-}
-
-func NewPlcBitString(value interface{}) PlcBitString {
-	var bools []apiValues.PlcValue
-	switch value.(type) {
-	case uint8:
-		bools = make([]apiValues.PlcValue, 8)
-		for i := 0; i < 8; i++ {
-			bools[i] = NewPlcBOOL(((value.(uint8) >> uint8((8-1)-i)) & 0x01) == 0x01)
-		}
-	case uint16:
-		bools = make([]apiValues.PlcValue, 16)
-		for i := 0; i < 16; i++ {
-			bools[i] = NewPlcBOOL(((value.(uint16) >> uint8((16-1)-i)) & 0x01) == 0x01)
-		}
-	case uint32:
-		bools = make([]apiValues.PlcValue, 32)
-		for i := 0; i < 32; i++ {
-			bools[i] = NewPlcBOOL(((value.(uint32) >> uint8((32-1)-i)) & 0x01) == 0x01)
-		}
-	case uint64:
-		bools = make([]apiValues.PlcValue, 64)
-		for i := 0; i < 64; i++ {
-			bools[i] = NewPlcBOOL(((value.(uint64) >> uint8((64-1)-i)) & 0x01) == 0x01)
-		}
-	}
-
-	return PlcBitString{
-		PlcList{Values: bools},
-	}
-}
-
-func (m PlcBitString) GetRaw() []byte {
-	theBytes, _ := m.Serialize()
-	return theBytes
-}
-
-func (m PlcBitString) IsList() bool {
-	return true
-}
-
-func (m PlcBitString) GetLength() uint32 {
-	return uint32(len(m.Values))
-}
-
-func (m PlcBitString) GetIndex(i uint32) apiValues.PlcValue {
-	return m.Values[i]
-}
-
-func (m PlcBitString) GetList() []apiValues.PlcValue {
-	return m.Values
-}
-
-func (m PlcBitString) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.BIT_STRING
-}
diff --git a/plc4go/spi/values/CHAR.go b/plc4go/spi/values/PlcCHAR.go
similarity index 99%
rename from plc4go/spi/values/CHAR.go
rename to plc4go/spi/values/PlcCHAR.go
index ab215f4fd8..550efce23e 100644
--- a/plc4go/spi/values/CHAR.go
+++ b/plc4go/spi/values/PlcCHAR.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/DATE.go b/plc4go/spi/values/PlcDATE.go
similarity index 99%
rename from plc4go/spi/values/DATE.go
rename to plc4go/spi/values/PlcDATE.go
index 05baea4616..26e6ea6653 100644
--- a/plc4go/spi/values/DATE.go
+++ b/plc4go/spi/values/PlcDATE.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"time"
 )
 
 type PlcDATE struct {
diff --git a/plc4go/spi/values/DATE_AND_TIME.go b/plc4go/spi/values/PlcDATE_AND_TIME.go
similarity index 99%
rename from plc4go/spi/values/DATE_AND_TIME.go
rename to plc4go/spi/values/PlcDATE_AND_TIME.go
index 53ff927bf6..d87c72a39f 100644
--- a/plc4go/spi/values/DATE_AND_TIME.go
+++ b/plc4go/spi/values/PlcDATE_AND_TIME.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"time"
 )
 
 type PlcDATE_AND_TIME struct {
diff --git a/plc4go/spi/values/DINT.go b/plc4go/spi/values/PlcDINT.go
similarity index 99%
rename from plc4go/spi/values/DINT.go
rename to plc4go/spi/values/PlcDINT.go
index fb6571fc85..4dd1ba75cd 100644
--- a/plc4go/spi/values/DINT.go
+++ b/plc4go/spi/values/PlcDINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcDINT struct {
diff --git a/plc4go/spi/values/DWORD.go b/plc4go/spi/values/PlcDWORD.go
similarity index 99%
rename from plc4go/spi/values/DWORD.go
rename to plc4go/spi/values/PlcDWORD.go
index ef3ec2bc77..d9538f3805 100644
--- a/plc4go/spi/values/DWORD.go
+++ b/plc4go/spi/values/PlcDWORD.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/INT.go b/plc4go/spi/values/PlcINT.go
similarity index 99%
rename from plc4go/spi/values/INT.go
rename to plc4go/spi/values/PlcINT.go
index 78c2b3b392..e2fba65705 100644
--- a/plc4go/spi/values/INT.go
+++ b/plc4go/spi/values/PlcINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcINT struct {
diff --git a/plc4go/spi/values/PlcLDATE.go b/plc4go/spi/values/PlcLDATE.go
new file mode 100644
index 0000000000..4cc8144e41
--- /dev/null
+++ b/plc4go/spi/values/PlcLDATE.go
@@ -0,0 +1 @@
+package values
diff --git a/plc4go/spi/values/PlcLDATE_AND_TIME.go b/plc4go/spi/values/PlcLDATE_AND_TIME.go
new file mode 100644
index 0000000000..4cc8144e41
--- /dev/null
+++ b/plc4go/spi/values/PlcLDATE_AND_TIME.go
@@ -0,0 +1 @@
+package values
diff --git a/plc4go/spi/values/LINT.go b/plc4go/spi/values/PlcLINT.go
similarity index 99%
rename from plc4go/spi/values/LINT.go
rename to plc4go/spi/values/PlcLINT.go
index 13b210c989..3d0d559b0b 100644
--- a/plc4go/spi/values/LINT.go
+++ b/plc4go/spi/values/PlcLINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcLINT struct {
diff --git a/plc4go/spi/values/LREAL.go b/plc4go/spi/values/PlcLREAL.go
similarity index 99%
rename from plc4go/spi/values/LREAL.go
rename to plc4go/spi/values/PlcLREAL.go
index a050803dda..846929e033 100644
--- a/plc4go/spi/values/LREAL.go
+++ b/plc4go/spi/values/PlcLREAL.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"math"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"math"
 )
 
 type PlcLREAL struct {
diff --git a/plc4go/spi/values/LTIME.go b/plc4go/spi/values/PlcLTIME.go
similarity index 99%
rename from plc4go/spi/values/LTIME.go
rename to plc4go/spi/values/PlcLTIME.go
index 2424254786..5654dbfebd 100644
--- a/plc4go/spi/values/LTIME.go
+++ b/plc4go/spi/values/PlcLTIME.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"time"
 )
 
 type PlcLTIME struct {
diff --git a/plc4go/spi/values/PlcLTIME_OF_DAY.go b/plc4go/spi/values/PlcLTIME_OF_DAY.go
new file mode 100644
index 0000000000..4cc8144e41
--- /dev/null
+++ b/plc4go/spi/values/PlcLTIME_OF_DAY.go
@@ -0,0 +1 @@
+package values
diff --git a/plc4go/spi/values/LWORD.go b/plc4go/spi/values/PlcLWORD.go
similarity index 99%
rename from plc4go/spi/values/LWORD.go
rename to plc4go/spi/values/PlcLWORD.go
index a504a3330f..aec6c88e63 100644
--- a/plc4go/spi/values/LWORD.go
+++ b/plc4go/spi/values/PlcLWORD.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/PlcList.go b/plc4go/spi/values/PlcList.go
index e2f77255b7..a09b1769c4 100644
--- a/plc4go/spi/values/PlcList.go
+++ b/plc4go/spi/values/PlcList.go
@@ -22,12 +22,13 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"strings"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
-	"strings"
-	"time"
 )
 
 type PlcList struct {
@@ -204,7 +205,7 @@ func (m PlcList) GetStruct() map[string]apiValues.PlcValue {
 ///
 
 func (m PlcList) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.LIST
+	return apiValues.List
 }
 
 func (m PlcList) Serialize() ([]byte, error) {
diff --git a/plc4go/spi/values/NULL.go b/plc4go/spi/values/PlcNull.go
similarity index 83%
rename from plc4go/spi/values/NULL.go
rename to plc4go/spi/values/PlcNull.go
index abe6125823..b5d5abe2ea 100644
--- a/plc4go/spi/values/NULL.go
+++ b/plc4go/spi/values/PlcNull.go
@@ -21,25 +21,26 @@ package values
 
 import (
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 )
 
-type PlcNULL struct {
+type PlcNull struct {
 	PlcValueAdapter
 }
 
-func NewPlcNULL() PlcNULL {
-	return PlcNULL{}
+func NewPlcNULL() PlcNull {
+	return PlcNull{}
 }
 
-func (m PlcNULL) GetRaw() []byte {
+func (m PlcNull) GetRaw() []byte {
 	return []byte{}
 }
 
-func (m PlcNULL) GetPlcValueType() apiValues.PlcValueType {
+func (m PlcNull) GetPlcValueType() apiValues.PlcValueType {
 	return apiValues.NULL
 }
 
-func (m PlcNULL) String() string {
+func (m PlcNull) String() string {
 	return fmt.Sprintf("%s", m.GetPlcValueType())
 }
diff --git a/plc4go/spi/values/REAL.go b/plc4go/spi/values/PlcREAL.go
similarity index 99%
rename from plc4go/spi/values/REAL.go
rename to plc4go/spi/values/PlcREAL.go
index c66e1345c7..56ee2df6fe 100644
--- a/plc4go/spi/values/REAL.go
+++ b/plc4go/spi/values/PlcREAL.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"math"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"math"
 )
 
 type PlcREAL struct {
diff --git a/plc4go/spi/values/PlcByteArray.go b/plc4go/spi/values/PlcRawByteArray.go
similarity index 98%
rename from plc4go/spi/values/PlcByteArray.go
rename to plc4go/spi/values/PlcRawByteArray.go
index 6882e4c65d..b77e22d843 100644
--- a/plc4go/spi/values/PlcByteArray.go
+++ b/plc4go/spi/values/PlcRawByteArray.go
@@ -21,6 +21,7 @@ package values
 
 import (
 	"encoding/binary"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
@@ -61,7 +62,7 @@ func (m PlcByteArray) GetList() []apiValues.PlcValue {
 }
 
 func (m PlcByteArray) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.BYTE_ARRAY
+	return apiValues.RAW_BYTE_ARRAY
 }
 
 func (m PlcByteArray) Serialize() ([]byte, error) {
diff --git a/plc4go/spi/values/SINT.go b/plc4go/spi/values/PlcSINT.go
similarity index 99%
rename from plc4go/spi/values/SINT.go
rename to plc4go/spi/values/PlcSINT.go
index bf0de7dced..d643d4d420 100644
--- a/plc4go/spi/values/SINT.go
+++ b/plc4go/spi/values/PlcSINT.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"strconv"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"strconv"
 )
 
 type PlcSINT struct {
diff --git a/plc4go/spi/values/STRING.go b/plc4go/spi/values/PlcSTRING.go
similarity index 99%
rename from plc4go/spi/values/STRING.go
rename to plc4go/spi/values/PlcSTRING.go
index 1699b32683..94b3443488 100644
--- a/plc4go/spi/values/STRING.go
+++ b/plc4go/spi/values/PlcSTRING.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/PlcStruct.go b/plc4go/spi/values/PlcStruct.go
index 10d42a1d23..6a65e31088 100644
--- a/plc4go/spi/values/PlcStruct.go
+++ b/plc4go/spi/values/PlcStruct.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"strings"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/pkg/errors"
-	"strings"
 )
 
 type PlcStruct struct {
@@ -84,7 +85,7 @@ func (m PlcStruct) GetString() string {
 }
 
 func (m PlcStruct) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.STRUCT
+	return apiValues.Struct
 }
 
 func (m PlcStruct) Serialize() ([]byte, error) {
diff --git a/plc4go/spi/values/TIME.go b/plc4go/spi/values/PlcTIME.go
similarity index 99%
rename from plc4go/spi/values/TIME.go
rename to plc4go/spi/values/PlcTIME.go
index 0cff5a9ac6..3ef2f2844f 100644
--- a/plc4go/spi/values/TIME.go
+++ b/plc4go/spi/values/PlcTIME.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"time"
 )
 
 type PlcTIME struct {
diff --git a/plc4go/spi/values/TIME_OF_DAY.go b/plc4go/spi/values/PlcTIME_OF_DAY.go
similarity index 99%
rename from plc4go/spi/values/TIME_OF_DAY.go
rename to plc4go/spi/values/PlcTIME_OF_DAY.go
index 9a5c71ee31..1b84b7ae89 100644
--- a/plc4go/spi/values/TIME_OF_DAY.go
+++ b/plc4go/spi/values/PlcTIME_OF_DAY.go
@@ -22,9 +22,10 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+	"time"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
-	"time"
 )
 
 type PlcTIME_OF_DAY struct {
diff --git a/plc4go/spi/values/UDINT.go b/plc4go/spi/values/PlcUDINT.go
similarity index 99%
rename from plc4go/spi/values/UDINT.go
rename to plc4go/spi/values/PlcUDINT.go
index 99801147ab..7ab5cdd647 100644
--- a/plc4go/spi/values/UDINT.go
+++ b/plc4go/spi/values/PlcUDINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcUDINT struct {
diff --git a/plc4go/spi/values/UINT.go b/plc4go/spi/values/PlcUINT.go
similarity index 99%
rename from plc4go/spi/values/UINT.go
rename to plc4go/spi/values/PlcUINT.go
index dbd13f8e64..e5c31250ea 100644
--- a/plc4go/spi/values/UINT.go
+++ b/plc4go/spi/values/PlcUINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcUINT struct {
diff --git a/plc4go/spi/values/ULINT.go b/plc4go/spi/values/PlcULINT.go
similarity index 99%
rename from plc4go/spi/values/ULINT.go
rename to plc4go/spi/values/PlcULINT.go
index a81d8dcf61..85b60cd99b 100644
--- a/plc4go/spi/values/ULINT.go
+++ b/plc4go/spi/values/PlcULINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcULINT struct {
diff --git a/plc4go/spi/values/USINT.go b/plc4go/spi/values/PlcUSINT.go
similarity index 99%
rename from plc4go/spi/values/USINT.go
rename to plc4go/spi/values/PlcUSINT.go
index fc66e94a3f..315b6a1362 100644
--- a/plc4go/spi/values/USINT.go
+++ b/plc4go/spi/values/PlcUSINT.go
@@ -22,10 +22,11 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"math"
 	"strconv"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
 type PlcUSINT struct {
diff --git a/plc4go/spi/values/IEC61131ValueHandler.go b/plc4go/spi/values/PlcValueHandler.go
similarity index 100%
rename from plc4go/spi/values/IEC61131ValueHandler.go
rename to plc4go/spi/values/PlcValueHandler.go
diff --git a/plc4go/spi/values/WCHAR.go b/plc4go/spi/values/PlcWCHAR.go
similarity index 99%
rename from plc4go/spi/values/WCHAR.go
rename to plc4go/spi/values/PlcWCHAR.go
index 530e799217..4f66e441ab 100644
--- a/plc4go/spi/values/WCHAR.go
+++ b/plc4go/spi/values/PlcWCHAR.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/WORD.go b/plc4go/spi/values/PlcWORD.go
similarity index 99%
rename from plc4go/spi/values/WORD.go
rename to plc4go/spi/values/PlcWORD.go
index b169bccc2a..af15cc3a88 100644
--- a/plc4go/spi/values/WORD.go
+++ b/plc4go/spi/values/PlcWORD.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/WSTRING.go b/plc4go/spi/values/PlcWSTRING.go
similarity index 99%
rename from plc4go/spi/values/WSTRING.go
rename to plc4go/spi/values/PlcWSTRING.go
index 71dfe3003d..2a4c77bea4 100644
--- a/plc4go/spi/values/WSTRING.go
+++ b/plc4go/spi/values/PlcWSTRING.go
@@ -22,6 +22,7 @@ package values
 import (
 	"encoding/binary"
 	"fmt"
+
 	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
diff --git a/plc4go/spi/values/RawPlcValue.go b/plc4go/spi/values/RawPlcValue.go
deleted file mode 100644
index 30b7bc3df4..0000000000
--- a/plc4go/spi/values/RawPlcValue.go
+++ /dev/null
@@ -1,92 +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 values
-
-import (
-	"encoding/hex"
-	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-)
-
-type PlcValueDecoder interface {
-	Decode(typeName string) apiValues.PlcValue
-}
-
-type RawPlcValue struct {
-	PlcValueAdapter
-	readBuffer utils.ReadBuffer
-	decoder    PlcValueDecoder
-}
-
-func NewRawPlcValue(readBuffer utils.ReadBuffer, decoder PlcValueDecoder) RawPlcValue {
-	return RawPlcValue{
-		readBuffer: readBuffer,
-		decoder:    decoder,
-	}
-}
-
-func (m RawPlcValue) GetRaw() []byte {
-	return m.readBuffer.(utils.ReadBufferByteBased).GetBytes()
-}
-
-func (m RawPlcValue) IsList() bool {
-	return true
-}
-
-func (m RawPlcValue) GetLength() uint32 {
-	return uint32(m.readBuffer.(utils.ReadBufferByteBased).GetTotalBytes())
-}
-
-func (m RawPlcValue) GetIndex(i uint32) apiValues.PlcValue {
-	return NewPlcUSINT(m.readBuffer.(utils.ReadBufferByteBased).GetBytes()[i])
-}
-
-func (m RawPlcValue) GetList() []apiValues.PlcValue {
-	var plcValues []apiValues.PlcValue
-	for _, value := range m.readBuffer.(utils.ReadBufferByteBased).GetBytes() {
-		plcValues = append(plcValues, NewPlcUSINT(value))
-	}
-	return plcValues
-}
-
-func (m RawPlcValue) RawDecodeValue(typeName string) apiValues.PlcValue {
-	return m.decoder.Decode(typeName)
-}
-
-func (m RawPlcValue) RawHasMore() bool {
-	return m.readBuffer.HasMore(1)
-}
-
-func (m RawPlcValue) RawReset() {
-	m.readBuffer.(utils.ReadBufferByteBased).Reset(0)
-}
-
-func (m RawPlcValue) GetString() string {
-	return hex.EncodeToString(m.GetRaw())
-}
-
-func (m RawPlcValue) GetPlcValueType() apiValues.PlcValueType {
-	return apiValues.RAW_PLC_VALUE
-}
-
-func (m RawPlcValue) String() string {
-	return fmt.Sprintf("%s", m.GetPlcValueType())
-}
diff --git a/plc4go/spi/values/value_combination_test.go b/plc4go/spi/values/value_combination_test.go
index b913a1d3c1..1b5378028f 100644
--- a/plc4go/spi/values/value_combination_test.go
+++ b/plc4go/spi/values/value_combination_test.go
@@ -21,15 +21,15 @@ package values
 
 import (
 	"fmt"
-	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-	"github.com/stretchr/testify/assert"
 	"math"
-	"math/big"
 	"reflect"
 	"strings"
 	"testing"
 	"time"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi/utils"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestCombinations(t *testing.T) {
@@ -37,7 +37,7 @@ func TestCombinations(t *testing.T) {
 		name      apiValues.PlcValueType
 		arguments []apiValues.PlcValue
 	}{
-		{
+		/*{
 			name: apiValues.BINT,
 			arguments: []apiValues.PlcValue{
 				NewPlcBINT(big.NewInt(0)),
@@ -46,7 +46,7 @@ func TestCombinations(t *testing.T) {
 				NewPlcBINT(big.NewInt(math.MinInt64)),
 				NewPlcBINT(big.NewInt(math.MaxInt64)),
 			},
-		},
+		},*/
 		{
 			name: apiValues.BOOL,
 			arguments: []apiValues.PlcValue{
@@ -54,7 +54,7 @@ func TestCombinations(t *testing.T) {
 				NewPlcBOOL(false),
 			},
 		},
-		{
+		/*{
 			name: apiValues.BREAL,
 			arguments: []apiValues.PlcValue{
 				NewPlcBREAL(big.NewFloat(0)),
@@ -63,7 +63,7 @@ func TestCombinations(t *testing.T) {
 				NewPlcBREAL(big.NewFloat(math.MinInt64)),
 				NewPlcBREAL(big.NewFloat(math.MaxInt64)),
 			},
-		},
+		},*/
 		{
 			name: apiValues.BYTE,
 			arguments: []apiValues.PlcValue{
@@ -127,7 +127,7 @@ func TestCombinations(t *testing.T) {
 			},
 		},
 		{
-			name: apiValues.LIST,
+			name: apiValues.List,
 			arguments: []apiValues.PlcValue{
 				NewPlcList(nil),
 				NewPlcList([]apiValues.PlcValue{
@@ -172,7 +172,7 @@ func TestCombinations(t *testing.T) {
 			},
 		},
 		{
-			name: apiValues.RAW_PLC_VALUE,
+			name: apiValues.RAW_BYTE_ARRAY,
 			arguments: []apiValues.PlcValue{
 				NewRawPlcValue(utils.NewReadBufferByteBased([]byte{0x47, 0x11}), nil),
 			},
@@ -187,7 +187,7 @@ func TestCombinations(t *testing.T) {
 			},
 		},
 		{
-			name: apiValues.STRUCT,
+			name: apiValues.Struct,
 			arguments: []apiValues.PlcValue{
 				NewPlcStruct(map[string]apiValues.PlcValue{
 					"something": NewPlcStruct(map[string]apiValues.PlcValue{
diff --git a/protocols/eip/src/main/resources/protocols/eip/eip.mspec b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
index 27f1023267..37e4369d0c 100644
--- a/protocols/eip/src/main/resources/protocols/eip/eip.mspec
+++ b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
@@ -122,7 +122,7 @@
     ['0X00C5'   LINT            ['8']]
     ['0X00CA'   REAL            ['4']]
     ['0X00D3'   DWORD           ['4']]
-    ['0X02A0'   STRUCTURED      ['88']]
+    ['0X02A0'   Struct          ['88']]
     ['0X02A0'   STRING          ['88']]
     //['0X02A0'   STRING36        ['40']]
     //TODO: -1 is not a valid value for uint