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 3ec51ecc82 feat(plc4go/cbus): implemented bridge support in message 
mapper
3ec51ecc82 is described below

commit 3ec51ecc82acbbd4ec974a446d00a362d40d6078
Author: Sebastian Rühl <[email protected]>
AuthorDate: Fri Mar 24 18:03:47 2023 +0100

    feat(plc4go/cbus): implemented bridge support in message mapper
---
 plc4go/internal/cbus/CBusMessageMapper.go | 77 +++++++++++++++++++++++++------
 plc4go/internal/cbus/Tag.go               | 65 +++++++++++++++++++++-----
 plc4go/internal/cbus/TagHandler.go        |  8 +++-
 3 files changed, 123 insertions(+), 27 deletions(-)

diff --git a/plc4go/internal/cbus/CBusMessageMapper.go 
b/plc4go/internal/cbus/CBusMessageMapper.go
index 901c75cf43..b295b8958e 100644
--- a/plc4go/internal/cbus/CBusMessageMapper.go
+++ b/plc4go/internal/cbus/CBusMessageMapper.go
@@ -46,18 +46,33 @@ func TagToCBusMessage(tag apiModel.PlcTag, value 
apiValues.PlcValue, alphaGenera
                case StatusRequestTypeLevel:
                        statusRequest = 
readWriteModel.NewStatusRequestLevel(tagType.application, 
*tagType.startingGroupAddressLabel, 0x73)
                }
-               //TODO: we need support for bridged commands
-               command := 
readWriteModel.NewCBusPointToMultiPointCommandStatus(statusRequest, 
byte(tagType.application), cbusOptions)
-               header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToMultiPoint)
-               cbusCommand := 
readWriteModel.NewCBusCommandPointToMultiPoint(command, header, cbusOptions)
+               var cbusCommand readWriteModel.CBusCommand
+               bridgeAddresses := tagType.bridgeAddresses
+               numberOfBridgeAddresses := len(bridgeAddresses)
+               if numberOfBridgeAddresses <= 0 {
+                       command := 
readWriteModel.NewCBusPointToMultiPointCommandStatus(statusRequest, 
byte(tagType.application), cbusOptions)
+                       header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToMultiPoint)
+                       cbusCommand = 
readWriteModel.NewCBusCommandPointToMultiPoint(command, header, cbusOptions)
+               } else {
+                       var networkRoute readWriteModel.NetworkRoute
+                       if numberOfBridgeAddresses > 1 {
+                               networkRoute = 
readWriteModel.NewNetworkRoute(readWriteModel.NewNetworkProtocolControlInformation(uint8(numberOfBridgeAddresses),
 uint8(numberOfBridgeAddresses)), bridgeAddresses[1:])
+                       }
+                       command := 
readWriteModel.NewCBusPointToPointToMultiPointCommandStatus(statusRequest, 
bridgeAddresses[0], networkRoute, byte(tagType.application), cbusOptions)
+                       header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPointToMultiPoint)
+                       cbusCommand = 
readWriteModel.NewCBusCommandPointToPointToMultiPoint(command, header, 
cbusOptions)
+               }
                request := readWriteModel.NewRequestCommand(cbusCommand, nil, 
readWriteModel.NewAlpha(alphaGenerator.getAndIncrement()), 
readWriteModel.RequestType_REQUEST_COMMAND, nil, nil, 
readWriteModel.RequestType_EMPTY, readWriteModel.NewRequestTermination(), 
cbusOptions)
 
                cBusMessage, supportsRead, supportsSubscribe = 
readWriteModel.NewCBusMessageToServer(request, requestContext, cbusOptions), 
true, true
                return
        case *calRecallTag:
                calData := readWriteModel.NewCALDataRecall(tagType.parameter, 
tagType.count, readWriteModel.CALCommandTypeContainer_CALCommandRecall, nil, 
requestContext)
-               //TODO: we need support for bridged commands
-               command := 
readWriteModel.NewCBusPointToPointCommandDirect(tagType.unitAddress, 0x0000, 
calData, cbusOptions)
+               var command readWriteModel.CBusPointToPointCommand
+               command, err = producePointToPointCommand(tagType.unitAddress, 
tagType.bridgeAddresses, calData, cbusOptions)
+               if err != nil {
+                       return nil, false, false, false, errors.Wrap(err, 
"error producing cal command")
+               }
                header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPoint)
                cbusCommand := 
