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/07/15 15:17:36 UTC

[plc4x] 02/03: feat(cbus): added support for lighting label

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 e2f61c4a583fd90889d0ef66efb7b28d8299d46c
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Jul 15 16:51:36 2022 +0200

    feat(cbus): added support for lighting label
---
 plc4go/protocols/cbus/readwrite/ParserHelper.go    |   6 +
 plc4go/protocols/cbus/readwrite/XmlParserHelper.go |   8 +
 .../protocols/cbus/readwrite/model/LabelFlavour.go | 145 +++++
 .../protocols/cbus/readwrite/model/LabelOptions.go | 304 ++++++++++
 plc4go/protocols/cbus/readwrite/model/LabelType.go | 145 +++++
 plc4go/protocols/cbus/readwrite/model/Language.go  | 657 +++++++++++++++++++++
 .../cbus/readwrite/model/SALCommandType.go         |   8 +
 .../readwrite/model/SALCommandTypeContainer.go     | 607 +++++++++++++++++++
 plc4go/protocols/cbus/readwrite/model/SALData.go   |   2 +
 .../protocols/cbus/readwrite/model/SALDataLabel.go | 291 +++++++++
 .../protocols/cbus/readwrite/model/StaticHelper.go |  46 +-
 .../internal/cbusanalyzer/analyzer.go              |  44 +-
 plc4j/drivers/c-bus/pom.xml                        |   4 +
 .../java/cbus/readwrite/utils/StaticHelper.java    |  37 +-
 .../apache/plc4x/java/cbus/RandomPackagesTest.java | 212 +++++--
 .../src/main/resources/protocols/cbus/c-bus.mspec  | 241 ++++++--
 16 files changed, 2559 insertions(+), 198 deletions(-)

diff --git a/plc4go/protocols/cbus/readwrite/ParserHelper.go b/plc4go/protocols/cbus/readwrite/ParserHelper.go
index 43642eb94..19f19dbb9 100644
--- a/plc4go/protocols/cbus/readwrite/ParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/ParserHelper.go
@@ -37,6 +37,8 @@ func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.Re
 		return model.CALDataParse(io, requestContext)
 	case "ApplicationAddress2":
 		return model.ApplicationAddress2Parse(io)
+	case "LabelOptions":
+		return model.LabelOptionsParse(io)
 	case "ApplicationAddress1":
 		return model.ApplicationAddress1Parse(io)
 	case "Checksum":
@@ -143,6 +145,10 @@ func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.Re
 		return model.StatusHeaderParse(io)
 	case "StatusRequest":
 		return model.StatusRequestParse(io)
+	case "EncodedReply":
+		var cBusOptions model.CBusOptions
+		var requestContext model.RequestContext
+		return model.EncodedReplyParse(io, cBusOptions, requestContext)
 	case "InterfaceOptions3":
 		return model.InterfaceOptions3Parse(io)
 	case "InterfaceOptions1":
diff --git a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
index 874b1002d..a442d2109 100644
--- a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
@@ -48,6 +48,8 @@ func (m CbusXmlParserHelper) Parse(typeName string, xmlString string, parserArgu
 		return model.CALDataParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), requestContext)
 	case "ApplicationAddress2":
 		return model.ApplicationAddress2Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
+	case "LabelOptions":
+		return model.LabelOptionsParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ApplicationAddress1":
 		return model.ApplicationAddress1Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "Checksum":
@@ -166,6 +168,12 @@ func (m CbusXmlParserHelper) Parse(typeName string, xmlString string, parserArgu
 		return model.StatusHeaderParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "StatusRequest":
 		return model.StatusRequestParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
+	case "EncodedReply":
+		// TODO: find a way to parse the sub types
+		var cBusOptions model.CBusOptions
+		// TODO: find a way to parse the sub types
+		var requestContext model.RequestContext
+		return model.EncodedReplyParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), cBusOptions, requestContext)
 	case "InterfaceOptions3":
 		return model.InterfaceOptions3Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "InterfaceOptions1":
