diff --git a/plc4go/internal/bacnetip/CommunicationsModule.go b/plc4go/internal/bacnetip/CommunicationsModule.go index 2a93f7b44ec..e2c39c7abe5 100644 --- a/plc4go/internal/bacnetip/CommunicationsModule.go +++ b/plc4go/internal/bacnetip/CommunicationsModule.go @@ -21,10 +21,13 @@ package bacnetip import ( "fmt" + "strconv" + "strings" + "github.com/apache/plc4x/plc4go/spi" + "github.com/pkg/errors" "github.com/rs/zerolog" - "strconv" ) // maps of named clients and servers @@ -42,16 +45,60 @@ func init() { elementMap = make(map[int]*ApplicationServiceElement) } +type IPCI interface { + fmt.Stringer + GetPDUUserData() spi.Message + GetPDUSource() *Address + SetPDUSource(source *Address) + GetPDUDestination() *Address + SetPDUDestination(*Address) + Update(pci Arg) error +} + type __PCI struct { - pduUserData spi.Message + pduUserData spi.Message // TODO: should that be PDUUserData rater than spi.Message and do we need another field... lets see... pduSource *Address pduDestination *Address } +var _ IPCI = (*__PCI)(nil) + func new__PCI(pduUserData spi.Message, pduSource *Address, pduDestination *Address) *__PCI { return &__PCI{pduUserData, pduSource, pduDestination} } +func (p *__PCI) GetPDUUserData() spi.Message { + return p.pduUserData +} + +func (p *__PCI) GetPDUSource() *Address { + return p.pduSource +} + +func (p *__PCI) SetPDUSource(source *Address) { + p.pduSource = source +} + +func (p *__PCI) GetPDUDestination() *Address { + return p.pduDestination +} + +func (p *__PCI) SetPDUDestination(destination *Address) { + p.pduDestination = destination +} + +func (p *__PCI) Update(pci Arg) error { + switch pci := pci.(type) { + case IPCI: + p.pduUserData = pci.GetPDUUserData() + p.pduSource = pci.GetPDUSource() + p.pduDestination = pci.GetPDUDestination() + return nil + default: + return errors.Errorf("invalid IPCI type %T", pci) + } +} + func (p *__PCI) deepCopy() *__PCI { pduUserData := p.pduUserData // those are immutable so no copy needed pduSource := p.pduSource @@ -68,7 +115,15 @@ func (p *__PCI) deepCopy() *__PCI { } func (p *__PCI) String() string { - return fmt.Sprintf("__PCI{pduUserData:\n%s\n, pduSource: %s, pduDestination: %s}", p.pduUserData, p.pduSource, p.pduDestination) + pduUserDataString := "" + if p.pduUserData != nil { + pduUserDataString = p.pduUserData.String() + if strings.Contains(pduUserDataString, "\n") { + pduUserDataString = "\n" + pduUserDataString + "\n" + } + pduUserDataString = "pduUserData: " + pduUserDataString + " ," + } + return fmt.Sprintf("__PCI{%spduSource: %s, pduDestination: %s}", pduUserDataString, p.pduSource, p.pduDestination) } // _Client is an interface used for documentation diff --git a/plc4go/internal/bacnetip/IOCBModule.go b/plc4go/internal/bacnetip/IOCBModule.go index 67db307f634..f619c2fc1c6 100644 --- a/plc4go/internal/bacnetip/IOCBModule.go +++ b/plc4go/internal/bacnetip/IOCBModule.go @@ -22,12 +22,13 @@ package bacnetip import ( "container/heap" "fmt" - "github.com/rs/zerolog" "sync" "time" "github.com/apache/plc4x/plc4go/spi/utils" + "github.com/pkg/errors" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) diff --git a/plc4go/internal/bacnetip/LocalDevice.go b/plc4go/internal/bacnetip/LocalDevice.go index 124dbb33992..807294ea731 100644 --- a/plc4go/internal/bacnetip/LocalDevice.go +++ b/plc4go/internal/bacnetip/LocalDevice.go @@ -21,6 +21,7 @@ package bacnetip import ( "fmt" + readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" ) diff --git a/plc4go/internal/bacnetip/NetworkService.go b/plc4go/internal/bacnetip/NetworkService.go index a033dbcdbfb..32eb5d2e803 100644 --- a/plc4go/internal/bacnetip/NetworkService.go +++ b/plc4go/internal/bacnetip/NetworkService.go @@ -22,12 +22,14 @@ package bacnetip import ( "bytes" "fmt" - readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" - "github.com/pkg/errors" - "github.com/rs/zerolog" "math" "slices" "time" + + readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" + + "github.com/pkg/errors" + "github.com/rs/zerolog" ) type RouterStatus uint8 @@ -520,6 +522,7 @@ func (n *NetworkServiceAccessPoint) Indication(args Args, kwargs KWArgs) error { panic("not implemented yet") } +// TODO: should us the one in NPDU func buildNPDU(hopCount uint8, source *Address, destination *Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority, nlm readWriteModel.NLM, apdu readWriteModel.APDU) (readWriteModel.NPDU, error) { switch { case nlm != nil && apdu != nil: diff --git a/plc4go/internal/bacnetip/PDU.go b/plc4go/internal/bacnetip/PDU.go index 54a9635549d..169a7da129a 100644 --- a/plc4go/internal/bacnetip/PDU.go +++ b/plc4go/internal/bacnetip/PDU.go @@ -853,12 +853,20 @@ func NewGlobalBroadcast(route *Address) *Address { return g } +type PCI interface { + IPCI + GetExpectingReply() bool + GetNetworkPriority() readWriteModel.NPDUNetworkPriority +} + type _PCI struct { *__PCI expectingReply bool networkPriority readWriteModel.NPDUNetworkPriority } +var _ PCI = (*_PCI)(nil) + func newPCI(msg spi.Message, pduSource *Address, pduDestination *Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority) *_PCI { return &_PCI{ new__PCI(msg, pduSource, pduDestination), @@ -867,6 +875,28 @@ func newPCI(msg spi.Message, pduSource *Address, pduDestination *Address, expect } } +func (p *_PCI) Update(pci Arg) error { + if err := p.__PCI.Update(pci); err != nil { + return errors.Wrap(err, "error updating __PCI") + } + switch pci := pci.(type) { + case PCI: + p.expectingReply = pci.GetExpectingReply() + p.networkPriority = pci.GetNetworkPriority() + return nil + default: + return errors.Errorf("invalid PCI type %T", pci) + } +} + +func (p *_PCI) GetExpectingReply() bool { + return p.expectingReply +} + +func (p *_PCI) GetNetworkPriority() readWriteModel.NPDUNetworkPriority { + return p.networkPriority +} + func (p *_PCI) deepCopy() *_PCI { __pci := p.__PCI.deepCopy() expectingReply := p.expectingReply @@ -879,6 +909,7 @@ func (p *_PCI) String() string { } type PDUData interface { + SetPduData([]byte) GetPduData() []byte Get() (byte, error) GetShort() (int16, error) @@ -914,6 +945,10 @@ func NewPDUData(args Args) PDUData { return newPDUData(args[0].(_PDUDataRequirements)) } +func (d *_PDUData) SetPduData(data []byte) { + d.cachedData = data +} + func (d *_PDUData) GetPduData() []byte { d.checkCache() return d.cachedData @@ -1001,26 +1036,57 @@ func (d *_PDUData) deepCopy() *_PDUData { return ©PDUData } +type APCI interface { + PCI +} + +type _APCI struct { + *_PCI +} + +func newAPCI(msg spi.Message, pduSource *Address, pduDestination *Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority) *_APCI { + return &_APCI{ + _PCI: newPCI(msg, pduSource, pduDestination, expectingReply, networkPriority), + } +} + +func (a *_APCI) Update(apci Arg) error { + if err := a._PCI.Update(apci); err != nil { + return errors.Wrap(err, "error updating _PCI") + } + switch pci := apci.(type) { + case APCI: + // TODO: update coordinates.... + return nil + default: + return errors.Errorf("invalid APCI type %T", pci) + } +} + +func (a *_APCI) deepCopy() *_APCI { + _pci := a._PCI.deepCopy() + return &_APCI{_pci} +} + +func (a *_APCI) String() string { + return fmt.Sprintf("APCI{%s}", a._PCI) +} + type PDU interface { - fmt.Stringer - GetMessage() spi.Message - GetPDUSource() *Address - SetPDUSource(source *Address) - GetPDUDestination() *Address - SetPDUDestination(*Address) - GetExpectingReply() bool - GetNetworkPriority() readWriteModel.NPDUNetworkPriority + APCI + PDUData + GetMessage() spi.Message // TODO: check if we still need that... () DeepCopy() PDU } type _PDU struct { - *_PCI + *_APCI *_PDUData } func NewPDU(msg spi.Message, pduOptions ...PDUOption) PDU { p := &_PDU{ - _PCI: newPCI(msg, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE), + _APCI: newAPCI(msg, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE), } for _, option := range pduOptions { option(p) @@ -1032,7 +1098,7 @@ func NewPDU(msg spi.Message, pduOptions ...PDUOption) PDU { func NewPDUFromPDU(pdu PDU, pduOptions ...PDUOption) PDU { msg := pdu.(*_PDU).pduUserData p := &_PDU{ - _PCI: newPCI(msg, pdu.GetPDUSource(), pdu.GetPDUDestination(), pdu.GetExpectingReply(), pdu.GetNetworkPriority()), + _APCI: newAPCI(msg, pdu.GetPDUSource(), pdu.GetPDUDestination(), pdu.GetExpectingReply(), pdu.GetNetworkPriority()), } for _, option := range pduOptions { option(p) @@ -1043,7 +1109,7 @@ func NewPDUFromPDU(pdu PDU, pduOptions ...PDUOption) PDU { func NewPDUFromPDUWithNewMessage(pdu PDU, msg spi.Message, pduOptions ...PDUOption) PDU { p := &_PDU{ - _PCI: newPCI(msg, pdu.GetPDUSource(), pdu.GetPDUDestination(), pdu.GetExpectingReply(), pdu.GetNetworkPriority()), + _APCI: newAPCI(msg, pdu.GetPDUSource(), pdu.GetPDUDestination(), pdu.GetExpectingReply(), pdu.GetNetworkPriority()), } for _, option := range pduOptions { option(p) @@ -1054,7 +1120,7 @@ func NewPDUFromPDUWithNewMessage(pdu PDU, msg spi.Message, pduOptions ...PDUOpti func NewPDUWithAllOptions(msg spi.Message, pduSource *Address, pduDestination *Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority) *_PDU { p := &_PDU{ - _PCI: newPCI(msg, pduSource, pduDestination, expectingReply, networkPriority), + _APCI: newAPCI(msg, pduSource, pduDestination, expectingReply, networkPriority), } p._PDUData = newPDUData(p) return p @@ -1087,6 +1153,9 @@ func WithPDUNetworkPriority(networkPriority readWriteModel.NPDUNetworkPriority) } func (p *_PDU) getPDUData() []byte { + if p.GetMessage() == nil { + return nil + } writeBufferByteBased := utils.NewWriteBufferByteBased() if err := p.GetMessage().SerializeWithWriteBuffer(context.Background(), writeBufferByteBased); err != nil { panic(err) // TODO: graceful handle @@ -1098,32 +1167,8 @@ func (p *_PDU) GetMessage() spi.Message { return p.pduUserData } -func (p *_PDU) GetPDUSource() *Address { - return p.pduSource -} - -func (p *_PDU) SetPDUSource(source *Address) { - p.pduSource = source -} - -func (p *_PDU) GetPDUDestination() *Address { - return p.pduDestination -} - -func (p *_PDU) SetPDUDestination(destination *Address) { - p.pduDestination = destination -} - -func (p *_PDU) GetExpectingReply() bool { - return p.expectingReply -} - -func (p *_PDU) GetNetworkPriority() readWriteModel.NPDUNetworkPriority { - return p.networkPriority -} - func (p *_PDU) deepCopy() *_PDU { - return &_PDU{_PCI: p._PCI.deepCopy(), _PDUData: p._PDUData.deepCopy()} + return &_PDU{_APCI: p._APCI.deepCopy(), _PDUData: p._PDUData.deepCopy()} } func (p *_PDU) DeepCopy() PDU { diff --git a/plc4go/internal/bacnetip/UDPCommunicationsModule.go b/plc4go/internal/bacnetip/UDPCommunicationsModule.go index 489ff668b30..07b8093ab27 100644 --- a/plc4go/internal/bacnetip/UDPCommunicationsModule.go +++ b/plc4go/internal/bacnetip/UDPCommunicationsModule.go @@ -22,14 +22,15 @@ package bacnetip import ( "context" "fmt" - "github.com/apache/plc4x/plc4go/spi/options" - "github.com/rs/zerolog" "net" "time" "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" + "github.com/apache/plc4x/plc4go/spi/options" + "github.com/libp2p/go-reuseport" "github.com/pkg/errors" + "github.com/rs/zerolog" ) //go:generate go run ../../tools/plc4xgenerator/gen.go -type=UDPActor @@ -228,7 +229,7 @@ func (d *UDPDirector) AddActor(actor *UDPActor) { // tell the ASE there is a new client if d.serviceElement != nil { - if err := d.SapRequest(NoArgs, NewKWArgs(kwAddActor, actor)); err != nil { + if err := d.SapRequest(NoArgs, NewKWArgs(KWAddActor, actor)); err != nil { d.log.Error().Err(err).Msg("Error in add actor") } } @@ -242,7 +243,7 @@ func (d *UDPDirector) DelActor(actor *UDPActor) { // tell the ASE the client has gone away if d.serviceElement != nil { - if err := d.SapRequest(NoArgs, NewKWArgs(kwDelActor, actor)); err != nil { + if err := d.SapRequest(NoArgs, NewKWArgs(KWDelActor, actor)); err != nil { d.log.Error().Err(err).Msg("Error in del actor") } } @@ -255,7 +256,7 @@ func (d *UDPDirector) GetActor(address Address) *UDPActor { func (d *UDPDirector) ActorError(actor *UDPActor, err error) { // tell the ASE the actor had an error if d.serviceElement != nil { - if err := d.SapRequest(NoArgs, NewKWArgs(kwActorError, actor, kwError, err)); err != nil { + if err := d.SapRequest(NoArgs, NewKWArgs(KWActorError, actor, KWError, err)); err != nil { d.log.Error().Err(err).Msg("Error in actor error") } } diff --git a/plc4go/internal/bacnetip/comp.go b/plc4go/internal/bacnetip/comp.go index 611557a881a..8440fc9f5c7 100644 --- a/plc4go/internal/bacnetip/comp.go +++ b/plc4go/internal/bacnetip/comp.go @@ -45,6 +45,10 @@ func (a Args) Get1PDU() PDU { return a[1].(PDU) } +func (a Args) Get0NPDU() NPDU { + return a[0].(NPDU) +} + func (a Args) Get0NetworkAdapter() *NetworkAdapter { return a[0].(*NetworkAdapter) } @@ -68,7 +72,7 @@ func (a Args) String() string { return r } -type KWArgs map[knownKey]any +type KWArgs map[KnownKey]any var NoKWArgs = NewKWArgs() @@ -78,9 +82,9 @@ func NewKWArgs(kw ...any) KWArgs { } r := make(KWArgs) for i := 0; i < len(kw)-1; i += 2 { - key, ok := kw[i].(knownKey) + key, ok := kw[i].(KnownKey) if !ok { - panic("keys must be of type knownKey") + panic("keys must be of type KnownKey") } r[key] = kw[i+1] } @@ -97,13 +101,28 @@ func (k KWArgs) String() string { return r } -type knownKey string +type KnownKey string const ( - kwAddActor = knownKey("addActor") - kwDelActor = knownKey("delActor") - kwActorError = knownKey("actorError") - kwError = knownKey("error") + //// + // General keys + + KWAddActor = KnownKey("addActor") + KWDelActor = KnownKey("delActor") + KWActorError = KnownKey("actorError") + KWError = KnownKey("error") + + //// + // PDU related Keys + + KWPPDUSource = KnownKey("pduSource") + KWPDUDestination = KnownKey("pduDestination") + KWPDUData = KnownKey("pduData") + + //// + // NPDU related keys + + KWWirtnNetwork = KnownKey("wirtnNetwork") ) type MessageBridge struct { diff --git a/plc4go/internal/bacnetip/npdu.go b/plc4go/internal/bacnetip/npdu.go new file mode 100644 index 00000000000..9b568091b7a --- /dev/null +++ b/plc4go/internal/bacnetip/npdu.go @@ -0,0 +1,488 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package bacnetip + +import ( + "context" + "fmt" + "math" + + readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" + "github.com/apache/plc4x/plc4go/spi" + "github.com/apache/plc4x/plc4go/spi/utils" + + "github.com/pkg/errors" +) + +// NPDUTypes is a dictionary of message type values and structs +var NPDUTypes map[uint8]func() interface{ Decode(Arg) error } + +type NPCI interface { + PCI + + GetNPDUNetMessage() *uint8 + + Encode(pdu Arg) error + Decode(pdu Arg) error + + setNLM(nlm readWriteModel.NLM) +} + +type _NPCI struct { + *_PCI + *DebugContents + + nlm readWriteModel.NLM +} + +var _ NPCI = (*_NPCI)(nil) + +func NewNPCI(msg spi.Message, nlm readWriteModel.NLM) NPCI { + n := &_NPCI{ + nlm: nlm, + } + n._PCI = newPCI(msg, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE) + return n +} + +func (n *_NPCI) GetNPDUNetMessage() *uint8 { + if n.nlm == nil { + return nil + } + messageType := n.nlm.GetMessageType() + return &messageType +} + +func (n *_NPCI) setNLM(nlm readWriteModel.NLM) { + n.nlm = nlm +} + +func (n *_NPCI) deepCopy() *_NPCI { + return &_NPCI{_PCI: n._PCI.deepCopy()} +} + +func (n *_NPCI) Update(npci Arg) error { + if err := n._PCI.Update(npci); err != nil { + return errors.Wrap(err, "error updating _PCI") + } + switch pci := npci.(type) { + case NPCI: + // TODO: update coordinates.... + return nil + default: + return errors.Errorf("invalid APCI type %T", pci) + } +} + +func (n *_NPCI) Encode(pdu Arg) error { + if err := pdu.(interface{ Update(Arg) error }).Update(n); err != nil { // TODO: better validate that arg is really PDUData... use switch similar to Update + return errors.Wrap(err, "error updating pdu") + } + // TODO: what should we do here?? + return nil +} + +func (n *_NPCI) Decode(pdu Arg) error { + if err := n._PCI.Update(pdu); err != nil { + return errors.Wrap(err, "error updating pdu") + } + // TODO: what should we do here?? + return nil +} + +type NPDU interface { + NPCI + PDUData + + setNPDU(npdu readWriteModel.NPDU) + setAPDU(apdu readWriteModel.APDU) +} + +type _NPDU struct { + *_NPCI + *_PDUData + + npdu readWriteModel.NPDU + apdu readWriteModel.APDU +} + +var _ NPDU = (*_NPDU)(nil) + +func NewNPDU(nlm readWriteModel.NLM, apdu readWriteModel.APDU) (NPDU, error) { + n := &_NPDU{ + apdu: apdu, + } + var err error + n.npdu, err = n.buildNPDU(0, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE, nlm, apdu) + if err != nil { + // TODO: seems to be a legit case, which means we don't build our npdu yet... check that + //return nil, errors.Wrap(err, "error building NPDU") + } + n._NPCI = NewNPCI(n.npdu, nlm).(*_NPCI) + n._PDUData = newPDUData(n) + return n, nil +} + +func (n *_NPDU) setNPDU(npdu readWriteModel.NPDU) { + n.npdu = npdu +} + +func (n *_NPDU) setAPDU(apdu readWriteModel.APDU) { + n.apdu = apdu +} + +func (n *_NPDU) buildNPDU(hopCount uint8, source *Address, destination *Address, expectingReply bool, networkPriority readWriteModel.NPDUNetworkPriority, nlm readWriteModel.NLM, apdu readWriteModel.APDU) (readWriteModel.NPDU, error) { + switch { + case nlm != nil && apdu != nil: + return nil, errors.New("either specify a NLM or a APDU exclusive") + case nlm == nil && apdu == nil: + return nil, errors.New("either specify a NLM or a APDU") + } + sourceSpecified := source != nil + var sourceNetworkAddress *uint16 + var sourceLength *uint8 + var sourceAddress []uint8 + if sourceSpecified { + sourceSpecified = true + sourceNetworkAddress = source.AddrNet + sourceLengthValue := *source.AddrLen + if sourceLengthValue > math.MaxUint8 { + return nil, errors.New("source address length overflows") + } + sourceLengthValueUint8 := uint8(sourceLengthValue) + sourceLength = &sourceLengthValueUint8 + sourceAddress = source.AddrAddress + if sourceLengthValueUint8 == 0 { + // If we define the len 0 we must not send the array + sourceAddress = nil + } + } + destinationSpecified := destination != nil + var destinationNetworkAddress *uint16 + var destinationLength *uint8 + var destinationAddress []uint8 + var destinationHopCount *uint8 + if destinationSpecified { + destinationSpecified = true + destinationNetworkAddress = destination.AddrNet + destinationLengthValue := *destination.AddrLen + if destinationLengthValue > math.MaxUint8 { + return nil, errors.New("source address length overflows") + } + destinationLengthValueUint8 := uint8(destinationLengthValue) + destinationLength = &destinationLengthValueUint8 + destinationAddress = destination.AddrAddress + if destinationLengthValueUint8 == 0 { + // If we define the len 0 we must not send the array + destinationAddress = nil + } + destinationHopCount = &hopCount + } + control := readWriteModel.NewNPDUControl(nlm != nil, destinationSpecified, sourceSpecified, expectingReply, networkPriority) + return readWriteModel.NewNPDU(1, control, destinationNetworkAddress, destinationLength, destinationAddress, sourceNetworkAddress, sourceLength, sourceAddress, destinationHopCount, nlm, apdu, 0), nil +} + +func (n *_NPDU) Encode(pdu Arg) error { + if err := n._NPCI.Encode(pdu); err != nil { + return errors.Wrap(err, "error encoding _NPCI") + } + var err error + n.npdu, err = n.buildNPDU(0, n.GetPDUSource(), n.GetPDUDestination(), n.GetExpectingReply(), n.GetNetworkPriority(), n.nlm, n.apdu) + 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 + return nil +} + +func (n *_NPDU) Decode(pdu Arg) error { + if err := n._NPCI.Decode(pdu); err != nil { + return errors.Wrap(err, "error decoding _NPCI") + } + switch pdu := pdu.(type) { + case PDUData: + data := pdu.GetPduData() + var err error + n.npdu, err = readWriteModel.NPDUParse(context.Background(), data, uint16(len(data))) + if err != nil { + return errors.Wrap(err, "error parsing NPDU") + } + n.pduUserData = n.npdu + n.nlm = n.npdu.GetNlm() + n.apdu = n.npdu.GetApdu() + } + return nil +} + +func (n *_NPDU) GetMessage() spi.Message { + return n.npdu +} + +func (n *_NPDU) getPDUData() []byte { + if n.GetMessage() == nil { + return nil + } + writeBufferByteBased := utils.NewWriteBufferByteBased() + if err := n.GetMessage().SerializeWithWriteBuffer(context.Background(), writeBufferByteBased); err != nil { + panic(err) // TODO: graceful handle + } + return writeBufferByteBased.GetBytes() +} + +func (n *_NPDU) deepCopy() *_NPDU { + return &_NPDU{_NPCI: n._NPCI.deepCopy(), _PDUData: n._PDUData.deepCopy()} +} + +func (n *_NPDU) DeepCopy() PDU { + return n.deepCopy() +} + +func (n *_NPDU) String() string { + return fmt.Sprintf("_NPDU{%s}", n._PCI) +} + +type WhoIsRouterToNetwork struct { + *_NPDU + + wirtnNetwork *uint16 + + readWriteModel.NLMWhoIsRouterToNetwork +} + +func NewWhoIsRouterToNetwork(opts ...func(network *WhoIsRouterToNetwork)) (*WhoIsRouterToNetwork, error) { + w := &WhoIsRouterToNetwork{} + for _, opt := range opts { + opt(w) + } + w.NLMWhoIsRouterToNetwork = readWriteModel.NewNLMWhoIsRouterToNetwork(w.wirtnNetwork, 0) + npdu, err := NewNPDU(w.NLMWhoIsRouterToNetwork, nil) + if err != nil { + return nil, errors.Wrap(err, "error creating NPDU") + } + w._NPDU = npdu.(*_NPDU) + return w, nil +} + +func WithWhoIsRouterToNetworkNet(net uint16) func(*WhoIsRouterToNetwork) { + return func(n *WhoIsRouterToNetwork) { + n.wirtnNetwork = &net + } +} + +func (n *WhoIsRouterToNetwork) GetWirtnNetwork() *uint16 { + return n.wirtnNetwork +} + +func (n *WhoIsRouterToNetwork) Encode(npdu Arg) error { + switch npdu := npdu.(type) { + case NPDU: + if err := npdu.Update(n); err != nil { + return errors.Wrap(err, "error updating _NPCI") + } + if n.wirtnNetwork != nil { + npdu.PutShort(int16(*n.wirtnNetwork)) + } + 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 *WhoIsRouterToNetwork) 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.NLMWhoIsRouterToNetworkExactly: + n.setNLM(nlm) + n.NLMWhoIsRouterToNetwork = nlm + n.wirtnNetwork = nlm.GetDestinationNetworkAddress() + } + } + return nil + default: + return errors.Errorf("invalid NPDU type %T", npdu) + } +} + +func (n *WhoIsRouterToNetwork) String() string { + return fmt.Sprintf("WhoIsRouterToNetwork{%s, wirtnNetwork: %d}", n._NPDU, n.wirtnNetwork) +} + +type IAmRouterToNetwork struct { + *_NPDU +} + +func NewIAmRouterToNetwork() (*IAmRouterToNetwork, error) { + panic("implement me") +} + +type ICouldBeRouterToNetwork struct { + *_NPDU +} + +func NewICouldBeRouterToNetwork() (*ICouldBeRouterToNetwork, error) { + panic("implement me") +} + +type RejectMessageToNetwork struct { + *_NPDU +} + +func NewRejectMessageToNetwork() (*RejectMessageToNetwork, error) { + panic("implement me") +} + +type RouterBusyToNetwork struct { + *_NPDU +} + +func NewRouterBusyToNetwork() (*RouterBusyToNetwork, error) { + panic("implement me") +} + +type RouterAvailableToNetwork struct { + *_NPDU +} + +func NewRouterAvailableToNetwork() (*RouterAvailableToNetwork, error) { + panic("implement me") +} + +type RoutingTableEntry struct { + *_NPDU +} + +func NewRoutingTableEntry() (*RoutingTableEntry, error) { + panic("implement me") +} + +type InitializeRoutingTable struct { + *_NPDU +} + +func NewInitializeRoutingTable() (*InitializeRoutingTable, error) { + panic("implement me") +} + +type InitializeRoutingTableAck struct { + *_NPDU +} + +func NewInitializeRoutingTableAck() (*InitializeRoutingTableAck, error) { + panic("implement me") +} + +type EstablishConnectionToNetwork struct { + *_NPDU +} + +func NewEstablishConnectionToNetwork() (*EstablishConnectionToNetwork, error) { + panic("implement me") +} + +type DisconnectConnectionToNetwork struct { + *_NPDU +} + +func NewDisconnectConnectionToNetwork() (*DisconnectConnectionToNetwork, error) { + panic("implement me") +} + +type WhatIsNetworkNumber struct { + *_NPDU +} + +func NewWhatIsNetworkNumber() (*WhatIsNetworkNumber, error) { + panic("implement me") +} + +type NetworkNumberIs struct { + *_NPDU +} + +func NewNetworkNumberIs() (*NetworkNumberIs, error) { + panic("implement me") +} + +func init() { + NPDUTypes = map[uint8]func() interface{ Decode(Arg) error }{ + 0x00: func() interface{ Decode(Arg) error } { + v, _ := NewWhoIsRouterToNetwork() + return v + }, + 0x01: func() interface{ Decode(Arg) error } { + v, _ := NewIAmRouterToNetwork() + return v + }, + 0x02: func() interface{ Decode(Arg) error } { + v, _ := NewICouldBeRouterToNetwork() + return v + }, + // 0x03: NewRejectRouterToNetwork, // TODO: not present upstream + 0x04: func() interface{ Decode(Arg) error } { + v, _ := NewRouterBusyToNetwork() + return v + }, + 0x05: func() interface{ Decode(Arg) error } { + v, _ := NewRouterBusyToNetwork() + return v + }, + 0x06: func() interface{ Decode(Arg) error } { + v, _ := NewInitializeRoutingTable() + return v + }, + 0x07: func() interface{ Decode(Arg) error } { + v, _ := NewInitializeRoutingTableAck() + return v + }, + 0x08: func() interface{ Decode(Arg) error } { + v, _ := NewEstablishConnectionToNetwork() + return v + }, + 0x09: func() interface{ Decode(Arg) error } { + v, _ := NewDisconnectConnectionToNetwork() + return v + }, + // 0x0A: NewChallengeRequest, // TODO: not present upstream + // 0x0B: NewSecurityPayload, // TODO: not present upstream + // 0x0C: NewSecurityResponse, // TODO: not present upstream + // 0x0D: NewRequestKeyUpdate, // TODO: not present upstream + // 0x0E: NewUpdateKeyUpdate, // TODO: not present upstream + // 0x0F: NewUpdateKeyDistributionKey, // TODO: not present upstream + // 0x10: NewRequestMasterKey, // TODO: not present upstream + // 0x11: NewSetMasterKey, // TODO: not present upstream + 0x12: func() interface{ Decode(Arg) error } { + v, _ := NewWhatIsNetworkNumber() + return v + }, + 0x13: func() interface{ Decode(Arg) error } { + v, _ := NewNetworkNumberIs() + return v + }, + } +} diff --git a/plc4go/internal/bacnetip/tests/state_machine.go b/plc4go/internal/bacnetip/tests/state_machine.go index bbfc0db13ae..b3e96c8360e 100644 --- a/plc4go/internal/bacnetip/tests/state_machine.go +++ b/plc4go/internal/bacnetip/tests/state_machine.go @@ -52,7 +52,7 @@ func (t SendTransition) String() string { type criteria struct { pduType any - pduAttrs map[string]any + pduAttrs map[bacnetip.KnownKey]any } func (c criteria) String() string { @@ -105,20 +105,20 @@ func (t CallTransition) String() string { return fmt.Sprintf("CallTransition{Transition: %s, fnargs: %s}", t.Transition, t.fnargs) } -func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs map[string]any) bool { +func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs map[bacnetip.KnownKey]any) bool { // check the type if pduType != nil && fmt.Sprintf("%T", pdu) != fmt.Sprintf("%T", pduType) { - localLog.Debug().Msg("failed match, wrong type") + localLog.Debug().Type("got", pdu).Type("want", pduType).Msg("failed match, wrong type") return false } for attrName, attrValue := range pduAttrs { switch attrName { - case "pduSource": + case bacnetip.KWPPDUSource: if !pdu.GetPDUSource().Equals(attrValue) { localLog.Debug().Msg("source doesn't match") return false } - case "pduDestination": + case bacnetip.KWPDUDestination: if !pdu.GetPDUDestination().Equals(attrValue) { localLog.Debug().Msg("destination doesn't match") return false @@ -139,8 +139,29 @@ func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs m return false } return b == attrValue.(int) - case "pduData": - return reflect.DeepEqual(pdu.GetMessage(), attrValue) + case bacnetip.KWPDUData: + got := pdu.GetPduData() + want := attrValue + equal := reflect.DeepEqual(got, want) + if !equal { + switch want := want.(type) { + case []byte: + localLog.Debug().Bytes("got", got).Bytes("want", want).Msg("mismatch") + default: + localLog.Debug().Bytes("got", got).Interface("want", want).Msg("mismatch") + } + } + return equal + case bacnetip.KWWirtnNetwork: + wirtn, ok := pdu.(*bacnetip.WhoIsRouterToNetwork) + if !ok { + return false + } + net := wirtn.GetWirtnNetwork() + if net == nil { + return false + } + return *net == attrValue default: panic("implement " + attrName) } @@ -199,7 +220,7 @@ type State interface { fmt.Stringer Send(pdu bacnetip.PDU, nextState State) State - Receive(pduType any, pduAttrs map[string]any) State + Receive(args bacnetip.Args, kwargs bacnetip.KWArgs) State Reset() Fail(docstring string) State Success(docstring string) State @@ -455,8 +476,10 @@ func (s *state) AfterSend(pdu bacnetip.PDU) { // // criteria tPDU to match // next_state destination state after a successful match -func (s *state) Receive(pduType any, pduAttrs map[string]any) State { - s.log.Debug().Interface("pduType", pduType).Interface("pduAttrs", pduAttrs).Msg("Receive") +func (s *state) Receive(args bacnetip.Args, kwargs bacnetip.KWArgs) State { + s.log.Debug().Stringer("args", args).Stringer("kwargs", kwargs).Msg("Receive") + pduType := args[0] + pduAttrs := kwargs var nextState State if _nextState, ok := pduAttrs["next_state"]; ok { nextState = _nextState.(State) @@ -497,7 +520,7 @@ func (s *state) AfterReceive(pdu bacnetip.PDU) { // Ignore Create a ReceiveTransition from this state to itself, if match is successful the effect is to Ignore the tPDU. // // criteria tPDU to match -func (s *state) Ignore(pduType any, pduAttrs map[string]any) State { +func (s *state) Ignore(pduType any, pduAttrs map[bacnetip.KnownKey]any) State { s.log.Debug().Interface("pduType", pduType).Interface("pduAttrs", pduAttrs).Msg("Ignore") s.receiveTransitions = append(s.receiveTransitions, ReceiveTransition{ Transition: Transition{}, diff --git a/plc4go/internal/bacnetip/tests/test_bvll/test_simple_test.go b/plc4go/internal/bacnetip/tests/test_bvll/test_simple_test.go index 6b237ffae0c..41b06a9daa2 100644 --- a/plc4go/internal/bacnetip/tests/test_bvll/test_simple_test.go +++ b/plc4go/internal/bacnetip/tests/test_bvll/test_simple_test.go @@ -149,17 +149,16 @@ func TestSimple(t *testing.T) { pdu.SetPDUSource(tnet.td.address) pdu.SetPDUDestination(tnet.iut.address) tnet.td.GetStartState().Send(pdu, nil).Success("") - tnet.iut.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": tnet.td.address, - }).Success("") + tnet.iut.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, tnet.td.address, + )).Success("") // sniffer sees message on the wire - tnet.sniffer.GetStartState().Receive(bacnetip.NewPDU(npdu), map[string]any{ - "pduSource": tnet.td.address.AddrTuple, - "pduDestination": tnet.iut.address.AddrTuple, - "pduData": pduData, - }, - ).Timeout(1.0*time.Millisecond, nil).Success("") + tnet.sniffer.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(npdu)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, tnet.td.address.AddrTuple, + bacnetip.KWPDUDestination, tnet.iut.address.AddrTuple, + bacnetip.KWPDUData, pduData, + )).Timeout(1.0*time.Millisecond, nil).Success("") // run the group tnet.Run(0) @@ -197,17 +196,16 @@ func TestSimple(t *testing.T) { // test device sends it, iut gets it tnet.td.GetStartState().Send(bacnetip.NewPDU(npdu, bacnetip.WithPDUSource(tnet.td.address), bacnetip.WithPDUDestination(bacnetip.NewLocalBroadcast(nil))), nil).Success("") - tnet.iut.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": tnet.td.address, - }).Success("") + tnet.iut.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, tnet.td.address, + )).Success("") // sniffer sees message on the wire - tnet.sniffer.GetStartState().Receive(bacnetip.NewPDU(npdu), map[string]any{ - "pduSource": tnet.td.address.AddrTuple, - //"pduDestination": tnet.iut.address.AddrTuple, - "pduData": pduData, - }, - ).Timeout(1.0*time.Second, nil).Success("") + tnet.sniffer.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(npdu)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, tnet.td.address.AddrTuple, + //bacnetip.KWPDUDestination, tnet.iut.address.AddrTuple, + bacnetip.KWPDUData, pduData, + )).Timeout(1.0*time.Second, nil).Success("") // run the group tnet.Run(0) diff --git a/plc4go/internal/bacnetip/tests/test_npdu/helpers.go b/plc4go/internal/bacnetip/tests/test_npdu/helpers.go index 6a6142cc90e..8f61f138a86 100644 --- a/plc4go/internal/bacnetip/tests/test_npdu/helpers.go +++ b/plc4go/internal/bacnetip/tests/test_npdu/helpers.go @@ -18,3 +18,91 @@ */ package test_npdu + +import ( + "github.com/apache/plc4x/plc4go/internal/bacnetip" + + "github.com/pkg/errors" + "github.com/rs/zerolog" +) + +type NPDUCodec struct { + *bacnetip.Client + *bacnetip.Server + + log zerolog.Logger +} + +func NewNPDUCodec(localLog zerolog.Logger) (*NPDUCodec, error) { + n := &NPDUCodec{ + log: localLog, + } + var err error + n.Client, err = bacnetip.NewClient(localLog, n) + if err != nil { + return nil, errors.Wrap(err, "error creating client") + } + n.Server, err = bacnetip.NewServer(localLog, n) + if err != nil { + return nil, errors.Wrap(err, "error creating client") + } + return n, nil +} + +func (n *NPDUCodec) Indication(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + n.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Indication") + + npdu := args.Get0NPDU() + + // first a generic _NPDU + xpdu, err := bacnetip.NewNPDU(nil, nil) + if err != nil { + return errors.Wrap(err, "error creating NPDU") + } + if err := npdu.Encode(xpdu); err != nil { + return errors.Wrap(err, "error encoding xpdu") + } + + // Now as a vanilla PDU + ypdu := bacnetip.NewPDU(&bacnetip.MessageBridge{}) + if err := xpdu.Encode(ypdu); err != nil { + return errors.Wrap(err, "error decoding xpdu") + } + n.log.Debug().Stringer("ypdu", ypdu).Msg("encoded") + + // send it downstream + return n.Request(bacnetip.NewArgs(ypdu), bacnetip.NoKWArgs) +} + +func (n *NPDUCodec) Confirmation(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + n.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Indication") + + pdu := args.Get0PDU() + + // decode as generic _NPDU + xpdu, err := bacnetip.NewNPDU(nil, nil) + if err != nil { + return errors.Wrap(err, "error creating NPDU") + } + if err := xpdu.Decode(pdu); err != nil { + return errors.Wrap(err, "error decoding xpdu") + } + + // drop application layer message + if xpdu.GetNPDUNetMessage() == nil { + n.log.Trace().Msg("drop message") + return nil + } + + // do a deeper decode of the _NPDU + ypdu := bacnetip.NPDUTypes[*xpdu.GetNPDUNetMessage()]() + if err := ypdu.Decode(xpdu); err != nil { + return errors.Wrap(err, "error decoding ypdu") + } + + return n.Response(bacnetip.NewArgs(ypdu), bacnetip.NoKWArgs) +} + +func (n *NPDUCodec) String() string { + return "NPDUCodec" +} 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 d63467626df..d0ab4d90050 100644 --- a/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go +++ b/plc4go/internal/bacnetip/tests/test_npdu/test_codec_test.go @@ -19,4 +19,124 @@ package test_npdu -// TODO: implement me +import ( + "testing" + + "github.com/apache/plc4x/plc4go/internal/bacnetip" + "github.com/apache/plc4x/plc4go/internal/bacnetip/tests" + readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model" + "github.com/apache/plc4x/plc4go/spi/testutils" + + "github.com/rs/zerolog" + "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() + panic(err) + return network + } +} + +type TestNPDUCodecSuite struct { + suite.Suite + + client *tests.TrappedClient + codec *NPDUCodec + server *tests.TrappedServer + + log zerolog.Logger +} + +func (suite *TestNPDUCodecSuite) SetupSuite() { + t := suite.T() + suite.log = testutils.ProduceTestingLogger(t) +} + +func (suite *TestNPDUCodecSuite) SetupTest() { + var err error + suite.codec, err = NewNPDUCodec(suite.log) + suite.Require().NoError(err) + suite.client, err = tests.NewTrappedClient(suite.log) + suite.Require().NoError(err) + suite.server, err = tests.NewTrappedServer(suite.log) + suite.Require().NoError(err) + err = bacnetip.Bind(suite.log, suite.client, suite.codec, suite.server) + suite.Require().NoError(err) +} + +// Pass the PDU to the client to send down the stack. +func (suite *TestNPDUCodecSuite) Request(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + suite.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Request") + + return suite.client.Request(args, kwargs) +} + +// Check what the server received. +func (suite *TestNPDUCodecSuite) Indication(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + suite.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Indication") + + var pduType any + if len(args) > 0 { + pduType = args[0].(any) + } + pduAttrs := kwargs + suite.Assert().True(tests.MatchPdu(suite.log, suite.server.GetIndicationReceived(), pduType, pduAttrs)) + return nil +} + +// Check what the server received. +func (suite *TestNPDUCodecSuite) Response(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + suite.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Response") + + return suite.server.Response(args, kwargs) +} + +// Check what the server received. +func (suite *TestNPDUCodecSuite) Confirmation(args bacnetip.Args, kwargs bacnetip.KWArgs) error { + suite.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwargs).Msg("Confirmation") + + pduType := args[0].(any) + pduAttrs := kwargs + suite.Assert().True(tests.MatchPdu(suite.log, suite.client.GetConfirmationReceived(), pduType, pduAttrs)) + return nil +} + +func (suite *TestNPDUCodecSuite) TestWhoIsRouterToNetwork() { // Test the Result encoding and decoding. + // Request successful + pduBytes, err := bacnetip.Xtob( + "01.80" + // version, network layer message + "00 0001" + // message type and network + "00 01", // whois + ) + 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(WhoIsRouterToNetwork(1)), 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.WhoIsRouterToNetwork{}), bacnetip.NewKWArgs(bacnetip.KWWirtnNetwork, uint16(1))) +} + +func TestNPDUCodec(t *testing.T) { + suite.Run(t, new(TestNPDUCodecSuite)) +} diff --git a/plc4go/internal/bacnetip/tests/test_segmentation/test_1_test.go b/plc4go/internal/bacnetip/tests/test_segmentation/test_1_test.go index 87f9edb399e..b3c7eb71d8f 100644 --- a/plc4go/internal/bacnetip/tests/test_segmentation/test_1_test.go +++ b/plc4go/internal/bacnetip/tests/test_segmentation/test_1_test.go @@ -501,7 +501,7 @@ func SegmentationTest(t *testing.T, prefix string, cLen, sLen int) { // send the request, get it acked anet.td.GetStartState().Doc(prefix+"-0"). Send(rq, nil).Doc(prefix+"-1"). - Receive(trq, nil).Doc(prefix + "-2"). + Receive(bacnetip.NewArgs(trq), bacnetip.NoKWArgs).Doc(prefix + "-2"). Success("") // no IUT application layer matching diff --git a/plc4go/internal/bacnetip/tests/test_utilities/test_client_state_machine_test.go b/plc4go/internal/bacnetip/tests/test_utilities/test_client_state_machine_test.go index 4e2c30d0038..bc6b76715cc 100644 --- a/plc4go/internal/bacnetip/tests/test_utilities/test_client_state_machine_test.go +++ b/plc4go/internal/bacnetip/tests/test_utilities/test_client_state_machine_test.go @@ -35,7 +35,7 @@ func TestClientStateMachine(t *testing.T) { // create a client state machine, trapped server, and bind them together client, err := tests.NewClientStateMachine(testingLogger) require.NoError(t, err) - server, err := tests.NewTrappedServer(testingLogger, nil) + server, err := tests.NewTrappedServer(testingLogger) require.NoError(t, err) err = bacnetip.Bind(testingLogger, client, server) require.NoError(t, err) diff --git a/plc4go/internal/bacnetip/tests/test_utilities/test_server_state_machine_test.go b/plc4go/internal/bacnetip/tests/test_utilities/test_server_state_machine_test.go index e938f5c1dee..79487ed0e20 100644 --- a/plc4go/internal/bacnetip/tests/test_utilities/test_server_state_machine_test.go +++ b/plc4go/internal/bacnetip/tests/test_utilities/test_server_state_machine_test.go @@ -33,7 +33,7 @@ import ( func TestServerStateMachine(t *testing.T) { testingLogger := testutils.ProduceTestingLogger(t) // create a client state machine, trapped server, and bind them together - client, err := tests.NewTrappedClient(testingLogger, nil) + client, err := tests.NewTrappedClient(testingLogger) require.NoError(t, err) server, err := tests.NewServerStateMachine(testingLogger) require.NoError(t, err) 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 8c2ffbbcdaa..81cf636cead 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 @@ -39,6 +39,8 @@ type TPDU struct { a, b int } +var _ bacnetip.PDU = (TPDU{}) + func (t TPDU) X() []byte { return t.x } @@ -93,6 +95,66 @@ func (t TPDU) GetNetworkPriority() readWriteModel.NPDUNetworkPriority { panic("implement me") } +func (t TPDU) GetPDUUserData() spi.Message { + //TODO implement me + panic("implement me") +} + +func (t TPDU) Update(pci bacnetip.Arg) error { + //TODO implement me + panic("implement me") +} + +func (t TPDU) SetPduData(bytes []byte) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) GetPduData() []byte { + //TODO implement me + panic("implement me") +} + +func (t TPDU) Get() (byte, error) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) GetShort() (int16, error) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) GetLong() (int64, error) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) GetData(dlen int) ([]byte, error) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) Put(b byte) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) PutData(b ...byte) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) PutShort(i int16) { + //TODO implement me + panic("implement me") +} + +func (t TPDU) PutLong(i int64) { + //TODO implement me + panic("implement me") +} + func (t TPDU) DeepCopy() bacnetip.PDU { panic("implement me") } @@ -117,16 +179,16 @@ func TestMatchPdu(t *testing.T) { // Note the other testcase is irrelevant as we don't have dynamic types // matching/not matching attributes - assert.True(t, tests.MatchPdu(testingLogger, tpdu, nil, map[string]any{"x": []byte{1}})) - assert.False(t, tests.MatchPdu(testingLogger, tpdu, nil, map[string]any{"x": []byte{2}})) - assert.False(t, tests.MatchPdu(testingLogger, tpdu, nil, map[string]any{"y": []byte{1}})) - assert.False(t, tests.MatchPdu(testingLogger, anon, nil, map[string]any{"x": []byte{1}})) + assert.True(t, tests.MatchPdu(testingLogger, tpdu, nil, map[bacnetip.KnownKey]any{"x": []byte{1}})) + assert.False(t, tests.MatchPdu(testingLogger, tpdu, nil, map[bacnetip.KnownKey]any{"x": []byte{2}})) + assert.False(t, tests.MatchPdu(testingLogger, tpdu, nil, map[bacnetip.KnownKey]any{"y": []byte{1}})) + assert.False(t, tests.MatchPdu(testingLogger, anon, nil, map[bacnetip.KnownKey]any{"x": []byte{1}})) // matching/not matching types and attributes - assert.True(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[string]any{"x": []byte{1}})) - assert.False(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[string]any{"x": []byte{2}})) - assert.False(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[string]any{"y": []byte{1}})) - assert.False(t, tests.MatchPdu(testingLogger, anon, Anon{}, map[string]any{"x": []byte{1}})) + assert.True(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[bacnetip.KnownKey]any{"x": []byte{1}})) + assert.False(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[bacnetip.KnownKey]any{"x": []byte{2}})) + assert.False(t, tests.MatchPdu(testingLogger, tpdu, TPDU{}, map[bacnetip.KnownKey]any{"y": []byte{1}})) + assert.False(t, tests.MatchPdu(testingLogger, anon, Anon{}, map[bacnetip.KnownKey]any{"x": []byte{1}})) } func TestState(t *testing.T) { @@ -259,7 +321,7 @@ func TestStateMachine(t *testing.T) { pdu := TPDU{} // make a send transition from start to success, run the machine - tsm.GetStartState().Receive(pdu, nil).Success("") + tsm.GetStartState().Receive(bacnetip.NewArgs(pdu), bacnetip.NoKWArgs).Success("") err := tsm.Run() assert.NoError(t, err) @@ -294,7 +356,7 @@ func TestStateMachine(t *testing.T) { badPdu := TPDU{b: 2} // make a send transition from start to success, run the machine - tsm.GetStartState().Receive(TPDU{}, map[string]any{"a": 1}).Success("") + tsm.GetStartState().Receive(bacnetip.NewArgs(TPDU{}), bacnetip.NewKWArgs(bacnetip.KnownKey("a"), 1)).Success("") err := tsm.Run() assert.NoError(t, err) @@ -382,7 +444,7 @@ func TestStateMachine(t *testing.T) { // after sending the first pdu, wait for the second s0 := tsm.GetStartState() s1 := s0.Send(firstPdu, nil) - s2 := s1.Receive(TPDU{}, map[string]any{"a": 2}) + s2 := s1.Receive(bacnetip.NewArgs(TPDU{}), bacnetip.NewKWArgs(bacnetip.KnownKey("a"), 2)) s2.Success("") // run the machine @@ -427,7 +489,7 @@ func TestStateMachine(t *testing.T) { // when the first pdu is received, send the second s0 := tsm.GetStartState() - s1 := s0.Receive(TPDU{}, map[string]any{"a": 1}) + s1 := s0.Receive(bacnetip.NewArgs(TPDU{}), bacnetip.NewKWArgs(bacnetip.KnownKey("a"), 1)) s2 := s1.Send(secondPdu, nil) s2.Success("") diff --git a/plc4go/internal/bacnetip/tests/test_utilities/test_time_machine_test.go b/plc4go/internal/bacnetip/tests/test_utilities/test_time_machine_test.go index 062bd37bd16..d7e0aea8e4a 100644 --- a/plc4go/internal/bacnetip/tests/test_utilities/test_time_machine_test.go +++ b/plc4go/internal/bacnetip/tests/test_utilities/test_time_machine_test.go @@ -46,7 +46,8 @@ func (suite *TimeMachineSuite) SetupSuite() { } func (suite *TimeMachineSuite) SetupTest() { - tests.LockGlobalTimeMachine(suite.T()) + t := suite.T() + tests.LockGlobalTimeMachine(t) tests.NewGlobalTimeMachine(suite.log) // TODO: this is really stupid because of concurrency... } diff --git a/plc4go/internal/bacnetip/tests/test_vlan/test_ipnetwork_test.go b/plc4go/internal/bacnetip/tests/test_vlan/test_ipnetwork_test.go index 4835a2315c4..699d9b21f35 100644 --- a/plc4go/internal/bacnetip/tests/test_vlan/test_ipnetwork_test.go +++ b/plc4go/internal/bacnetip/tests/test_vlan/test_ipnetwork_test.go @@ -145,9 +145,9 @@ func TestIPVLAN(t *testing.T) { // node 1 sends the pdu, mode 2 gets it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // run the group err = tnet.Run(0) @@ -174,12 +174,12 @@ func TestIPVLAN(t *testing.T) { // node 1 sends the pdu, node 2 and 3 each get it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") - tnode3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") + tnode3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // run the group err = tnet.Run(0) @@ -233,9 +233,9 @@ func TestIPVLAN(t *testing.T) { // node 1 sends the pdu, but gets it back as if it was from node 3 tnode1.GetStartState(). Send(pdu, nil). - Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }). + Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )). Success("") // run the group @@ -262,12 +262,12 @@ func TestIPVLAN(t *testing.T) { // node 1 sends the pdu, node 2 and 3 each get it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") - tnode3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduDestination": dest, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") + tnode3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPDUDestination, dest, + )).Success("") // run the group err = tnet.Run(0) @@ -293,9 +293,9 @@ func TestIPVLAN(t *testing.T) { // node 1 sends the pdu to node 2, node 3 waits and gets nothing tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // if node 3 receives anything it will trigger unexpected receive and fail tnode3.GetStartState().Timeout(500*time.Millisecond, nil).Success("") @@ -409,9 +409,9 @@ func (suite *RouterSuite) TestSendReceive() { // Test that a node can send a mes // node 1 sends the pdu, mode 2 gets it csm_10_2.GetStartState().Send(pdu, nil).Success("") - csm_20_3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + csm_20_3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // other nodes get nothing csm_10_3.GetStartState().Timeout(1*time.Second, nil).Success("") @@ -436,9 +436,9 @@ func (suite *RouterSuite) TestLocalBroadcast() { // Test that a node can send a // node 10-2 sends the pdu, node 10-3 gets pdu, nodes 20-2 and 20-3 dont csm_10_2.GetStartState().Send(pdu, nil).Success("") - csm_10_3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + csm_10_3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") csm_20_3.GetStartState().Timeout(1*time.Second, nil).Success("") csm_20_2.GetStartState().Timeout(1*time.Second, nil).Success("") } @@ -462,12 +462,12 @@ func (suite *RouterSuite) TestRemoteBroadcast() { // Test that a node can send a // node 10-2 sends the pdu, node 10-3 gets pdu, nodes 20-2 and 20-3 dont csm_10_2.GetStartState().Send(pdu, nil).Success("") csm_10_3.GetStartState().Timeout(1*time.Second, nil).Success("") - csm_20_2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") - csm_20_3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + csm_20_2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") + csm_20_3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") } func TestRouter(t *testing.T) { diff --git a/plc4go/internal/bacnetip/tests/test_vlan/test_network_test.go b/plc4go/internal/bacnetip/tests/test_vlan/test_network_test.go index bf3102f9234..52bc37a1d90 100644 --- a/plc4go/internal/bacnetip/tests/test_vlan/test_network_test.go +++ b/plc4go/internal/bacnetip/tests/test_vlan/test_network_test.go @@ -145,9 +145,9 @@ func TestVLAN(t *testing.T) { // node 1 sends the pdu, mode 2 gets it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // run the group err = tnet.Run(0) @@ -173,12 +173,12 @@ func TestVLAN(t *testing.T) { // node 1 sends the pdu, node 2 and 3 each get it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") - tnode3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") + tnode3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // run the group err = tnet.Run(0) @@ -230,9 +230,9 @@ func TestVLAN(t *testing.T) { // node 1 sends the pdu, but gets it back as if it was from node 3 tnode1.GetStartState(). Send(pdu, nil). - Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }). + Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )). Success("") // run the group @@ -259,12 +259,12 @@ func TestVLAN(t *testing.T) { // node 1 sends the pdu, node 2 and 3 each get it tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") - tnode3.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduDestination": dest, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") + tnode3.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPDUDestination, dest, + )).Success("") // run the group err = tnet.Run(0) @@ -290,9 +290,9 @@ func TestVLAN(t *testing.T) { // node 1 sends the pdu to node 2, node 3 waits and gets nothing tnode1.GetStartState().Send(pdu, nil).Success("") - tnode2.GetStartState().Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduSource": src, - }).Success("") + tnode2.GetStartState().Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPPDUSource, src, + )).Success("") // if node 3 receives anything it will trigger unexpected receive and fail tnode3.GetStartState().Timeout(500*time.Millisecond, nil).Success("") @@ -305,6 +305,7 @@ func TestVLAN(t *testing.T) { func TestVLANEvents(t *testing.T) { t.Run("test_send_receive", func(t *testing.T) { // Test that a node can send a message to another node and use events to continue with the messages. + t.Skip("not yet read") // TODO: fix testingLogger := testutils.ProduceTestingLogger(t) tests.LockGlobalTimeMachine(t) @@ -334,12 +335,12 @@ func TestVLANEvents(t *testing.T) { // node 2 receives dead_pdu, sets event, waits for beef_pdu tnode2.GetStartState(). - Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduData": tests.NewDummyMessage(0xde, 0xad), - }).SetEvent("e"). - Receive(bacnetip.NewPDU(nil), map[string]any{ - "pduData": tests.NewDummyMessage(0xbe, 0xef), - }).Success("") + Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPDUData, tests.NewDummyMessage(0xde, 0xad), + )).SetEvent("e"). + Receive(bacnetip.NewArgs(bacnetip.NewPDU(nil)), bacnetip.NewKWArgs( + bacnetip.KWPDUData, tests.NewDummyMessage(0xbe, 0xef), + )).Success("") // run the group err = tnet.Run(0) diff --git a/plc4go/internal/bacnetip/tests/trapped_classes.go b/plc4go/internal/bacnetip/tests/trapped_classes.go index 37f7df1981a..3146a53a9c1 100644 --- a/plc4go/internal/bacnetip/tests/trapped_classes.go +++ b/plc4go/internal/bacnetip/tests/trapped_classes.go @@ -254,13 +254,15 @@ func (t *TrappedStateMachine) DecorateState(state State) State { return NewTrappedState(state, t.Trapper) } -type TrappedClientRequirements interface { +// TrappedClientContract provides a set of functions which can be overwritten by a sub struct +type TrappedClientContract interface { Request(bacnetip.Args, bacnetip.KWArgs) error + Confirmation(args bacnetip.Args, kwargs bacnetip.KWArgs) error } // TrappedClient An instance of this class sits at the top of a stack. type TrappedClient struct { - TrappedClientRequirements + TrappedClientContract *bacnetip.Client requestSent bacnetip.PDU @@ -269,10 +271,13 @@ type TrappedClient struct { log zerolog.Logger } -func NewTrappedClient(localLog zerolog.Logger, requirements TrappedClientRequirements) (*TrappedClient, error) { +func NewTrappedClient(localLog zerolog.Logger, opts ...func(*TrappedClient)) (*TrappedClient, error) { t := &TrappedClient{ - TrappedClientRequirements: requirements, - log: localLog, + log: localLog, + } + t.TrappedClientContract = t + for _, opt := range opts { + opt(t) } var err error t.Client, err = bacnetip.NewClient(localLog, t) @@ -282,6 +287,12 @@ func NewTrappedClient(localLog zerolog.Logger, requirements TrappedClientRequire return t, nil } +func WithTrappedClientContract(trappedClientContract TrappedClientContract) func(*TrappedClient) { + return func(t *TrappedClient) { + t.TrappedClientContract = trappedClientContract + } +} + func (t *TrappedClient) GetRequestSent() bacnetip.PDU { return t.requestSent } @@ -295,8 +306,8 @@ func (t *TrappedClient) Request(args bacnetip.Args, kwargs bacnetip.KWArgs) erro // a reference for checking t.requestSent = args.Get0PDU() - // Call sub - return t.TrappedClientRequirements.Request(args, kwargs) + // continue with regular processing + return t.Client.Request(args, kwargs) } func (t *TrappedClient) Confirmation(args bacnetip.Args, kwargs bacnetip.KWArgs) error { @@ -306,13 +317,19 @@ func (t *TrappedClient) Confirmation(args bacnetip.Args, kwargs bacnetip.KWArgs) return nil } -type TrappedServerRequirements interface { +func (t *TrappedClient) String() string { + return fmt.Sprintf("TrappedClient{%s, requestSent: %v, confirmationReceived: %v}", t.Client, t.requestSent, t.confirmationReceived) +} + +// TrappedServerContract provides a set of functions which can be overwritten by a sub struct +type TrappedServerContract interface { + Indication(args bacnetip.Args, kwargs bacnetip.KWArgs) error Response(bacnetip.Args, bacnetip.KWArgs) error } // TrappedServer An instance of this class sits at the bottom of a stack. type TrappedServer struct { - TrappedServerRequirements + TrappedServerContract *bacnetip.Server indicationReceived bacnetip.PDU @@ -321,10 +338,13 @@ type TrappedServer struct { log zerolog.Logger } -func NewTrappedServer(localLog zerolog.Logger, requirements TrappedServerRequirements) (*TrappedServer, error) { +func NewTrappedServer(localLog zerolog.Logger, opts ...func(*TrappedServer)) (*TrappedServer, error) { t := &TrappedServer{ - TrappedServerRequirements: requirements, - log: localLog, + log: localLog, + } + t.TrappedServerContract = t + for _, opt := range opts { + opt(t) } var err error t.Server, err = bacnetip.NewServer(localLog, t) @@ -334,6 +354,12 @@ func NewTrappedServer(localLog zerolog.Logger, requirements TrappedServerRequire return t, nil } +func WithTrappedServerContract(trappedServerContract TrappedServerContract) func(*TrappedServer) { + return func(t *TrappedServer) { + t.TrappedServerContract = trappedServerContract + } +} + func (t *TrappedServer) GetIndicationReceived() bacnetip.PDU { return t.indicationReceived } @@ -355,8 +381,12 @@ func (t *TrappedServer) Response(args bacnetip.Args, kwargs bacnetip.KWArgs) err // a reference for checking t.responseSent = args.Get0PDU() - // Call sub - return t.TrappedServerRequirements.Response(args, kwargs) + // continue with regular processing + return t.Server.Response(args, kwargs) +} + +func (t *TrappedServer) String() string { + return fmt.Sprintf("TrappedServer{%s, indicationReceived: %v, responseSent: %v}", t.Server, t.indicationReceived, t.responseSent) } type TrappedServerStateMachine struct { @@ -369,7 +399,7 @@ type TrappedServerStateMachine struct { func NewTrappedServerStateMachine(localLog zerolog.Logger) (*TrappedServerStateMachine, error) { t := &TrappedServerStateMachine{log: localLog} var err error - t.TrappedServer, err = NewTrappedServer(localLog, t) + t.TrappedServer, err = NewTrappedServer(localLog, WithTrappedServerContract(t)) if err != nil { return nil, errors.Wrap(err, "error building trapped server") } diff --git a/plc4go/internal/bacnetip/tests/util.go b/plc4go/internal/bacnetip/tests/util.go index 82888091282..9cafdc56b7c 100644 --- a/plc4go/internal/bacnetip/tests/util.go +++ b/plc4go/internal/bacnetip/tests/util.go @@ -46,8 +46,8 @@ func (d DummyMessage) Serialize() ([]byte, error) { return d.Data, nil } -func (d DummyMessage) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error { - return writeBuffer.WriteSerializable(ctx, d) +func (d DummyMessage) SerializeWithWriteBuffer(_ context.Context, writeBuffer utils.WriteBuffer) error { + return writeBuffer.WriteByteArray("data", d.Data) } func (d DummyMessage) GetLengthInBytes(_ context.Context) uint16 { diff --git a/plc4go/internal/bacnetip/vlan.go b/plc4go/internal/bacnetip/vlan.go index 79042112be5..a30a7fc922f 100644 --- a/plc4go/internal/bacnetip/vlan.go +++ b/plc4go/internal/bacnetip/vlan.go @@ -21,8 +21,10 @@ package bacnetip import ( "fmt" + "github.com/pkg/errors" "github.com/rs/zerolog" + "math/rand" )