readWriteModel.NewCBusCommandPointToPoint(command, header, cbusOptions)
                request := readWriteModel.NewRequestCommand(cbusCommand, nil, 
readWriteModel.NewAlpha(alphaGenerator.getAndIncrement()), 
readWriteModel.RequestType_REQUEST_COMMAND, nil, nil, 
readWriteModel.RequestType_EMPTY, readWriteModel.NewRequestTermination(), 
cbusOptions)
@@ -66,8 +81,11 @@ func TagToCBusMessage(tag apiModel.PlcTag, value 
apiValues.PlcValue, alphaGenera
                return
        case *calIdentifyTag:
                calData := readWriteModel.NewCALDataIdentify(tagType.attribute, 
readWriteModel.CALCommandTypeContainer_CALCommandIdentify, nil, requestContext)
-               //TODO: we need support for bridged commands
-               command := 
readWriteModel.NewCBusPointToPointCommandDirect(tagType.unitAddress, 0x0000, 
calData, cbusOptions)
+               var command readWriteModel.CBusPointToPointCommand
+               command, err = producePointToPointCommand(tagType.unitAddress, 
tagType.bridgeAddresses, calData, cbusOptions)
+               if err != nil {
+                       return nil, false, false, false, errors.Wrap(err, 
"error producing cal command")
+               }
                header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPoint)
                cbusCommand := 
readWriteModel.NewCBusCommandPointToPoint(command, header, cbusOptions)
                request := readWriteModel.NewRequestCommand(cbusCommand, nil, 
readWriteModel.NewAlpha(alphaGenerator.getAndIncrement()), 
readWriteModel.RequestType_REQUEST_COMMAND, nil, nil, 
readWriteModel.RequestType_EMPTY, readWriteModel.NewRequestTermination(), 
cbusOptions)
@@ -76,8 +94,11 @@ func TagToCBusMessage(tag apiModel.PlcTag, value 
apiValues.PlcValue, alphaGenera
                return
        case *calGetStatusTag:
                calData := 
readWriteModel.NewCALDataGetStatus(tagType.parameter, tagType.count, 
readWriteModel.CALCommandTypeContainer_CALCommandGetStatus, nil, requestContext)
-               //TODO: we need support for bridged commands
-               command := 
readWriteModel.NewCBusPointToPointCommandDirect(tagType.unitAddress, 0x0000, 
calData, cbusOptions)
+               var command readWriteModel.CBusPointToPointCommand
+               command, err = producePointToPointCommand(tagType.unitAddress, 
tagType.bridgeAddresses, calData, cbusOptions)
+               if err == nil {
+                       return nil, false, false, false, errors.Wrap(err, 
"error producing cal command")
+               }
                header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPoint)
                cbusCommand := 
