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/11 15:42:55 UTC

[plc4x] branch develop updated: feat(c-bus): added missing crc checks (parsing only)

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


The following commit(s) were added to refs/heads/develop by this push:
     new 820d27234 feat(c-bus): added missing crc checks (parsing only)
820d27234 is described below

commit 820d27234e00e3148dfda22794446586343061ed
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Jul 11 17:42:42 2022 +0200

    feat(c-bus): added missing crc checks (parsing only)
---
 plc4go/protocols/cbus/readwrite/ParserHelper.go    |  6 +-
 plc4go/protocols/cbus/readwrite/XmlParserHelper.go |  8 ++-
 plc4go/protocols/cbus/readwrite/model/CALReply.go  | 69 +++++++++++++++++++---
 .../protocols/cbus/readwrite/model/CALReplyLong.go | 10 ++--
 .../cbus/readwrite/model/CALReplyShort.go          | 10 ++--
 .../protocols/cbus/readwrite/model/MonitoredSAL.go | 69 +++++++++++++++++++---
 .../model/MonitoredSALLongFormSmartMode.go         | 13 ++--
 .../cbus/readwrite/model/MonitoredSALReply.go      |  2 +-
 .../model/MonitoredSALShortFormBasicMode.go        | 13 ++--
 .../cbus/readwrite/model/ReplyCALReply.go          |  2 +-
 .../protocols/cbus/readwrite/model/StaticHelper.go |  8 +--
 .../java/cbus/readwrite/utils/StaticHelper.java    |  8 +--
 .../apache/plc4x/java/cbus/RandomPackagesTest.java |  4 +-
 .../src/main/resources/protocols/cbus/c-bus.mspec  | 16 ++---
 14 files changed, 180 insertions(+), 58 deletions(-)

diff --git a/plc4go/protocols/cbus/readwrite/ParserHelper.go b/plc4go/protocols/cbus/readwrite/ParserHelper.go
index 6e65481ad..6fdb1cdc4 100644
--- a/plc4go/protocols/cbus/readwrite/ParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/ParserHelper.go
@@ -40,8 +40,9 @@ func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.Re
 	case "RequestContext":
 		return model.RequestContextParse(io)
 	case "CALReply":
+		var cBusOptions model.CBusOptions
 		var requestContext model.RequestContext
-		return model.CALReplyParse(io, requestContext)
+		return model.CALReplyParse(io, cBusOptions, requestContext)
 	case "NetworkRoute":
 		return model.NetworkRouteParse(io)
 	case "NetworkNumber":
@@ -103,7 +104,8 @@ func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.Re
 	case "BridgeAddress":
 		return model.BridgeAddressParse(io)
 	case "MonitoredSAL":
-		return model.MonitoredSALParse(io)
+		var cBusOptions model.CBusOptions
+		return model.MonitoredSALParse(io, cBusOptions)
 	case "ParameterChange":
 		return model.ParameterChangeParse(io)
 	case "StatusByte":
diff --git a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
index 64d5b44f8..85f641e49 100644
--- a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
@@ -51,9 +51,11 @@ func (m CbusXmlParserHelper) Parse(typeName string, xmlString string, parserArgu
 	case "RequestContext":
 		return model.RequestContextParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "CALReply":
+		// 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.CALReplyParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), requestContext)
+		return model.CALReplyParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), cBusOptions, requestContext)
 	case "NetworkRoute":
 		return model.NetworkRouteParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "NetworkNumber":
@@ -122,7 +124,9 @@ func (m CbusXmlParserHelper) Parse(typeName string, xmlString string, parserArgu
 	case "BridgeAddress":
 		return model.BridgeAddressParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "MonitoredSAL":
-		return model.MonitoredSALParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
+		// TODO: find a way to parse the sub types
+		var cBusOptions model.CBusOptions
+		return model.MonitoredSALParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)), cBusOptions)
 	case "ParameterChange":
 		return model.ParameterChangeParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "StatusByte":
diff --git a/plc4go/protocols/cbus/readwrite/model/CALReply.go b/plc4go/protocols/cbus/readwrite/model/CALReply.go
index 8d293aeb9..258b17f87 100644
--- a/plc4go/protocols/cbus/readwrite/model/CALReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/CALReply.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.
@@ -34,6 +36,8 @@ type CALReply interface {
 	GetCalType() byte
 	// GetCalData returns CalData (property field)
 	GetCalData() CALData
+	// GetCrc returns Crc (property field)
+	GetCrc() Checksum
 }
 
 // CALReplyExactly can be used when we want exactly this type and not a type which fulfills CALReply.
