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/05 10:14:14 UTC

[plc4x] 02/02: fix(c-bus): fixed several issues parsing messages

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 5e4ac864397905f3486ba84449d2d918b7ddc1ac
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Tue Jul 5 12:13:57 2022 +0200

    fix(c-bus): fixed several issues parsing messages
---
 .../cbus/readwrite/model/ConfirmationReply.go      |  64 +++++++-
 plc4go/protocols/cbus/readwrite/model/Request.go   | 163 +++++++++++++++++++--
 .../cbus/readwrite/model/RequestCommand.go         |   9 +-
 .../readwrite/model/RequestDirectCommandAccess.go  |   9 +-
 .../protocols/cbus/readwrite/model/RequestEmpty.go |   9 +-
 .../protocols/cbus/readwrite/model/RequestNull.go  |   9 +-
 .../protocols/cbus/readwrite/model/RequestReset.go |  45 +-----
 .../readwrite/model/RequestSmartConnectShortcut.go |  76 +++++++++-
 .../protocols/cbus/readwrite/model/StaticHelper.go | 100 ++++++-------
 .../internal/analyzer/analyzer.go                  |   6 +-
 .../internal/cbusanalyzer/analyzer.go              |  45 +++++-
 .../java/cbus/readwrite/utils/StaticHelper.java    |  70 ++++-----
 .../apache/plc4x/java/cbus/RandomPackagesTest.java |  18 ++-
 .../src/main/resources/protocols/cbus/c-bus.mspec  |  18 ++-
 14 files changed, 454 insertions(+), 187 deletions(-)