readWriteModel.NewCBusCommandPointToPoint(command, header, cbusOptions)
                request := readWriteModel.NewRequestCommand(cbusCommand, nil, 
readWriteModel.NewAlpha(alphaGenerator.getAndIncrement()), 
readWriteModel.RequestType_REQUEST_COMMAND, nil, nil, 
readWriteModel.RequestType_EMPTY, readWriteModel.NewRequestTermination(), 
cbusOptions)
@@ -194,10 +215,22 @@ func TagToCBusMessage(tag apiModel.PlcTag, value 
apiValues.PlcValue, alphaGenera
                default:
                        return nil, false, false, false, errors.Errorf("No 
support for %s", tagType.application)
                }
-               //TODO: we need support for bridged commands
-               command := 
readWriteModel.NewCBusPointToMultiPointCommandNormal(tagType.application, 
salData, 0x00, cbusOptions)
-               header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPoint)
-               cbusCommand := 
readWriteModel.NewCBusCommandPointToMultiPoint(command, header, cbusOptions)
+               var cbusCommand readWriteModel.CBusCommand
+               bridgeAddresses := tagType.bridgeAddresses
+               numberOfBridgeAddresses := len(bridgeAddresses)
+               if numberOfBridgeAddresses <= 0 {
+                       command := 
readWriteModel.NewCBusPointToMultiPointCommandNormal(tagType.application, 
salData, 0x00, cbusOptions)
+                       header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPoint)
+                       cbusCommand = 
readWriteModel.NewCBusCommandPointToMultiPoint(command, header, cbusOptions)
+               } else {
+                       var networkRoute readWriteModel.NetworkRoute
+                       if numberOfBridgeAddresses > 1 {
+                               networkRoute = 
readWriteModel.NewNetworkRoute(readWriteModel.NewNetworkProtocolControlInformation(uint8(numberOfBridgeAddresses),
 uint8(numberOfBridgeAddresses)), bridgeAddresses[1:])
+                       }
+                       command := 
readWriteModel.NewCBusPointToPointToMultiPointCommandNormal(tagType.application,
 salData, bridgeAddresses[0], networkRoute, byte(tagType.application), 
cbusOptions)
+                       header := 
readWriteModel.NewCBusHeader(readWriteModel.PriorityClass_Class4, false, 0, 
readWriteModel.DestinationAddressType_PointToPointToMultiPoint)
+                       cbusCommand = 
readWriteModel.NewCBusCommandPointToPointToMultiPoint(command, header, 
cbusOptions)
+               }
                request := readWriteModel.NewRequestCommand(cbusCommand, nil, 
readWriteModel.NewAlpha(alphaGenerator.getAndIncrement()), 
readWriteModel.RequestType_REQUEST_COMMAND, nil, nil, 
readWriteModel.RequestType_EMPTY, readWriteModel.NewRequestTermination(), 
cbusOptions)
                cBusMessage = readWriteModel.NewCBusMessageToServer(request, 
requestContext, cbusOptions)
                return
@@ -206,6 +239,22 @@ func TagToCBusMessage(tag apiModel.PlcTag, value 
apiValues.PlcValue, alphaGenera
        }
 }
 