@@ -48,8 +52,10 @@ type _CALReply struct {
 	_CALReplyChildRequirements
 	CalType byte
 	CalData CALData
+	Crc     Checksum
 
 	// Arguments.
+	CBusOptions    CBusOptions
 	RequestContext RequestContext
 }
 
@@ -66,7 +72,7 @@ type CALReplyParent interface {
 
 type CALReplyChild interface {
 	utils.Serializable
-	InitializeParent(parent CALReply, calType byte, calData CALData)
+	InitializeParent(parent CALReply, calType byte, calData CALData, crc Checksum)
 	GetParent() *CALReply
 
 	GetTypeName() string
@@ -86,14 +92,18 @@ func (m *_CALReply) GetCalData() CALData {
 	return m.CalData
 }
 
+func (m *_CALReply) GetCrc() Checksum {
+	return m.Crc
+}
+
 ///////////////////////
 ///////////////////////
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
 // NewCALReply factory function for _CALReply
-func NewCALReply(calType byte, calData CALData, requestContext RequestContext) *_CALReply {
-	return &_CALReply{CalType: calType, CalData: calData, RequestContext: requestContext}
+func NewCALReply(calType byte, calData CALData, crc Checksum, cBusOptions CBusOptions, requestContext RequestContext) *_CALReply {
+	return &_CALReply{CalType: calType, CalData: calData, Crc: crc, CBusOptions: cBusOptions, RequestContext: requestContext}
 }
 
 // Deprecated: use the interface for direct cast
@@ -117,6 +127,11 @@ func (m *_CALReply) GetParentLengthInBits() uint16 {
 	// Simple field (calData)
 	lengthInBits += m.CalData.GetLengthInBits()
 
+	// Optional Field (crc)
+	if m.Crc != nil {
+		lengthInBits += m.Crc.GetLengthInBits()
+	}
+
 	return lengthInBits
 }
 
@@ -124,7 +139,7 @@ func (m *_CALReply) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func CALReplyParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (CALReply, error) {
+func CALReplyParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions, requestContext RequestContext) (CALReply, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("CALReply"); pullErr != nil {
@@ -145,7 +160,7 @@ func CALReplyParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (
 	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
 	type CALReplyChildSerializeRequirement interface {
 		CALReply
-		InitializeParent(CALReply, byte, CALData)
+		InitializeParent(CALReply, byte, CALData, Checksum)
 		GetParent() CALReply
 	}
 	var _childTemp interface{}
@@ -153,9 +168,9 @@ func CALReplyParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (
 	var typeSwitchError error
 	switch {
 	case calType == 0x86: // CALReplyLong
-		_childTemp, typeSwitchError = CALReplyLongParse(readBuffer, requestContext)
+		_childTemp, typeSwitchError = CALReplyLongParse(readBuffer, cBusOptions, requestContext)
 	case true: // CALReplyShort
-		_childTemp, typeSwitchError = CALReplyShortParse(readBuffer, requestContext)
+		_childTemp, typeSwitchError = CALReplyShortParse(readBuffer, cBusOptions, requestContext)
 	default:
 		typeSwitchError = errors.Errorf("Unmapped type for parameters [calType=%v]", calType)
 	}
@@ -177,12 +192,34 @@ func CALReplyParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (
 		return nil, errors.Wrap(closeErr, "Error closing for calData")
 	}
 
+	// Optional Field (crc) (Can be skipped, if a given expression evaluates to false)
+	var crc Checksum = nil
+	if cBusOptions.GetSrchk() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("crc"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for crc")
+		}
+		_val, _err := ChecksumParse(readBuffer)
+		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 'crc' field of CALReply")
+		default:
+			crc = _val.(Checksum)
+			if closeErr := readBuffer.CloseContext("crc"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for crc")
+			}
+		}
+	}
+
 	if closeErr := readBuffer.CloseContext("CALReply"); closeErr != nil {
 		return nil, errors.Wrap(closeErr, "Error closing for CALReply")
 	}
 
 	// Finish initializing
-	_child.InitializeParent(_child, calType, calData)
+	_child.InitializeParent(_child, calType, calData, crc)
 	return _child, nil
 }
 
@@ -213,6 +250,22 @@ func (pm *_CALReply) SerializeParent(writeBuffer utils.WriteBuffer, child CALRep
 		return errors.Wrap(_calDataErr, "Error serializing 'calData' field")
 	}
 
+	// Optional Field (crc) (Can be skipped, if the value is null)
+	var crc Checksum = nil
+	if m.GetCrc() != nil {
+		if pushErr := writeBuffer.PushContext("crc"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for crc")
+		}
+		crc = m.GetCrc()
+		_crcErr := writeBuffer.WriteSerializable(crc)
+		if popErr := writeBuffer.PopContext("crc"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for crc")
+		}
+		if _crcErr != nil {
+			return errors.Wrap(_crcErr, "Error serializing 'crc' field")
+		}
+	}
+
 	if popErr := writeBuffer.PopContext("CALReply"); popErr != nil {
 		return errors.Wrap(popErr, "Error popping for CALReply")
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/CALReplyLong.go b/plc4go/protocols/cbus/readwrite/model/CALReplyLong.go
index 7184732fe..57202bfef 100644
--- a/plc4go/protocols/cbus/readwrite/model/CALReplyLong.go
+++ b/plc4go/protocols/cbus/readwrite/model/CALReplyLong.go
@@ -77,9 +77,10 @@ type _CALReplyLong struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_CALReplyLong) InitializeParent(parent CALReply, calType byte, calData CALData) {
+func (m *_CALReplyLong) InitializeParent(parent CALReply, calType byte, calData CALData, crc Checksum) {
 	m.CalType = calType
 	m.CalData = calData
+	m.Crc = crc
 }
 
 func (m *_CALReplyLong) GetParent() CALReply {
@@ -142,7 +143,7 @@ func (m *_CALReplyLong) GetIsUnitAddress() bool {
 ///////////////////////////////////////////////////////////
 
 // NewCALReplyLong factory function for _CALReplyLong
-func NewCALReplyLong(terminatingByte uint32, unitAddress UnitAddress, bridgeAddress BridgeAddress, serialInterfaceAddress SerialInterfaceAddress, reservedByte *byte, replyNetwork ReplyNetwork, calType byte, calData CALData, requestContext RequestContext) *_CALReplyLong {
+func NewCALReplyLong(terminatingByte uint32, unitAddress UnitAddress, bridgeAddress BridgeAddress, serialInterfaceAddress SerialInterfaceAddress, reservedByte *byte, replyNetwork ReplyNetwork, calType byte, calData CALData, crc Checksum, cBusOptions CBusOptions, requestContext RequestContext) *_CALReplyLong {
 	_result := &_CALReplyLong{
 		TerminatingByte:        terminatingByte,
 		UnitAddress:            unitAddress,
@@ -150,7 +151,7 @@ func NewCALReplyLong(terminatingByte uint32, unitAddress UnitAddress, bridgeAddr
 		SerialInterfaceAddress: serialInterfaceAddress,
 		ReservedByte:           reservedByte,
 		ReplyNetwork:           replyNetwork,
-		_CALReply:              NewCALReply(calType, calData, requestContext),
+		_CALReply:              NewCALReply(calType, calData, crc, cBusOptions, requestContext),
 	}
 	_result._CALReply._CALReplyChildRequirements = _result
 	return _result
@@ -213,7 +214,7 @@ func (m *_CALReplyLong) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func CALReplyLongParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (CALReplyLong, error) {
+func CALReplyLongParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions, requestContext RequestContext) (CALReplyLong, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("CALReplyLong"); pullErr != nil {
@@ -357,6 +358,7 @@ func CALReplyLongParse(readBuffer utils.ReadBuffer, requestContext RequestContex
 		ReservedByte:           reservedByte,
 		ReplyNetwork:           replyNetwork,
 		_CALReply: &_CALReply{
+			CBusOptions:    cBusOptions,
 			RequestContext: requestContext,
 		},
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/CALReplyShort.go b/plc4go/protocols/cbus/readwrite/model/CALReplyShort.go
index ec33cbd86..cc2897ae3 100644
--- a/plc4go/protocols/cbus/readwrite/model/CALReplyShort.go
+++ b/plc4go/protocols/cbus/readwrite/model/CALReplyShort.go
@@ -55,9 +55,10 @@ type _CALReplyShort struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_CALReplyShort) InitializeParent(parent CALReply, calType byte, calData CALData) {
+func (m *_CALReplyShort) InitializeParent(parent CALReply, calType byte, calData CALData, crc Checksum) {
 	m.CalType = calType
 	m.CalData = calData
+	m.Crc = crc
 }
 
 func (m *_CALReplyShort) GetParent() CALReply {
@@ -65,9 +66,9 @@ func (m *_CALReplyShort) GetParent() CALReply {
 }
 
 // NewCALReplyShort factory function for _CALReplyShort
-func NewCALReplyShort(calType byte, calData CALData, requestContext RequestContext) *_CALReplyShort {
+func NewCALReplyShort(calType byte, calData CALData, crc Checksum, cBusOptions CBusOptions, requestContext RequestContext) *_CALReplyShort {
 	_result := &_CALReplyShort{
-		_CALReply: NewCALReply(calType, calData, requestContext),
+		_CALReply: NewCALReply(calType, calData, crc, cBusOptions, requestContext),
 	}
 	_result._CALReply._CALReplyChildRequirements = _result
 	return _result
@@ -102,7 +103,7 @@ func (m *_CALReplyShort) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func CALReplyShortParse(readBuffer utils.ReadBuffer, requestContext RequestContext) (CALReplyShort, error) {
+func CALReplyShortParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions, requestContext RequestContext) (CALReplyShort, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("CALReplyShort"); pullErr != nil {
@@ -118,6 +119,7 @@ func CALReplyShortParse(readBuffer utils.ReadBuffer, requestContext RequestConte
 	// Create a partially initialized instance
 	_child := &_CALReplyShort{
 		_CALReply: &_CALReply{
+			CBusOptions:    cBusOptions,
 			RequestContext: requestContext,
 		},
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go b/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
index 5f3332582..8fc5e8b96 100644
--- a/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
+++ b/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
@@ -36,6 +36,8 @@ type MonitoredSAL interface {
 	GetSalType() byte
 	// GetSalData returns SalData (property field)
 	GetSalData() SALData
+	// GetCrc returns Crc (property field)
+	GetCrc() Checksum
 }
 
 // MonitoredSALExactly can be used when we want exactly this type and not a type which fulfills MonitoredSAL.
@@ -50,6 +52,10 @@ type _MonitoredSAL struct {
 	_MonitoredSALChildRequirements
 	SalType byte
 	SalData SALData
+	Crc     Checksum
+
+	// Arguments.
+	CBusOptions CBusOptions
 }
 
 type _MonitoredSALChildRequirements interface {
@@ -65,7 +71,7 @@ type MonitoredSALParent interface {
 
 type MonitoredSALChild interface {
 	utils.Serializable
-	InitializeParent(parent MonitoredSAL, salType byte, salData SALData)
+	InitializeParent(parent MonitoredSAL, salType byte, salData SALData, crc Checksum)
 	GetParent() *MonitoredSAL
 
 	GetTypeName() string
@@ -85,14 +91,18 @@ func (m *_MonitoredSAL) GetSalData() SALData {
 	return m.SalData
 }
 
+func (m *_MonitoredSAL) GetCrc() Checksum {
+	return m.Crc
+}
+
 ///////////////////////
 ///////////////////////
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
 // NewMonitoredSAL factory function for _MonitoredSAL
-func NewMonitoredSAL(salType byte, salData SALData) *_MonitoredSAL {
-	return &_MonitoredSAL{SalType: salType, SalData: salData}
+func NewMonitoredSAL(salType byte, salData SALData, crc Checksum, cBusOptions CBusOptions) *_MonitoredSAL {
+	return &_MonitoredSAL{SalType: salType, SalData: salData, Crc: crc, CBusOptions: cBusOptions}
 }
 
 // Deprecated: use the interface for direct cast
@@ -118,6 +128,11 @@ func (m *_MonitoredSAL) GetParentLengthInBits() uint16 {
 		lengthInBits += m.SalData.GetLengthInBits()
 	}
 
+	// Optional Field (crc)
+	if m.Crc != nil {
+		lengthInBits += m.Crc.GetLengthInBits()
+	}
+
 	return lengthInBits
 }
 
@@ -125,7 +140,7 @@ func (m *_MonitoredSAL) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func MonitoredSALParse(readBuffer utils.ReadBuffer) (MonitoredSAL, error) {
+func MonitoredSALParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions) (MonitoredSAL, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("MonitoredSAL"); pullErr != nil {
@@ -146,7 +161,7 @@ func MonitoredSALParse(readBuffer utils.ReadBuffer) (MonitoredSAL, error) {
 	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
 	type MonitoredSALChildSerializeRequirement interface {
 		MonitoredSAL
-		InitializeParent(MonitoredSAL, byte, SALData)
+		InitializeParent(MonitoredSAL, byte, SALData, Checksum)
 		GetParent() MonitoredSAL
 	}
 	var _childTemp interface{}
@@ -154,9 +169,9 @@ func MonitoredSALParse(readBuffer utils.ReadBuffer) (MonitoredSAL, error) {
 	var typeSwitchError error
 	switch {
 	case salType == 0x05: // MonitoredSALLongFormSmartMode
-		_childTemp, typeSwitchError = MonitoredSALLongFormSmartModeParse(readBuffer)
+		_childTemp, typeSwitchError = MonitoredSALLongFormSmartModeParse(readBuffer, cBusOptions)
 	case true: // MonitoredSALShortFormBasicMode
-		_childTemp, typeSwitchError = MonitoredSALShortFormBasicModeParse(readBuffer)
+		_childTemp, typeSwitchError = MonitoredSALShortFormBasicModeParse(readBuffer, cBusOptions)
 	default:
 		typeSwitchError = errors.Errorf("Unmapped type for parameters [salType=%v]", salType)
 	}
@@ -187,12 +202,34 @@ func MonitoredSALParse(readBuffer utils.ReadBuffer) (MonitoredSAL, error) {
 		}
 	}
 
+	// Optional Field (crc) (Can be skipped, if a given expression evaluates to false)
+	var crc Checksum = nil
+	if cBusOptions.GetSrchk() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("crc"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for crc")
+		}
+		_val, _err := ChecksumParse(readBuffer)
+		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 'crc' field of MonitoredSAL")
+		default:
+			crc = _val.(Checksum)
+			if closeErr := readBuffer.CloseContext("crc"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for crc")
+			}
+		}
+	}
+
 	if closeErr := readBuffer.CloseContext("MonitoredSAL"); closeErr != nil {
 		return nil, errors.Wrap(closeErr, "Error closing for MonitoredSAL")
 	}
 
 	// Finish initializing
-	_child.InitializeParent(_child, salType, salData)
+	_child.InitializeParent(_child, salType, salData, crc)
 	return _child, nil
 }
 
@@ -227,6 +264,22 @@ func (pm *_MonitoredSAL) SerializeParent(writeBuffer utils.WriteBuffer, child Mo
 		}
 	}
 
+	// Optional Field (crc) (Can be skipped, if the value is null)
+	var crc Checksum = nil
+	if m.GetCrc() != nil {
+		if pushErr := writeBuffer.PushContext("crc"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for crc")
+		}
+		crc = m.GetCrc()
+		_crcErr := writeBuffer.WriteSerializable(crc)
+		if popErr := writeBuffer.PopContext("crc"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for crc")
+		}
+		if _crcErr != nil {
+			return errors.Wrap(_crcErr, "Error serializing 'crc' field")
+		}
+	}
+
 	if popErr := writeBuffer.PopContext("MonitoredSAL"); popErr != nil {
 		return errors.Wrap(popErr, "Error popping for MonitoredSAL")
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/MonitoredSALLongFormSmartMode.go b/plc4go/protocols/cbus/readwrite/model/MonitoredSALLongFormSmartMode.go
index 1778f5da4..dbfcbbe0c 100644
--- a/plc4go/protocols/cbus/readwrite/model/MonitoredSALLongFormSmartMode.go
+++ b/plc4go/protocols/cbus/readwrite/model/MonitoredSALLongFormSmartMode.go
@@ -77,9 +77,10 @@ type _MonitoredSALLongFormSmartMode struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_MonitoredSALLongFormSmartMode) InitializeParent(parent MonitoredSAL, salType byte, salData SALData) {
+func (m *_MonitoredSALLongFormSmartMode) InitializeParent(parent MonitoredSAL, salType byte, salData SALData, crc Checksum) {
 	m.SalType = salType
 	m.SalData = salData
+	m.Crc = crc
 }
 
 func (m *_MonitoredSALLongFormSmartMode) GetParent() MonitoredSAL {
@@ -142,7 +143,7 @@ func (m *_MonitoredSALLongFormSmartMode) GetIsUnitAddress() bool {
 ///////////////////////////////////////////////////////////
 
 // NewMonitoredSALLongFormSmartMode factory function for _MonitoredSALLongFormSmartMode
-func NewMonitoredSALLongFormSmartMode(terminatingByte uint32, unitAddress UnitAddress, bridgeAddress BridgeAddress, serialInterfaceAddress SerialInterfaceAddress, reservedByte *byte, replyNetwork ReplyNetwork, salType byte, salData SALData) *_MonitoredSALLongFormSmartMode {
+func NewMonitoredSALLongFormSmartMode(terminatingByte uint32, unitAddress UnitAddress, bridgeAddress BridgeAddress, serialInterfaceAddress SerialInterfaceAddress, reservedByte *byte, replyNetwork ReplyNetwork, salType byte, salData SALData, crc Checksum, cBusOptions CBusOptions) *_MonitoredSALLongFormSmartMode {
 	_result := &_MonitoredSALLongFormSmartMode{
 		TerminatingByte:        terminatingByte,
 		UnitAddress:            unitAddress,
@@ -150,7 +151,7 @@ func NewMonitoredSALLongFormSmartMode(terminatingByte uint32, unitAddress UnitAd
 		SerialInterfaceAddress: serialInterfaceAddress,
 		ReservedByte:           reservedByte,
 		ReplyNetwork:           replyNetwork,
-		_MonitoredSAL:          NewMonitoredSAL(salType, salData),
+		_MonitoredSAL:          NewMonitoredSAL(salType, salData, crc, cBusOptions),
 	}
 	_result._MonitoredSAL._MonitoredSALChildRequirements = _result
 	return _result
@@ -213,7 +214,7 @@ func (m *_MonitoredSALLongFormSmartMode) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func MonitoredSALLongFormSmartModeParse(readBuffer utils.ReadBuffer) (MonitoredSALLongFormSmartMode, error) {
+func MonitoredSALLongFormSmartModeParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions) (MonitoredSALLongFormSmartMode, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("MonitoredSALLongFormSmartMode"); pullErr != nil {
@@ -356,7 +357,9 @@ func MonitoredSALLongFormSmartModeParse(readBuffer utils.ReadBuffer) (MonitoredS
 		SerialInterfaceAddress: serialInterfaceAddress,
 		ReservedByte:           reservedByte,
 		ReplyNetwork:           replyNetwork,
-		_MonitoredSAL:          &_MonitoredSAL{},
+		_MonitoredSAL: &_MonitoredSAL{
+			CBusOptions: cBusOptions,
+		},
 	}
 	_child._MonitoredSAL._MonitoredSALChildRequirements = _child
 	return _child, nil
diff --git a/plc4go/protocols/cbus/readwrite/model/MonitoredSALReply.go b/plc4go/protocols/cbus/readwrite/model/MonitoredSALReply.go
index c186024f1..b31f7ad08 100644
--- a/plc4go/protocols/cbus/readwrite/model/MonitoredSALReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/MonitoredSALReply.go
@@ -154,7 +154,7 @@ func MonitoredSALReplyParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions
 	_ = payloadLength
 
 	// Manual Field (monitoredSAL)
-	_monitoredSAL, _monitoredSALErr := ReadMonitoredSAL(readBuffer, payloadLength)
+	_monitoredSAL, _monitoredSALErr := ReadMonitoredSAL(readBuffer, payloadLength, cBusOptions)
 	if _monitoredSALErr != nil {
 		return nil, errors.Wrap(_monitoredSALErr, "Error parsing 'monitoredSAL' field of MonitoredSALReply")
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/MonitoredSALShortFormBasicMode.go b/plc4go/protocols/cbus/readwrite/model/MonitoredSALShortFormBasicMode.go
index d80add221..1672ec77f 100644
--- a/plc4go/protocols/cbus/readwrite/model/MonitoredSALShortFormBasicMode.go
+++ b/plc4go/protocols/cbus/readwrite/model/MonitoredSALShortFormBasicMode.go
@@ -72,9 +72,10 @@ type _MonitoredSALShortFormBasicMode struct {
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
 
-func (m *_MonitoredSALShortFormBasicMode) InitializeParent(parent MonitoredSAL, salType byte, salData SALData) {
+func (m *_MonitoredSALShortFormBasicMode) InitializeParent(parent MonitoredSAL, salType byte, salData SALData, crc Checksum) {
 	m.SalType = salType
 	m.SalData = salData
+	m.Crc = crc
 }
 
 func (m *_MonitoredSALShortFormBasicMode) GetParent() MonitoredSAL {
@@ -112,14 +113,14 @@ func (m *_MonitoredSALShortFormBasicMode) GetApplication() ApplicationIdContaine
 ///////////////////////////////////////////////////////////
 
 // NewMonitoredSALShortFormBasicMode factory function for _MonitoredSALShortFormBasicMode
-func NewMonitoredSALShortFormBasicMode(counts byte, bridgeCount BridgeCount, networkNumber NetworkNumber, noCounts *byte, application ApplicationIdContainer, salType byte, salData SALData) *_MonitoredSALShortFormBasicMode {
+func NewMonitoredSALShortFormBasicMode(counts byte, bridgeCount BridgeCount, networkNumber NetworkNumber, noCounts *byte, application ApplicationIdContainer, salType byte, salData SALData, crc Checksum, cBusOptions CBusOptions) *_MonitoredSALShortFormBasicMode {
 	_result := &_MonitoredSALShortFormBasicMode{
 		Counts:        counts,
 		BridgeCount:   bridgeCount,
 		NetworkNumber: networkNumber,
 		NoCounts:      noCounts,
 		Application:   application,
-		_MonitoredSAL: NewMonitoredSAL(salType, salData),
+		_MonitoredSAL: NewMonitoredSAL(salType, salData, crc, cBusOptions),
 	}
 	_result._MonitoredSAL._MonitoredSALChildRequirements = _result
 	return _result
@@ -172,7 +173,7 @@ func (m *_MonitoredSALShortFormBasicMode) GetLengthInBytes() uint16 {
 	return m.GetLengthInBits() / 8
 }
 
-func MonitoredSALShortFormBasicModeParse(readBuffer utils.ReadBuffer) (MonitoredSALShortFormBasicMode, error) {
+func MonitoredSALShortFormBasicModeParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions) (MonitoredSALShortFormBasicMode, error) {
 	positionAware := readBuffer
 	_ = positionAware
 	if pullErr := readBuffer.PullContext("MonitoredSALShortFormBasicMode"); pullErr != nil {
@@ -268,7 +269,9 @@ func MonitoredSALShortFormBasicModeParse(readBuffer utils.ReadBuffer) (Monitored
 		NetworkNumber: networkNumber,
 		NoCounts:      noCounts,
 		Application:   application,
-		_MonitoredSAL: &_MonitoredSAL{},
+		_MonitoredSAL: &_MonitoredSAL{
+			CBusOptions: cBusOptions,
+		},
 	}
 	_child._MonitoredSAL._MonitoredSALChildRequirements = _child
 	return _child, nil
diff --git a/plc4go/protocols/cbus/readwrite/model/ReplyCALReply.go b/plc4go/protocols/cbus/readwrite/model/ReplyCALReply.go
index 332d30d26..373bfee3a 100644
--- a/plc4go/protocols/cbus/readwrite/model/ReplyCALReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/ReplyCALReply.go
@@ -154,7 +154,7 @@ func ReplyCALReplyParse(readBuffer utils.ReadBuffer, cBusOptions CBusOptions, re
 	_ = payloadLength
 
 	// Manual Field (calReply)
-	_calReply, _calReplyErr := ReadCALReply(readBuffer, payloadLength, requestContext)
+	_calReply, _calReplyErr := ReadCALReply(readBuffer, payloadLength, cBusOptions, requestContext)
 	if _calReplyErr != nil {
 		return nil, errors.Wrap(_calReplyErr, "Error parsing 'calReply' field of ReplyCALReply")
 	}
diff --git a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
index 66dcbc387..25545ae37 100644
--- a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
@@ -42,12 +42,12 @@ func WriteCALReply(writeBuffer utils.WriteBuffer, calReply CALReply) error {
 	return writeToHex("calReply", writeBuffer, calReply)
 }
 
-func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16, requestContext RequestContext) (CALReply, error) {
+func ReadCALReply(readBuffer utils.ReadBuffer, payloadLength uint16, options CBusOptions, requestContext RequestContext) (CALReply, error) {
 	rawBytes, err := readBytesFromHex("calReply", readBuffer, payloadLength)
 	if err != nil {
 		return nil, errors.Wrap(err, "Error getting hex")
 	}
-	return CALReplyParse(utils.NewReadBufferByteBased(rawBytes), requestContext)
+	return CALReplyParse(utils.NewReadBufferByteBased(rawBytes), options, requestContext)
 }
 
 func WriteCALDataOrSetParameter(writeBuffer utils.WriteBuffer, calDataOrSetParameter CALDataOrSetParameter) error {
@@ -66,12 +66,12 @@ func WriteMonitoredSAL(writeBuffer utils.WriteBuffer, monitoredSAL MonitoredSAL)
 	return writeToHex("monitoredSAL", writeBuffer, monitoredSAL)
 }
 
-func ReadMonitoredSAL(readBuffer utils.ReadBuffer, payloadLength uint16) (MonitoredSAL, error) {
+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))
+	return MonitoredSALParse(utils.NewReadBufferByteBased(rawBytes), options)
 }
 
 func WriteStandardFormatStatusReply(writeBuffer utils.WriteBuffer, reply StandardFormatStatusReply) error {
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 ce7041386..9d2dd2c50 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
@@ -42,9 +42,9 @@ public class StaticHelper {
         writeToHex("calReply", writeBuffer, calReply, calReply.getLengthInBytes());
     }
 
-    public static CALReply readCALReply(ReadBuffer readBuffer, Integer payloadLength, RequestContext requestContext) throws ParseException {
+    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), requestContext);
+        return CALReply.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions, requestContext);
     }
 
     public static void writeCALDataOrSetParameter(WriteBuffer writeBuffer, CALDataOrSetParameter calDataOrSetParameter) throws SerializationException {
@@ -60,9 +60,9 @@ public class StaticHelper {
         writeToHex("monitoredSAL", writeBuffer, monitoredSAL, monitoredSAL.getLengthInBytes());
     }
 
-    public static MonitoredSAL readMonitoredSAL(ReadBuffer readBuffer, Integer payloadLength) throws ParseException {
+    public static MonitoredSAL readMonitoredSAL(ReadBuffer readBuffer, Integer payloadLength, CBusOptions cBusOptions) throws ParseException {
         byte[] rawBytes = readBytesFromHex("monitoredSAL", readBuffer, payloadLength);
-        return MonitoredSAL.staticParse(new ReadBufferByteBased(rawBytes));
+        return MonitoredSAL.staticParse(new ReadBufferByteBased(rawBytes), cBusOptions);
     }
 
     public static void writeStandardFormatStatusReply(WriteBuffer writeBuffer, StandardFormatStatusReply standardFormatStatusReply) throws SerializationException {
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 8be84640f..7771d1a8c 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
@@ -252,7 +252,7 @@ public class RandomPackagesTest {
             void calReplyNormal() throws Exception {
                 byte[] bytes = Hex.decodeHex("8902312E322E363620200A");
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                CALReply msg = CALReplyShort.staticParse(readBufferByteBased, requestContext);
+                CALReply msg = CALReplyShort.staticParse(readBufferByteBased, cBusOptions, requestContext);
                 assertThat(msg)
                     .isNotNull();
                 System.out.println(msg);
@@ -262,7 +262,7 @@ public class RandomPackagesTest {
             void calReplySmart() throws Exception {
                 byte[] bytes = Hex.decodeHex("860593008902312E322E363620207F");
                 ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-                CALReply msg = CALReplyLong.staticParse(readBufferByteBased, requestContext);
+                CALReply msg = CALReplyLong.staticParse(readBufferByteBased, cBusOptions, requestContext);
                 assertThat(msg)
                     .isNotNull();
                 System.out.println(msg);
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 748688139..6e98dfa78 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
@@ -225,8 +225,8 @@
             [simple UnitAddress   unitAddress                                                   ]
         ]
     ]
-    [simple   CALData('null') calData                                                                   ]
-    [optional Checksum      crc      'cBusOptions.srchk'                                                    ] // checksum is optional but mspec checksum isn't
+    [simple   CALData('null') calData                                                           ]
+    [optional Checksum      crc      'cBusOptions.srchk'                                        ] // checksum is optional but mspec checksum isn't
 ]
 
 [discriminatedType CBusPointToMultiPointCommand(CBusOptions cBusOptions)
@@ -997,7 +997,7 @@
             [virtual uint 16 payloadLength 'replyLength']
             [manual   CALReply
                               calReply
-                                    'STATIC_CALL("readCALReply", readBuffer, payloadLength, requestContext)'
+                                    'STATIC_CALL("readCALReply", readBuffer, payloadLength, cBusOptions, requestContext)'
                                     'STATIC_CALL("writeCALReply", writeBuffer, calReply)'
                                     '_value.lengthInBytes*2'                                     ]
         ]
@@ -1005,14 +1005,14 @@
             [virtual uint 16 payloadLength 'replyLength']
             [manual   MonitoredSAL
                               monitoredSAL
-                                    'STATIC_CALL("readMonitoredSAL", readBuffer, payloadLength)'
+                                    'STATIC_CALL("readMonitoredSAL", readBuffer, payloadLength, cBusOptions)'
                                     'STATIC_CALL("writeMonitoredSAL", writeBuffer, monitoredSAL)'
                                     '_value.lengthInBytes*2'                                     ]
         ]
     ]
 ]
 
-[type CALReply(RequestContext requestContext)
+[type CALReply(CBusOptions cBusOptions, RequestContext requestContext)
     [peek    byte     calType                                                                    ]
     [typeSwitch calType
         ['0x86' CALReplyLong
@@ -1031,7 +1031,7 @@
         ]
     ]
     [simple   CALData('requestContext')   calData                                                ]
-    //[checksum byte crc   '0x00'                                                                ] // TODO: Fix this
+    [optional Checksum      crc      'cBusOptions.srchk'                                         ] // checksum is optional but mspec checksum isn't
 ]
 
 [type BridgeCount
@@ -1042,7 +1042,7 @@
     [simple uint 8 number]
 ]
 
-[type MonitoredSAL
+[type MonitoredSAL(CBusOptions cBusOptions)
     [peek    byte     salType             ]
     [typeSwitch salType
         ['0x05' MonitoredSALLongFormSmartMode
@@ -1069,7 +1069,7 @@
         ]
     ]
     [optional SALData salData                                               ]
-    //[checksum byte crc   '0x00'                                                                ] // TODO: Fix this
+    [optional Checksum      crc      'cBusOptions.srchk'                                                    ] // checksum is optional but mspec checksum isn't
 ]
 
 [type Confirmation