You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/08/18 12:27:46 UTC

[plc4x] 02/02: feat(plc4go/cbus): implemented value handler for writes

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

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

commit 96a452e4d539595a388818c4a0be3ddc9d5a44f7
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Aug 18 14:27:37 2022 +0200

    feat(plc4go/cbus): implemented value handler for writes
---
 plc4go/internal/cbus/CBusMessageFactory.go |  22 ++---
 plc4go/internal/cbus/FieldHandler.go       |  91 +++++++++++++------
 plc4go/internal/cbus/ValueHandler.go       | 141 ++++++++++++++++++++++++++++-
 plc4go/internal/cbus/fieldtype_string.go   |  23 +++--
 plc4go/spi/values/IEC61131ValueHandler.go  |  11 +--
 5 files changed, 226 insertions(+), 62 deletions(-)

diff --git a/plc4go/internal/cbus/CBusMessageFactory.go b/plc4go/internal/cbus/CBusMessageFactory.go
index 1b8cb1811..a66038424 100644
--- a/plc4go/internal/cbus/CBusMessageFactory.go
+++ b/plc4go/internal/cbus/CBusMessageFactory.go
@@ -104,8 +104,14 @@ func FieldToCBusMessage(field model.PlcField, value values.PlcValue, alphaGenera
 			salData = readWriteModel.NewSALDataTemperatureBroadcast(temperatureBroadcastData, nil)
 		case readWriteModel.ApplicationId_ROOM_CONTROL_SYSTEM:
 			panic("Implement me")
-		case readWriteModel.ApplicationId_LIGHTING:
-			// TODO: is this more are write?? maybe we a wrong here at the reader
+		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:
 			var lightingData readWriteModel.LightingData
 			switch salCommand {
 			case readWriteModel.LightingCommandType_OFF.PLC4XEnumName():
@@ -154,22 +160,12 @@ func FieldToCBusMessage(field model.PlcField, value values.PlcValue, alphaGenera
 				return nil, false, false, false, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
 			}
 			salData = readWriteModel.NewSALDataLighting(lightingData, nil)
-		case readWriteModel.ApplicationId_VENTILATION:
-			panic("Implement me")
-		case readWriteModel.ApplicationId_IRRIGATION_CONTROL:
-			panic("Implement me")
-		case readWriteModel.ApplicationId_POOLS_SPAS_PONDS_FOUNTAINS_CONTROL:
-			panic("Implement me")
-		case readWriteModel.ApplicationId_HEATING:
-			panic("Implement me")
 		case readWriteModel.ApplicationId_AIR_CONDITIONING:
 			panic("Implement me")
 		case readWriteModel.ApplicationId_TRIGGER_CONTROL:
 			panic("Implement me")
 		case readWriteModel.ApplicationId_ENABLE_CONTROL:
 			panic("Implement me")
-		case readWriteModel.ApplicationId_AUDIO_AND_VIDEO:
-			panic("Implement me")
 		case readWriteModel.ApplicationId_SECURITY:
 			panic("Implement me")
 		case readWriteModel.ApplicationId_METERING:
@@ -188,8 +184,6 @@ func FieldToCBusMessage(field model.PlcField, value values.PlcValue, alphaGenera
 			panic("Implement me")
 		case readWriteModel.ApplicationId_ERROR_REPORTING:
 			panic("Implement me")
-		case readWriteModel.ApplicationId_HVAC_ACTUATOR:
-			panic("Implement me")
 		default:
 			return nil, false, false, false, errors.Errorf("No support for %s", field.application)
 		}
diff --git a/plc4go/internal/cbus/FieldHandler.go b/plc4go/internal/cbus/FieldHandler.go
index adfdff9e0..62766c183 100644
--- a/plc4go/internal/cbus/FieldHandler.go
+++ b/plc4go/internal/cbus/FieldHandler.go
@@ -36,9 +36,19 @@ type FieldType uint8
 //go:generate stringer -type FieldType
 const (
 	STATUS FieldType = iota
+	// TODO: implement
+	CAL_RESET
 	CAL_RECALL
 	CAL_IDENTIFY
 	CAL_GETSTATUS
+	// TODO: implement
+	CAL_WRITE
+	// TODO: implement
+	CAL_IDENTIFY_REPLY
+	// TODO: implement
+	CAL_STATUS
+	// TODO: implement
+	CAL_STATUS_EXTENDED
 	SAL
 	SAL_MONITOR
 	MMI_STATUS_MONITOR
@@ -61,7 +71,7 @@ type FieldHandler struct {
 func NewFieldHandler() FieldHandler {
 	return FieldHandler{
 		statusRequestPattern: regexp.MustCompile(`^status/(?P<statusRequestType>(?P<binary>binary)|level=0x(?P<startingGroupAddressLabel>00|20|40|60|80|A0|C0|E0))/(?P<application>.*)`),
-		calPattern:           regexp.MustCompile(`^cal/(?P<unitAddress>.+)/(?P<calType>recall=\[(?P<recallParamNo>\w+), ?(?P<recallCount>\d+)]|identify=(?P<identifyAttribute>\w+)|getstatus=(?P<getstatusParamNo>\w+), ?(?P<getstatusCount>\d+))`),
+		calPattern:           regexp.MustCompile(`^cal/(?P<unitAddress>.+)/(?P<calType>reset|recall=\[(?P<recallParamNo>\w+), ?(?P<recallCount>\d+)]|identify=(?P<identifyAttribute>\w+), ?(?P<getstatusCount>\d+)|getstatus=(?P<getstatusParamNo>\w+)|write=\[(?P<writeParamNo>\w+), ?(?P<writeCode>0[xX][0-9a-fA-F][0-9a-fA-F])]|identifyReply=(?P<replyAttribute>\w+)|reply=(?P<replyParamNo>\w+)|status=(?P<statusApplication>.*)|statusExtended=(?P<statusExtendedApplication>.*))`),
 		salPattern:           regexp.MustCompile(`^sal/(?P<application>.*)/(?P<salCommand>.*)`),
 		salMonitorPattern:    regexp.MustCompile(`^salmonitor/(?P<unitAddress>.+)/(?P<application>.+)`),
 		mmiMonitorPattern:    regexp.MustCompile(`^mmimonitor/(?P<unitAddress>.+)/(?P<application>.+)`),
@@ -69,38 +79,36 @@ func NewFieldHandler() FieldHandler {
 	}
 }
 
-func ms2s[T fmt.Stringer](t []T) []string {
-	result := make([]string, len(t))
-	for i, stringer := range t {
-		result[i] = stringer.String()
-	}
-	return result
+type CommandAndArgumentsCount interface {
+	fmt.Stringer
+	PLC4XEnumName() string
+	NumberOfArguments() uint8
 }
 
-var PossibleSalCommands = map[readWriteModel.ApplicationId][]string{
+var PossibleSalCommands = map[readWriteModel.ApplicationId][]CommandAndArgumentsCount{
 	readWriteModel.ApplicationId_RESERVED:                           nil, // TODO: Not yet implemented
 	readWriteModel.ApplicationId_FREE_USAGE:                         nil, // TODO: Not yet implemented
-	readWriteModel.ApplicationId_TEMPERATURE_BROADCAST:              ms2s(readWriteModel.TemperatureBroadcastCommandTypeValues),
+	readWriteModel.ApplicationId_TEMPERATURE_BROADCAST:              c2nl(readWriteModel.TemperatureBroadcastCommandTypeValues),
 	readWriteModel.ApplicationId_ROOM_CONTROL_SYSTEM:                nil, // TODO: Not yet implemented
-	readWriteModel.ApplicationId_LIGHTING:                           ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_VENTILATION:                        ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_IRRIGATION_CONTROL:                 ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_POOLS_SPAS_PONDS_FOUNTAINS_CONTROL: ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_HEATING:                            ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_AIR_CONDITIONING:                   ms2s(readWriteModel.AirConditioningCommandTypeValues),
-	readWriteModel.ApplicationId_TRIGGER_CONTROL:                    ms2s(readWriteModel.TriggerControlCommandTypeValues),
-	readWriteModel.ApplicationId_ENABLE_CONTROL:                     ms2s(readWriteModel.EnableControlCommandTypeValues),
-	readWriteModel.ApplicationId_AUDIO_AND_VIDEO:                    ms2s(readWriteModel.LightingCommandTypeValues),
-	readWriteModel.ApplicationId_SECURITY:                           ms2s(readWriteModel.SecurityCommandTypeValues),
-	readWriteModel.ApplicationId_METERING:                           ms2s(readWriteModel.MeteringCommandTypeValues),
-	readWriteModel.ApplicationId_ACCESS_CONTROL:                     ms2s(readWriteModel.AccessControlCommandTypeValues),
-	readWriteModel.ApplicationId_CLOCK_AND_TIMEKEEPING:              ms2s(readWriteModel.ClockAndTimekeepingCommandTypeValues),
-	readWriteModel.ApplicationId_TELEPHONY_STATUS_AND_CONTROL:       ms2s(readWriteModel.TelephonyCommandTypeValues),
-	readWriteModel.ApplicationId_MEASUREMENT:                        ms2s(readWriteModel.MeasurementCommandTypeValues),
+	readWriteModel.ApplicationId_LIGHTING:                           c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_VENTILATION:                        c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_IRRIGATION_CONTROL:                 c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_POOLS_SPAS_PONDS_FOUNTAINS_CONTROL: c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_HEATING:                            c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_AIR_CONDITIONING:                   c2nl(readWriteModel.AirConditioningCommandTypeValues),
+	readWriteModel.ApplicationId_TRIGGER_CONTROL:                    c2nl(readWriteModel.TriggerControlCommandTypeValues),
+	readWriteModel.ApplicationId_ENABLE_CONTROL:                     c2nl(readWriteModel.EnableControlCommandTypeValues),
+	readWriteModel.ApplicationId_AUDIO_AND_VIDEO:                    c2nl(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_SECURITY:                           c2nl(readWriteModel.SecurityCommandTypeValues),
+	readWriteModel.ApplicationId_METERING:                           c2nl(readWriteModel.MeteringCommandTypeValues),
+	readWriteModel.ApplicationId_ACCESS_CONTROL:                     c2nl(readWriteModel.AccessControlCommandTypeValues),
+	readWriteModel.ApplicationId_CLOCK_AND_TIMEKEEPING:              c2nl(readWriteModel.ClockAndTimekeepingCommandTypeValues),
+	readWriteModel.ApplicationId_TELEPHONY_STATUS_AND_CONTROL:       c2nl(readWriteModel.TelephonyCommandTypeValues),
+	readWriteModel.ApplicationId_MEASUREMENT:                        c2nl(readWriteModel.MeasurementCommandTypeValues),
 	readWriteModel.ApplicationId_TESTING:                            nil, // TODO: Not yet implemented
-	readWriteModel.ApplicationId_MEDIA_TRANSPORT_CONTROL:            ms2s(readWriteModel.MediaTransportControlCommandTypeValues),
-	readWriteModel.ApplicationId_ERROR_REPORTING:                    ms2s(readWriteModel.ErrorReportingCommandTypeValues),
-	readWriteModel.ApplicationId_HVAC_ACTUATOR:                      ms2s(readWriteModel.LightingCommandTypeValues),
+	readWriteModel.ApplicationId_MEDIA_TRANSPORT_CONTROL:            c2nl(readWriteModel.MediaTransportControlCommandTypeValues),
+	readWriteModel.ApplicationId_ERROR_REPORTING:                    c2nl(readWriteModel.ErrorReportingCommandTypeValues),
+	readWriteModel.ApplicationId_HVAC_ACTUATOR:                      c2nl(readWriteModel.LightingCommandTypeValues),
 }
 
 func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
@@ -169,6 +177,8 @@ func (m FieldHandler) handleCalPattern(match map[string]string) (model.PlcField,
 
 	calTypeArgument := match["calType"]
 	switch {
+	case strings.HasPrefix(calTypeArgument, "reset"):
+		panic("Not implemented") // TODO: implement me
 	case strings.HasPrefix(calTypeArgument, "recall="):
 		var recalParamNo readWriteModel.Parameter
 		recallParamNoArgument := match["recallParamNo"]
@@ -254,6 +264,16 @@ func (m FieldHandler) handleCalPattern(match map[string]string) (model.PlcField,
 		}
 		count = uint8(atoi)
 		return NewCALGetstatusField(unitAddress, recalParamNo, count, 1), nil
+	case strings.HasPrefix(calTypeArgument, "write="):
+		panic("Not implemented") // TODO: implement me
+	case strings.HasPrefix(calTypeArgument, "identifyReply="):
+		panic("Not implemented") // TODO: implement me
+	case strings.HasPrefix(calTypeArgument, "reply="):
+		panic("Not implemented") // TODO: implement me
+	case strings.HasPrefix(calTypeArgument, "status="):
+		panic("Not implemented") // TODO: implement me
+	case strings.HasPrefix(calTypeArgument, "statusExtended="):
+		panic("Not implemented") // TODO: implement me
 	default:
 		return nil, errors.Errorf("Invalid cal type %s", calTypeArgument)
 	}
@@ -269,13 +289,18 @@ func (m FieldHandler) handleSALPattern(match map[string]string) (model.PlcField,
 		return nil, errors.Wrap(err, "Error getting salCommand from argument")
 	}
 	isValid := false
+	numElements := uint16(0)
 	for _, request := range PossibleSalCommands[application.ApplicationId()] {
-		isValid = isValid || strings.HasPrefix(salCommand, request)
+		if salCommand == request.PLC4XEnumName() {
+			isValid = true
+			numElements = uint16(request.NumberOfArguments())
+			break
+		}
 	}
 	if !isValid {
 		return nil, errors.Errorf("Invalid sal command %s for %s. Allowed requests: %s", salCommand, application, PossibleSalCommands[application.ApplicationId()])
 	}
-	return NewSALField(application, salCommand, 1), nil
+	return NewSALField(application, salCommand, numElements), nil
 }
 
 func (m FieldHandler) handleSALMonitorPattern(match map[string]string) (model.PlcField, error) {
@@ -490,3 +515,11 @@ func applicationIdFromArgument(applicationIdArgument string) (readWriteModel.App
 		return applicationIdByName, nil
 	}
 }
+
+func c2nl[T CommandAndArgumentsCount](t []T) []CommandAndArgumentsCount {
+	result := make([]CommandAndArgumentsCount, len(t))
+	for i, e := range t {
+		result[i] = e
+	}
+	return result
+}
diff --git a/plc4go/internal/cbus/ValueHandler.go b/plc4go/internal/cbus/ValueHandler.go
index 6c7a65fbb..7524a71ae 100644
--- a/plc4go/internal/cbus/ValueHandler.go
+++ b/plc4go/internal/cbus/ValueHandler.go
@@ -20,13 +20,150 @@
 package cbus
 
 import (
-	"github.com/apache/plc4x/plc4go/spi/values"
+	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 {
-	values.IEC61131ValueHandler
+	spiValues.IEC61131ValueHandler
 }
 
 func NewValueHandler() ValueHandler {
 	return 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")
+	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()
+			}
+		} else {
+			curValues = append(curValues, value)
+		}
+
+		field := field.(*salField)
+		salCommand := field.salCommand
+		switch field.application.ApplicationId() {
+		case readWriteModel.ApplicationId_FREE_USAGE:
+			panic("Not yet implemented") // TODO: implement
+		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())
+			}
+		case readWriteModel.ApplicationId_ROOM_CONTROL_SYSTEM:
+			panic("Implement me")
+		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")
+			default:
+				return nil, errors.Errorf("Unsupported command %s for %s", salCommand, field.application.ApplicationId())
+			}
+		case readWriteModel.ApplicationId_AIR_CONDITIONING:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_TRIGGER_CONTROL:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_ENABLE_CONTROL:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_SECURITY:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_METERING:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_ACCESS_CONTROL:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_CLOCK_AND_TIMEKEEPING:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_TELEPHONY_STATUS_AND_CONTROL:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_MEASUREMENT:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_TESTING:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_MEDIA_TRANSPORT_CONTROL:
+			panic("Implement me")
+		case readWriteModel.ApplicationId_ERROR_REPORTING:
+			panic("Implement me")
+		default:
+			return nil, errors.Errorf("No support for %s", field.application)
+		}
+	}
+	return m.IEC61131ValueHandler.NewPlcValue(field, value)
+}
diff --git a/plc4go/internal/cbus/fieldtype_string.go b/plc4go/internal/cbus/fieldtype_string.go
index 8e2831e00..8ce7ef761 100644
--- a/plc4go/internal/cbus/fieldtype_string.go
+++ b/plc4go/internal/cbus/fieldtype_string.go
@@ -26,18 +26,23 @@ func _() {
 	// Re-run the stringer command to generate them again.
 	var x [1]struct{}
 	_ = x[STATUS-0]
-	_ = x[CAL_RECALL-1]
-	_ = x[CAL_IDENTIFY-2]
-	_ = x[CAL_GETSTATUS-3]
-	_ = x[SAL-4]
-	_ = x[SAL_MONITOR-5]
-	_ = x[MMI_STATUS_MONITOR-6]
-	_ = x[UNIT_INFO-7]
+	_ = x[CAL_RESET-1]
+	_ = x[CAL_RECALL-2]
+	_ = x[CAL_IDENTIFY-3]
+	_ = x[CAL_GETSTATUS-4]
+	_ = x[CAL_WRITE-5]
+	_ = x[CAL_IDENTIFY_REPLY-6]
+	_ = x[CAL_STATUS-7]
+	_ = x[CAL_STATUS_EXTENDED-8]
+	_ = x[SAL-9]
+	_ = x[SAL_MONITOR-10]
+	_ = x[MMI_STATUS_MONITOR-11]
+	_ = x[UNIT_INFO-12]
 }
 
-const _FieldType_name = "STATUSCAL_RECALLCAL_IDENTIFYCAL_GETSTATUSSALSAL_MONITORMMI_STATUS_MONITORUNIT_INFO"
+const _FieldType_name = "STATUSCAL_RESETCAL_RECALLCAL_IDENTIFYCAL_GETSTATUSCAL_WRITECAL_IDENTIFY_REPLYCAL_STATUSCAL_STATUS_EXTENDEDSALSAL_MONITORMMI_STATUS_MONITORUNIT_INFO"
 
-var _FieldType_index = [...]uint8{0, 6, 16, 28, 41, 44, 55, 73, 82}
+var _FieldType_index = [...]uint8{0, 6, 15, 25, 37, 50, 59, 77, 87, 106, 109, 120, 138, 147}
 
 func (i FieldType) String() string {
 	if i >= FieldType(len(_FieldType_index)-1) {
diff --git a/plc4go/spi/values/IEC61131ValueHandler.go b/plc4go/spi/values/IEC61131ValueHandler.go
index 3872d74db..4a41f5e5f 100644
--- a/plc4go/spi/values/IEC61131ValueHandler.go
+++ b/plc4go/spi/values/IEC61131ValueHandler.go
@@ -86,10 +86,6 @@ const (
 type IEC61131ValueHandler struct {
 }
 
-func NewIEC61131ValueHandler() IEC61131ValueHandler {
-	return IEC61131ValueHandler{}
-}
-
 func (m IEC61131ValueHandler) NewPlcValue(field model.PlcField, value interface{}) (values.PlcValue, error) {
 	typeName := field.GetTypeName()
 	quantity := field.GetQuantity()
@@ -110,7 +106,7 @@ func (m IEC61131ValueHandler) NewPlcValue(field model.PlcField, value interface{
 		var plcValues []values.PlcValue
 		for i := uint16(0); i < quantity; i++ {
 			curValue := curValues[i]
-			plcValue, err := m.newPlcValue(typeName, 1, curValue)
+			plcValue, err := m.NewPlcValueFromType(typeName, curValue)
 			if err != nil {
 				return nil, errors.New("error parsing PlcValue: " + err.Error())
 			}
@@ -118,11 +114,10 @@ func (m IEC61131ValueHandler) NewPlcValue(field model.PlcField, value interface{
 		}
 		return NewPlcList(plcValues), nil
 	}
-	return m.newPlcValue(typeName, 1, value)
+	return m.NewPlcValueFromType(typeName, value)
 }
 
-func (m IEC61131ValueHandler) newPlcValue(typeName string, quantity uint16, value interface{}) (values.PlcValue, error) {
-
+func (m IEC61131ValueHandler) NewPlcValueFromType(typeName string, value interface{}) (values.PlcValue, error) {
 	stringValue, isString := value.(string)
 	switch typeName {
 	// Bit & Bit-Strings