diff --git a/plc4go/protocols/cbus/readwrite/model/ConfirmationReply.go b/plc4go/protocols/cbus/readwrite/model/ConfirmationReply.go
index 628205848..50640e429 100644
--- a/plc4go/protocols/cbus/readwrite/model/ConfirmationReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/ConfirmationReply.go
@@ -22,6 +22,8 @@ package model
 import (
 	"github.com/apache/plc4x/plc4go/internal/spi/utils"
 	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+	"io"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
@@ -33,6 +35,8 @@ type ConfirmationReply interface {
 	Reply
 	// GetConfirmation returns Confirmation (property field)
 	GetConfirmation() Confirmation
+	// GetEmbeddedReply returns EmbeddedReply (property field)
+	GetEmbeddedReply() Reply
 }
 
 // ConfirmationReplyExactly can be used when we want exactly this type and not a type which fulfills ConfirmationReply.
@@ -45,7 +49,8 @@ type ConfirmationReplyExactly interface {
 // _ConfirmationReply is the data-structure of this message
 type _ConfirmationReply struct {
 	*_Reply
-	Confirmation Confirmation
+	Confirmation  Confirmation
+	EmbeddedReply Reply
 }
 
 ///////////////////////////////////////////////////////////
@@ -75,16 +80,21 @@ func (m *_ConfirmationReply) GetConfirmation() Confirmation {
 	return m.Confirmation
 }
 
+func (m *_ConfirmationReply) GetEmbeddedReply() Reply {
+	return m.EmbeddedReply
+}
+
 ///////////////////////
 ///////////////////////
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
 // NewConfirmationReply factory function for _ConfirmationReply
-func NewConfirmationReply(confirmation Confirmation, peekedByte byte, messageLength uint16) *_ConfirmationReply {
+func NewConfirmationReply(confirmation Confirmation, embeddedReply Reply, peekedByte byte, messageLength uint16) *_ConfirmationReply {
 	_result := &_ConfirmationReply{
-		Confirmation: confirmation,
-		_Reply:       NewReply(peekedByte, messageLength),
+		Confirmation:  confirmation,
+		EmbeddedReply: embeddedReply,
+		_Reply:        NewReply(peekedByte, messageLength),
 	}
 	_result._Reply._ReplyChildRequirements = _result
 	return _result
@@ -115,6 +125,11 @@ func (m *_ConfirmationReply) GetLengthInBitsConditional(lastItem bool) uint16 {
 	// Simple field (confirmation)
 	lengthInBits += m.Confirmation.GetLengthInBits()
 
+	// Optional Field (embeddedReply)
+	if m.EmbeddedReply != nil {
+		lengthInBits += m.EmbeddedReply.GetLengthInBits()
+	}
+
 	return lengthInBits
 }
 
@@ -144,13 +159,36 @@ func ConfirmationReplyParse(readBuffer utils.ReadBuffer, messageLength uint16) (
 		return nil, errors.Wrap(closeErr, "Error closing for confirmation")
 	}
 
+	// Optional Field (embeddedReply) (Can be skipped, if a given expression evaluates to false)
+	var embeddedReply Reply = nil
+	{
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("embeddedReply"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for embeddedReply")
+		}
+		_val, _err := ReplyParse(readBuffer, uint16(messageLength)-uint16(confirmation.GetLengthInBytes()))
+		switch {
+		case errors.Is(_err, utils.ParseAssertError{}) || errors.Is(_err, io.EOF):
+			log.Debug().Err(_err).Msg("Resetting position because optional threw an error")
+			readBuffer.Reset(currentPos)
+		case _err != nil:
+			return nil, errors.Wrap(_err, "Error parsing 'embeddedReply' field of ConfirmationReply")
+		default:
+			embeddedReply = _val.(Reply)
+			if closeErr := readBuffer.CloseContext("embeddedReply"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for embeddedReply")
+			}
+		}
+	}
+
 	if closeErr := readBuffer.CloseContext("ConfirmationReply"); closeErr != nil {
 		return nil, errors.Wrap(closeErr, "Error closing for ConfirmationReply")
 	}
 
 	// Create a partially initialized instance
 	_child := &_ConfirmationReply{
-		Confirmation: confirmation,
+		Confirmation:  confirmation,
+		EmbeddedReply: embeddedReply,
 		_Reply: &_Reply{
 			MessageLength: messageLength,
 		},
@@ -179,6 +217,22 @@ func (m *_ConfirmationReply) Serialize(writeBuffer utils.WriteBuffer) error {
 			return errors.Wrap(_confirmationErr, "Error serializing 'confirmation' field")
 		}
 
+		// Optional Field (embeddedReply) (Can be skipped, if the value is null)
+		var embeddedReply Reply = nil
+		if m.GetEmbeddedReply() != nil {
+			if pushErr := writeBuffer.PushContext("embeddedReply"); pushErr != nil {
+				return errors.Wrap(pushErr, "Error pushing for embeddedReply")
+			}
+			embeddedReply = m.GetEmbeddedReply()
+			_embeddedReplyErr := writeBuffer.WriteSerializable(embeddedReply)
+			if popErr := writeBuffer.PopContext("embeddedReply"); popErr != nil {
+				return errors.Wrap(popErr, "Error popping for embeddedReply")
+			}
+			if _embeddedReplyErr != nil {
+				return errors.Wrap(_embeddedReplyErr, "Error serializing 'embeddedReply' field")
+			}
+		}
+
 		if popErr := writeBuffer.PopContext("ConfirmationReply"); popErr != nil {
 			return errors.Wrap(popErr, "Error popping for ConfirmationReply")
 		}
diff --git a/plc4go/protocols/cbus/readwrite/model/Request.go b/plc4go/protocols/cbus/readwrite/model/Request.go
index 9c73385dd..9c1804d42 100644
--- a/plc4go/protocols/cbus/readwrite/model/Request.go
+++ b/plc4go/protocols/cbus/readwrite/model/Request.go
@@ -32,8 +32,16 @@ type Request interface {
 	utils.Serializable
 	// GetPeekedByte returns PeekedByte (property field)
 	GetPeekedByte() RequestType
+	// GetStartingCR returns StartingCR (property field)
+	GetStartingCR() *RequestType
+	// GetResetMode returns ResetMode (property field)
+	GetResetMode() *RequestType
+	// GetSecondPeek returns SecondPeek (property field)
+	GetSecondPeek() RequestType
 	// GetTermination returns Termination (property field)
 	GetTermination() RequestTermination
+	// GetActualPeek returns ActualPeek (virtual field)
+	GetActualPeek() RequestType
 	// GetPayloadLength returns PayloadLength (virtual field)
 	GetPayloadLength() uint16
 }
@@ -49,6 +57,9 @@ type RequestExactly interface {
 type _Request struct {
 	_RequestChildRequirements
 	PeekedByte  RequestType
+	StartingCR  *RequestType
+	ResetMode   *RequestType
+	SecondPeek  RequestType
 	Termination RequestTermination
 
 	// Arguments.
@@ -69,7 +80,7 @@ type RequestParent interface {
 
 type RequestChild interface {
 	utils.Serializable
-	InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination)
+	InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination)
 	GetParent() *Request
 
 	GetTypeName() string
@@ -85,6 +96,18 @@ func (m *_Request) GetPeekedByte() RequestType {
 	return m.PeekedByte
 }
 
+func (m *_Request) GetStartingCR() *RequestType {
+	return m.StartingCR
+}
+
+func (m *_Request) GetResetMode() *RequestType {
+	return m.ResetMode
+}
+
+func (m *_Request) GetSecondPeek() RequestType {
+	return m.SecondPeek
+}
+
 func (m *_Request) GetTermination() RequestTermination {
 	return m.Termination
 }
@@ -98,8 +121,20 @@ func (m *_Request) GetTermination() RequestTermination {
 /////////////////////// Accessors for virtual fields.
 ///////////////////////
 
+func (m *_Request) GetActualPeek() RequestType {
+	startingCR := m.StartingCR
+	_ = startingCR
+	resetMode := m.ResetMode
+	_ = resetMode
+	return CastRequestType(CastRequestType(utils.InlineIf(bool(bool(bool(bool((m.GetStartingCR()) == (nil))) && bool(bool((m.GetResetMode()) == (nil))))) || bool(bool(bool(bool(bool((m.GetStartingCR()) == (nil))) && bool(bool((m.GetResetMode()) != (nil)))) && bool(bool((m.GetSecondPeek()) == (RequestType_EMPTY))))), func() interface{} { return CastRequestType(m.GetPeekedByte()) }, func() interface{} { return CastRequestType(m.GetSecondPeek()) })))
+}
+
 func (m *_Request) GetPayloadLength() uint16 {
-	return uint16(uint16(m.MessageLength) - uint16(uint16(2)))
+	startingCR := m.StartingCR
+	_ = startingCR
+	resetMode := m.ResetMode
+	_ = resetMode
+	return uint16(uint16(uint16(uint16(m.MessageLength)-uint16(uint16(2)))) - uint16(uint16(utils.InlineIf(bool(bool((m.GetResetMode()) != (nil))), func() interface{} { return uint16(uint16(1)) }, func() interface{} { return uint16(uint16(0)) }).(uint16))))
 }
 
 ///////////////////////
@@ -108,8 +143,8 @@ func (m *_Request) GetPayloadLength() uint16 {
 ///////////////////////////////////////////////////////////
 
 // NewRequest factory function for _Request
-func NewRequest(peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_Request {
-	return &_Request{PeekedByte: peekedByte, Termination: termination, Srchk: srchk, MessageLength: messageLength}
+func NewRequest(peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_Request {
+	return &_Request{PeekedByte: peekedByte, StartingCR: startingCR, ResetMode: resetMode, SecondPeek: secondPeek, Termination: termination, Srchk: srchk, MessageLength: messageLength}
 }
 
 // Deprecated: use the interface for direct cast
@@ -130,6 +165,18 @@ func (m *_Request) GetTypeName() string {
 func (m *_Request) GetParentLengthInBits() uint16 {
 	lengthInBits := uint16(0)
 
+	// Optional Field (startingCR)
+	if m.StartingCR != nil {
+		lengthInBits += 8
+	}
+
+	// Optional Field (resetMode)
+	if m.ResetMode != nil {
+		lengthInBits += 8
+	}
+
+	// A virtual field doesn't have any in- or output.
+
 	// A virtual field doesn't have any in- or output.
 
 	// Simple field (termination)
@@ -166,35 +213,87 @@ func RequestParse(readBuffer utils.ReadBuffer, srchk bool, messageLength uint16)
 
 	readBuffer.Reset(currentPos)
 
+	// Optional Field (startingCR) (Can be skipped, if a given expression evaluates to false)
+	var startingCR *RequestType = nil
+	if bool((peekedByte) == (RequestType_EMPTY)) {
+		if pullErr := readBuffer.PullContext("startingCR"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for startingCR")
+		}
+		_val, _err := RequestTypeParse(readBuffer)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'startingCR' field of Request")
+		}
+		startingCR = &_val
+		if closeErr := readBuffer.CloseContext("startingCR"); closeErr != nil {
+			return nil, errors.Wrap(closeErr, "Error closing for startingCR")
+		}
+	}
+
+	// Optional Field (resetMode) (Can be skipped, if a given expression evaluates to false)
+	var resetMode *RequestType = nil
+	if bool((peekedByte) == (RequestType_RESET)) {
+		if pullErr := readBuffer.PullContext("resetMode"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for resetMode")
+		}
+		_val, _err := RequestTypeParse(readBuffer)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'resetMode' field of Request")
+		}
+		resetMode = &_val
+		if closeErr := readBuffer.CloseContext("resetMode"); closeErr != nil {
+			return nil, errors.Wrap(closeErr, "Error closing for resetMode")
+		}
+	}
+
+	// Peek Field (secondPeek)
+	currentPos = positionAware.GetPos()
+	if pullErr := readBuffer.PullContext("secondPeek"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for secondPeek")
+	}
+	secondPeek, _err := RequestTypeParse(readBuffer)
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing 'secondPeek' field of Request")
+	}
+	if closeErr := readBuffer.CloseContext("secondPeek"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for secondPeek")
+	}
+
+	readBuffer.Reset(currentPos)
+
 	// Virtual field
-	_payloadLength := uint16(messageLength) - uint16(uint16(2))
+	_actualPeek := CastRequestType(utils.InlineIf(bool(bool(bool(bool((startingCR) == (nil))) && bool(bool((resetMode) == (nil))))) || bool(bool(bool(bool(bool((startingCR) == (nil))) && bool(bool((resetMode) != (nil)))) && bool(bool((secondPeek) == (RequestType_EMPTY))))), func() interface{} { return CastRequestType(peekedByte) }, func() interface{} { return CastRequestType(secondPeek) }))
+	actualPeek := RequestType(_actualPeek)
+	_ = actualPeek
+
+	// Virtual field
+	_payloadLength := uint16(uint16(uint16(messageLength)-uint16(uint16(2)))) - uint16(uint16(utils.InlineIf(bool(bool((resetMode) != (nil))), func() interface{} { return uint16(uint16(1)) }, func() interface{} { return uint16(uint16(0)) }).(uint16)))
 	payloadLength := uint16(_payloadLength)
 	_ = payloadLength
 
 	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
 	type RequestChildSerializeRequirement interface {
 		Request
-		InitializeParent(Request, RequestType, RequestTermination)
+		InitializeParent(Request, RequestType, *RequestType, *RequestType, RequestType, RequestTermination)
 		GetParent() Request
 	}
 	var _childTemp interface{}
 	var _child RequestChildSerializeRequirement
 	var typeSwitchError error
 	switch {
-	case peekedByte == RequestType_SMART_CONNECT_SHORTCUT: // RequestSmartConnectShortcut
+	case actualPeek == RequestType_SMART_CONNECT_SHORTCUT: // RequestSmartConnectShortcut
 		_childTemp, typeSwitchError = RequestSmartConnectShortcutParse(readBuffer, srchk, messageLength)
-	case peekedByte == RequestType_RESET: // RequestReset
+	case actualPeek == RequestType_RESET: // RequestReset
 		_childTemp, typeSwitchError = RequestResetParse(readBuffer, srchk, messageLength)
-	case peekedByte == RequestType_DIRECT_COMMAND: // RequestDirectCommandAccess
+	case actualPeek == RequestType_DIRECT_COMMAND: // RequestDirectCommandAccess
 		_childTemp, typeSwitchError = RequestDirectCommandAccessParse(readBuffer, srchk, messageLength, payloadLength)
-	case peekedByte == RequestType_REQUEST_COMMAND: // RequestCommand
+	case actualPeek == RequestType_REQUEST_COMMAND: // RequestCommand
 		_childTemp, typeSwitchError = RequestCommandParse(readBuffer, srchk, messageLength, payloadLength)
-	case peekedByte == RequestType_NULL: // RequestNull
+	case actualPeek == RequestType_NULL: // RequestNull
 		_childTemp, typeSwitchError = RequestNullParse(readBuffer, srchk, messageLength)
-	case peekedByte == RequestType_EMPTY: // RequestEmpty
+	case actualPeek == RequestType_EMPTY: // RequestEmpty
 		_childTemp, typeSwitchError = RequestEmptyParse(readBuffer, srchk, messageLength)
 	default:
-		typeSwitchError = errors.Errorf("Unmapped type for parameters [peekedByte=%v]", peekedByte)
+		typeSwitchError = errors.Errorf("Unmapped type for parameters [actualPeek=%v]", actualPeek)
 	}
 	if typeSwitchError != nil {
 		return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch of Request")
@@ -219,7 +318,7 @@ func RequestParse(readBuffer utils.ReadBuffer, srchk bool, messageLength uint16)
 	}
 
 	// Finish initializing
-	_child.InitializeParent(_child, peekedByte, termination)
+	_child.InitializeParent(_child, peekedByte, startingCR, resetMode, secondPeek, termination)
 	return _child, nil
 }
 
@@ -232,6 +331,42 @@ func (pm *_Request) SerializeParent(writeBuffer utils.WriteBuffer, child Request
 	if pushErr := writeBuffer.PushContext("Request"); pushErr != nil {
 		return errors.Wrap(pushErr, "Error pushing for Request")
 	}
+
+	// Optional Field (startingCR) (Can be skipped, if the value is null)
+	var startingCR *RequestType = nil
+	if m.GetStartingCR() != nil {
+		if pushErr := writeBuffer.PushContext("startingCR"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for startingCR")
+		}
+		startingCR = m.GetStartingCR()
+		_startingCRErr := writeBuffer.WriteSerializable(startingCR)
+		if popErr := writeBuffer.PopContext("startingCR"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for startingCR")
+		}
+		if _startingCRErr != nil {
+			return errors.Wrap(_startingCRErr, "Error serializing 'startingCR' field")
+		}
+	}
+
+	// Optional Field (resetMode) (Can be skipped, if the value is null)
+	var resetMode *RequestType = nil
+	if m.GetResetMode() != nil {
+		if pushErr := writeBuffer.PushContext("resetMode"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for resetMode")
+		}
+		resetMode = m.GetResetMode()
+		_resetModeErr := writeBuffer.WriteSerializable(resetMode)
+		if popErr := writeBuffer.PopContext("resetMode"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for resetMode")
+		}
+		if _resetModeErr != nil {
+			return errors.Wrap(_resetModeErr, "Error serializing 'resetMode' field")
+		}
+	}
+	// Virtual field
+	if _actualPeekErr := writeBuffer.WriteVirtual("actualPeek", m.GetActualPeek()); _actualPeekErr != nil {
+		return errors.Wrap(_actualPeekErr, "Error serializing 'actualPeek' field")
+	}
 	// Virtual field
 	if _payloadLengthErr := writeBuffer.WriteVirtual("payloadLength", m.GetPayloadLength()); _payloadLengthErr != nil {
 		return errors.Wrap(_payloadLengthErr, "Error serializing 'payloadLength' field")
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestCommand.go b/plc4go/protocols/cbus/readwrite/model/RequestCommand.go
index 0b7ad0561..f7f2ec876 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestCommand.go
@@ -70,8 +70,11 @@ type _RequestCommand struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestCommand) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestCommand) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -111,11 +114,11 @@ func (m *_RequestCommand) GetInitiator() byte {
 ///////////////////////////////////////////////////////////
 
 // NewRequestCommand factory function for _RequestCommand
-func NewRequestCommand(cbusCommand CBusCommand, alpha Alpha, peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16, payloadLength uint16) *_RequestCommand {
+func NewRequestCommand(cbusCommand CBusCommand, alpha Alpha, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16, payloadLength uint16) *_RequestCommand {
 	_result := &_RequestCommand{
 		CbusCommand: cbusCommand,
 		Alpha:       alpha,
-		_Request:    NewRequest(peekedByte, termination, srchk, messageLength),
+		_Request:    NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestDirectCommandAccess.go b/plc4go/protocols/cbus/readwrite/model/RequestDirectCommandAccess.go
index 662c90078..b5672d05d 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestDirectCommandAccess.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestDirectCommandAccess.go
@@ -65,8 +65,11 @@ type _RequestDirectCommandAccess struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestDirectCommandAccess) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestDirectCommandAccess) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -102,10 +105,10 @@ func (m *_RequestDirectCommandAccess) GetAt() byte {
 ///////////////////////////////////////////////////////////
 
 // NewRequestDirectCommandAccess factory function for _RequestDirectCommandAccess
-func NewRequestDirectCommandAccess(calData CALData, peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16, payloadLength uint16) *_RequestDirectCommandAccess {
+func NewRequestDirectCommandAccess(calData CALData, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16, payloadLength uint16) *_RequestDirectCommandAccess {
 	_result := &_RequestDirectCommandAccess{
 		CalData:  calData,
-		_Request: NewRequest(peekedByte, termination, srchk, messageLength),
+		_Request: NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestEmpty.go b/plc4go/protocols/cbus/readwrite/model/RequestEmpty.go
index 44b219a56..6538d8f4c 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestEmpty.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestEmpty.go
@@ -55,8 +55,11 @@ type _RequestEmpty struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestEmpty) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestEmpty) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -65,9 +68,9 @@ func (m *_RequestEmpty) GetParent() Request {
 }
 
 // NewRequestEmpty factory function for _RequestEmpty
-func NewRequestEmpty(peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestEmpty {
+func NewRequestEmpty(peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestEmpty {
 	_result := &_RequestEmpty{
-		_Request: NewRequest(peekedByte, termination, srchk, messageLength),
+		_Request: NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestNull.go b/plc4go/protocols/cbus/readwrite/model/RequestNull.go
index b9818c99e..c104d20dd 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestNull.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestNull.go
@@ -59,8 +59,11 @@ type _RequestNull struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestNull) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestNull) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -83,9 +86,9 @@ func (m *_RequestNull) GetNullIndicator() uint32 {
 ///////////////////////////////////////////////////////////
 
 // NewRequestNull factory function for _RequestNull
-func NewRequestNull(peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestNull {
+func NewRequestNull(peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestNull {
 	_result := &_RequestNull{
-		_Request: NewRequest(peekedByte, termination, srchk, messageLength),
+		_Request: NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestReset.go b/plc4go/protocols/cbus/readwrite/model/RequestReset.go
index feda68998..a0d39cd58 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestReset.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestReset.go
@@ -20,16 +20,12 @@
 package model
 
 import (
-	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/spi/utils"
 	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
 
-// Constant values.
-const RequestReset_TILDE byte = 0x7E
-
 // RequestReset is the corresponding interface of RequestReset
 type RequestReset interface {
 	utils.LengthAware
@@ -59,8 +55,11 @@ type _RequestReset struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestReset) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestReset) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -68,24 +67,10 @@ func (m *_RequestReset) GetParent() Request {
 	return m._Request
 }
 
-///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////
-/////////////////////// Accessors for const fields.
-///////////////////////
-
-func (m *_RequestReset) GetTilde() byte {
-	return RequestReset_TILDE
-}
-
-///////////////////////
-///////////////////////
-///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////
-
 // NewRequestReset factory function for _RequestReset
-func NewRequestReset(peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestReset {
+func NewRequestReset(peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestReset {
 	_result := &_RequestReset{
-		_Request: NewRequest(peekedByte, termination, srchk, messageLength),
+		_Request: NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
@@ -113,9 +98,6 @@ func (m *_RequestReset) GetLengthInBits() uint16 {
 func (m *_RequestReset) GetLengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.GetParentLengthInBits())
 
-	// Const Field (tilde)
-	lengthInBits += 8
-
 	return lengthInBits
 }
 
@@ -132,15 +114,6 @@ func RequestResetParse(readBuffer utils.ReadBuffer, srchk bool, messageLength ui
 	currentPos := positionAware.GetPos()
 	_ = currentPos
 
-	// Const Field (tilde)
-	tilde, _tildeErr := readBuffer.ReadByte("tilde")
-	if _tildeErr != nil {
-		return nil, errors.Wrap(_tildeErr, "Error parsing 'tilde' field of RequestReset")
-	}
-	if tilde != RequestReset_TILDE {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", RequestReset_TILDE) + " but got " + fmt.Sprintf("%d", tilde))
-	}
-
 	if closeErr := readBuffer.CloseContext("RequestReset"); closeErr != nil {
 		return nil, errors.Wrap(closeErr, "Error closing for RequestReset")
 	}
@@ -164,12 +137,6 @@ func (m *_RequestReset) Serialize(writeBuffer utils.WriteBuffer) error {
 			return errors.Wrap(pushErr, "Error pushing for RequestReset")
 		}
 
-		// Const Field (tilde)
-		_tildeErr := writeBuffer.WriteByte("tilde", 0x7E)
-		if _tildeErr != nil {
-			return errors.Wrap(_tildeErr, "Error serializing 'tilde' field")
-		}
-
 		if popErr := writeBuffer.PopContext("RequestReset"); popErr != nil {
 			return errors.Wrap(popErr, "Error popping for RequestReset")
 		}
diff --git a/plc4go/protocols/cbus/readwrite/model/RequestSmartConnectShortcut.go b/plc4go/protocols/cbus/readwrite/model/RequestSmartConnectShortcut.go
index e28580c0b..366c5043f 100644
--- a/plc4go/protocols/cbus/readwrite/model/RequestSmartConnectShortcut.go
+++ b/plc4go/protocols/cbus/readwrite/model/RequestSmartConnectShortcut.go
@@ -35,6 +35,10 @@ type RequestSmartConnectShortcut interface {
 	utils.LengthAware
 	utils.Serializable
 	Request
+	// GetPipePeek returns PipePeek (property field)
+	GetPipePeek() RequestType
+	// GetSecondPipe returns SecondPipe (property field)
+	GetSecondPipe() *byte
 }
 
 // RequestSmartConnectShortcutExactly can be used when we want exactly this type and not a type which fulfills RequestSmartConnectShortcut.
@@ -47,6 +51,8 @@ type RequestSmartConnectShortcutExactly interface {
 // _RequestSmartConnectShortcut is the data-structure of this message
 type _RequestSmartConnectShortcut struct {
 	*_Request
+	PipePeek   RequestType
+	SecondPipe *byte
 }
 
 ///////////////////////////////////////////////////////////
@@ -59,8 +65,11 @@ type _RequestSmartConnectShortcut struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_RequestSmartConnectShortcut) InitializeParent(parent Request, peekedByte RequestType, termination RequestTermination) {
+func (m *_RequestSmartConnectShortcut) InitializeParent(parent Request, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination) {
 	m.PeekedByte = peekedByte
+	m.StartingCR = startingCR
+	m.ResetMode = resetMode
+	m.SecondPeek = secondPeek
 	m.Termination = termination
 }
 
@@ -68,6 +77,23 @@ func (m *_RequestSmartConnectShortcut) GetParent() Request {
 	return m._Request
 }
 
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_RequestSmartConnectShortcut) GetPipePeek() RequestType {
+	return m.PipePeek
+}
+
+func (m *_RequestSmartConnectShortcut) GetSecondPipe() *byte {
+	return m.SecondPipe
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 /////////////////////// Accessors for const fields.
@@ -83,9 +109,11 @@ func (m *_RequestSmartConnectShortcut) GetPipe() byte {
 ///////////////////////////////////////////////////////////
 
 // NewRequestSmartConnectShortcut factory function for _RequestSmartConnectShortcut
-func NewRequestSmartConnectShortcut(peekedByte RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestSmartConnectShortcut {
+func NewRequestSmartConnectShortcut(pipePeek RequestType, secondPipe *byte, peekedByte RequestType, startingCR *RequestType, resetMode *RequestType, secondPeek RequestType, termination RequestTermination, srchk bool, messageLength uint16) *_RequestSmartConnectShortcut {
 	_result := &_RequestSmartConnectShortcut{
-		_Request: NewRequest(peekedByte, termination, srchk, messageLength),
+		PipePeek:   pipePeek,
+		SecondPipe: secondPipe,
+		_Request:   NewRequest(peekedByte, startingCR, resetMode, secondPeek, termination, srchk, messageLength),
 	}
 	_result._Request._RequestChildRequirements = _result
 	return _result
@@ -116,6 +144,11 @@ func (m *_RequestSmartConnectShortcut) GetLengthInBitsConditional(lastItem bool)
 	// Const Field (pipe)
 	lengthInBits += 8
 
+	// Optional Field (secondPipe)
+	if m.SecondPipe != nil {
+		lengthInBits += 8
+	}
+
 	return lengthInBits
 }
 
@@ -141,12 +174,39 @@ func RequestSmartConnectShortcutParse(readBuffer utils.ReadBuffer, srchk bool, m
 		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", RequestSmartConnectShortcut_PIPE) + " but got " + fmt.Sprintf("%d", pipe))
 	}
 
+	// Peek Field (pipePeek)
+	currentPos = positionAware.GetPos()
+	if pullErr := readBuffer.PullContext("pipePeek"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for pipePeek")
+	}
+	pipePeek, _err := RequestTypeParse(readBuffer)
+	if _err != nil {
+		return nil, errors.Wrap(_err, "Error parsing 'pipePeek' field of RequestSmartConnectShortcut")
+	}
+	if closeErr := readBuffer.CloseContext("pipePeek"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for pipePeek")
+	}
+
+	readBuffer.Reset(currentPos)
+
+	// Optional Field (secondPipe) (Can be skipped, if a given expression evaluates to false)
+	var secondPipe *byte = nil
+	if bool((pipePeek) == (RequestType_SMART_CONNECT_SHORTCUT)) {
+		_val, _err := readBuffer.ReadByte("secondPipe")
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'secondPipe' field of RequestSmartConnectShortcut")
+		}
+		secondPipe = &_val
+	}
+
 	if closeErr := readBuffer.CloseContext("RequestSmartConnectShortcut"); closeErr != nil {
 		return nil, errors.Wrap(closeErr, "Error closing for RequestSmartConnectShortcut")
 	}
 
 	// Create a partially initialized instance
 	_child := &_RequestSmartConnectShortcut{
+		PipePeek:   pipePeek,
+		SecondPipe: secondPipe,
 		_Request: &_Request{
 			Srchk:         srchk,
 			MessageLength: messageLength,
@@ -170,6 +230,16 @@ func (m *_RequestSmartConnectShortcut) Serialize(writeBuffer utils.WriteBuffer)
 			return errors.Wrap(_pipeErr, "Error serializing 'pipe' field")
 		}
 
+		// Optional Field (secondPipe) (Can be skipped, if the value is null)
+		var secondPipe *byte = nil
+		if m.GetSecondPipe() != nil {
+			secondPipe = m.GetSecondPipe()
+			_secondPipeErr := writeBuffer.WriteByte("secondPipe", *(secondPipe))
+			if _secondPipeErr != nil {
+				return errors.Wrap(_secondPipeErr, "Error serializing 'secondPipe' field")
+			}
+		}
+
 		if popErr := writeBuffer.PopContext("RequestSmartConnectShortcut"); popErr != nil {
 			return errors.Wrap(popErr, "Error popping for RequestSmartConnectShortcut")
 		}
diff --git a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
index 51f7d7088..a1115f7a9 100644
--- a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
@@ -27,53 +27,46 @@ import (
 )
 
 func WriteCBusCommand(writeBuffer utils.WriteBuffer, cbusCommand CBusCommand) error {
-	// TODO: maybe we use a writebuffer hex based
-	wbbb := utils.NewWriteBufferByteBased()
-	err := cbusCommand.Serialize(wbbb)
-	if err != nil {
-		return errors.Wrap(err, "Error serializing")
-	}
-	hexBytes := make([]byte, hex.EncodedLen(len(wbbb.GetBytes())))
-	n := hex.Encode(hexBytes, wbbb.GetBytes())
-	log.Debug().Msgf("%d bytes encoded", n)
-	return writeBuffer.WriteByteArray("cbusCommand", hexBytes)
+	return writeToHex("cbusCommand", writeBuffer, cbusCommand)
 }
 
 func ReadCBusCommand(readBuffer utils.ReadBuffer, payloadLength uint16, srcchk bool) (CBusCommand, error) {
-	hexBytes, err := readBuffer.ReadByteArray("cbusCommand", int(payloadLength))
+	rawBytes, err := readBytesFromHex("cbusCommand", readBuffer, payloadLength)
 	if err != nil {
-		return nil, errors.Wrap(err, "Error parsing")
+		return nil, errors.Wrap(err, "Error getting hex")
 	}
-	lastByte := hexBytes[len(hexBytes)-1]
-	if (lastByte >= 0x67) && (lastByte <= 0x7A) {
-		// We need to reset the alpha
-		readBuffer.Reset(readBuffer.GetPos() - 1)
-		hexBytes = hexBytes[:len(hexBytes)-1]
-	}
-	rawBytes := make([]byte, hex.DecodedLen(len(hexBytes)))
-	n, err := hex.Decode(rawBytes, hexBytes)
-	if err != nil {
-		return nil, err
-	}
-	log.Debug().Msgf("%d bytes decoded", n)
 	return CBusCommandParse(utils.NewReadBufferByteBased(rawBytes), srcchk)
 }
 
 func WriteCALReply(writeBuffer utils.WriteBuffer, calReply CALReply) error {
-	// TODO: maybe we use a writebuffer hex based
-	wbbb := utils.NewWriteBufferByteBased()
-	err := calReply.Serialize(wbbb)
+	return writeToHex("calReply", writeBuffer, calReply)
+}
+
+func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16) (CALReply, error) {
+	rawBytes, err := readBytesFromHex("calReply", readBuffer, payloadLength)
 	if err != nil {
-		return errors.Wrap(err, "Error serializing")
+		return nil, errors.Wrap(err, "Error getting hex")
 	}
-	hexBytes := make([]byte, hex.EncodedLen(len(wbbb.GetBytes())))
-	n := hex.Encode(hexBytes, wbbb.GetBytes())
-	log.Debug().Msgf("%d bytes encoded", n)
-	return writeBuffer.WriteByteArray("calReply", hexBytes)
+	return CALReplyParse(utils.NewReadBufferByteBased(rawBytes))
 }
 
-func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16) (CALReply, error) {
-	hexBytes, err := readBuffer.ReadByteArray("calReply", int(payloadLength))
+func WriteCALData(writeBuffer utils.WriteBuffer, calData CALData) error {
+	return writeToHex("calData", writeBuffer, calData)
+}
+
+func ReadCALData(readBuffer utils.ReadBuffer, payloadLength uint16) (CALData, error) {
+	rawBytes, err := readBytesFromHex("calData", readBuffer, payloadLength)
+	if err != nil {
+		return nil, errors.Wrap(err, "Error getting hex")
+	}
+	return CALDataParse(utils.NewReadBufferByteBased(rawBytes))
+}
+
+func readBytesFromHex(logicalName string, readBuffer utils.ReadBuffer, payloadLength uint16) ([]byte, error) {
+	if payloadLength == 0 {
+		return nil, errors.New("Length is 0")
+	}
+	hexBytes, err := readBuffer.ReadByteArray(logicalName, int(payloadLength))
 	if err != nil {
 		return nil, errors.Wrap(err, "Error parsing")
 	}
@@ -89,38 +82,31 @@ func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16) (CALReply,
 		return nil, err
 	}
 	log.Debug().Msgf("%d bytes decoded", n)
-	return CALReplyParse(utils.NewReadBufferByteBased(rawBytes))
+	return rawBytes, nil
 }
 
-func WriteCALData(writeBuffer utils.WriteBuffer, calData CALData) error {
-	// TODO: maybe we use a writebuffer hex based
+func writeToHex(logicalName string, writeBuffer utils.WriteBuffer, serializable utils.Serializable) error {
 	wbbb := utils.NewWriteBufferByteBased()
-	err := calData.Serialize(wbbb)
+	err := serializable.Serialize(wbbb)
 	if err != nil {
 		return errors.Wrap(err, "Error serializing")
 	}
 	hexBytes := make([]byte, hex.EncodedLen(len(wbbb.GetBytes())))
-	n := hex.Encode(hexBytes, wbbb.GetBytes())
+	// usually you use hex.Encode but we want the encoding in uppercase
+	//n := hex.Encode(hexBytes, wbbb.GetBytes())
+	n := encodeHexUpperCase(hexBytes, wbbb.GetBytes())
 	log.Debug().Msgf("%d bytes encoded", n)
-	return writeBuffer.WriteByteArray("calReply", hexBytes)
+	return writeBuffer.WriteByteArray(logicalName, hexBytes)
 }
 
-func ReadCALData(readBuffer utils.ReadBuffer, payloadLength uint16) (CALData, error) {
-	hexBytes, err := readBuffer.ReadByteArray("calReply", int(payloadLength))
-	if err != nil {
-		return nil, errors.Wrap(err, "Error parsing")
-	}
-	lastByte := hexBytes[len(hexBytes)-1]
-	if (lastByte >= 0x67) && (lastByte <= 0x7A) {
-		// We need to reset the alpha
-		readBuffer.Reset(readBuffer.GetPos() - 1)
-		hexBytes = hexBytes[:len(hexBytes)-1]
-	}
-	rawBytes := make([]byte, hex.DecodedLen(len(hexBytes)))
-	n, err := hex.Decode(rawBytes, hexBytes)
-	if err != nil {
-		return nil, err
+const hextable = "0123456789ABCDEF"
+
+func encodeHexUpperCase(dst, src []byte) int {
+	j := 0
+	for _, v := range src {
+		dst[j] = hextable[v>>4]
+		dst[j+1] = hextable[v&0x0f]
+		j += 2
 	}
-	log.Debug().Msgf("%d bytes decoded", n)
-	return CALDataParse(utils.NewReadBufferByteBased(rawBytes))
+	return len(src) * 2
 }
diff --git a/plc4go/tools/plc4xpcapanalyzer/internal/analyzer/analyzer.go b/plc4go/tools/plc4xpcapanalyzer/internal/analyzer/analyzer.go
index e010952c1..181391f80 100644
--- a/plc4go/tools/plc4xpcapanalyzer/internal/analyzer/analyzer.go
+++ b/plc4go/tools/plc4xpcapanalyzer/internal/analyzer/analyzer.go
@@ -44,6 +44,9 @@ func Analyze(pcapFile, protocolType, filter string, onlyParse, noBytesCompare bo
 	source := pcaphandler.GetPacketSource(handle)
 	var packageParse func(common.PacketInformation, []byte) (interface{}, error)
 	var serializePackage func(interface{}) ([]byte, error)
+	var prettyPrint = func(item interface{}) {
+		fmt.Printf("%v\n", item)
+	}
 	switch protocolType {
 	case "bacnet":
 		packageParse = bacnetanalyzer.PackageParse
@@ -52,6 +55,7 @@ func Analyze(pcapFile, protocolType, filter string, onlyParse, noBytesCompare bo
 		analyzer := cbusanalyzer.Analyzer{Client: net.ParseIP(client)}
 		packageParse = analyzer.PackageParse
 		serializePackage = analyzer.SerializePackage
+		prettyPrint = analyzer.PrettyPrint
 	}
 	bar := progressbar.NewOptions(numberOfPackage, progressbar.OptionSetWriter(ansi.NewAnsiStdout()),
 		progressbar.OptionEnableColorCodes(true),
@@ -99,7 +103,7 @@ func Analyze(pcapFile, protocolType, filter string, onlyParse, noBytesCompare bo
 		} else {
 			log.Info().Stringer("packetInformation", packetInformation).Msgf("No.[%d] Parsed", realPacketNumber)
 			if verbosity > 1 {
-				println(parsed.(fmt.Stringer).String())
+				prettyPrint(parsed)
 			}
 			if onlyParse {
 				log.Trace().Msg("only parsing")
diff --git a/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go b/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
index de8aa0a2b..429ab90c7 100644
--- a/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
+++ b/plc4go/tools/plc4xpcapanalyzer/internal/cbusanalyzer/analyzer.go
@@ -20,6 +20,7 @@
 package cbusanalyzer
 
 import (
+	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/spi/utils"
 	"github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
 	"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/internal/common"
@@ -45,15 +46,51 @@ func (a Analyzer) PackageParse(packetInformation common.PacketInformation, paylo
 	return parse, nil
 }
 
-func (a Analyzer) SerializePackage(command interface{}) ([]byte, error) {
-	if command, ok := command.(model.CBusMessage); !ok {
-		log.Fatal().Msgf("Unsupported type %T supplied", command)
+func (a Analyzer) SerializePackage(message interface{}) ([]byte, error) {
+	if message, ok := message.(model.CBusMessage); !ok {
+		log.Fatal().Msgf("Unsupported type %T supplied", message)
 		panic("unreachable statement")
 	} else {
 		based := utils.NewWriteBufferByteBased()
-		if err := command.Serialize(based); err != nil {
+		if err := message.Serialize(based); err != nil {
 			return nil, errors.Wrap(err, "Error serializing")
 		}
 		return based.GetBytes(), nil
 	}
 }
+
+func (a Analyzer) PrettyPrint(message interface{}) {
+	if message, ok := message.(model.CBusMessage); !ok {
+		log.Fatal().Msgf("Unsupported type %T supplied", message)
+		panic("unreachable statement")
+	} else {
+		fmt.Printf("%v\n", message)
+		switch message := message.(type) {
+		case model.CBusMessageToServerExactly:
+			switch request := message.GetRequest().(type) {
+			case model.RequestDirectCommandAccessExactly:
+				fmt.Printf("%v\n", request.GetCalData())
+			case model.RequestCommandExactly:
+				fmt.Printf("%v\n", request.GetCbusCommand())
+			}
+		case model.CBusMessageToClientExactly:
+			switch reply := message.GetReply().(type) {
+			case model.ConfirmationReplyExactly:
+				switch reply := reply.GetEmbeddedReply().(type) {
+				case model.ReplyNormalReplyExactly:
+					switch reply := reply.GetReply().(type) {
+					case model.CALReplyReplyExactly:
+						// We print this a second time as the first print contains only the hex part
+						fmt.Printf("%v\n", reply.GetCalReply())
+					}
+				}
+			case model.ReplyNormalReplyExactly:
+				switch reply := reply.GetReply().(type) {
+				case model.CALReplyReplyExactly:
+					// 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/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 06117c959..076c29c18 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
@@ -24,76 +24,50 @@ import org.apache.plc4x.java.cbus.readwrite.CALData;
 import org.apache.plc4x.java.cbus.readwrite.CALReply;
 import org.apache.plc4x.java.cbus.readwrite.CBusCommand;
 import org.apache.plc4x.java.spi.generation.*;
+import org.apache.plc4x.java.spi.utils.Serializable;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 public class StaticHelper {
+
     public static void writeCBusCommand(WriteBuffer writeBuffer, CBusCommand cbusCommand) throws SerializationException {
-        // TODO: maybe we use a writebuffer hex based
-        WriteBufferByteBased payloadWriteBuffer = new WriteBufferByteBased(cbusCommand.getLengthInBytes() * 2);
-        cbusCommand.serialize(payloadWriteBuffer);
-        byte[] hexBytes = Hex.encodeHexString(payloadWriteBuffer.getBytes()).getBytes(StandardCharsets.UTF_8);
-        writeBuffer.writeByteArray("cbusCommand", hexBytes);
+        writeToHex("cbusCommand", writeBuffer, cbusCommand, cbusCommand.getLengthInBytes());
     }
 
     public static CBusCommand readCBusCommand(ReadBuffer readBuffer, Integer payloadLength, boolean srcchk) throws ParseException {
-        byte[] hexBytes = readBuffer.readByteArray("cbusCommand", payloadLength);
-        byte lastByte = hexBytes[hexBytes.length - 1];
-        if ((lastByte >= 0x67) && (lastByte <= 0x7A)) {
-            // We need to reset the alpha
-            readBuffer.reset(readBuffer.getPos() - 1);
-            hexBytes = Arrays.copyOf(hexBytes,hexBytes.length-1);
-        }
-        byte[] rawBytes;
-        try {
-            rawBytes = Hex.decodeHex(new String(hexBytes));
-        } catch (DecoderException e) {
-            throw new ParseException("error getting hex", e);
-        }
+        byte[] rawBytes = readBytesFromHex("cbusCommand", readBuffer, payloadLength);
         return CBusCommand.staticParse(new ReadBufferByteBased(rawBytes), srcchk);
     }
 
     public static void writeCALReply(WriteBuffer writeBuffer, CALReply calReply) throws SerializationException {
-        // TODO: maybe we use a writebuffer hex based
-        WriteBufferByteBased payloadWriteBuffer = new WriteBufferByteBased(calReply.getLengthInBytes() * 2);
-        calReply.serialize(payloadWriteBuffer);
-        byte[] hexBytes = Hex.encodeHexString(payloadWriteBuffer.getBytes()).getBytes(StandardCharsets.UTF_8);
-        writeBuffer.writeByteArray("calReply", hexBytes);
+        writeToHex("calReply", writeBuffer, calReply, calReply.getLengthInBytes());
     }
 
     public static CALReply readCALReply(ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
-        byte[] hexBytes = readBuffer.readByteArray("calReply", payloadLength);
-        byte lastByte = hexBytes[hexBytes.length - 1];
-        if ((lastByte >= 0x67) && (lastByte <= 0x7A)) {
-            // We need to reset the alpha
-            readBuffer.reset(readBuffer.getPos() - 1);
-            hexBytes = Arrays.copyOf(hexBytes,hexBytes.length-1);
-        }
-        byte[] rawBytes;
-        try {
-            rawBytes = Hex.decodeHex(new String(hexBytes));
-        } catch (DecoderException e) {
-            throw new ParseException("error getting hex", e);
-        }
+        byte[] rawBytes = readBytesFromHex("calReply", readBuffer, payloadLength);
         return CALReply.staticParse(new ReadBufferByteBased(rawBytes));
     }
 
     public static void writeCALData(WriteBuffer writeBuffer, CALData calData) throws SerializationException {
-        // TODO: maybe we use a writebuffer hex based
-        WriteBufferByteBased payloadWriteBuffer = new WriteBufferByteBased(calData.getLengthInBytes() * 2);
-        calData.serialize(payloadWriteBuffer);
-        byte[] hexBytes = Hex.encodeHexString(payloadWriteBuffer.getBytes()).getBytes(StandardCharsets.UTF_8);
-        writeBuffer.writeByteArray("calReply", hexBytes);
+        writeToHex("calData", writeBuffer, calData, calData.getLengthInBytes());
     }
 
     public static CALData readCALData(ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
-        byte[] hexBytes = readBuffer.readByteArray("calReply", payloadLength);
+        byte[] rawBytes = readBytesFromHex("calReply", readBuffer, payloadLength);
+        return CALData.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");
+        }
+        byte[] hexBytes = readBuffer.readByteArray(logicalName, payloadLength);
         byte lastByte = hexBytes[hexBytes.length - 1];
         if ((lastByte >= 0x67) && (lastByte <= 0x7A)) {
             // We need to reset the alpha
             readBuffer.reset(readBuffer.getPos() - 1);
-            hexBytes = Arrays.copyOf(hexBytes,hexBytes.length-1);
+            hexBytes = Arrays.copyOf(hexBytes, hexBytes.length - 1);
         }
         byte[] rawBytes;
         try {
@@ -101,7 +75,15 @@ public class StaticHelper {
         } catch (DecoderException e) {
             throw new ParseException("error getting hex", e);
         }
-        return CALData.staticParse(new ReadBufferByteBased(rawBytes));
+        return rawBytes;
+    }
+
+    private static void writeToHex(String logicalName, WriteBuffer writeBuffer, Serializable serializable, int lengthInBytes) throws SerializationException {
+        // TODO: maybe we use a writebuffer hex based
+        WriteBufferByteBased payloadWriteBuffer = new WriteBufferByteBased(lengthInBytes * 2);
+        serializable.serialize(payloadWriteBuffer);
+        byte[] hexBytes = Hex.encodeHexString(payloadWriteBuffer.getBytes()).getBytes(StandardCharsets.UTF_8);
+        writeBuffer.writeByteArray(logicalName, hexBytes);
     }
 
 }
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 edc28b7d7..a1010566f 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
@@ -454,8 +454,7 @@ public class RandomPackagesTest {
         // 9.4
         @Test
         void SwitchMode() throws Exception {
-            // TODO: the section describes that on non smart mode the message doesn't have the last CR
-            byte[] bytes = "@A3300019\r".getBytes(StandardCharsets.UTF_8);
+            byte[] bytes = "~@A3300019\r".getBytes(StandardCharsets.UTF_8);
             ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
             CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, true, bytes.length);
             assertThat(msg)
@@ -538,5 +537,20 @@ public class RandomPackagesTest {
             CBusCommand cbusCommand = requestCommand.getCbusCommand();
             System.out.println(cbusCommand);
         }
+
+        @Test
+        void identifyResponse() throws Exception {
+            byte[] bytes = "g.890150435F434E49454421\r\n".getBytes(StandardCharsets.UTF_8);
+            ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+            CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, true, bytes.length);
+            assertThat(msg)
+                .isNotNull();
+            System.out.println(msg);
+            CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
+            ConfirmationReply confirmationReply = (ConfirmationReply) messageToClient.getReply();
+            ReplyNormalReply normalReply = (ReplyNormalReply) confirmationReply.getEmbeddedReply();
+            CALReplyReply calReplyReply = (CALReplyReply) normalReply.getReply();
+            System.out.println(calReplyReply.getCalReply());
+        }
     }
 }
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 3a00232bf..2d9ac3508 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
@@ -45,17 +45,22 @@
 ]
 
 [type Request(bit srchk, uint 16 messageLength)
-    [peek    RequestType peekedByte                                         ]
-    [virtual uint 16 payloadLength 'messageLength-2'                        ] // We subtract the command itself and the termination
-    [typeSwitch peekedByte
+    [peek     RequestType peekedByte                                        ]
+    [optional RequestType startingCR       'peekedByte == RequestType.EMPTY']
+    [optional RequestType resetMode        'peekedByte == RequestType.RESET']
+    [peek     RequestType secondPeek                                        ]
+    [virtual  RequestType actualPeek '(startingCR==null&&resetMode==null)||(startingCR==null&&resetMode!=null&&secondPeek==RequestType.EMPTY)?peekedByte:secondPeek']
+    [virtual uint 16 payloadLength '(messageLength-2)-((resetMode!=null)?1:0)'] // We subtract the command itself and the termination
+    [typeSwitch actualPeek
         ['SMART_CONNECT_SHORTCUT' *SmartConnectShortcut
-            [const    byte                pipe      0x7C                    ]
+            [const    byte        pipe      0x7C                            ]
+            [peek     RequestType pipePeek                                  ]
+            [optional byte        secondPipe 'pipePeek == RequestType.SMART_CONNECT_SHORTCUT']
         ]
         ['RESET' *Reset
-            [const    byte                tilde     0x7E                    ]
         ]
         ['DIRECT_COMMAND' *DirectCommandAccess(uint 16 payloadLength)
-            [const    byte                at        0x40                    ]
+            [const    byte         at        0x40                           ]
             // Usually you would read the command now here but we need to decode ascii first
             //[simple   CALData     calData    ]
             [manual   CALData
@@ -916,6 +921,7 @@
     [typeSwitch isAlpha
         ['true' ConfirmationReply
             [simple   Confirmation                      confirmation        ]
+            [optional Reply('messageLength-confirmation.lengthInBytes') embeddedReply]
         ]
         ['false' *NormalReply
             [simple   NormalReply('messageLength')      reply               ]