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 fdb5c66d4b01270056634b3a56856bb0fdddf36c Author: Sebastian Rühl <[email protected]> AuthorDate: Wed Aug 21 22:31:57 2024 +0200 feat(plc4go/bacnet): RouterBusyToNetwork --- plc4go/internal/bacnetip/comp.go | 1 + plc4go/internal/bacnetip/npdu.go | 70 +++++++++++++++++++++- plc4go/internal/bacnetip/tests/state_machine.go | 11 ++++ .../bacnetip/tests/test_npdu/test_codec_test.go | 62 ++++++++++++++++++- 4 files changed, 141 insertions(+), 3 deletions(-) diff --git a/plc4go/internal/bacnetip/comp.go b/plc4go/internal/bacnetip/comp.go index 174e569a71..05ad939480 100644 --- a/plc4go/internal/bacnetip/comp.go +++ b/plc4go/internal/bacnetip/comp.go @@ -128,6 +128,7 @@ const ( KWIcbrtnPerformanceIndex = KnownKey("icbrtnPerformanceIndex") KWRmtnRejectionReason = KnownKey("rmtnRejectionReason") KWRmtnDNET = KnownKey("rmtnDNET") + KWRbtnNetworkList = KnownKey("rbtnNetworkList") ) type MessageBridge struct { diff --git a/plc4go/internal/bacnetip/npdu.go b/plc4go/internal/bacnetip/npdu.go index 5fa6939442..0736ce1ca6 100644 --- a/plc4go/internal/bacnetip/npdu.go +++ b/plc4go/internal/bacnetip/npdu.go @@ -580,10 +580,76 @@ func (n *RejectMessageToNetwork) String() string { type RouterBusyToNetwork struct { *_NPDU + rbtnNetworkList []uint16 + + readWriteModel.NLMRouterBusyToNetwork } -func NewRouterBusyToNetwork() (*RouterBusyToNetwork, error) { - panic("implement me") +func NewRouterBusyToNetwork(opts ...func(*RouterBusyToNetwork)) (*RouterBusyToNetwork, error) { + i := &RouterBusyToNetwork{} + for _, opt := range opts { + opt(i) + } + i.NLMRouterBusyToNetwork = readWriteModel.NewNLMRouterBusyToNetwork(i.rbtnNetworkList, 0) + npdu, err := NewNPDU(i.NLMRouterBusyToNetwork, nil) + if err != nil { + return nil, errors.Wrap(err, "error creating NPDU") + } + i._NPDU = npdu.(*_NPDU) + return i, nil +} + +func WithRouterBusyToNetworkDnet(networkList []uint16) func(*RouterBusyToNetwork) { + return func(n *RouterBusyToNetwork) { + n.rbtnNetworkList = networkList + } +} + +func (r *RouterBusyToNetwork) GetRbtnNetworkList() []uint16 { + return r.rbtnNetworkList +} + +func (r *RouterBusyToNetwork) Encode(npdu Arg) error { + switch npdu := npdu.(type) { + case NPDU: + if err := npdu.Update(r); err != nil { + return errors.Wrap(err, "error updating _NPCI") + } + for _, net := range r.GetRbtnNetworkList() { + npdu.PutShort(int16(net)) + } + npdu.setNPDU(r.npdu) + npdu.setNLM(r.nlm) + npdu.setAPDU(r.apdu) + return nil + default: + return errors.Errorf("invalid NPDU type %T", npdu) + } +} + +func (r *RouterBusyToNetwork) Decode(npdu Arg) error { + switch npdu := npdu.(type) { + case NPDU: + if err := r.Update(npdu); err != nil { + return errors.Wrap(err, "error updating _NPCI") + } + switch pduUserData := npdu.GetPDUUserData().(type) { + case readWriteModel.NPDUExactly: + switch nlm := pduUserData.GetNlm().(type) { + case readWriteModel.NLMRouterBusyToNetwork: + r.setNLM(nlm) + r.NLMRouterBusyToNetwork = nlm + r.rbtnNetworkList = nlm.GetDestinationNetworkAddresses() + } + } + return nil + default: + return errors.Errorf("invalid NPDU type %T", npdu) + } +} + +func (r *RouterBusyToNetwork) String() string { + return fmt.Sprintf("RouterBusyToNetwork{%s, rbtnNetworkList: %v}", r._NPDU, r.rbtnNetworkList) } type RouterAvailableToNetwork struct { diff --git a/plc4go/internal/bacnetip/tests/state_machine.go b/plc4go/internal/bacnetip/tests/state_machine.go index 5b46866411..06de94058c 100644 --- a/plc4go/internal/bacnetip/tests/state_machine.go +++ b/plc4go/internal/bacnetip/tests/state_machine.go @@ -197,6 +197,17 @@ func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs m return false } return iamrtn.GetDestinationNetworkAddress() == attrValue + case bacnetip.KWRbtnNetworkList: + rbtn, ok := pdu.(*bacnetip.RouterBusyToNetwork) + if !ok { + return false + } + net := rbtn.GetRbtnNetworkList() + uint16s, ok := attrValue.([]uint16) + if !ok { + return false + } + return slices.Equal(net, uint16s) default: panic("implement " + attrName) } diff --git a/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go b/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go index 1dca7c188e..6922d78912 100644 --- a/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go +++ b/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go @@ -63,6 +63,14 @@ func RejectMessageToNetwork(reason uint8, dnet uint16) *bacnetip.RejectMessageTo return network } +func RouterBusyToNetwork(netList ...uint16) *bacnetip.RouterBusyToNetwork { + network, err := bacnetip.NewRouterBusyToNetwork(bacnetip.WithRouterBusyToNetworkDnet(netList)) + if err != nil { + panic(err) + } + return network +} + type TestNPDUCodecSuite struct { suite.Suite @@ -229,7 +237,7 @@ func (suite *TestNPDUCodecSuite) TestICouldBeRouterToNetworks() { // Test the Re err = suite.Confirmation(bacnetip.NewArgs(&bacnetip.ICouldBeRouterToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWIcbrtnNetwork, uint16(1), bacnetip.KWIcbrtnPerformanceIndex, uint8(2))) } -func (suite *TestNPDUCodecSuite) TestRejectMessageToNetworks() { // Test the Result encoding and decoding. +func (suite *TestNPDUCodecSuite) TestRejectMessageToNetwork() { // Test the Result encoding and decoding. // Request successful pduBytes, err := bacnetip.Xtob( "01.80" + // version, network layer message @@ -254,6 +262,58 @@ func (suite *TestNPDUCodecSuite) TestRejectMessageToNetworks() { // Test the Res err = suite.Confirmation(bacnetip.NewArgs(&bacnetip.RejectMessageToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWRmtnRejectionReason, readWriteModel.NLMRejectMessageToNetworkRejectReason(1), bacnetip.KWRmtnDNET, uint16(2))) } +func (suite *TestNPDUCodecSuite) TestRouterBusyToNetworkEmpty() { // Test the Result encoding and decoding. + // Request successful + networkList := []uint16{} + pduBytes, err := bacnetip.Xtob( + "01.80" + // version, network layer message + "04", // message type, no networks + ) + suite.Require().NoError(err) + { // Parse with plc4x parser to validate + parse, err := readWriteModel.NPDUParse(testutils.TestContext(suite.T()), pduBytes, uint16(len(pduBytes))) + suite.Assert().NoError(err) + if parse != nil { + suite.T().Log("\n" + parse.String()) + } + } + + err = suite.Request(bacnetip.NewArgs(RouterBusyToNetwork(networkList...)), bacnetip.NoKWArgs) + suite.Assert().NoError(err) + err = suite.Indication(bacnetip.NoArgs, bacnetip.NewKWArgs(bacnetip.KWPDUData, pduBytes)) + suite.Assert().NoError(err) + + err = suite.Response(bacnetip.NewArgs(bacnetip.NewPDU(&bacnetip.MessageBridge{Bytes: pduBytes})), bacnetip.NoKWArgs) + suite.Assert().NoError(err) + err = suite.Confirmation(bacnetip.NewArgs(&bacnetip.RouterBusyToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWRbtnNetworkList, networkList)) +} + +func (suite *TestNPDUCodecSuite) TestRouterBusyToNetworkNetworks() { // Test the Result encoding and decoding. + // Request successful + networkList := []uint16{1, 2, 3} + pduBytes, err := bacnetip.Xtob( + "01.80" + // version, network layer message + "04 0001 0002 0003", // message type and network list + ) + suite.Require().NoError(err) + { // Parse with plc4x parser to validate + parse, err := readWriteModel.NPDUParse(testutils.TestContext(suite.T()), pduBytes, uint16(len(pduBytes))) + suite.Assert().NoError(err) + if parse != nil { + suite.T().Log("\n" + parse.String()) + } + } + + err = suite.Request(bacnetip.NewArgs(RouterBusyToNetwork(networkList...)), bacnetip.NoKWArgs) + suite.Assert().NoError(err) + err = suite.Indication(bacnetip.NoArgs, bacnetip.NewKWArgs(bacnetip.KWPDUData, pduBytes)) + suite.Assert().NoError(err) + + err = suite.Response(bacnetip.NewArgs(bacnetip.NewPDU(&bacnetip.MessageBridge{Bytes: pduBytes})), bacnetip.NoKWArgs) + suite.Assert().NoError(err) + err = suite.Confirmation(bacnetip.NewArgs(&bacnetip.RouterBusyToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWRbtnNetworkList, networkList)) +} + func TestNPDUCodec(t *testing.T) { suite.Run(t, new(TestNPDUCodecSuite)) }