+func producePointToPointCommand(unitAddress readWriteModel.UnitAddress, 
bridgeAddresses []readWriteModel.BridgeAddress, calData readWriteModel.CALData, 
cbusOptions readWriteModel.CBusOptions) 
(readWriteModel.CBusPointToPointCommand, error) {
+       numberOfBridgeAddresses := len(bridgeAddresses)
+       if numberOfBridgeAddresses > 0 {
+               if numberOfBridgeAddresses > 6 {
+                       return nil, errors.Errorf("invalid number of bridge 
addresses %d. Max 6 allowed", numberOfBridgeAddresses)
+               }
+               var networkRoute readWriteModel.NetworkRoute
+               if numberOfBridgeAddresses > 1 {
+                       networkRoute = 
readWriteModel.NewNetworkRoute(readWriteModel.NewNetworkProtocolControlInformation(uint8(numberOfBridgeAddresses),
 uint8(numberOfBridgeAddresses)), bridgeAddresses[1:])
+               }
+               return 
readWriteModel.NewCBusPointToPointCommandIndirect(bridgeAddresses[0], 
networkRoute, unitAddress, 0x0000, calData, cbusOptions), nil
+       }
+
+       return readWriteModel.NewCBusPointToPointCommandDirect(unitAddress, 
0x0000, calData, cbusOptions), nil
+}
+
 func MapEncodedReply(transaction *spi.RequestTransaction, encodedReply 
readWriteModel.EncodedReply, tagName string, addResponseCode func(name string, 
responseCode apiModel.PlcResponseCode), addPlcValue func(name string, plcValue 
apiValues.PlcValue)) error {
        switch reply := encodedReply.(type) {
        case readWriteModel.EncodedReplyCALReplyExactly:
diff --git a/plc4go/internal/cbus/Tag.go b/plc4go/internal/cbus/Tag.go
index 373fc5bd73..0f3965d89f 100644
--- a/plc4go/internal/cbus/Tag.go
+++ b/plc4go/internal/cbus/Tag.go
@@ -58,13 +58,15 @@ type Tag interface {
 type StatusTag interface {
        Tag
 
+       GetBridgeAddresses() []readWriteModel.BridgeAddress
        GetStatusRequestType() StatusRequestType
        GetStartingGroupAddressLabel() *byte
        GetApplication() readWriteModel.ApplicationIdContainer
 }
 
-func NewStatusTag(statusRequestType StatusRequestType, 
startingGroupAddressLabel *byte, application 
readWriteModel.ApplicationIdContainer, numElements uint16) StatusTag {
+func NewStatusTag(bridgeAddresses []readWriteModel.BridgeAddress, 
statusRequestType StatusRequestType, startingGroupAddressLabel *byte, 
application readWriteModel.ApplicationIdContainer, numElements uint16) 
StatusTag {
        return &statusTag{
+               bridgeAddresses:           bridgeAddresses,
                tagType:                   STATUS,
                startingGroupAddressLabel: startingGroupAddressLabel,
                statusRequestType:         statusRequestType,
@@ -137,16 +139,18 @@ func NewCALGetStatusTag(unitAddress 
readWriteModel.UnitAddress, bridgeAddresses
 type SALTag interface {
        Tag
 
+       GetBridgeAddresses() []readWriteModel.BridgeAddress
        GetApplication() readWriteModel.ApplicationIdContainer
        GetSALCommand() string
 }
 
-func NewSALTag(application readWriteModel.ApplicationIdContainer, salCommand 
string, numElements uint16) SALTag {
+func NewSALTag(bridgeAddresses []readWriteModel.BridgeAddress, application 
readWriteModel.ApplicationIdContainer, salCommand string, numElements uint16) 
SALTag {
        return &salTag{
-               tagType:     SAL,
-               application: application,
-               salCommand:  salCommand,
-               numElements: numElements,
+               bridgeAddresses: bridgeAddresses,
+               tagType:         SAL,
+               application:     application,
+               salCommand:      salCommand,
+               numElements:     numElements,
        }
 }
 
@@ -191,6 +195,7 @@ func NewMMIMonitorTag(unitAddress 
*readWriteModel.UnitAddress, application *read
 //
 
 type statusTag struct {
+       bridgeAddresses           []readWriteModel.BridgeAddress
        tagType                   TagType
        statusRequestType         StatusRequestType
        startingGroupAddressLabel *byte
@@ -227,11 +232,13 @@ type calGetStatusTag struct {
 }
 
 type salTag struct {
-       tagType     TagType
-       application readWriteModel.ApplicationIdContainer
-       salCommand  string
-       numElements uint16
+       bridgeAddresses []readWriteModel.BridgeAddress
+       tagType         TagType
+       application     readWriteModel.ApplicationIdContainer
+       salCommand      string
+       numElements     uint16
 }
+
 type salMonitorTag struct {
        tagType     TagType
        unitAddress *readWriteModel.UnitAddress
@@ -252,6 +259,10 @@ type mmiMonitorTag struct {
 ///////////////////////////////////////
 ///////////////////////////////////////
 
+func (s statusTag) GetBridgeAddresses() []readWriteModel.BridgeAddress {
+       return s.bridgeAddresses
+}
+
 func (s statusTag) GetAddressString() string {
        statusRequestType := ""
        switch s.statusRequestType {
@@ -304,11 +315,25 @@ func (s statusTag) Serialize() ([]byte, error) {
        return wb.GetBytes(), nil
 }
 
-func (s statusTag) SerializeWithWriteBuffer(_ context.Context, writeBuffer 
utils.WriteBuffer) error {
+func (s statusTag) SerializeWithWriteBuffer(ctx context.Context, writeBuffer 
utils.WriteBuffer) error {
        if err := writeBuffer.PushContext(s.tagType.GetName()); err != nil {
                return err
        }
 
+       if len(s.bridgeAddresses) > 0 {
+               if err := writeBuffer.PushContext("bridgeAddresses"); err != 
nil {
+                       return err
+               }
+               for _, address := range s.bridgeAddresses {
+                       if err := address.SerializeWithWriteBuffer(ctx, 
writeBuffer); err != nil {
+                               return err
+                       }
+               }
+               if err := writeBuffer.PopContext("bridgeAddresses"); err != nil 
{
+                       return err
+               }
+       }
+
        if err := writeBuffer.WriteUint8("statusRequestType", 8, 
uint8(s.statusRequestType), 
utils.WithAdditionalStringRepresentation(s.statusRequestType.String())); err != 
nil {
                return err
        }
@@ -584,6 +609,10 @@ func (c calGetStatusTag) String() string {
        return writeBuffer.GetBox().String()
 }
 
+func (s salTag) GetBridgeAddresses() []readWriteModel.BridgeAddress {
+       return s.bridgeAddresses
+}
+
 func (s salTag) GetApplication() readWriteModel.ApplicationIdContainer {
        return s.application
 }
@@ -629,6 +658,20 @@ func (s salTag) SerializeWithWriteBuffer(ctx 
context.Context, writeBuffer utils.
                return err
        }
 
+       if len(s.bridgeAddresses) > 0 {
+               if err := writeBuffer.PushContext("bridgeAddresses"); err != 
nil {
+                       return err
+               }
+               for _, address := range s.bridgeAddresses {
+                       if err := address.SerializeWithWriteBuffer(ctx, 
writeBuffer); err != nil {
+                               return err
+                       }
+               }
+               if err := writeBuffer.PopContext("bridgeAddresses"); err != nil 
{
+                       return err
+               }
+       }
+
        if err := s.application.SerializeWithWriteBuffer(ctx, writeBuffer); err 
!= nil {
                return err
        }
diff --git a/plc4go/internal/cbus/TagHandler.go 
b/plc4go/internal/cbus/TagHandler.go
index f6d4900f07..70510ae1ca 100644
--- a/plc4go/internal/cbus/TagHandler.go
+++ b/plc4go/internal/cbus/TagHandler.go
@@ -137,6 +137,8 @@ func (m TagHandler) ParseQuery(query string) 
(model.PlcQuery, error) {
 }
 
 func (m TagHandler) handleStatusRequestPattern(match map[string]string) 
(model.PlcTag, error) {
+       var bridgeAddresses []readWriteModel.BridgeAddress
+       // TODO: extract bridge addresses
        var startingGroupAddressLabel *byte
        var statusRequestType StatusRequestType
        statusRequestArgument := match["statusRequestType"]
@@ -159,7 +161,7 @@ func (m TagHandler) handleStatusRequestPattern(match 
map[string]string) (model.P
        if err != nil {
                return nil, errors.Wrap(err, "Error getting application id from 
argument")
        }
-       return NewStatusTag(statusRequestType, startingGroupAddressLabel, 
application, 1), nil
+       return NewStatusTag(bridgeAddresses, statusRequestType, 
startingGroupAddressLabel, application, 1), nil
 }
 
 func (m TagHandler) handleCalPattern(match map[string]string) (model.PlcTag, 
error) {
@@ -289,6 +291,8 @@ func (m TagHandler) handleCalPattern(match 
map[string]string) (model.PlcTag, err
 }
 
 func (m TagHandler) handleSALPattern(match map[string]string) (model.PlcTag, 
error) {
+       var bridgeAddresses []readWriteModel.BridgeAddress
+       // TODO: extract bridge addresses
        application, err := applicationIdFromArgument(match["application"])
        if err != nil {
                return nil, errors.Wrap(err, "Error getting application id from 
argument")
@@ -309,7 +313,7 @@ func (m TagHandler) handleSALPattern(match 
map[string]string) (model.PlcTag, err
        if !isValid {
                return nil, errors.Errorf("Invalid sal command %s for %s. 
Allowed requests: %s", salCommand, application, 
PossibleSalCommands[application.ApplicationId()])
        }
-       return NewSALTag(application, salCommand, numElements), nil
+       return NewSALTag(bridgeAddresses, application, salCommand, 
numElements), nil
 }
 
 func (m TagHandler) handleSALMonitorPattern(match map[string]string) 
(model.PlcTag, error) {

Reply via email to