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 6eaf6faa15307f3b910a143acaa030670fedf15b Author: Sebastian Rühl <[email protected]> AuthorDate: Wed Aug 21 17:34:41 2024 +0200 fix(plc4go/bacnet): IAmRouterToNetwork --- plc4go/internal/bacnetip/CommunicationsModule.go | 4 ++ plc4go/internal/bacnetip/PDU.go | 24 ++++++- plc4go/internal/bacnetip/comp.go | 3 +- plc4go/internal/bacnetip/npdu.go | 73 ++++++++++++++++++- plc4go/internal/bacnetip/tests/state_machine.go | 11 +++ .../bacnetip/tests/test_npdu/test_codec_test.go | 81 ++++++++++++++++++---- .../test_utilities/test_state_machine_test.go | 5 ++ 7 files changed, 180 insertions(+), 21 deletions(-) diff --git a/plc4go/internal/bacnetip/CommunicationsModule.go b/plc4go/internal/bacnetip/CommunicationsModule.go index e2c39c7abe..99912ba3f4 100644 --- a/plc4go/internal/bacnetip/CommunicationsModule.go +++ b/plc4go/internal/bacnetip/CommunicationsModule.go @@ -47,6 +47,7 @@ func init() { type IPCI interface { fmt.Stringer + SetPDUUserData(spi.Message) GetPDUUserData() spi.Message GetPDUSource() *Address SetPDUSource(source *Address) @@ -67,6 +68,9 @@ func new__PCI(pduUserData spi.Message, pduSource *Address, pduDestination *Addre return &__PCI{pduUserData, pduSource, pduDestination} } +func (p *__PCI) SetPDUUserData(pduUserData spi.Message) { + p.pduUserData = pduUserData +} func (p *__PCI) GetPDUUserData() spi.Message { return p.pduUserData } diff --git a/plc4go/internal/bacnetip/PDU.go b/plc4go/internal/bacnetip/PDU.go index 169a7da129..206c1abc73 100644 --- a/plc4go/internal/bacnetip/PDU.go +++ b/plc4go/internal/bacnetip/PDU.go @@ -638,9 +638,29 @@ func (a *Address) Equals(other any) bool { if a == other { return true } - return a.String() == other.String() + thisString := a.String() + otherString := other.String() + equals := thisString == otherString + if !equals { + a.log.Debug().Str("thisString", thisString).Str("otherString", otherString).Msg("Mismatch") + } + return equals case Address: - return a.String() == other.String() + thisString := a.String() + otherString := other.String() + equals := thisString == otherString + if !equals { + a.log.Debug().Str("thisString", thisString).Str("otherString", otherString).Msg("Mismatch") + } + return equals + case *AddressTuple[string, uint16]: + thisString := a.AddrTuple.String() + otherString := other.String() + equals := thisString == otherString + if !equals { + a.log.Debug().Str("thisString", thisString).Str("otherString", otherString).Msg("Mismatch") + } + return equals default: return false } diff --git a/plc4go/internal/bacnetip/comp.go b/plc4go/internal/bacnetip/comp.go index 8440fc9f5c..5978a94dd5 100644 --- a/plc4go/internal/bacnetip/comp.go +++ b/plc4go/internal/bacnetip/comp.go @@ -122,7 +122,8 @@ const ( //// // NPDU related keys - KWWirtnNetwork = KnownKey("wirtnNetwork") + KWWirtnNetwork = KnownKey("wirtnNetwork") + KWIartnNetworkList = KnownKey("iartnNetworkList") ) type MessageBridge struct { diff --git a/plc4go/internal/bacnetip/npdu.go b/plc4go/internal/bacnetip/npdu.go index 9b568091b7..e7d5f5842b 100644 --- a/plc4go/internal/bacnetip/npdu.go +++ b/plc4go/internal/bacnetip/npdu.go @@ -208,7 +208,7 @@ func (n *_NPDU) Encode(pdu Arg) error { if err != nil { return errors.Wrap(err, "error building NPDU") } - pdu.(PDUData).PutData(n.GetPduData()...) // TODO: better validate that arg is really PDUData... use switch similar to Update + n.SetPDUUserData(n.npdu) return nil } @@ -335,10 +335,77 @@ func (n *WhoIsRouterToNetwork) String() string { type IAmRouterToNetwork struct { *_NPDU + + iartnNetworkList []uint16 + + readWriteModel.NLMIAmRouterToNetwork } -func NewIAmRouterToNetwork() (*IAmRouterToNetwork, error) { - panic("implement me") +func NewIAmRouterToNetwork(opts ...func(*IAmRouterToNetwork)) (*IAmRouterToNetwork, error) { + w := &IAmRouterToNetwork{} + for _, opt := range opts { + opt(w) + } + w.NLMIAmRouterToNetwork = readWriteModel.NewNLMIAmRouterToNetwork(w.iartnNetworkList, 0) + npdu, err := NewNPDU(w.NLMIAmRouterToNetwork, nil) + if err != nil { + return nil, errors.Wrap(err, "error creating NPDU") + } + w._NPDU = npdu.(*_NPDU) + return w, nil +} + +func WithIAmRouterToNetworkNetworkList(iartnNetworkList ...uint16) func(*IAmRouterToNetwork) { + return func(n *IAmRouterToNetwork) { + n.iartnNetworkList = iartnNetworkList + } +} + +func (n *IAmRouterToNetwork) GetIartnNetworkList() []uint16 { + return n.iartnNetworkList +} + +func (n *IAmRouterToNetwork) Encode(npdu Arg) error { + switch npdu := npdu.(type) { + case NPDU: + if err := npdu.Update(n); err != nil { + return errors.Wrap(err, "error updating _NPCI") + } + for _, net := range n.iartnNetworkList { + npdu.PutShort(int16(net)) + } + npdu.setNPDU(n.npdu) + npdu.setNLM(n.nlm) + npdu.setAPDU(n.apdu) + return nil + default: + return errors.Errorf("invalid NPDU type %T", npdu) + } +} + +func (n *IAmRouterToNetwork) Decode(npdu Arg) error { + switch npdu := npdu.(type) { + case NPDU: + if err := n.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.NLMIAmRouterToNetworkExactly: + n.setNLM(nlm) + n.NLMIAmRouterToNetwork = nlm + n.iartnNetworkList = nlm.GetDestinationNetworkAddresses() + } + } + return nil + default: + return errors.Errorf("invalid NPDU type %T", npdu) + } +} + +func (n *IAmRouterToNetwork) String() string { + return fmt.Sprintf("IAmRouterToNetwork{%s, iartnNetworkList: %v}", n._NPDU, n.iartnNetworkList) } type ICouldBeRouterToNetwork struct { diff --git a/plc4go/internal/bacnetip/tests/state_machine.go b/plc4go/internal/bacnetip/tests/state_machine.go index b3e96c8360..37fa005ee8 100644 --- a/plc4go/internal/bacnetip/tests/state_machine.go +++ b/plc4go/internal/bacnetip/tests/state_machine.go @@ -162,6 +162,17 @@ func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs m return false } return *net == attrValue + case bacnetip.KWIartnNetworkList: + iamrtn, ok := pdu.(*bacnetip.IAmRouterToNetwork) + if !ok { + return false + } + net := iamrtn.GetIartnNetworkList() + 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 d0ab4d9005..7967781e36 100644 --- a/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go +++ b/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go @@ -31,20 +31,20 @@ import ( "github.com/stretchr/testify/suite" ) -func WhoIsRouterToNetwork(args ...any) *bacnetip.WhoIsRouterToNetwork { - if len(args) == 1 { - var net uint16 - net = uint16(args[0].(int)) - network, err := bacnetip.NewWhoIsRouterToNetwork(bacnetip.WithWhoIsRouterToNetworkNet(net)) - if err != nil { - panic(err) - } - return network - } else { - network, err := bacnetip.NewWhoIsRouterToNetwork() +func WhoIsRouterToNetwork(net uint16) *bacnetip.WhoIsRouterToNetwork { + network, err := bacnetip.NewWhoIsRouterToNetwork(bacnetip.WithWhoIsRouterToNetworkNet(net)) + if err != nil { + panic(err) + } + return network +} + +func IAmRouterToNetwork(netList ...uint16) *bacnetip.IAmRouterToNetwork { + network, err := bacnetip.NewIAmRouterToNetwork(bacnetip.WithIAmRouterToNetworkNetworkList(netList...)) + if err != nil { panic(err) - return network } + return network } type TestNPDUCodecSuite struct { @@ -115,15 +115,14 @@ func (suite *TestNPDUCodecSuite) TestWhoIsRouterToNetwork() { // Test the Result // Request successful pduBytes, err := bacnetip.Xtob( "01.80" + // version, network layer message - "00 0001" + // message type and network - "00 01", // whois + "00 0001", // message type and network ) 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(parse.String()) + suite.T().Log("\n" + parse.String()) } } @@ -137,6 +136,58 @@ func (suite *TestNPDUCodecSuite) TestWhoIsRouterToNetwork() { // Test the Result err = suite.Confirmation(bacnetip.NewArgs(&bacnetip.WhoIsRouterToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWWirtnNetwork, uint16(1))) } +func (suite *TestNPDUCodecSuite) TestIAMRouterToNetworkEmpty() { // Test the Result encoding and decoding. + // Request successful + networkList := []uint16{} + pduBytes, err := bacnetip.Xtob( + "01.80" + // version, network layer message + "01", // message type, no network + ) + 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(IAmRouterToNetwork(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.IAmRouterToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWIartnNetworkList, networkList)) +} + +func (suite *TestNPDUCodecSuite) TestIAMRouterToNetworks() { // Test the Result encoding and decoding. + // Request successful + networkList := []uint16{1, 2, 3} + pduBytes, err := bacnetip.Xtob( + "01.80" + // version, network layer message + "01 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(parse.String()) + } + } + + err = suite.Request(bacnetip.NewArgs(IAmRouterToNetwork(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.IAmRouterToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWIartnNetworkList, networkList)) +} + func TestNPDUCodec(t *testing.T) { suite.Run(t, new(TestNPDUCodecSuite)) } diff --git a/plc4go/internal/bacnetip/tests/test_utilities/test_state_machine_test.go b/plc4go/internal/bacnetip/tests/test_utilities/test_state_machine_test.go index 81cf636cea..01304cf902 100644 --- a/plc4go/internal/bacnetip/tests/test_utilities/test_state_machine_test.go +++ b/plc4go/internal/bacnetip/tests/test_utilities/test_state_machine_test.go @@ -71,6 +71,11 @@ func (t TPDU) GetMessage() spi.Message { panic("implement me") } +func (t TPDU) SetPDUUserData(message spi.Message) { + //TODO implement me + panic("implement me") +} + func (t TPDU) GetPDUSource() *bacnetip.Address { panic("implement me") }