diff --git a/plc4go/protocols/cbus/readwrite/model/LabelFlavour.go b/plc4go/protocols/cbus/readwrite/model/LabelFlavour.go
new file mode 100644
index 000000000..ddf411e89
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/LabelFlavour.go
@@ -0,0 +1,145 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// LabelFlavour is an enum
+type LabelFlavour uint8
+
+type ILabelFlavour interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	LabelFlavour_FLAVOUR_1 LabelFlavour = 0
+	LabelFlavour_FLAVOUR_2 LabelFlavour = 1
+	LabelFlavour_FLAVOUR_3 LabelFlavour = 2
+	LabelFlavour_FLAVOUR_4 LabelFlavour = 3
+)
+
+var LabelFlavourValues []LabelFlavour
+
+func init() {
+	_ = errors.New
+	LabelFlavourValues = []LabelFlavour{
+		LabelFlavour_FLAVOUR_1,
+		LabelFlavour_FLAVOUR_2,
+		LabelFlavour_FLAVOUR_3,
+		LabelFlavour_FLAVOUR_4,
+	}
+}
+
+func LabelFlavourByValue(value uint8) (enum LabelFlavour, ok bool) {
+	switch value {
+	case 0:
+		return LabelFlavour_FLAVOUR_1, true
+	case 1:
+		return LabelFlavour_FLAVOUR_2, true
+	case 2:
+		return LabelFlavour_FLAVOUR_3, true
+	case 3:
+		return LabelFlavour_FLAVOUR_4, true
+	}
+	return 0, false
+}
+
+func LabelFlavourByName(value string) (enum LabelFlavour, ok bool) {
+	switch value {
+	case "FLAVOUR_1":
+		return LabelFlavour_FLAVOUR_1, true
+	case "FLAVOUR_2":
+		return LabelFlavour_FLAVOUR_2, true
+	case "FLAVOUR_3":
+		return LabelFlavour_FLAVOUR_3, true
+	case "FLAVOUR_4":
+		return LabelFlavour_FLAVOUR_4, true
+	}
+	return 0, false
+}
+
+func LabelFlavourKnows(value uint8) bool {
+	for _, typeValue := range LabelFlavourValues {
+		if uint8(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastLabelFlavour(structType interface{}) LabelFlavour {
+	castFunc := func(typ interface{}) LabelFlavour {
+		if sLabelFlavour, ok := typ.(LabelFlavour); ok {
+			return sLabelFlavour
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m LabelFlavour) GetLengthInBits() uint16 {
+	return 2
+}
+
+func (m LabelFlavour) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func LabelFlavourParse(readBuffer utils.ReadBuffer) (LabelFlavour, error) {
+	val, err := readBuffer.ReadUint8("LabelFlavour", 2)
+	if err != nil {
+		return 0, errors.Wrap(err, "error reading LabelFlavour")
+	}
+	if enum, ok := LabelFlavourByValue(val); !ok {
+		log.Debug().Msgf("no value %x found for RequestType", val)
+		return LabelFlavour(val), nil
+	} else {
+		return enum, nil
+	}
+}
+
+func (e LabelFlavour) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint8("LabelFlavour", 2, uint8(e), utils.WithAdditionalStringRepresentation(e.PLC4XEnumName()))
+}
+
+// PLC4XEnumName returns the name that is used in code to identify this enum
+func (e LabelFlavour) PLC4XEnumName() string {
+	switch e {
+	case LabelFlavour_FLAVOUR_1:
+		return "FLAVOUR_1"
+	case LabelFlavour_FLAVOUR_2:
+		return "FLAVOUR_2"
+	case LabelFlavour_FLAVOUR_3:
+		return "FLAVOUR_3"
+	case LabelFlavour_FLAVOUR_4:
+		return "FLAVOUR_4"
+	}
+	return ""
+}
+
+func (e LabelFlavour) String() string {
+	return e.PLC4XEnumName()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/LabelOptions.go b/plc4go/protocols/cbus/readwrite/model/LabelOptions.go
new file mode 100644
index 000000000..846bdce16
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/LabelOptions.go
@@ -0,0 +1,304 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// LabelOptions is the corresponding interface of LabelOptions
+type LabelOptions interface {
+	utils.LengthAware
+	utils.Serializable
+	// GetLabelFlavour returns LabelFlavour (property field)
+	GetLabelFlavour() LabelFlavour
+	// GetLabelType returns LabelType (property field)
+	GetLabelType() LabelType
+}
+
+// LabelOptionsExactly can be used when we want exactly this type and not a type which fulfills LabelOptions.
+// This is useful for switch cases.
+type LabelOptionsExactly interface {
+	LabelOptions
+	isLabelOptions() bool
+}
+
+// _LabelOptions is the data-structure of this message
+type _LabelOptions struct {
+	LabelFlavour LabelFlavour
+	LabelType    LabelType
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_LabelOptions) GetLabelFlavour() LabelFlavour {
+	return m.LabelFlavour
+}
+
+func (m *_LabelOptions) GetLabelType() LabelType {
+	return m.LabelType
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewLabelOptions factory function for _LabelOptions
+func NewLabelOptions(labelFlavour LabelFlavour, labelType LabelType) *_LabelOptions {
+	return &_LabelOptions{LabelFlavour: labelFlavour, LabelType: labelType}
+}
+
+// Deprecated: use the interface for direct cast
+func CastLabelOptions(structType interface{}) LabelOptions {
+	if casted, ok := structType.(LabelOptions); ok {
+		return casted
+	}
+	if casted, ok := structType.(*LabelOptions); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_LabelOptions) GetTypeName() string {
+	return "LabelOptions"
+}
+
+func (m *_LabelOptions) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_LabelOptions) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(0)
+
+	// Reserved Field (reserved)
+	lengthInBits += 1
+
+	// Simple field (labelFlavour)
+	lengthInBits += 2
+
+	// Reserved Field (reserved)
+	lengthInBits += 1
+
+	// Reserved Field (reserved)
+	lengthInBits += 1
+
+	// Simple field (labelType)
+	lengthInBits += 2
+
+	// Reserved Field (reserved)
+	lengthInBits += 1
+
+	return lengthInBits
+}
+
+func (m *_LabelOptions) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func LabelOptionsParse(readBuffer utils.ReadBuffer) (LabelOptions, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("LabelOptions"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for LabelOptions")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Reserved Field (Compartmentalized so the "reserved" variable can't leak)
+	{
+		reserved, _err := readBuffer.ReadBit("reserved")
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'reserved' field of LabelOptions")
+		}
+		if reserved != bool(false) {
+			log.Info().Fields(map[string]interface{}{
+				"expected value": bool(false),
+				"got value":      reserved,
+			}).Msg("Got unexpected response for reserved field.")
+		}
+	}
+
+	// Simple Field (labelFlavour)
+	if pullErr := readBuffer.PullContext("labelFlavour"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for labelFlavour")
+	}
+	_labelFlavour, _labelFlavourErr := LabelFlavourParse(readBuffer)
+	if _labelFlavourErr != nil {
+		return nil, errors.Wrap(_labelFlavourErr, "Error parsing 'labelFlavour' field of LabelOptions")
+	}
+	labelFlavour := _labelFlavour
+	if closeErr := readBuffer.CloseContext("labelFlavour"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for labelFlavour")
+	}
+
+	// Reserved Field (Compartmentalized so the "reserved" variable can't leak)
+	{
+		reserved, _err := readBuffer.ReadBit("reserved")
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'reserved' field of LabelOptions")
+		}
+		if reserved != bool(false) {
+			log.Info().Fields(map[string]interface{}{
+				"expected value": bool(false),
+				"got value":      reserved,
+			}).Msg("Got unexpected response for reserved field.")
+		}
+	}
+
+	// Reserved Field (Compartmentalized so the "reserved" variable can't leak)
+	{
+		reserved, _err := readBuffer.ReadBit("reserved")
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'reserved' field of LabelOptions")
+		}
+		if reserved != bool(false) {
+			log.Info().Fields(map[string]interface{}{
+				"expected value": bool(false),
+				"got value":      reserved,
+			}).Msg("Got unexpected response for reserved field.")
+		}
+	}
+
+	// Simple Field (labelType)
+	if pullErr := readBuffer.PullContext("labelType"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for labelType")
+	}
+	_labelType, _labelTypeErr := LabelTypeParse(readBuffer)
+	if _labelTypeErr != nil {
+		return nil, errors.Wrap(_labelTypeErr, "Error parsing 'labelType' field of LabelOptions")
+	}
+	labelType := _labelType
+	if closeErr := readBuffer.CloseContext("labelType"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for labelType")
+	}
+
+	// Reserved Field (Compartmentalized so the "reserved" variable can't leak)
+	{
+		reserved, _err := readBuffer.ReadBit("reserved")
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'reserved' field of LabelOptions")
+		}
+		if reserved != bool(false) {
+			log.Info().Fields(map[string]interface{}{
+				"expected value": bool(false),
+				"got value":      reserved,
+			}).Msg("Got unexpected response for reserved field.")
+		}
+	}
+
+	if closeErr := readBuffer.CloseContext("LabelOptions"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for LabelOptions")
+	}
+
+	// Create the instance
+	return NewLabelOptions(labelFlavour, labelType), nil
+}
+
+func (m *_LabelOptions) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	if pushErr := writeBuffer.PushContext("LabelOptions"); pushErr != nil {
+		return errors.Wrap(pushErr, "Error pushing for LabelOptions")
+	}
+
+	// Reserved Field (reserved)
+	{
+		_err := writeBuffer.WriteBit("reserved", bool(false))
+		if _err != nil {
+			return errors.Wrap(_err, "Error serializing 'reserved' field")
+		}
+	}
+
+	// Simple Field (labelFlavour)
+	if pushErr := writeBuffer.PushContext("labelFlavour"); pushErr != nil {
+		return errors.Wrap(pushErr, "Error pushing for labelFlavour")
+	}
+	_labelFlavourErr := writeBuffer.WriteSerializable(m.GetLabelFlavour())
+	if popErr := writeBuffer.PopContext("labelFlavour"); popErr != nil {
+		return errors.Wrap(popErr, "Error popping for labelFlavour")
+	}
+	if _labelFlavourErr != nil {
+		return errors.Wrap(_labelFlavourErr, "Error serializing 'labelFlavour' field")
+	}
+
+	// Reserved Field (reserved)
+	{
+		_err := writeBuffer.WriteBit("reserved", bool(false))
+		if _err != nil {
+			return errors.Wrap(_err, "Error serializing 'reserved' field")
+		}
+	}
+
+	// Reserved Field (reserved)
+	{
+		_err := writeBuffer.WriteBit("reserved", bool(false))
+		if _err != nil {
+			return errors.Wrap(_err, "Error serializing 'reserved' field")
+		}
+	}
+
+	// Simple Field (labelType)
+	if pushErr := writeBuffer.PushContext("labelType"); pushErr != nil {
+		return errors.Wrap(pushErr, "Error pushing for labelType")
+	}
+	_labelTypeErr := writeBuffer.WriteSerializable(m.GetLabelType())
+	if popErr := writeBuffer.PopContext("labelType"); popErr != nil {
+		return errors.Wrap(popErr, "Error popping for labelType")
+	}
+	if _labelTypeErr != nil {
+		return errors.Wrap(_labelTypeErr, "Error serializing 'labelType' field")
+	}
+
+	// Reserved Field (reserved)
+	{
+		_err := writeBuffer.WriteBit("reserved", bool(false))
+		if _err != nil {
+			return errors.Wrap(_err, "Error serializing 'reserved' field")
+		}
+	}
+
+	if popErr := writeBuffer.PopContext("LabelOptions"); popErr != nil {
+		return errors.Wrap(popErr, "Error popping for LabelOptions")
+	}
+	return nil
+}
+
+func (m *_LabelOptions) isLabelOptions() bool {
+	return true
+}
+
+func (m *_LabelOptions) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/LabelType.go b/plc4go/protocols/cbus/readwrite/model/LabelType.go
new file mode 100644
index 000000000..e582c18de
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/LabelType.go
@@ -0,0 +1,145 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// LabelType is an enum
+type LabelType uint8
+
+type ILabelType interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	LabelType_TEXT_LABEL             LabelType = 0
+	LabelType_PREDEFINED_ICON        LabelType = 1
+	LabelType_LOAD_DYNAMIC_ICON      LabelType = 2
+	LabelType_SET_PREFERRED_LANGUAGE LabelType = 3
+)
+
+var LabelTypeValues []LabelType
+
+func init() {
+	_ = errors.New
+	LabelTypeValues = []LabelType{
+		LabelType_TEXT_LABEL,
+		LabelType_PREDEFINED_ICON,
+		LabelType_LOAD_DYNAMIC_ICON,
+		LabelType_SET_PREFERRED_LANGUAGE,
+	}
+}
+
+func LabelTypeByValue(value uint8) (enum LabelType, ok bool) {
+	switch value {
+	case 0:
+		return LabelType_TEXT_LABEL, true
+	case 1:
+		return LabelType_PREDEFINED_ICON, true
+	case 2:
+		return LabelType_LOAD_DYNAMIC_ICON, true
+	case 3:
+		return LabelType_SET_PREFERRED_LANGUAGE, true
+	}
+	return 0, false
+}
+
+func LabelTypeByName(value string) (enum LabelType, ok bool) {
+	switch value {
+	case "TEXT_LABEL":
+		return LabelType_TEXT_LABEL, true
+	case "PREDEFINED_ICON":
+		return LabelType_PREDEFINED_ICON, true
+	case "LOAD_DYNAMIC_ICON":
+		return LabelType_LOAD_DYNAMIC_ICON, true
+	case "SET_PREFERRED_LANGUAGE":
+		return LabelType_SET_PREFERRED_LANGUAGE, true
+	}
+	return 0, false
+}
+
+func LabelTypeKnows(value uint8) bool {
+	for _, typeValue := range LabelTypeValues {
+		if uint8(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastLabelType(structType interface{}) LabelType {
+	castFunc := func(typ interface{}) LabelType {
+		if sLabelType, ok := typ.(LabelType); ok {
+			return sLabelType
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m LabelType) GetLengthInBits() uint16 {
+	return 2
+}
+
+func (m LabelType) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func LabelTypeParse(readBuffer utils.ReadBuffer) (LabelType, error) {
+	val, err := readBuffer.ReadUint8("LabelType", 2)
+	if err != nil {
+		return 0, errors.Wrap(err, "error reading LabelType")
+	}
+	if enum, ok := LabelTypeByValue(val); !ok {
+		log.Debug().Msgf("no value %x found for RequestType", val)
+		return LabelType(val), nil
+	} else {
+		return enum, nil
+	}
+}
+
+func (e LabelType) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint8("LabelType", 2, uint8(e), utils.WithAdditionalStringRepresentation(e.PLC4XEnumName()))
+}
+
+// PLC4XEnumName returns the name that is used in code to identify this enum
+func (e LabelType) PLC4XEnumName() string {
+	switch e {
+	case LabelType_TEXT_LABEL:
+		return "TEXT_LABEL"
+	case LabelType_PREDEFINED_ICON:
+		return "PREDEFINED_ICON"
+	case LabelType_LOAD_DYNAMIC_ICON:
+		return "LOAD_DYNAMIC_ICON"
+	case LabelType_SET_PREFERRED_LANGUAGE:
+		return "SET_PREFERRED_LANGUAGE"
+	}
+	return ""
+}
+
+func (e LabelType) String() string {
+	return e.PLC4XEnumName()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/Language.go b/plc4go/protocols/cbus/readwrite/model/Language.go
new file mode 100644
index 000000000..6558bfcce
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/Language.go
@@ -0,0 +1,657 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// Language is an enum
+type Language uint8
+
+type ILanguage interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	Language_ENGLISH                    Language = 0x01
+	Language_ENGLISH_AUSTRALIA          Language = 0x02
+	Language_ENGLISH_BELIZE             Language = 0x03
+	Language_ENGLISH_CANADA             Language = 0x04
+	Language_ENGLISH_CARRIBEAN          Language = 0x05
+	Language_ENGLISH_IRELAND            Language = 0x06
+	Language_ENGLISH_JAMAICA            Language = 0x07
+	Language_ENGLISH_NEW_ZEALAND        Language = 0x08
+	Language_ENGLISH_PHILIPPINES        Language = 0x09
+	Language_ENGLISH_SOUTH_AFRICA       Language = 0x0A
+	Language_ENGLISH_TRINIDAD           Language = 0x0B
+	Language_ENGLISH_UK                 Language = 0x0C
+	Language_ENGLISH_USA                Language = 0x0D
+	Language_ENGLISH_ZIMBABWE           Language = 0x0E
+	Language_AFRIKAANS                  Language = 0x40
+	Language_BASQUE                     Language = 0x41
+	Language_CATALAN                    Language = 0x42
+	Language_DANISH                     Language = 0x43
+	Language_DUTCH_BELGIUM              Language = 0x44
+	Language_DUTCH_NETHERLANDS          Language = 0x45
+	Language_FAEROESE                   Language = 0x46
+	Language_FINNISH                    Language = 0x47
+	Language_FRENCH_BELGIUM             Language = 0x48
+	Language_FRENCH_CANADA              Language = 0x49
+	Language_FRENCH                     Language = 0x4A
+	Language_FRENCH_LUXEMBOURG          Language = 0x4B
+	Language_FRENCH_MONACO              Language = 0x4C
+	Language_FRENCH_SWITZERLAND         Language = 0x4D
+	Language_GALICIAN                   Language = 0x4E
+	Language_GERMAN_AUSTRIA             Language = 0x4F
+	Language_GERMAN                     Language = 0x50
+	Language_GERMAN_LIECHTENSTEIN       Language = 0x51
+	Language_GERMAN_LUXEMBOURG          Language = 0x52
+	Language_GERMAN_SWITZERLAND         Language = 0x53
+	Language_ICELANDIC                  Language = 0x54
+	Language_INDONESIAN                 Language = 0x55
+	Language_ITALIAN                    Language = 0x56
+	Language_ITALIAN_SWITZERLAND        Language = 0x57
+	Language_MALAY_BRUNEI               Language = 0x58
+	Language_MALAY                      Language = 0x59
+	Language_NORWEGIAN                  Language = 0x5A
+	Language_NORWEGIAN_NYNORSK          Language = 0x5B
+	Language_PORTUGUESE_BRAZIL          Language = 0x5C
+	Language_PORTUGUESE                 Language = 0x5D
+	Language_SPANISH_ARGENTINE          Language = 0x5E
+	Language_SPANISH_BOLIVIA            Language = 0x5F
+	Language_SPANISH_CHILE              Language = 0x60
+	Language_SPANISH_COLOMBIA           Language = 0x61
+	Language_SPANISH_COSTA_RICA         Language = 0x62
+	Language_SPANISH_DOMINICAN_REPUBLIC Language = 0x63
+	Language_SPANISH_ECUADOR            Language = 0x64
+	Language_SPANISH_EL_SALVADOR        Language = 0x65
+	Language_SPANISH_GUATEMALA          Language = 0x66
+	Language_SPANISH_HONDURAS           Language = 0x67
+	Language_SPANISH                    Language = 0x68
+	Language_SPANISH_MEXICO             Language = 0x69
+	Language_SPANISH_NICARAGUA          Language = 0x6A
+	Language_SPANISH_PANAMA             Language = 0x6B
+	Language_SPANISH_PARAGUAY           Language = 0x6C
+	Language_SPANISH_PERU               Language = 0x6D
+	Language_SPANISH_PERTO_RICO         Language = 0x6E
+	Language_SPANISH_TRADITIONAL        Language = 0x6F
+	Language_SPANISH_URUGUAY            Language = 0x70
+	Language_SPANISH_VENEZUELA          Language = 0x71
+	Language_SWAHILI                    Language = 0x72
+	Language_SWEDISH                    Language = 0x73
+	Language_SWEDISH_FINLAND            Language = 0x74
+	Language_CHINESE_CP936              Language = 0xCA
+)
+
+var LanguageValues []Language
+
+func init() {
+	_ = errors.New
+	LanguageValues = []Language{
+		Language_ENGLISH,
+		Language_ENGLISH_AUSTRALIA,
+		Language_ENGLISH_BELIZE,
+		Language_ENGLISH_CANADA,
+		Language_ENGLISH_CARRIBEAN,
+		Language_ENGLISH_IRELAND,
+		Language_ENGLISH_JAMAICA,
+		Language_ENGLISH_NEW_ZEALAND,
+		Language_ENGLISH_PHILIPPINES,
+		Language_ENGLISH_SOUTH_AFRICA,
+		Language_ENGLISH_TRINIDAD,
+		Language_ENGLISH_UK,
+		Language_ENGLISH_USA,
+		Language_ENGLISH_ZIMBABWE,
+		Language_AFRIKAANS,
+		Language_BASQUE,
+		Language_CATALAN,
+		Language_DANISH,
+		Language_DUTCH_BELGIUM,
+		Language_DUTCH_NETHERLANDS,
+		Language_FAEROESE,
+		Language_FINNISH,
+		Language_FRENCH_BELGIUM,
+		Language_FRENCH_CANADA,
+		Language_FRENCH,
+		Language_FRENCH_LUXEMBOURG,
+		Language_FRENCH_MONACO,
+		Language_FRENCH_SWITZERLAND,
+		Language_GALICIAN,
+		Language_GERMAN_AUSTRIA,
+		Language_GERMAN,
+		Language_GERMAN_LIECHTENSTEIN,
+		Language_GERMAN_LUXEMBOURG,
+		Language_GERMAN_SWITZERLAND,
+		Language_ICELANDIC,
+		Language_INDONESIAN,
+		Language_ITALIAN,
+		Language_ITALIAN_SWITZERLAND,
+		Language_MALAY_BRUNEI,
+		Language_MALAY,
+		Language_NORWEGIAN,
+		Language_NORWEGIAN_NYNORSK,
+		Language_PORTUGUESE_BRAZIL,
+		Language_PORTUGUESE,
+		Language_SPANISH_ARGENTINE,
+		Language_SPANISH_BOLIVIA,
+		Language_SPANISH_CHILE,
+		Language_SPANISH_COLOMBIA,
+		Language_SPANISH_COSTA_RICA,
+		Language_SPANISH_DOMINICAN_REPUBLIC,
+		Language_SPANISH_ECUADOR,
+		Language_SPANISH_EL_SALVADOR,
+		Language_SPANISH_GUATEMALA,
+		Language_SPANISH_HONDURAS,
+		Language_SPANISH,
+		Language_SPANISH_MEXICO,
+		Language_SPANISH_NICARAGUA,
+		Language_SPANISH_PANAMA,
+		Language_SPANISH_PARAGUAY,
+		Language_SPANISH_PERU,
+		Language_SPANISH_PERTO_RICO,
+		Language_SPANISH_TRADITIONAL,
+		Language_SPANISH_URUGUAY,
+		Language_SPANISH_VENEZUELA,
+		Language_SWAHILI,
+		Language_SWEDISH,
+		Language_SWEDISH_FINLAND,
+		Language_CHINESE_CP936,
+	}
+}
+
+func LanguageByValue(value uint8) (enum Language, ok bool) {
+	switch value {
+	case 0x01:
+		return Language_ENGLISH, true
+	case 0x02:
+		return Language_ENGLISH_AUSTRALIA, true
+	case 0x03:
+		return Language_ENGLISH_BELIZE, true
+	case 0x04:
+		return Language_ENGLISH_CANADA, true
+	case 0x05:
+		return Language_ENGLISH_CARRIBEAN, true
+	case 0x06:
+		return Language_ENGLISH_IRELAND, true
+	case 0x07:
+		return Language_ENGLISH_JAMAICA, true
+	case 0x08:
+		return Language_ENGLISH_NEW_ZEALAND, true
+	case 0x09:
+		return Language_ENGLISH_PHILIPPINES, true
+	case 0x0A:
+		return Language_ENGLISH_SOUTH_AFRICA, true
+	case 0x0B:
+		return Language_ENGLISH_TRINIDAD, true
+	case 0x0C:
+		return Language_ENGLISH_UK, true
+	case 0x0D:
+		return Language_ENGLISH_USA, true
+	case 0x0E:
+		return Language_ENGLISH_ZIMBABWE, true
+	case 0x40:
+		return Language_AFRIKAANS, true
+	case 0x41:
+		return Language_BASQUE, true
+	case 0x42:
+		return Language_CATALAN, true
+	case 0x43:
+		return Language_DANISH, true
+	case 0x44:
+		return Language_DUTCH_BELGIUM, true
+	case 0x45:
+		return Language_DUTCH_NETHERLANDS, true
+	case 0x46:
+		return Language_FAEROESE, true
+	case 0x47:
+		return Language_FINNISH, true
+	case 0x48:
+		return Language_FRENCH_BELGIUM, true
+	case 0x49:
+		return Language_FRENCH_CANADA, true
+	case 0x4A:
+		return Language_FRENCH, true
+	case 0x4B:
+		return Language_FRENCH_LUXEMBOURG, true
+	case 0x4C:
+		return Language_FRENCH_MONACO, true
+	case 0x4D:
+		return Language_FRENCH_SWITZERLAND, true
+	case 0x4E:
+		return Language_GALICIAN, true
+	case 0x4F:
+		return Language_GERMAN_AUSTRIA, true
+	case 0x50:
+		return Language_GERMAN, true
+	case 0x51:
+		return Language_GERMAN_LIECHTENSTEIN, true
+	case 0x52:
+		return Language_GERMAN_LUXEMBOURG, true
+	case 0x53:
+		return Language_GERMAN_SWITZERLAND, true
+	case 0x54:
+		return Language_ICELANDIC, true
+	case 0x55:
+		return Language_INDONESIAN, true
+	case 0x56:
+		return Language_ITALIAN, true
+	case 0x57:
+		return Language_ITALIAN_SWITZERLAND, true
+	case 0x58:
+		return Language_MALAY_BRUNEI, true
+	case 0x59:
+		return Language_MALAY, true
+	case 0x5A:
+		return Language_NORWEGIAN, true
+	case 0x5B:
+		return Language_NORWEGIAN_NYNORSK, true
+	case 0x5C:
+		return Language_PORTUGUESE_BRAZIL, true
+	case 0x5D:
+		return Language_PORTUGUESE, true
+	case 0x5E:
+		return Language_SPANISH_ARGENTINE, true
+	case 0x5F:
+		return Language_SPANISH_BOLIVIA, true
+	case 0x60:
+		return Language_SPANISH_CHILE, true
+	case 0x61:
+		return Language_SPANISH_COLOMBIA, true
+	case 0x62:
+		return Language_SPANISH_COSTA_RICA, true
+	case 0x63:
+		return Language_SPANISH_DOMINICAN_REPUBLIC, true
+	case 0x64:
+		return Language_SPANISH_ECUADOR, true
+	case 0x65:
+		return Language_SPANISH_EL_SALVADOR, true
+	case 0x66:
+		return Language_SPANISH_GUATEMALA, true
+	case 0x67:
+		return Language_SPANISH_HONDURAS, true
+	case 0x68:
+		return Language_SPANISH, true
+	case 0x69:
+		return Language_SPANISH_MEXICO, true
+	case 0x6A:
+		return Language_SPANISH_NICARAGUA, true
+	case 0x6B:
+		return Language_SPANISH_PANAMA, true
+	case 0x6C:
+		return Language_SPANISH_PARAGUAY, true
+	case 0x6D:
+		return Language_SPANISH_PERU, true
+	case 0x6E:
+		return Language_SPANISH_PERTO_RICO, true
+	case 0x6F:
+		return Language_SPANISH_TRADITIONAL, true
+	case 0x70:
+		return Language_SPANISH_URUGUAY, true
+	case 0x71:
+		return Language_SPANISH_VENEZUELA, true
+	case 0x72:
+		return Language_SWAHILI, true
+	case 0x73:
+		return Language_SWEDISH, true
+	case 0x74:
+		return Language_SWEDISH_FINLAND, true
+	case 0xCA:
+		return Language_CHINESE_CP936, true
+	}
+	return 0, false
+}
+
+func LanguageByName(value string) (enum Language, ok bool) {
+	switch value {
+	case "ENGLISH":
+		return Language_ENGLISH, true
+	case "ENGLISH_AUSTRALIA":
+		return Language_ENGLISH_AUSTRALIA, true
+	case "ENGLISH_BELIZE":
+		return Language_ENGLISH_BELIZE, true
+	case "ENGLISH_CANADA":
+		return Language_ENGLISH_CANADA, true
+	case "ENGLISH_CARRIBEAN":
+		return Language_ENGLISH_CARRIBEAN, true
+	case "ENGLISH_IRELAND":
+		return Language_ENGLISH_IRELAND, true
+	case "ENGLISH_JAMAICA":
+		return Language_ENGLISH_JAMAICA, true
+	case "ENGLISH_NEW_ZEALAND":
+		return Language_ENGLISH_NEW_ZEALAND, true
+	case "ENGLISH_PHILIPPINES":
+		return Language_ENGLISH_PHILIPPINES, true
+	case "ENGLISH_SOUTH_AFRICA":
+		return Language_ENGLISH_SOUTH_AFRICA, true
+	case "ENGLISH_TRINIDAD":
+		return Language_ENGLISH_TRINIDAD, true
+	case "ENGLISH_UK":
+		return Language_ENGLISH_UK, true
+	case "ENGLISH_USA":
+		return Language_ENGLISH_USA, true
+	case "ENGLISH_ZIMBABWE":
+		return Language_ENGLISH_ZIMBABWE, true
+	case "AFRIKAANS":
+		return Language_AFRIKAANS, true
+	case "BASQUE":
+		return Language_BASQUE, true
+	case "CATALAN":
+		return Language_CATALAN, true
+	case "DANISH":
+		return Language_DANISH, true
+	case "DUTCH_BELGIUM":
+		return Language_DUTCH_BELGIUM, true
+	case "DUTCH_NETHERLANDS":
+		return Language_DUTCH_NETHERLANDS, true
+	case "FAEROESE":
+		return Language_FAEROESE, true
+	case "FINNISH":
+		return Language_FINNISH, true
+	case "FRENCH_BELGIUM":
+		return Language_FRENCH_BELGIUM, true
+	case "FRENCH_CANADA":
+		return Language_FRENCH_CANADA, true
+	case "FRENCH":
+		return Language_FRENCH, true
+	case "FRENCH_LUXEMBOURG":
+		return Language_FRENCH_LUXEMBOURG, true
+	case "FRENCH_MONACO":
+		return Language_FRENCH_MONACO, true
+	case "FRENCH_SWITZERLAND":
+		return Language_FRENCH_SWITZERLAND, true
+	case "GALICIAN":
+		return Language_GALICIAN, true
+	case "GERMAN_AUSTRIA":
+		return Language_GERMAN_AUSTRIA, true
+	case "GERMAN":
+		return Language_GERMAN, true
+	case "GERMAN_LIECHTENSTEIN":
+		return Language_GERMAN_LIECHTENSTEIN, true
+	case "GERMAN_LUXEMBOURG":
+		return Language_GERMAN_LUXEMBOURG, true
+	case "GERMAN_SWITZERLAND":
+		return Language_GERMAN_SWITZERLAND, true
+	case "ICELANDIC":
+		return Language_ICELANDIC, true
+	case "INDONESIAN":
+		return Language_INDONESIAN, true
+	case "ITALIAN":
+		return Language_ITALIAN, true
+	case "ITALIAN_SWITZERLAND":
+		return Language_ITALIAN_SWITZERLAND, true
+	case "MALAY_BRUNEI":
+		return Language_MALAY_BRUNEI, true
+	case "MALAY":
+		return Language_MALAY, true
+	case "NORWEGIAN":
+		return Language_NORWEGIAN, true
+	case "NORWEGIAN_NYNORSK":
+		return Language_NORWEGIAN_NYNORSK, true
+	case "PORTUGUESE_BRAZIL":
+		return Language_PORTUGUESE_BRAZIL, true
+	case "PORTUGUESE":
+		return Language_PORTUGUESE, true
+	case "SPANISH_ARGENTINE":
+		return Language_SPANISH_ARGENTINE, true
+	case "SPANISH_BOLIVIA":
+		return Language_SPANISH_BOLIVIA, true
+	case "SPANISH_CHILE":
+		return Language_SPANISH_CHILE, true
+	case "SPANISH_COLOMBIA":
+		return Language_SPANISH_COLOMBIA, true
+	case "SPANISH_COSTA_RICA":
+		return Language_SPANISH_COSTA_RICA, true
+	case "SPANISH_DOMINICAN_REPUBLIC":
+		return Language_SPANISH_DOMINICAN_REPUBLIC, true
+	case "SPANISH_ECUADOR":
+		return Language_SPANISH_ECUADOR, true
+	case "SPANISH_EL_SALVADOR":
+		return Language_SPANISH_EL_SALVADOR, true
+	case "SPANISH_GUATEMALA":
+		return Language_SPANISH_GUATEMALA, true
+	case "SPANISH_HONDURAS":
+		return Language_SPANISH_HONDURAS, true
+	case "SPANISH":
+		return Language_SPANISH, true
+	case "SPANISH_MEXICO":
+		return Language_SPANISH_MEXICO, true
+	case "SPANISH_NICARAGUA":
+		return Language_SPANISH_NICARAGUA, true
+	case "SPANISH_PANAMA":
+		return Language_SPANISH_PANAMA, true
+	case "SPANISH_PARAGUAY":
+		return Language_SPANISH_PARAGUAY, true
+	case "SPANISH_PERU":
+		return Language_SPANISH_PERU, true
+	case "SPANISH_PERTO_RICO":
+		return Language_SPANISH_PERTO_RICO, true
+	case "SPANISH_TRADITIONAL":
+		return Language_SPANISH_TRADITIONAL, true
+	case "SPANISH_URUGUAY":
+		return Language_SPANISH_URUGUAY, true
+	case "SPANISH_VENEZUELA":
+		return Language_SPANISH_VENEZUELA, true
+	case "SWAHILI":
+		return Language_SWAHILI, true
+	case "SWEDISH":
+		return Language_SWEDISH, true
+	case "SWEDISH_FINLAND":
+		return Language_SWEDISH_FINLAND, true
+	case "CHINESE_CP936":
+		return Language_CHINESE_CP936, true
+	}
+	return 0, false
+}
+
+func LanguageKnows(value uint8) bool {
+	for _, typeValue := range LanguageValues {
+		if uint8(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastLanguage(structType interface{}) Language {
+	castFunc := func(typ interface{}) Language {
+		if sLanguage, ok := typ.(Language); ok {
+			return sLanguage
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m Language) GetLengthInBits() uint16 {
+	return 8
+}
+
+func (m Language) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func LanguageParse(readBuffer utils.ReadBuffer) (Language, error) {
+	val, err := readBuffer.ReadUint8("Language", 8)
+	if err != nil {
+		return 0, errors.Wrap(err, "error reading Language")
+	}
+	if enum, ok := LanguageByValue(val); !ok {
+		log.Debug().Msgf("no value %x found for RequestType", val)
+		return Language(val), nil
+	} else {
+		return enum, nil
+	}
+}
+
+func (e Language) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint8("Language", 8, uint8(e), utils.WithAdditionalStringRepresentation(e.PLC4XEnumName()))
+}
+
+// PLC4XEnumName returns the name that is used in code to identify this enum
+func (e Language) PLC4XEnumName() string {
+	switch e {
+	case Language_ENGLISH:
+		return "ENGLISH"
+	case Language_ENGLISH_AUSTRALIA:
+		return "ENGLISH_AUSTRALIA"
+	case Language_ENGLISH_BELIZE:
+		return "ENGLISH_BELIZE"
+	case Language_ENGLISH_CANADA:
+		return "ENGLISH_CANADA"
+	case Language_ENGLISH_CARRIBEAN:
+		return "ENGLISH_CARRIBEAN"
+	case Language_ENGLISH_IRELAND:
+		return "ENGLISH_IRELAND"
+	case Language_ENGLISH_JAMAICA:
+		return "ENGLISH_JAMAICA"
+	case Language_ENGLISH_NEW_ZEALAND:
+		return "ENGLISH_NEW_ZEALAND"
+	case Language_ENGLISH_PHILIPPINES:
+		return "ENGLISH_PHILIPPINES"
+	case Language_ENGLISH_SOUTH_AFRICA:
+		return "ENGLISH_SOUTH_AFRICA"
+	case Language_ENGLISH_TRINIDAD:
+		return "ENGLISH_TRINIDAD"
+	case Language_ENGLISH_UK:
+		return "ENGLISH_UK"
+	case Language_ENGLISH_USA:
+		return "ENGLISH_USA"
+	case Language_ENGLISH_ZIMBABWE:
+		return "ENGLISH_ZIMBABWE"
+	case Language_AFRIKAANS:
+		return "AFRIKAANS"
+	case Language_BASQUE:
+		return "BASQUE"
+	case Language_CATALAN:
+		return "CATALAN"
+	case Language_DANISH:
+		return "DANISH"
+	case Language_DUTCH_BELGIUM:
+		return "DUTCH_BELGIUM"
+	case Language_DUTCH_NETHERLANDS:
+		return "DUTCH_NETHERLANDS"
+	case Language_FAEROESE:
+		return "FAEROESE"
+	case Language_FINNISH:
+		return "FINNISH"
+	case Language_FRENCH_BELGIUM:
+		return "FRENCH_BELGIUM"
+	case Language_FRENCH_CANADA:
+		return "FRENCH_CANADA"
+	case Language_FRENCH:
+		return "FRENCH"
+	case Language_FRENCH_LUXEMBOURG:
+		return "FRENCH_LUXEMBOURG"
+	case Language_FRENCH_MONACO:
+		return "FRENCH_MONACO"
+	case Language_FRENCH_SWITZERLAND:
+		return "FRENCH_SWITZERLAND"
+	case Language_GALICIAN:
+		return "GALICIAN"
+	case Language_GERMAN_AUSTRIA:
+		return "GERMAN_AUSTRIA"
+	case Language_GERMAN:
+		return "GERMAN"
+	case Language_GERMAN_LIECHTENSTEIN:
+		return "GERMAN_LIECHTENSTEIN"
+	case Language_GERMAN_LUXEMBOURG:
+		return "GERMAN_LUXEMBOURG"
+	case Language_GERMAN_SWITZERLAND:
+		return "GERMAN_SWITZERLAND"
+	case Language_ICELANDIC:
+		return "ICELANDIC"
+	case Language_INDONESIAN:
+		return "INDONESIAN"
+	case Language_ITALIAN:
+		return "ITALIAN"
+	case Language_ITALIAN_SWITZERLAND:
+		return "ITALIAN_SWITZERLAND"
+	case Language_MALAY_BRUNEI:
+		return "MALAY_BRUNEI"
+	case Language_MALAY:
+		return "MALAY"
+	case Language_NORWEGIAN:
+		return "NORWEGIAN"
+	case Language_NORWEGIAN_NYNORSK:
+		return "NORWEGIAN_NYNORSK"
+	case Language_PORTUGUESE_BRAZIL:
+		return "PORTUGUESE_BRAZIL"
+	case Language_PORTUGUESE:
+		return "PORTUGUESE"
+	case Language_SPANISH_ARGENTINE:
+		return "SPANISH_ARGENTINE"
+	case Language_SPANISH_BOLIVIA:
+		return "SPANISH_BOLIVIA"
+	case Language_SPANISH_CHILE:
+		return "SPANISH_CHILE"
+	case Language_SPANISH_COLOMBIA:
+		return "SPANISH_COLOMBIA"
+	case Language_SPANISH_COSTA_RICA:
+		return "SPANISH_COSTA_RICA"
+	case Language_SPANISH_DOMINICAN_REPUBLIC:
+		return "SPANISH_DOMINICAN_REPUBLIC"
+	case Language_SPANISH_ECUADOR:
+		return "SPANISH_ECUADOR"
+	case Language_SPANISH_EL_SALVADOR:
+		return "SPANISH_EL_SALVADOR"
+	case Language_SPANISH_GUATEMALA:
+		return "SPANISH_GUATEMALA"
+	case Language_SPANISH_HONDURAS:
+		return "SPANISH_HONDURAS"
+	case Language_SPANISH:
+		return "SPANISH"
+	case Language_SPANISH_MEXICO:
+		return "SPANISH_MEXICO"
+	case Language_SPANISH_NICARAGUA:
+		return "SPANISH_NICARAGUA"
+	case Language_SPANISH_PANAMA:
+		return "SPANISH_PANAMA"
+	case Language_SPANISH_PARAGUAY:
+		return "SPANISH_PARAGUAY"
+	case Language_SPANISH_PERU:
+		return "SPANISH_PERU"
+	case Language_SPANISH_PERTO_RICO:
+		return "SPANISH_PERTO_RICO"
+	case Language_SPANISH_TRADITIONAL:
+		return "SPANISH_TRADITIONAL"
+	case Language_SPANISH_URUGUAY:
+		return "SPANISH_URUGUAY"
+	case Language_SPANISH_VENEZUELA:
+		return "SPANISH_VENEZUELA"
+	case Language_SWAHILI:
+		return "SWAHILI"
+	case Language_SWEDISH:
+		return "SWEDISH"
+	case Language_SWEDISH_FINLAND:
+		return "SWEDISH_FINLAND"
+	case Language_CHINESE_CP936:
+		return "CHINESE_CP936"
+	}
+	return ""
+}
+
+func (e Language) String() string {
+	return e.PLC4XEnumName()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/SALCommandType.go b/plc4go/protocols/cbus/readwrite/model/SALCommandType.go
index cae3330cb..d0ef210f9 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALCommandType.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALCommandType.go
@@ -39,6 +39,7 @@ const (
 	SALCommandType_ON             SALCommandType = 0x01
 	SALCommandType_RAMP_TO_LEVEL  SALCommandType = 0x02
 	SALCommandType_TERMINATE_RAMP SALCommandType = 0x03
+	SALCommandType_LABEL          SALCommandType = 0x04
 )
 
 var SALCommandTypeValues []SALCommandType
@@ -50,6 +51,7 @@ func init() {
 		SALCommandType_ON,
 		SALCommandType_RAMP_TO_LEVEL,
 		SALCommandType_TERMINATE_RAMP,
+		SALCommandType_LABEL,
 	}
 }
 
@@ -63,6 +65,8 @@ func SALCommandTypeByValue(value uint8) (enum SALCommandType, ok bool) {
 		return SALCommandType_RAMP_TO_LEVEL, true
 	case 0x03:
 		return SALCommandType_TERMINATE_RAMP, true
+	case 0x04:
+		return SALCommandType_LABEL, true
 	}
 	return 0, false
 }
@@ -77,6 +81,8 @@ func SALCommandTypeByName(value string) (enum SALCommandType, ok bool) {
 		return SALCommandType_RAMP_TO_LEVEL, true
 	case "TERMINATE_RAMP":
 		return SALCommandType_TERMINATE_RAMP, true
+	case "LABEL":
+		return SALCommandType_LABEL, true
 	}
 	return 0, false
 }
@@ -136,6 +142,8 @@ func (e SALCommandType) PLC4XEnumName() string {
 		return "RAMP_TO_LEVEL"
 	case SALCommandType_TERMINATE_RAMP:
 		return "TERMINATE_RAMP"
+	case SALCommandType_LABEL:
+		return "LABEL"
 	}
 	return ""
 }
diff --git a/plc4go/protocols/cbus/readwrite/model/SALCommandTypeContainer.go b/plc4go/protocols/cbus/readwrite/model/SALCommandTypeContainer.go
index 15d671a5e..fb1d65c68 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALCommandTypeContainer.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALCommandTypeContainer.go
@@ -31,6 +31,7 @@ import (
 type SALCommandTypeContainer uint8
 
 type ISALCommandTypeContainer interface {
+	NumBytes() uint8
 	CommandType() SALCommandType
 	Serialize(writeBuffer utils.WriteBuffer) error
 }
@@ -55,6 +56,38 @@ const (
 	SALCommandTypeContainer_SALCommandRampToLevel_900Second     SALCommandTypeContainer = 0x72
 	SALCommandTypeContainer_SALCommandRampToLevel_1020Second    SALCommandTypeContainer = 0x7A
 	SALCommandTypeContainer_SALCommandTerminateRamp             SALCommandTypeContainer = 0x09
+	SALCommandTypeContainer_SALCommandLabel_0Bytes              SALCommandTypeContainer = 0xA0
+	SALCommandTypeContainer_SALCommandLabel_1Bytes              SALCommandTypeContainer = 0xA1
+	SALCommandTypeContainer_SALCommandLabel_2Bytes              SALCommandTypeContainer = 0xA2
+	SALCommandTypeContainer_SALCommandLabel_3Bytes              SALCommandTypeContainer = 0xA3
+	SALCommandTypeContainer_SALCommandLabel_4Bytes              SALCommandTypeContainer = 0xA4
+	SALCommandTypeContainer_SALCommandLabel_5Bytes              SALCommandTypeContainer = 0xA5
+	SALCommandTypeContainer_SALCommandLabel_6Bytes              SALCommandTypeContainer = 0xA6
+	SALCommandTypeContainer_SALCommandLabel_7Bytes              SALCommandTypeContainer = 0xA7
+	SALCommandTypeContainer_SALCommandLabel_8Bytes              SALCommandTypeContainer = 0xA8
+	SALCommandTypeContainer_SALCommandLabel_9Bytes              SALCommandTypeContainer = 0xA9
+	SALCommandTypeContainer_SALCommandLabel_10Bytes             SALCommandTypeContainer = 0xAA
+	SALCommandTypeContainer_SALCommandLabel_11Bytes             SALCommandTypeContainer = 0xAB
+	SALCommandTypeContainer_SALCommandLabel_12Bytes             SALCommandTypeContainer = 0xAC
+	SALCommandTypeContainer_SALCommandLabel_13Bytes             SALCommandTypeContainer = 0xAD
+	SALCommandTypeContainer_SALCommandLabel_14Bytes             SALCommandTypeContainer = 0xAE
+	SALCommandTypeContainer_SALCommandLabel_15Bytes             SALCommandTypeContainer = 0xAF
+	SALCommandTypeContainer_SALCommandLabel_16Bytes             SALCommandTypeContainer = 0xB0
+	SALCommandTypeContainer_SALCommandLabel_17Bytes             SALCommandTypeContainer = 0xB1
+	SALCommandTypeContainer_SALCommandLabel_18Bytes             SALCommandTypeContainer = 0xB2
+	SALCommandTypeContainer_SALCommandLabel_19Bytes             SALCommandTypeContainer = 0xB3
+	SALCommandTypeContainer_SALCommandLabel_20Bytes             SALCommandTypeContainer = 0xB4
+	SALCommandTypeContainer_SALCommandLabel_21Bytes             SALCommandTypeContainer = 0xB5
+	SALCommandTypeContainer_SALCommandLabel_22Bytes             SALCommandTypeContainer = 0xB6
+	SALCommandTypeContainer_SALCommandLabel_23Bytes             SALCommandTypeContainer = 0xB7
+	SALCommandTypeContainer_SALCommandLabel_24Bytes             SALCommandTypeContainer = 0xB8
+	SALCommandTypeContainer_SALCommandLabel_25Bytes             SALCommandTypeContainer = 0xB9
+	SALCommandTypeContainer_SALCommandLabel_26Bytes             SALCommandTypeContainer = 0xBA
+	SALCommandTypeContainer_SALCommandLabel_27Bytes             SALCommandTypeContainer = 0xBB
+	SALCommandTypeContainer_SALCommandLabel_28Bytes             SALCommandTypeContainer = 0xBC
+	SALCommandTypeContainer_SALCommandLabel_29Bytes             SALCommandTypeContainer = 0xBD
+	SALCommandTypeContainer_SALCommandLabel_30Bytes             SALCommandTypeContainer = 0xBE
+	SALCommandTypeContainer_SALCommandLabel_32Bytes             SALCommandTypeContainer = 0xBF
 )
 
 var SALCommandTypeContainerValues []SALCommandTypeContainer
@@ -81,9 +114,263 @@ func init() {
 		SALCommandTypeContainer_SALCommandRampToLevel_900Second,
 		SALCommandTypeContainer_SALCommandRampToLevel_1020Second,
 		SALCommandTypeContainer_SALCommandTerminateRamp,
+		SALCommandTypeContainer_SALCommandLabel_0Bytes,
+		SALCommandTypeContainer_SALCommandLabel_1Bytes,
+		SALCommandTypeContainer_SALCommandLabel_2Bytes,
+		SALCommandTypeContainer_SALCommandLabel_3Bytes,
+		SALCommandTypeContainer_SALCommandLabel_4Bytes,
+		SALCommandTypeContainer_SALCommandLabel_5Bytes,
+		SALCommandTypeContainer_SALCommandLabel_6Bytes,
+		SALCommandTypeContainer_SALCommandLabel_7Bytes,
+		SALCommandTypeContainer_SALCommandLabel_8Bytes,
+		SALCommandTypeContainer_SALCommandLabel_9Bytes,
+		SALCommandTypeContainer_SALCommandLabel_10Bytes,
+		SALCommandTypeContainer_SALCommandLabel_11Bytes,
+		SALCommandTypeContainer_SALCommandLabel_12Bytes,
+		SALCommandTypeContainer_SALCommandLabel_13Bytes,
+		SALCommandTypeContainer_SALCommandLabel_14Bytes,
+		SALCommandTypeContainer_SALCommandLabel_15Bytes,
+		SALCommandTypeContainer_SALCommandLabel_16Bytes,
+		SALCommandTypeContainer_SALCommandLabel_17Bytes,
+		SALCommandTypeContainer_SALCommandLabel_18Bytes,
+		SALCommandTypeContainer_SALCommandLabel_19Bytes,
+		SALCommandTypeContainer_SALCommandLabel_20Bytes,
+		SALCommandTypeContainer_SALCommandLabel_21Bytes,
+		SALCommandTypeContainer_SALCommandLabel_22Bytes,
+		SALCommandTypeContainer_SALCommandLabel_23Bytes,
+		SALCommandTypeContainer_SALCommandLabel_24Bytes,
+		SALCommandTypeContainer_SALCommandLabel_25Bytes,
+		SALCommandTypeContainer_SALCommandLabel_26Bytes,
+		SALCommandTypeContainer_SALCommandLabel_27Bytes,
+		SALCommandTypeContainer_SALCommandLabel_28Bytes,
+		SALCommandTypeContainer_SALCommandLabel_29Bytes,
+		SALCommandTypeContainer_SALCommandLabel_30Bytes,
+		SALCommandTypeContainer_SALCommandLabel_32Bytes,
 	}
 }
 
+func (e SALCommandTypeContainer) NumBytes() uint8 {
+	switch e {
+	case 0x01:
+		{ /* '0x01' */
+			return 1
+		}
+	case 0x02:
+		{ /* '0x02' */
+			return 1
+		}
+	case 0x09:
+		{ /* '0x09' */
+			return 1
+		}
+	case 0x0A:
+		{ /* '0x0A' */
+			return 2
+		}
+	case 0x12:
+		{ /* '0x12' */
+			return 2
+		}
+	case 0x1A:
+		{ /* '0x1A' */
+			return 2
+		}
+	case 0x22:
+		{ /* '0x22' */
+			return 2
+		}
+	case 0x2A:
+		{ /* '0x2A' */
+			return 2
+		}
+	case 0x32:
+		{ /* '0x32' */
+			return 2
+		}
+	case 0x3A:
+		{ /* '0x3A' */
+			return 2
+		}
+	case 0x42:
+		{ /* '0x42' */
+			return 2
+		}
+	case 0x4A:
+		{ /* '0x4A' */
+			return 2
+		}
+	case 0x52:
+		{ /* '0x52' */
+			return 2
+		}
+	case 0x5A:
+		{ /* '0x5A' */
+			return 2
+		}
+	case 0x62:
+		{ /* '0x62' */
+			return 2
+		}
+	case 0x6A:
+		{ /* '0x6A' */
+			return 2
+		}
+	case 0x72:
+		{ /* '0x72' */
+			return 2
+		}
+	case 0x79:
+		{ /* '0x79' */
+			return 1
+		}
+	case 0x7A:
+		{ /* '0x7A' */
+			return 2
+		}
+	case 0xA0:
+		{ /* '0xA0' */
+			return 0
+		}
+	case 0xA1:
+		{ /* '0xA1' */
+			return 1
+		}
+	case 0xA2:
+		{ /* '0xA2' */
+			return 2
+		}
+	case 0xA3:
+		{ /* '0xA3' */
+			return 3
+		}
+	case 0xA4:
+		{ /* '0xA4' */
+			return 4
+		}
+	case 0xA5:
+		{ /* '0xA5' */
+			return 5
+		}
+	case 0xA6:
+		{ /* '0xA6' */
+			return 6
+		}
+	case 0xA7:
+		{ /* '0xA7' */
+			return 7
+		}
+	case 0xA8:
+		{ /* '0xA8' */
+			return 8
+		}
+	case 0xA9:
+		{ /* '0xA9' */
+			return 9
+		}
+	case 0xAA:
+		{ /* '0xAA' */
+			return 10
+		}
+	case 0xAB:
+		{ /* '0xAB' */
+			return 11
+		}
+	case 0xAC:
+		{ /* '0xAC' */
+			return 12
+		}
+	case 0xAD:
+		{ /* '0xAD' */
+			return 13
+		}
+	case 0xAE:
+		{ /* '0xAE' */
+			return 14
+		}
+	case 0xAF:
+		{ /* '0xAF' */
+			return 15
+		}
+	case 0xB0:
+		{ /* '0xB0' */
+			return 16
+		}
+	case 0xB1:
+		{ /* '0xB1' */
+			return 17
+		}
+	case 0xB2:
+		{ /* '0xB2' */
+			return 18
+		}
+	case 0xB3:
+		{ /* '0xB3' */
+			return 19
+		}
+	case 0xB4:
+		{ /* '0xB4' */
+			return 20
+		}
+	case 0xB5:
+		{ /* '0xB5' */
+			return 21
+		}
+	case 0xB6:
+		{ /* '0xB6' */
+			return 22
+		}
+	case 0xB7:
+		{ /* '0xB7' */
+			return 23
+		}
+	case 0xB8:
+		{ /* '0xB8' */
+			return 24
+		}
+	case 0xB9:
+		{ /* '0xB9' */
+			return 25
+		}
+	case 0xBA:
+		{ /* '0xBA' */
+			return 26
+		}
+	case 0xBB:
+		{ /* '0xBB' */
+			return 27
+		}
+	case 0xBC:
+		{ /* '0xBC' */
+			return 28
+		}
+	case 0xBD:
+		{ /* '0xBD' */
+			return 29
+		}
+	case 0xBE:
+		{ /* '0xBE' */
+			return 30
+		}
+	case 0xBF:
+		{ /* '0xBF' */
+			return 31
+		}
+	default:
+		{
+			return 0
+		}
+	}
+}
+
+func SALCommandTypeContainerFirstEnumForFieldNumBytes(value uint8) (SALCommandTypeContainer, error) {
+	for _, sizeValue := range SALCommandTypeContainerValues {
+		if sizeValue.NumBytes() == value {
+			return sizeValue, nil
+		}
+	}
+	return 0, errors.Errorf("enum for %v describing NumBytes not found", value)
+}
+
 func (e SALCommandTypeContainer) CommandType() SALCommandType {
 	switch e {
 	case 0x01:
@@ -162,6 +449,134 @@ func (e SALCommandTypeContainer) CommandType() SALCommandType {
 		{ /* '0x7A' */
 			return SALCommandType_RAMP_TO_LEVEL
 		}
+	case 0xA0:
+		{ /* '0xA0' */
+			return SALCommandType_LABEL
+		}
+	case 0xA1:
+		{ /* '0xA1' */
+			return SALCommandType_LABEL
+		}
+	case 0xA2:
+		{ /* '0xA2' */
+			return SALCommandType_LABEL
+		}
+	case 0xA3:
+		{ /* '0xA3' */
+			return SALCommandType_LABEL
+		}
+	case 0xA4:
+		{ /* '0xA4' */
+			return SALCommandType_LABEL
+		}
+	case 0xA5:
+		{ /* '0xA5' */
+			return SALCommandType_LABEL
+		}
+	case 0xA6:
+		{ /* '0xA6' */
+			return SALCommandType_LABEL
+		}
+	case 0xA7:
+		{ /* '0xA7' */
+			return SALCommandType_LABEL
+		}
+	case 0xA8:
+		{ /* '0xA8' */
+			return SALCommandType_LABEL
+		}
+	case 0xA9:
+		{ /* '0xA9' */
+			return SALCommandType_LABEL
+		}
+	case 0xAA:
+		{ /* '0xAA' */
+			return SALCommandType_LABEL
+		}
+	case 0xAB:
+		{ /* '0xAB' */
+			return SALCommandType_LABEL
+		}
+	case 0xAC:
+		{ /* '0xAC' */
+			return SALCommandType_LABEL
+		}
+	case 0xAD:
+		{ /* '0xAD' */
+			return SALCommandType_LABEL
+		}
+	case 0xAE:
+		{ /* '0xAE' */
+			return SALCommandType_LABEL
+		}
+	case 0xAF:
+		{ /* '0xAF' */
+			return SALCommandType_LABEL
+		}
+	case 0xB0:
+		{ /* '0xB0' */
+			return SALCommandType_LABEL
+		}
+	case 0xB1:
+		{ /* '0xB1' */
+			return SALCommandType_LABEL
+		}
+	case 0xB2:
+		{ /* '0xB2' */
+			return SALCommandType_LABEL
+		}
+	case 0xB3:
+		{ /* '0xB3' */
+			return SALCommandType_LABEL
+		}
+	case 0xB4:
+		{ /* '0xB4' */
+			return SALCommandType_LABEL
+		}
+	case 0xB5:
+		{ /* '0xB5' */
+			return SALCommandType_LABEL
+		}
+	case 0xB6:
+		{ /* '0xB6' */
+			return SALCommandType_LABEL
+		}
+	case 0xB7:
+		{ /* '0xB7' */
+			return SALCommandType_LABEL
+		}
+	case 0xB8:
+		{ /* '0xB8' */
+			return SALCommandType_LABEL
+		}
+	case 0xB9:
+		{ /* '0xB9' */
+			return SALCommandType_LABEL
+		}
+	case 0xBA:
+		{ /* '0xBA' */
+			return SALCommandType_LABEL
+		}
+	case 0xBB:
+		{ /* '0xBB' */
+			return SALCommandType_LABEL
+		}
+	case 0xBC:
+		{ /* '0xBC' */
+			return SALCommandType_LABEL
+		}
+	case 0xBD:
+		{ /* '0xBD' */
+			return SALCommandType_LABEL
+		}
+	case 0xBE:
+		{ /* '0xBE' */
+			return SALCommandType_LABEL
+		}
+	case 0xBF:
+		{ /* '0xBF' */
+			return SALCommandType_LABEL
+		}
 	default:
 		{
 			return 0
@@ -217,6 +632,70 @@ func SALCommandTypeContainerByValue(value uint8) (enum SALCommandTypeContainer,
 		return SALCommandTypeContainer_SALCommandOn, true
 	case 0x7A:
 		return SALCommandTypeContainer_SALCommandRampToLevel_1020Second, true
+	case 0xA0:
+		return SALCommandTypeContainer_SALCommandLabel_0Bytes, true
+	case 0xA1:
+		return SALCommandTypeContainer_SALCommandLabel_1Bytes, true
+	case 0xA2:
+		return SALCommandTypeContainer_SALCommandLabel_2Bytes, true
+	case 0xA3:
+		return SALCommandTypeContainer_SALCommandLabel_3Bytes, true
+	case 0xA4:
+		return SALCommandTypeContainer_SALCommandLabel_4Bytes, true
+	case 0xA5:
+		return SALCommandTypeContainer_SALCommandLabel_5Bytes, true
+	case 0xA6:
+		return SALCommandTypeContainer_SALCommandLabel_6Bytes, true
+	case 0xA7:
+		return SALCommandTypeContainer_SALCommandLabel_7Bytes, true
+	case 0xA8:
+		return SALCommandTypeContainer_SALCommandLabel_8Bytes, true
+	case 0xA9:
+		return SALCommandTypeContainer_SALCommandLabel_9Bytes, true
+	case 0xAA:
+		return SALCommandTypeContainer_SALCommandLabel_10Bytes, true
+	case 0xAB:
+		return SALCommandTypeContainer_SALCommandLabel_11Bytes, true
+	case 0xAC:
+		return SALCommandTypeContainer_SALCommandLabel_12Bytes, true
+	case 0xAD:
+		return SALCommandTypeContainer_SALCommandLabel_13Bytes, true
+	case 0xAE:
+		return SALCommandTypeContainer_SALCommandLabel_14Bytes, true
+	case 0xAF:
+		return SALCommandTypeContainer_SALCommandLabel_15Bytes, true
+	case 0xB0:
+		return SALCommandTypeContainer_SALCommandLabel_16Bytes, true
+	case 0xB1:
+		return SALCommandTypeContainer_SALCommandLabel_17Bytes, true
+	case 0xB2:
+		return SALCommandTypeContainer_SALCommandLabel_18Bytes, true
+	case 0xB3:
+		return SALCommandTypeContainer_SALCommandLabel_19Bytes, true
+	case 0xB4:
+		return SALCommandTypeContainer_SALCommandLabel_20Bytes, true
+	case 0xB5:
+		return SALCommandTypeContainer_SALCommandLabel_21Bytes, true
+	case 0xB6:
+		return SALCommandTypeContainer_SALCommandLabel_22Bytes, true
+	case 0xB7:
+		return SALCommandTypeContainer_SALCommandLabel_23Bytes, true
+	case 0xB8:
+		return SALCommandTypeContainer_SALCommandLabel_24Bytes, true
+	case 0xB9:
+		return SALCommandTypeContainer_SALCommandLabel_25Bytes, true
+	case 0xBA:
+		return SALCommandTypeContainer_SALCommandLabel_26Bytes, true
+	case 0xBB:
+		return SALCommandTypeContainer_SALCommandLabel_27Bytes, true
+	case 0xBC:
+		return SALCommandTypeContainer_SALCommandLabel_28Bytes, true
+	case 0xBD:
+		return SALCommandTypeContainer_SALCommandLabel_29Bytes, true
+	case 0xBE:
+		return SALCommandTypeContainer_SALCommandLabel_30Bytes, true
+	case 0xBF:
+		return SALCommandTypeContainer_SALCommandLabel_32Bytes, true
 	}
 	return 0, false
 }
@@ -261,6 +740,70 @@ func SALCommandTypeContainerByName(value string) (enum SALCommandTypeContainer,
 		return SALCommandTypeContainer_SALCommandOn, true
 	case "SALCommandRampToLevel_1020Second":
 		return SALCommandTypeContainer_SALCommandRampToLevel_1020Second, true
+	case "SALCommandLabel_0Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_0Bytes, true
+	case "SALCommandLabel_1Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_1Bytes, true
+	case "SALCommandLabel_2Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_2Bytes, true
+	case "SALCommandLabel_3Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_3Bytes, true
+	case "SALCommandLabel_4Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_4Bytes, true
+	case "SALCommandLabel_5Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_5Bytes, true
+	case "SALCommandLabel_6Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_6Bytes, true
+	case "SALCommandLabel_7Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_7Bytes, true
+	case "SALCommandLabel_8Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_8Bytes, true
+	case "SALCommandLabel_9Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_9Bytes, true
+	case "SALCommandLabel_10Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_10Bytes, true
+	case "SALCommandLabel_11Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_11Bytes, true
+	case "SALCommandLabel_12Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_12Bytes, true
+	case "SALCommandLabel_13Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_13Bytes, true
+	case "SALCommandLabel_14Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_14Bytes, true
+	case "SALCommandLabel_15Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_15Bytes, true
+	case "SALCommandLabel_16Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_16Bytes, true
+	case "SALCommandLabel_17Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_17Bytes, true
+	case "SALCommandLabel_18Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_18Bytes, true
+	case "SALCommandLabel_19Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_19Bytes, true
+	case "SALCommandLabel_20Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_20Bytes, true
+	case "SALCommandLabel_21Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_21Bytes, true
+	case "SALCommandLabel_22Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_22Bytes, true
+	case "SALCommandLabel_23Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_23Bytes, true
+	case "SALCommandLabel_24Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_24Bytes, true
+	case "SALCommandLabel_25Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_25Bytes, true
+	case "SALCommandLabel_26Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_26Bytes, true
+	case "SALCommandLabel_27Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_27Bytes, true
+	case "SALCommandLabel_28Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_28Bytes, true
+	case "SALCommandLabel_29Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_29Bytes, true
+	case "SALCommandLabel_30Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_30Bytes, true
+	case "SALCommandLabel_32Bytes":
+		return SALCommandTypeContainer_SALCommandLabel_32Bytes, true
 	}
 	return 0, false
 }
@@ -350,6 +893,70 @@ func (e SALCommandTypeContainer) PLC4XEnumName() string {
 		return "SALCommandOn"
 	case SALCommandTypeContainer_SALCommandRampToLevel_1020Second:
 		return "SALCommandRampToLevel_1020Second"
+	case SALCommandTypeContainer_SALCommandLabel_0Bytes:
+		return "SALCommandLabel_0Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_1Bytes:
+		return "SALCommandLabel_1Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_2Bytes:
+		return "SALCommandLabel_2Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_3Bytes:
+		return "SALCommandLabel_3Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_4Bytes:
+		return "SALCommandLabel_4Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_5Bytes:
+		return "SALCommandLabel_5Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_6Bytes:
+		return "SALCommandLabel_6Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_7Bytes:
+		return "SALCommandLabel_7Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_8Bytes:
+		return "SALCommandLabel_8Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_9Bytes:
+		return "SALCommandLabel_9Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_10Bytes:
+		return "SALCommandLabel_10Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_11Bytes:
+		return "SALCommandLabel_11Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_12Bytes:
+		return "SALCommandLabel_12Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_13Bytes:
+		return "SALCommandLabel_13Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_14Bytes:
+		return "SALCommandLabel_14Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_15Bytes:
+		return "SALCommandLabel_15Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_16Bytes:
+		return "SALCommandLabel_16Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_17Bytes:
+		return "SALCommandLabel_17Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_18Bytes:
+		return "SALCommandLabel_18Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_19Bytes:
+		return "SALCommandLabel_19Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_20Bytes:
+		return "SALCommandLabel_20Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_21Bytes:
+		return "SALCommandLabel_21Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_22Bytes:
+		return "SALCommandLabel_22Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_23Bytes:
+		return "SALCommandLabel_23Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_24Bytes:
+		return "SALCommandLabel_24Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_25Bytes:
+		return "SALCommandLabel_25Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_26Bytes:
+		return "SALCommandLabel_26Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_27Bytes:
+		return "SALCommandLabel_27Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_28Bytes:
+		return "SALCommandLabel_28Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_29Bytes:
+		return "SALCommandLabel_29Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_30Bytes:
+		return "SALCommandLabel_30Bytes"
+	case SALCommandTypeContainer_SALCommandLabel_32Bytes:
+		return "SALCommandLabel_32Bytes"
 	}
 	return ""
 }
diff --git a/plc4go/protocols/cbus/readwrite/model/SALData.go b/plc4go/protocols/cbus/readwrite/model/SALData.go
index 3819ab9f0..c27a1fa43 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALData.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALData.go
@@ -197,6 +197,8 @@ func SALDataParse(readBuffer utils.ReadBuffer) (SALData, error) {
 		_childTemp, typeSwitchError = SALDataRampToLevelParse(readBuffer)
 	case commandType == SALCommandType_TERMINATE_RAMP: // SALDataTerminateRamp
 		_childTemp, typeSwitchError = SALDataTerminateRampParse(readBuffer)
+	case commandType == SALCommandType_LABEL: // SALDataLabel
+		_childTemp, typeSwitchError = SALDataLabelParse(readBuffer, commandTypeContainer)
 	default:
 		typeSwitchError = errors.Errorf("Unmapped type for parameters [commandType=%v]", commandType)
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataLabel.go b/plc4go/protocols/cbus/readwrite/model/SALDataLabel.go
new file mode 100644
index 000000000..05308d896
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataLabel.go
@@ -0,0 +1,291 @@
+/*
+ * 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 model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// SALDataLabel is the corresponding interface of SALDataLabel
+type SALDataLabel interface {
+	utils.LengthAware
+	utils.Serializable
+	SALData
+	// GetGroup returns Group (property field)
+	GetGroup() byte
+	// GetLabelOptions returns LabelOptions (property field)
+	GetLabelOptions() LabelOptions
+	// GetLanguage returns Language (property field)
+	GetLanguage() Language
+	// GetData returns Data (property field)
+	GetData() []byte
+}
+
+// SALDataLabelExactly can be used when we want exactly this type and not a type which fulfills SALDataLabel.
+// This is useful for switch cases.
+type SALDataLabelExactly interface {
+	SALDataLabel
+	isSALDataLabel() bool
+}
+
+// _SALDataLabel is the data-structure of this message
+type _SALDataLabel struct {
+	*_SALData
+	Group        byte
+	LabelOptions LabelOptions
+	Language     Language
+	Data         []byte
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_SALDataLabel) InitializeParent(parent SALData, commandTypeContainer SALCommandTypeContainer, salData SALData) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.SalData = salData
+}
+
+func (m *_SALDataLabel) GetParent() SALData {
+	return m._SALData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_SALDataLabel) GetGroup() byte {
+	return m.Group
+}
+
+func (m *_SALDataLabel) GetLabelOptions() LabelOptions {
+	return m.LabelOptions
+}
+
+func (m *_SALDataLabel) GetLanguage() Language {
+	return m.Language
+}
+
+func (m *_SALDataLabel) GetData() []byte {
+	return m.Data
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewSALDataLabel factory function for _SALDataLabel
+func NewSALDataLabel(group byte, labelOptions LabelOptions, language Language, data []byte, commandTypeContainer SALCommandTypeContainer, salData SALData) *_SALDataLabel {
+	_result := &_SALDataLabel{
+		Group:        group,
+		LabelOptions: labelOptions,
+		Language:     language,
+		Data:         data,
+		_SALData:     NewSALData(commandTypeContainer, salData),
+	}
+	_result._SALData._SALDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastSALDataLabel(structType interface{}) SALDataLabel {
+	if casted, ok := structType.(SALDataLabel); ok {
+		return casted
+	}
+	if casted, ok := structType.(*SALDataLabel); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_SALDataLabel) GetTypeName() string {
+	return "SALDataLabel"
+}
+
+func (m *_SALDataLabel) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_SALDataLabel) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (group)
+	lengthInBits += 8
+
+	// Simple field (labelOptions)
+	lengthInBits += m.LabelOptions.GetLengthInBits()
+
+	// Simple field (language)
+	lengthInBits += 8
+
+	// Array field
+	if len(m.Data) > 0 {
+		lengthInBits += 8 * uint16(len(m.Data))
+	}
+
+	return lengthInBits
+}
+
+func (m *_SALDataLabel) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func SALDataLabelParse(readBuffer utils.ReadBuffer, commandTypeContainer SALCommandTypeContainer) (SALDataLabel, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("SALDataLabel"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for SALDataLabel")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (group)
+	_group, _groupErr := readBuffer.ReadByte("group")
+	if _groupErr != nil {
+		return nil, errors.Wrap(_groupErr, "Error parsing 'group' field of SALDataLabel")
+	}
+	group := _group
+
+	// Simple Field (labelOptions)
+	if pullErr := readBuffer.PullContext("labelOptions"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for labelOptions")
+	}
+	_labelOptions, _labelOptionsErr := LabelOptionsParse(readBuffer)
+	if _labelOptionsErr != nil {
+		return nil, errors.Wrap(_labelOptionsErr, "Error parsing 'labelOptions' field of SALDataLabel")
+	}
+	labelOptions := _labelOptions.(LabelOptions)
+	if closeErr := readBuffer.CloseContext("labelOptions"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for labelOptions")
+	}
+
+	// Simple Field (language)
+	if pullErr := readBuffer.PullContext("language"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for language")
+	}
+	_language, _languageErr := LanguageParse(readBuffer)
+	if _languageErr != nil {
+		return nil, errors.Wrap(_languageErr, "Error parsing 'language' field of SALDataLabel")
+	}
+	language := _language
+	if closeErr := readBuffer.CloseContext("language"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for language")
+	}
+	// Byte Array field (data)
+	numberOfBytesdata := int(uint16(commandTypeContainer.NumBytes()) - uint16(uint16(3)))
+	data, _readArrayErr := readBuffer.ReadByteArray("data", numberOfBytesdata)
+	if _readArrayErr != nil {
+		return nil, errors.Wrap(_readArrayErr, "Error parsing 'data' field of SALDataLabel")
+	}
+
+	if closeErr := readBuffer.CloseContext("SALDataLabel"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for SALDataLabel")
+	}
+
+	// Create a partially initialized instance
+	_child := &_SALDataLabel{
+		Group:        group,
+		LabelOptions: labelOptions,
+		Language:     language,
+		Data:         data,
+		_SALData:     &_SALData{},
+	}
+	_child._SALData._SALDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_SALDataLabel) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("SALDataLabel"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for SALDataLabel")
+		}
+
+		// Simple Field (group)
+		group := byte(m.GetGroup())
+		_groupErr := writeBuffer.WriteByte("group", (group))
+		if _groupErr != nil {
+			return errors.Wrap(_groupErr, "Error serializing 'group' field")
+		}
+
+		// Simple Field (labelOptions)
+		if pushErr := writeBuffer.PushContext("labelOptions"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for labelOptions")
+		}
+		_labelOptionsErr := writeBuffer.WriteSerializable(m.GetLabelOptions())
+		if popErr := writeBuffer.PopContext("labelOptions"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for labelOptions")
+		}
+		if _labelOptionsErr != nil {
+			return errors.Wrap(_labelOptionsErr, "Error serializing 'labelOptions' field")
+		}
+
+		// Simple Field (language)
+		if pushErr := writeBuffer.PushContext("language"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for language")
+		}
+		_languageErr := writeBuffer.WriteSerializable(m.GetLanguage())
+		if popErr := writeBuffer.PopContext("language"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for language")
+		}
+		if _languageErr != nil {
+			return errors.Wrap(_languageErr, "Error serializing 'language' field")
+		}
+
+		// Array Field (data)
+		// Byte Array field (data)
+		if err := writeBuffer.WriteByteArray("data", m.GetData()); err != nil {
+			return errors.Wrap(err, "Error serializing 'data' field")
+		}
+
+		if popErr := writeBuffer.PopContext("SALDataLabel"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for SALDataLabel")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_SALDataLabel) isSALDataLabel() bool {
+	return true
+}
+
+func (m *_SALDataLabel) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
index 61a9c0890..f456a6bc7 100644
--- a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
@@ -38,16 +38,16 @@ func ReadCBusCommand(readBuffer utils.ReadBuffer, payloadLength uint16, cBusOpti
 	return CBusCommandParse(utils.NewReadBufferByteBased(rawBytes), cBusOptions)
 }
 
-func WriteCALReply(writeBuffer utils.WriteBuffer, calReply CALReply) error {
-	return writeToHex("calReply", writeBuffer, calReply)
+func WriteEncodedReply(writeBuffer utils.WriteBuffer, encodedReply EncodedReply) error {
+	return writeToHex("encodedReply", writeBuffer, encodedReply)
 }
 
-func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16, options CBusOptions, requestContext RequestContext) (CALReply, error) {
-	rawBytes, err := readBytesFromHex("calReply", readBuffer, payloadLength)
+func ReadEncodedReply(readBuffer utils.ReadBuffer, payloadLength uint16, options CBusOptions, requestContext RequestContext) (EncodedReply, error) {
+	rawBytes, err := readBytesFromHex("encodedReply", readBuffer, payloadLength)
 	if err != nil {
 		return nil, errors.Wrap(err, "Error getting hex")
 	}
-	return CALReplyParse(utils.NewReadBufferByteBased(rawBytes), options, requestContext)
+	return EncodedReplyParse(utils.NewReadBufferByteBased(rawBytes), options, requestContext)
 }
 
 func WriteCALDataOrSetParameter(writeBuffer utils.WriteBuffer, calDataOrSetParameter CALDataOrSetParameter) error {
@@ -62,42 +62,6 @@ func ReadCALDataOrSetParameter(readBuffer utils.ReadBuffer, payloadLength uint16
 	return CALDataOrSetParameterParse(utils.NewReadBufferByteBased(rawBytes))
 }
 
-func WriteMonitoredSAL(writeBuffer utils.WriteBuffer, monitoredSAL MonitoredSAL) error {
-	return writeToHex("monitoredSAL", writeBuffer, monitoredSAL)
-}
-
-func ReadMonitoredSAL(readBuffer utils.ReadBuffer, payloadLength uint16, options CBusOptions) (MonitoredSAL, error) {
-	rawBytes, err := readBytesFromHex("monitoredSAL", readBuffer, payloadLength)
-	if err != nil {
-		return nil, errors.Wrap(err, "Error getting hex")
-	}
-	return MonitoredSALParse(utils.NewReadBufferByteBased(rawBytes), options)
-}
-
-func WriteStandardFormatStatusReply(writeBuffer utils.WriteBuffer, reply StandardFormatStatusReply) error {
-	return writeToHex("reply", writeBuffer, reply)
-}
-
-func ReadStandardFormatStatusReply(readBuffer utils.ReadBuffer, payloadLength uint16) (StandardFormatStatusReply, error) {
-	rawBytes, err := readBytesFromHex("reply", readBuffer, payloadLength)
-	if err != nil {
-		return nil, errors.Wrap(err, "Error getting hex")
-	}
-	return StandardFormatStatusReplyParse(utils.NewReadBufferByteBased(rawBytes))
-}
-
-func WriteExtendedFormatStatusReply(writeBuffer utils.WriteBuffer, reply ExtendedFormatStatusReply) error {
-	return writeToHex("reply", writeBuffer, reply)
-}
-
-func ReadExtendedFormatStatusReply(readBuffer utils.ReadBuffer, payloadLength uint16) (ExtendedFormatStatusReply, error) {
-	rawBytes, err := readBytesFromHex("reply", readBuffer, payloadLength)
-	if err != nil {
-		return nil, errors.Wrap(err, "Error getting hex")
-	}
-	return ExtendedFormatStatusReplyParse(utils.NewReadBufferByteBased(rawBytes))
-}
-
 func readBytesFromHex(logicalName string, readBuffer utils.ReadBuffer, payloadLength uint16) ([]byte, error) {
 	if payloadLength == 0 {
 		return nil, errors.New("Length is 0")
diff --git a/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go b/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
index 36d6d4a0b..eb46dab1d 100644
--- a/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
+++ b/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
@@ -120,6 +120,8 @@ func (a *Analyzer) PackageParse(packetInformation common.PacketInformation, payl
 			a.requestContext = model.NewRequestContext(true, false, sendIdentifyRequestBefore)
 		}
 	case model.CBusMessageToClientExactly:
+		// We received a request so we need to reset our flags
+		a.requestContext = model.NewRequestContext(false, false, false)
 	}
 	log.Debug().Msgf("Parsed c-bus command \n%v", parse)
 	return parse, nil
@@ -256,32 +258,38 @@ func (a *Analyzer) PrettyPrint(message interface{}) {
 				// TODO: add recursion
 				case model.ReplyOrConfirmationReplyExactly:
 					switch reply := reply.GetReply().(type) {
-					case model.ReplyExtendedFormatStatusReplyExactly:
+					case model.ReplyEncodedReplyExactly:
+						switch reply := reply.GetEncodedReply().(type) {
+						case model.EncodedReplyExtendedFormatStatusReplyExactly:
+							// We print this a second time as the first print contains only the hex part
+							fmt.Printf("%v\n", reply.GetReply())
+						case model.EncodedReplyStandardFormatStatusReplyExactly:
+							// We print this a second time as the first print contains only the hex part
+							fmt.Printf("%v\n", reply.GetReply())
+						case model.EncodedReplyCALReplyExactly:
+							// We print this a second time as the first print contains only the hex part
+							fmt.Printf("%v\n", reply.GetCalReply())
+						case model.MonitoredSALReplyExactly:
+							// We print this a second time as the first print contains only the hex part
+							fmt.Printf("%v\n", reply.GetMonitoredSAL())
+						}
+					}
+				}
+			case model.ReplyOrConfirmationReplyExactly:
+				switch reply := reply.GetReply().(type) {
+				case model.ReplyEncodedReplyExactly:
+					switch reply := reply.GetEncodedReply().(type) {
+					case model.EncodedReplyExtendedFormatStatusReplyExactly:
 						// We print this a second time as the first print contains only the hex part
 						fmt.Printf("%v\n", reply.GetReply())
-					case model.ReplyStandardFormatStatusReplyExactly:
+					case model.EncodedReplyStandardFormatStatusReplyExactly:
 						// We print this a second time as the first print contains only the hex part
 						fmt.Printf("%v\n", reply.GetReply())
-					case model.ReplyCALReplyExactly:
+					case model.EncodedReplyCALReplyExactly:
 						// We print this a second time as the first print contains only the hex part
 						fmt.Printf("%v\n", reply.GetCalReply())
-					case model.MonitoredSALReplyExactly:
-						// We print this a second time as the first print contains only the hex part
-						fmt.Printf("%v\n", reply.GetMonitoredSAL())
 					}
 				}
-			case model.ReplyOrConfirmationReplyExactly:
-				switch reply := reply.GetReply().(type) {
-				case model.ReplyExtendedFormatStatusReplyExactly:
-					// We print this a second time as the first print contains only the hex part
-					fmt.Printf("%v\n", reply.GetReply())
-				case model.ReplyStandardFormatStatusReplyExactly:
-					// We print this a second time as the first print contains only the hex part
-					fmt.Printf("%v\n", reply.GetReply())
-				case model.ReplyCALReplyExactly:
-					// We print this a second time as the first print contains only the hex part
-					fmt.Printf("%v\n", reply.GetCalReply())
-				}
 			}
 		}
 	}
diff --git a/plc4j/drivers/c-bus/pom.xml b/plc4j/drivers/c-bus/pom.xml
index a6babaa32..1600f6ca5 100644
--- a/plc4j/drivers/c-bus/pom.xml
+++ b/plc4j/drivers/c-bus/pom.xml
@@ -169,6 +169,10 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-text</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
diff --git a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
index 973db0a40..7bfccb913 100644
--- a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
+++ b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
@@ -38,13 +38,13 @@ public class StaticHelper {
         return CBusCommand.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions);
     }
 
-    public static void writeCALReply(WriteBuffer writeBuffer, CALReply calReply) throws SerializationException {
-        writeToHex("calReply", writeBuffer, calReply, calReply.getLengthInBytes());
+    public static void writeEncodedReply(WriteBuffer writeBuffer, EncodedReply encodedReply) throws SerializationException{
+        writeToHex("encodedReply", writeBuffer, encodedReply, encodedReply.getLengthInBytes());
     }
 
-    public static CALReply readCALReply(ReadBuffer readBuffer, Integer payloadLength, CBusOptions cBusOptions, RequestContext requestContext) throws ParseException {
-        byte[] rawBytes = readBytesFromHex("calReply", readBuffer, payloadLength);
-        return CALReply.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions, requestContext);
+    public static EncodedReply readEncodedReply(ReadBuffer readBuffer, Integer payloadLength, CBusOptions cBusOptions, RequestContext requestContext) throws ParseException {
+        byte[] rawBytes = readBytesFromHex("encodedReply", readBuffer, payloadLength);
+        return EncodedReply.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions, requestContext);
     }
 
     public static void writeCALDataOrSetParameter(WriteBuffer writeBuffer, CALDataOrSetParameter calDataOrSetParameter) throws SerializationException {
@@ -56,33 +56,6 @@ public class StaticHelper {
         return CALDataOrSetParameter.staticParse(new ReadBufferByteBased(rawBytes));
     }
 
-    public static void writeMonitoredSAL(WriteBuffer writeBuffer, MonitoredSAL monitoredSAL) throws SerializationException {
-        writeToHex("monitoredSAL", writeBuffer, monitoredSAL, monitoredSAL.getLengthInBytes());
-    }
-
-    public static MonitoredSAL readMonitoredSAL(ReadBuffer readBuffer, Integer payloadLength, CBusOptions cBusOptions) throws ParseException {
-        byte[] rawBytes = readBytesFromHex("monitoredSAL", readBuffer, payloadLength);
-        return MonitoredSAL.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions);
-    }
-
-    public static void writeStandardFormatStatusReply(WriteBuffer writeBuffer, StandardFormatStatusReply standardFormatStatusReply) throws SerializationException {
-        writeToHex("reply", writeBuffer, standardFormatStatusReply, standardFormatStatusReply.getLengthInBytes());
-    }
-
-    public static StandardFormatStatusReply readStandardFormatStatusReply(ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
-        byte[] rawBytes = readBytesFromHex("reply", readBuffer, payloadLength);
-        return StandardFormatStatusReply.staticParse(new ReadBufferByteBased(rawBytes));
-    }
-
-    public static void writeExtendedFormatStatusReply(WriteBuffer writeBuffer, ExtendedFormatStatusReply extendedFormatStatusReply) throws SerializationException {
-        writeToHex("reply", writeBuffer, extendedFormatStatusReply, extendedFormatStatusReply.getLengthInBytes());
-    }
-
-    public static ExtendedFormatStatusReply readExtendedFormatStatusReply(ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
-        byte[] rawBytes = readBytesFromHex("reply", readBuffer, payloadLength);
-        return ExtendedFormatStatusReply.staticParse(new ReadBufferByteBased(rawBytes));
-    }
-
     private static byte[] readBytesFromHex(String logicalName, ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
         if (payloadLength == 0) {
             throw new ParseException("Length is 0");
diff --git a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
index 49ffd6743..3ef9aaf58 100644
--- a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
+++ b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
@@ -19,9 +19,11 @@
 package org.apache.plc4x.java.cbus;
 
 import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.text.StringEscapeUtils;
 import org.apache.plc4x.java.cbus.readwrite.*;
 import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
+import org.apache.plc4x.java.spi.utils.Serializable;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
@@ -135,9 +137,9 @@ public class RandomPackagesTest {
                 System.out.println(msg);
                 CALData calData = ((CALDataOrSetParameterValue) ((RequestDirectCommandAccess) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter()).getCalData();
                 System.out.println(calData);
+                assertMessageMatches(bytes, msg);
             }
 
-            @Disabled("not implemented yet")
             // 4.2.7
             @Test
             void directCommandAccess2() throws Exception {
@@ -147,8 +149,9 @@ public class RandomPackagesTest {
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                CALData calData = ((CALDataOrSetParameterValue) ((RequestDirectCommandAccess) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter()).getCalData();
+                CALData calData = ((CALDataOrSetParameterValue) ((RequestObsolete) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter()).getCalData();
                 System.out.println(calData);
+                assertMessageMatches(bytes, msg);
             }
 
         }
@@ -188,22 +191,26 @@ public class RandomPackagesTest {
             void pointToMultiPointCommandDirect() throws Exception {
                 byte[] bytes = "\\0538000108BA\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
                 CBusCommand cbusCommand = ((RequestCommand) ((CBusMessageToServer) msg).getRequest()).getCbusCommand();
                 System.out.println(cbusCommand);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void pointToMultiPointCommandBridged() throws Exception {
                 byte[] bytes = "\\05FF007A38004A\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
                 CBusCommand cbusCommand = ((RequestCommand) ((CBusMessageToServer) msg).getRequest()).getCbusCommand();
                 System.out.println(cbusCommand);
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -214,11 +221,13 @@ public class RandomPackagesTest {
             void pointToPointToMultiPointCommand2() throws Exception {
                 byte[] bytes = "\\03420938010871\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
                 CBusCommand cbusCommand = ((RequestCommand) ((CBusMessageToServer) msg).getRequest()).getCbusCommand();
                 System.out.println(cbusCommand);
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -232,24 +241,29 @@ public class RandomPackagesTest {
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void calReplyNormal() throws Exception {
                 byte[] bytes = Hex.decodeHex("8902312E322E363620200A");
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CALReply msg = CALReplyShort.staticParse(readBufferByteBased, cBusOptions, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void calReplySmart() throws Exception {
                 byte[] bytes = Hex.decodeHex("860593008902312E322E363620207F");
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CALReply msg = CALReplyLong.staticParse(readBufferByteBased, cBusOptions, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -260,11 +274,14 @@ public class RandomPackagesTest {
             void monitoredSal() throws Exception {
                 byte[] bytes = "0503380079083F\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                MonitoredSAL monitoredSAL = ((MonitoredSALReply) ((ReplyOrConfirmationReply) msg).getReply()).getMonitoredSAL();
+                EncodedReply encodedReply = ((ReplyEncodedReply) ((ReplyOrConfirmationReply) msg).getReply()).getEncodedReply();
+                MonitoredSAL monitoredSAL = ((MonitoredSALReply) encodedReply).getMonitoredSAL();
                 System.out.println(monitoredSAL);
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -278,6 +295,7 @@ public class RandomPackagesTest {
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
@@ -287,6 +305,7 @@ public class RandomPackagesTest {
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
@@ -296,6 +315,7 @@ public class RandomPackagesTest {
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
@@ -305,6 +325,7 @@ public class RandomPackagesTest {
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
@@ -314,6 +335,7 @@ public class RandomPackagesTest {
                 ReplyOrConfirmation msg = ReplyOrConfirmation.staticParse(readBufferByteBased, cBusOptions, bytes.length, requestContext);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -325,6 +347,7 @@ public class RandomPackagesTest {
             StandardFormatStatusReply msg = StandardFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -334,6 +357,7 @@ public class RandomPackagesTest {
             StandardFormatStatusReply msg = StandardFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -343,6 +367,7 @@ public class RandomPackagesTest {
             StandardFormatStatusReply msg = StandardFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         // 7.4
@@ -353,6 +378,7 @@ public class RandomPackagesTest {
             ExtendedFormatStatusReply msg = ExtendedFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -362,6 +388,7 @@ public class RandomPackagesTest {
             ExtendedFormatStatusReply msg = ExtendedFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -371,6 +398,7 @@ public class RandomPackagesTest {
             ExtendedFormatStatusReply msg = ExtendedFormatStatusReply.staticParse(readBufferByteBased, false);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         // 9.1
@@ -378,101 +406,96 @@ public class RandomPackagesTest {
         class PointToMultiPointCommandsIntoLocalCBusNetwork {
             @Test
             void LightningOff() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "\\0538000114AE\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatus() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "\\05FF007A38004A\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatusReply1() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "D83800A8AA02000000000000000000000000000000000000009C\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
                 requestContext = new RequestContext(false, true, false);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
+                StandardFormatStatusReply reply = ((EncodedReplyStandardFormatStatusReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getReply();
                 System.out.println(reply);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatusReply2() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "D838580000000000000000000000000000000000000000000098\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(false, true, false);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
-                System.out.println(reply);
+                System.out.println(((EncodedReplyStandardFormatStatusReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getReply());
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatusReply3() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "D638B0000000000000000000000000000000000000000042\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(false, true, false);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
-                System.out.println(reply);
+                System.out.println(((EncodedReplyStandardFormatStatusReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getReply());
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatusReply4() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "86999900F8003800A8AA0200000000000000000000000000000000000000C4\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(false, true, false);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
-                System.out.println(reply);
+                System.out.println(((EncodedReplyCALReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getCalReply());
+                assertMessageMatches(bytes, msg);
             }
 
 
             @Test
             void LightningStatusReply5() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "86999900F800385800000000000000000000000000000000000000000000C0\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(false, true, false);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
-                System.out.println(reply);
+                System.out.println(((EncodedReplyCALReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getCalReply());
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void LightningStatusReply6() throws Exception {
-                // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "86999900F60038B000000000000000000000000000000000000000008F\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(false, true, false);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
-                StandardFormatStatusReply reply = ((ReplyStandardFormatStatusReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getReply();
-                System.out.println(reply);
+                System.out.println(((EncodedReplyCALReply) ((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply()).getCalReply());
+                assertMessageMatches(bytes, msg);
             }
         }
 
@@ -484,19 +507,22 @@ public class RandomPackagesTest {
                 // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "\\0604001A3001AB\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
             @Test
             void Reply() throws Exception {
                 byte[] bytes = "8604990082300328\r\n".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                requestContext = new RequestContext(true, false, false);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
         }
@@ -509,11 +535,13 @@ public class RandomPackagesTest {
                 // TODO: the section describes that on non smart mode the message doesn't have the last CR
                 byte[] bytes = "\\03421B53643801149C\r".getBytes(StandardCharsets.UTF_8);
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+                cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
                 CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
                 CBusCommand cbusCommand = ((RequestCommand) ((CBusMessageToServer) msg).getRequest()).getCbusCommand();
                 System.out.println(cbusCommand);
+                assertMessageMatches(bytes, msg);
             }
 
             @Disabled("the transformation from point to point to multipoint message is not yet implemented as described in 8.4... not sure if we will ever implement that")
@@ -524,6 +552,7 @@ public class RandomPackagesTest {
                 CBusCommand msg = CBusCommand.staticParse(readBufferByteBased, cBusOptions);
                 assertThat(msg).isNotNull();
                 System.out.println(msg);
+                assertMessageMatches(bytes, msg);
             }
 
         }
@@ -536,6 +565,7 @@ public class RandomPackagesTest {
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         // 9.5
@@ -543,9 +573,11 @@ public class RandomPackagesTest {
         void MultipleCommands() throws Exception {
             byte[] bytes = "\\05380001210122012301240A25010A2601D4\r".getBytes(StandardCharsets.UTF_8);
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         // 10.2.1
@@ -556,6 +588,7 @@ public class RandomPackagesTest {
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         // 10.2.1
@@ -569,6 +602,7 @@ public class RandomPackagesTest {
 
             CALDataOrSetParameterSetParameter calDataOrSetParameter = (CALDataOrSetParameterSetParameter) ((RequestObsolete) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter();
             System.out.println(calDataOrSetParameter);
+            assertMessageMatches(bytes, msg);
         }
     }
 
@@ -580,9 +614,11 @@ public class RandomPackagesTest {
         void pointToPointCommandDirect() throws Exception {
             byte[] bytes = "\\0538007902D4\r".getBytes(StandardCharsets.UTF_8);
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
     }
@@ -595,9 +631,11 @@ public class RandomPackagesTest {
         void whatEverThisIs() throws Exception {
             byte[] bytes = "\\3436303230303231303167\r".getBytes(StandardCharsets.UTF_8);
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -607,6 +645,7 @@ public class RandomPackagesTest {
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -620,6 +659,7 @@ public class RandomPackagesTest {
             RequestCommand requestCommand = (RequestCommand) msgToServer.getRequest();
             CBusCommand cbusCommand = requestCommand.getCbusCommand();
             System.out.println(cbusCommand);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -628,14 +668,16 @@ public class RandomPackagesTest {
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
             // We know we send an identify command so we set the cal flag
             requestContext = new RequestContext(true, false, false);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
             CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
             ReplyOrConfirmationConfirmation confirmationReply = (ReplyOrConfirmationConfirmation) messageToClient.getReply();
             ReplyOrConfirmationReply normalReply = (ReplyOrConfirmationReply) confirmationReply.getEmbeddedReply();
-            ReplyCALReply calReplyReply = (ReplyCALReply) normalReply.getReply();
-            System.out.println(calReplyReply.getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) normalReply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -643,14 +685,16 @@ public class RandomPackagesTest {
             byte[] bytes = "nl.8220025C\r\n".getBytes(StandardCharsets.UTF_8);
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
             requestContext = new RequestContext(true, false, false);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
             CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
             ReplyOrConfirmationConfirmation confirmationReply = (ReplyOrConfirmationConfirmation) messageToClient.getReply();
             ReplyOrConfirmationReply normalReply = (ReplyOrConfirmationReply) confirmationReply.getEmbeddedReply();
-            ReplyCALReply calReplyReply = (ReplyCALReply) normalReply.getReply();
-            System.out.println(calReplyReply.getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) normalReply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -663,6 +707,7 @@ public class RandomPackagesTest {
             CBusMessageToServer messageToServer = (CBusMessageToServer) msg;
             RequestCommand requestCommand = (RequestCommand) messageToServer.getRequest();
             System.out.println(requestCommand.getCbusCommand());
+            assertMessageMatches(bytes, msg);
         }
 
 
@@ -677,6 +722,7 @@ public class RandomPackagesTest {
             RequestObsolete requestObsolete = (RequestObsolete) messageToServer.getRequest();
             CALData calData = ((CALDataOrSetParameterValue) requestObsolete.getCalDataOrSetParameter()).getCalData();
             System.out.println(calData);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -685,13 +731,16 @@ public class RandomPackagesTest {
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
             // We know we send an identify command so we set the cal flag
             requestContext = new RequestContext(true, false, true);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
             assertThat(msg).isNotNull();
             System.out.println(msg);
             CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
             ReplyOrConfirmationConfirmation confirmationReply = (ReplyOrConfirmationConfirmation) messageToClient.getReply();
             ReplyOrConfirmationReply normalReply = (ReplyOrConfirmationReply) confirmationReply.getEmbeddedReply();
-            System.out.println(((ReplyCALReply) normalReply.getReply()).getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) normalReply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -709,6 +758,7 @@ public class RandomPackagesTest {
             WriteBufferByteBased writeBuffer = new WriteBufferByteBased(bytes.length);
             msg.serialize(writeBuffer);
             assertThat(writeBuffer.getBytes()).isEqualTo(bytes);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -723,13 +773,10 @@ public class RandomPackagesTest {
             CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
             ReplyOrConfirmationConfirmation confirmationReply = (ReplyOrConfirmationConfirmation) messageToClient.getReply();
             ReplyOrConfirmationReply normalReply = (ReplyOrConfirmationReply) confirmationReply.getEmbeddedReply();
-            ReplyCALReply calReplyReply = (ReplyCALReply) normalReply.getReply();
-            System.out.println(calReplyReply.getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) normalReply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
 
-            WriteBufferByteBased writeBuffer = new WriteBufferByteBased(bytes.length);
-            msg.serialize(writeBuffer);
-            byte[] bytes1 = writeBuffer.getBytes();
-            assertThat(bytes1).isEqualTo(bytes);
+            assertMessageMatches(bytes, msg);
         }
 
         @Disabled
@@ -743,10 +790,7 @@ public class RandomPackagesTest {
             System.out.println(msg);
             System.out.println(((RequestObsolete) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter());
 
-            WriteBufferByteBased writeBuffer = new WriteBufferByteBased(bytes.length);
-            msg.serialize(writeBuffer);
-            byte[] bytes1 = writeBuffer.getBytes();
-            assertThat(bytes1).isEqualTo(bytes);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -761,13 +805,10 @@ public class RandomPackagesTest {
             CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
             ReplyOrConfirmationConfirmation confirmationReply = (ReplyOrConfirmationConfirmation) messageToClient.getReply();
             ReplyOrConfirmationReply normalReply = (ReplyOrConfirmationReply) confirmationReply.getEmbeddedReply();
-            ReplyCALReply calReplyReply = (ReplyCALReply) normalReply.getReply();
-            System.out.println(calReplyReply.getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) normalReply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
 
-            WriteBufferByteBased writeBuffer = new WriteBufferByteBased(bytes.length);
-            msg.serialize(writeBuffer);
-            byte[] bytes1 = writeBuffer.getBytes();
-            assertThat(bytes1).isEqualTo(bytes);
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -782,8 +823,10 @@ public class RandomPackagesTest {
             RequestCommand requestCommand = (RequestCommand) messageToServer.getRequest();
             CBusCommand cbusCommand = requestCommand.getCbusCommand();
             System.out.println(cbusCommand);
+            assertMessageMatches(bytes, msg);
         }
 
+        @Disabled
         @Test
         void wat() throws Exception {
             byte[] bytes = "D8FF0024000002000000000000000008000000000000000000\r\n".getBytes(StandardCharsets.UTF_8);
@@ -799,8 +842,9 @@ public class RandomPackagesTest {
             MonitoredSALReply monitoredSALReply = (MonitoredSALReply) reply.getReply();
             System.out.println(monitoredSALReply.getMonitoredSAL());
              */
-            ReplyCALReply replyReply = (ReplyCALReply) reply.getReply();
-            System.out.println(replyReply.getCalReply());
+            EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) reply.getReply()).getEncodedReply();
+            System.out.println(encodedReplyCALReply.getCalReply());
+            assertMessageMatches(bytes, msg);
         }
 
         @Test
@@ -812,6 +856,72 @@ public class RandomPackagesTest {
             assertThat(msg).isNotNull();
             System.out.println(msg);
             System.out.println(((RequestCommand) ((CBusMessageToServer) msg).getRequest()).getCbusCommand());
+            assertMessageMatches(bytes, msg);
         }
+
+        @Test
+        void statusReply() throws Exception {
+            byte[] bytes = "D8FF5800000000000000000000000000000000000000000000D1\r\n".getBytes(StandardCharsets.UTF_8);
+            ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+            requestContext = new RequestContext(false, true, false);
+            CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
+            assertThat(msg).isNotNull();
+            System.out.println(msg);
+            Reply normalReply = ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply();
+            EncodedReplyStandardFormatStatusReply encodedReplyStandardFormatStatusReply = (EncodedReplyStandardFormatStatusReply) ((ReplyEncodedReply) normalReply).getEncodedReply();
+            System.out.println(encodedReplyStandardFormatStatusReply.getReply());
+
+            assertMessageMatches(bytes, msg);
+        }
+
+        @Test
+        void identifyUnitSummary() throws Exception {
+            byte[] bytes = "2110\r".getBytes(StandardCharsets.UTF_8);
+            ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+            CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
+            assertThat(msg).isNotNull();
+            System.out.println(msg);
+            System.out.println(((RequestObsolete) ((CBusMessageToServer) msg).getRequest()).getCalDataOrSetParameter());
+
+            assertMessageMatches(bytes, msg);
+        }
+
+        @Test
+        void identifyUnitSummaryResponse() throws Exception {
+            byte[] bytes = "o.8510020000FF6A\r\n".getBytes(StandardCharsets.UTF_8);
+            ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+            requestContext = new RequestContext(true,false,true);
+            CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
+            assertThat(msg).isNotNull();
+            System.out.println(msg);
+            System.out.println(((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((ReplyOrConfirmationConfirmation) ((CBusMessageToClient) msg).getReply()).getEmbeddedReply()).getReply()).getEncodedReply());
+
+            assertMessageMatches(bytes, msg);
+        }
+
+        @Disabled
+        @Test
+        void strangeMonitoredCal() throws Exception {
+            byte[] bytes = "0531AC0079042F0401430316000011\r\n".getBytes(StandardCharsets.UTF_8);
+            ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+            requestContext = new RequestContext(false, false, false);
+            CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
+            assertThat(msg).isNotNull();
+            System.out.println(msg);
+            System.out.println(((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply());
+
+            assertMessageMatches(bytes, msg);
+        }
+    }
+
+    private void assertMessageMatches(byte[] expectedBytes, Serializable msg) throws Exception {
+        WriteBufferByteBased writeBuffer = new WriteBufferByteBased(expectedBytes.length);
+        msg.serialize(writeBuffer);
+        byte[] actualBytes = writeBuffer.getBytes();
+        assertThat(actualBytes).withFailMessage(() -> "Actual:\n" + StringEscapeUtils.escapeJava(new String(actualBytes))+"\ndoes not match expected\n"+ StringEscapeUtils.escapeJava(new String(expectedBytes))).isEqualTo(expectedBytes);
     }
 }
diff --git a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
index e0969beab..651b7c10b 100644
--- a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
+++ b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
@@ -1301,44 +1301,176 @@
     [simple  SALCommandTypeContainer commandTypeContainer                                   ]
     [virtual SALCommandType          commandType          'commandTypeContainer.commandType']
     [typeSwitch commandType
-        ['OFF'            SALDataOff
+        ['OFF'            *Off
             [simple byte group                                                              ]
         ]
-        ['ON'             SALDataOn
+        ['ON'             *On
             [simple byte group                                                              ]
         ]
-        ['RAMP_TO_LEVEL'  SALDataRampToLevel
+        ['RAMP_TO_LEVEL'  *RampToLevel
             [simple byte group                                                              ]
             [simple byte level                                                              ]
         ]
-        ['TERMINATE_RAMP' SALDataTerminateRamp
+        ['TERMINATE_RAMP' *TerminateRamp
             [simple byte group                                                              ]
         ]
+        ['LABEL'          *Label(SALCommandTypeContainer commandTypeContainer)
+            [simple byte            group                                                   ]
+            [simple LabelOptions    labelOptions                                            ]
+            [simple Language        language                                                ]
+            [array  byte      data        count 'commandTypeContainer.numBytes-3'           ]
+        ]
     ]
     // TODO: we need to check that we don't read the crc by accident
     [optional SALData salData                                                               ]
 ]
 
-[enum uint 8 SALCommandTypeContainer(SALCommandType commandType)
-    ['0x01' SALCommandOff                       ['OFF'           ]]
-    ['0x79' SALCommandOn                        ['ON'            ]]
-    ['0x02' SALCommandRampToLevel_Instantaneous ['RAMP_TO_LEVEL' ]]
-    ['0x0A' SALCommandRampToLevel_4Second       ['RAMP_TO_LEVEL' ]]
-    ['0x12' SALCommandRampToLevel_8Second       ['RAMP_TO_LEVEL' ]]
-    ['0x1A' SALCommandRampToLevel_12Second      ['RAMP_TO_LEVEL' ]]
-    ['0x22' SALCommandRampToLevel_20Second      ['RAMP_TO_LEVEL' ]]
-    ['0x2A' SALCommandRampToLevel_30Second      ['RAMP_TO_LEVEL' ]]
-    ['0x32' SALCommandRampToLevel_40Second      ['RAMP_TO_LEVEL' ]]
-    ['0x3A' SALCommandRampToLevel_60Second      ['RAMP_TO_LEVEL' ]]
-    ['0x42' SALCommandRampToLevel_90Second      ['RAMP_TO_LEVEL' ]]
-    ['0x4A' SALCommandRampToLevel_120Second     ['RAMP_TO_LEVEL' ]]
-    ['0x52' SALCommandRampToLevel_180Second     ['RAMP_TO_LEVEL' ]]
-    ['0x5A' SALCommandRampToLevel_300Second     ['RAMP_TO_LEVEL' ]]
-    ['0x62' SALCommandRampToLevel_420Second     ['RAMP_TO_LEVEL' ]]
-    ['0x6A' SALCommandRampToLevel_600Second     ['RAMP_TO_LEVEL' ]]
-    ['0x72' SALCommandRampToLevel_900Second     ['RAMP_TO_LEVEL' ]]
-    ['0x7A' SALCommandRampToLevel_1020Second    ['RAMP_TO_LEVEL' ]]
-    ['0x09' SALCommandTerminateRamp             ['TERMINATE_RAMP']]
+[type LabelOptions
+    [reserved bit           'false'     ] // only for dynamic icon loading can switch to 1
+    [simple   LabelFlavour  labelFlavour]
+    [reserved bit           'false'     ]
+    [reserved bit           'false'     ] // For Lighting, this bit must be 0
+    [simple   LabelType     labelType   ]
+    [reserved bit           'false'     ] // For Lighting, this bit must be 0
+]
+
+[enum uint 2 LabelFlavour
+    ['0' FLAVOUR_1              ]
+    ['1' FLAVOUR_2              ]
+    ['2' FLAVOUR_3              ]
+    ['3' FLAVOUR_4              ]
+]
+
+[enum uint 2 LabelType
+    ['0' TEXT_LABEL             ]
+    ['1' PREDEFINED_ICON        ]
+    ['2' LOAD_DYNAMIC_ICON      ]
+    ['3' SET_PREFERRED_LANGUAGE ]
+]
+
+[enum uint 8 Language
+    ['0x01' ENGLISH                     ]
+    ['0x02' ENGLISH_AUSTRALIA           ]
+    ['0x03' ENGLISH_BELIZE              ]
+    ['0x04' ENGLISH_CANADA              ]
+    ['0x05' ENGLISH_CARRIBEAN           ]
+    ['0x06' ENGLISH_IRELAND             ]
+    ['0x07' ENGLISH_JAMAICA             ]
+    ['0x08' ENGLISH_NEW_ZEALAND         ]
+    ['0x09' ENGLISH_PHILIPPINES         ]
+    ['0x0A' ENGLISH_SOUTH_AFRICA        ]
+    ['0x0B' ENGLISH_TRINIDAD            ]
+    ['0x0C' ENGLISH_UK                  ]
+    ['0x0D' ENGLISH_USA                 ]
+    ['0x0E' ENGLISH_ZIMBABWE            ]
+    ['0x40' AFRIKAANS                   ]
+    ['0x41' BASQUE                      ]
+    ['0x42' CATALAN                     ]
+    ['0x43' DANISH                      ]
+    ['0x44' DUTCH_BELGIUM               ]
+    ['0x45' DUTCH_NETHERLANDS           ]
+    ['0x46' FAEROESE                    ]
+    ['0x47' FINNISH                     ]
+    ['0x48' FRENCH_BELGIUM              ]
+    ['0x49' FRENCH_CANADA               ]
+    ['0x4A' FRENCH                      ]
+    ['0x4B' FRENCH_LUXEMBOURG           ]
+    ['0x4C' FRENCH_MONACO               ]
+    ['0x4D' FRENCH_SWITZERLAND          ]
+    ['0x4E' GALICIAN                    ]
+    ['0x4F' GERMAN_AUSTRIA              ]
+    ['0x50' GERMAN                      ]
+    ['0x51' GERMAN_LIECHTENSTEIN        ]
+    ['0x52' GERMAN_LUXEMBOURG           ]
+    ['0x53' GERMAN_SWITZERLAND          ]
+    ['0x54' ICELANDIC                   ]
+    ['0x55' INDONESIAN                  ]
+    ['0x56' ITALIAN                     ]
+    ['0x57' ITALIAN_SWITZERLAND         ]
+    ['0x58' MALAY_BRUNEI                ]
+    ['0x59' MALAY                       ]
+    ['0x5A' NORWEGIAN                   ]
+    ['0x5B' NORWEGIAN_NYNORSK           ]
+    ['0x5C' PORTUGUESE_BRAZIL           ]
+    ['0x5D' PORTUGUESE                  ]
+    ['0x5E' SPANISH_ARGENTINE           ]
+    ['0x5F' SPANISH_BOLIVIA             ]
+    ['0x60' SPANISH_CHILE               ]
+    ['0x61' SPANISH_COLOMBIA            ]
+    ['0x62' SPANISH_COSTA_RICA          ]
+    ['0x63' SPANISH_DOMINICAN_REPUBLIC  ]
+    ['0x64' SPANISH_ECUADOR             ]
+    ['0x65' SPANISH_EL_SALVADOR         ]
+    ['0x66' SPANISH_GUATEMALA           ]
+    ['0x67' SPANISH_HONDURAS            ]
+    ['0x68' SPANISH                     ]
+    ['0x69' SPANISH_MEXICO              ]
+    ['0x6A' SPANISH_NICARAGUA           ]
+    ['0x6B' SPANISH_PANAMA              ]
+    ['0x6C' SPANISH_PARAGUAY            ]
+    ['0x6D' SPANISH_PERU                ]
+    ['0x6E' SPANISH_PERTO_RICO          ]
+    ['0x6F' SPANISH_TRADITIONAL         ]
+    ['0x70' SPANISH_URUGUAY             ]
+    ['0x71' SPANISH_VENEZUELA           ]
+    ['0x72' SWAHILI                     ]
+    ['0x73' SWEDISH                     ]
+    ['0x74' SWEDISH_FINLAND             ]
+    ['0xCA' CHINESE_CP936               ]
+]
+
+[enum uint 8 SALCommandTypeContainer(SALCommandType commandType, uint 5 numBytes)
+    ['0x01' SALCommandOff                       ['OFF',             '1' ]]
+    ['0x79' SALCommandOn                        ['ON',              '1' ]]
+    ['0x02' SALCommandRampToLevel_Instantaneous ['RAMP_TO_LEVEL',   '1' ]]
+    ['0x0A' SALCommandRampToLevel_4Second       ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x12' SALCommandRampToLevel_8Second       ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x1A' SALCommandRampToLevel_12Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x22' SALCommandRampToLevel_20Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x2A' SALCommandRampToLevel_30Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x32' SALCommandRampToLevel_40Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x3A' SALCommandRampToLevel_60Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x42' SALCommandRampToLevel_90Second      ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x4A' SALCommandRampToLevel_120Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x52' SALCommandRampToLevel_180Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x5A' SALCommandRampToLevel_300Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x62' SALCommandRampToLevel_420Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x6A' SALCommandRampToLevel_600Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x72' SALCommandRampToLevel_900Second     ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x7A' SALCommandRampToLevel_1020Second    ['RAMP_TO_LEVEL',   '2' ]]
+    ['0x09' SALCommandTerminateRamp             ['TERMINATE_RAMP',  '1' ]]
+    ['0xA0' SALCommandLabel_0Bytes              ['LABEL',           '0' ]]
+    ['0xA1' SALCommandLabel_1Bytes              ['LABEL',           '1' ]]
+    ['0xA2' SALCommandLabel_2Bytes              ['LABEL',           '2' ]]
+    ['0xA3' SALCommandLabel_3Bytes              ['LABEL',           '3' ]]
+    ['0xA4' SALCommandLabel_4Bytes              ['LABEL',           '4' ]]
+    ['0xA5' SALCommandLabel_5Bytes              ['LABEL',           '5' ]]
+    ['0xA6' SALCommandLabel_6Bytes              ['LABEL',           '6' ]]
+    ['0xA7' SALCommandLabel_7Bytes              ['LABEL',           '7' ]]
+    ['0xA8' SALCommandLabel_8Bytes              ['LABEL',           '8' ]]
+    ['0xA9' SALCommandLabel_9Bytes              ['LABEL',           '9' ]]
+    ['0xAA' SALCommandLabel_10Bytes             ['LABEL',          '10' ]]
+    ['0xAB' SALCommandLabel_11Bytes             ['LABEL',          '11' ]]
+    ['0xAC' SALCommandLabel_12Bytes             ['LABEL',          '12' ]]
+    ['0xAD' SALCommandLabel_13Bytes             ['LABEL',          '13' ]]
+    ['0xAE' SALCommandLabel_14Bytes             ['LABEL',          '14' ]]
+    ['0xAF' SALCommandLabel_15Bytes             ['LABEL',          '15' ]]
+    ['0xB0' SALCommandLabel_16Bytes             ['LABEL',          '16' ]]
+    ['0xB1' SALCommandLabel_17Bytes             ['LABEL',          '17' ]]
+    ['0xB2' SALCommandLabel_18Bytes             ['LABEL',          '18' ]]
+    ['0xB3' SALCommandLabel_19Bytes             ['LABEL',          '19' ]]
+    ['0xB4' SALCommandLabel_20Bytes             ['LABEL',          '20' ]]
+    ['0xB5' SALCommandLabel_21Bytes             ['LABEL',          '21' ]]
+    ['0xB6' SALCommandLabel_22Bytes             ['LABEL',          '22' ]]
+    ['0xB7' SALCommandLabel_23Bytes             ['LABEL',          '23' ]]
+    ['0xB8' SALCommandLabel_24Bytes             ['LABEL',          '24' ]]
+    ['0xB9' SALCommandLabel_25Bytes             ['LABEL',          '25' ]]
+    ['0xBA' SALCommandLabel_26Bytes             ['LABEL',          '26' ]]
+    ['0xBB' SALCommandLabel_27Bytes             ['LABEL',          '27' ]]
+    ['0xBC' SALCommandLabel_28Bytes             ['LABEL',          '28' ]]
+    ['0xBD' SALCommandLabel_29Bytes             ['LABEL',          '29' ]]
+    ['0xBE' SALCommandLabel_30Bytes             ['LABEL',          '30' ]]
+    ['0xBF' SALCommandLabel_32Bytes             ['LABEL',          '31' ]]
 ]
 
 [enum uint 4 SALCommandType
@@ -1346,6 +1478,7 @@
     ['0x01' ON            ]
     ['0x02' RAMP_TO_LEVEL ]
     ['0x03' TERMINATE_RAMP]
+    ['0x04' LABEL         ]
 ]
 
 [type CommandHeader
@@ -1370,50 +1503,46 @@
 
 [type Reply(CBusOptions cBusOptions, uint 16 replyLength, RequestContext requestContext)
     [peek    byte peekedByte                                                                ]
-    [virtual bit  sendCalCommandBefore        'requestContext.sendCalCommandBefore'         ]
-    [virtual bit  sendSALStatusRequestBefore  'requestContext.sendSALStatusRequestBefore'   ]
-    [virtual bit  exstat                      'cBusOptions.exstat'                          ]
-    [typeSwitch peekedByte, sendCalCommandBefore, sendSALStatusRequestBefore, exstat
-        ['0x2B'                     PowerUpReply // is a +
+    [typeSwitch peekedByte
+        ['0x2B' PowerUpReply // is a +
             [simple PowerUp isA]
         ]
-        ['0x3D'                     ParameterChangeReply // is a =
+        ['0x3D' ParameterChangeReply // is a =
             [simple ParameterChange isA                 ]
         ]
-        ['0x21'                     ServerErrorReply // is a !
+        ['0x21' ServerErrorReply // is a !
             [const  byte    errorMarker     0x21        ]
         ]
-        [*, *, 'true', 'false'      *StandardFormatStatusReply
+        [*      *EncodedReply
             [virtual uint 16 payloadLength 'replyLength']
-            [manual   StandardFormatStatusReply
-                              reply
-                                    'STATIC_CALL("readStandardFormatStatusReply", readBuffer, payloadLength)'
-                                    'STATIC_CALL("writeStandardFormatStatusReply", writeBuffer, reply)'
+            [manual   EncodedReply
+                              encodedReply
+                                    'STATIC_CALL("readEncodedReply", readBuffer, payloadLength, cBusOptions, requestContext)'
+                                    'STATIC_CALL("writeEncodedReply", writeBuffer, encodedReply)'
                                     '_value.lengthInBytes*2'                                     ]
         ]
+    ]
+]
+
+[type EncodedReply(CBusOptions cBusOptions, RequestContext requestContext)
+    [peek    byte peekedByte                                                                ]
+    // TODO: if we reliable can detect this with the mask we don't need the request context anymore
+    [virtual bit  isCalCommand              '(peekedByte & 0x3F) == 0x06 || requestContext.sendCalCommandBefore'       ]
+    [virtual bit  isSALStatusRequest        '(peekedByte & 0xE0) == 0xC0 || requestContext.sendSALStatusRequestBefore' ]
+    [virtual bit  isMonitoredSAL            '(peekedByte & 0x3F) == 0x05'         ]
+    [virtual bit  exstat                    'cBusOptions.exstat'                  ]
+    [typeSwitch isMonitoredSAL, isCalCommand, isSALStatusRequest, exstat
+        ['true', 'false', 'false'   MonitoredSALReply
+            [simple   MonitoredSAL('cBusOptions') monitoredSAL    ]
+        ]
+        [*, *, 'true', 'false'      *StandardFormatStatusReply
+            [simple   StandardFormatStatusReply                     reply           ]
+        ]
         [*, *, 'true', 'true'       *ExtendedFormatStatusReply
-            [virtual uint 16 payloadLength 'replyLength']
-            [manual   ExtendedFormatStatusReply
-                              reply
-                                    'STATIC_CALL("readExtendedFormatStatusReply", readBuffer, payloadLength)'
-                                    'STATIC_CALL("writeExtendedFormatStatusReply", writeBuffer, reply)'
-                                    '_value.lengthInBytes*2'                                     ]
+            [simple   ExtendedFormatStatusReply                     reply           ]
         ]
         [*, 'true', *, *            *CALReply
-            [virtual uint 16 payloadLength 'replyLength']
-            [manual   CALReply
-                              calReply
-                                    'STATIC_CALL("readCALReply", readBuffer, payloadLength, cBusOptions, requestContext)'
-                                    'STATIC_CALL("writeCALReply", writeBuffer, calReply)'
-                                    '_value.lengthInBytes*2'                                     ]
-        ]
-        [*                          MonitoredSALReply
-            [virtual uint 16 payloadLength 'replyLength']
-            [manual   MonitoredSAL
-                              monitoredSAL
-                                    'STATIC_CALL("readMonitoredSAL", readBuffer, payloadLength, cBusOptions)'
-                                    'STATIC_CALL("writeMonitoredSAL", writeBuffer, monitoredSAL)'
-                                    '_value.lengthInBytes*2'                                     ]
+            [simple   CALReply('cBusOptions', 'requestContext')     calReply        ]
         ]
     ]
 ]