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 ]