Skip to content

Commit

Permalink
feat(plc4go/bacnetip): progressed APDU
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Aug 29, 2024
1 parent abc6879 commit 34f29bb
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 90 deletions.
10 changes: 5 additions & 5 deletions plc4go/internal/bacnetip/apdu_APCI.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ type APCI interface {
getApduMaxSegs() *uint8
setApduMaxResp(*uint8)
getApduMaxResp() *uint8
setApduService(*readWriteModel.BACnetConfirmedServiceChoice)
getApduService() *readWriteModel.BACnetConfirmedServiceChoice
setApduService(*uint8)
getApduService() *uint8
setApduInvokeID(*uint8)
getApduInvokeID() *uint8
setApduAbortRejectReason(*uint8)
Expand All @@ -76,7 +76,7 @@ type _APCI struct {
apduWin *uint8 // actual/proposed window size
apduMaxSegs *uint8 // maximum segments accepted (decoded)
apduMaxResp *uint8 // max response accepted (decoded)
apduService *readWriteModel.BACnetConfirmedServiceChoice
apduService *uint8
apduInvokeID *uint8
apduAbortRejectReason *uint8

Expand Down Expand Up @@ -155,10 +155,10 @@ func (a *_APCI) setApduMaxResp(apduMaxResp *uint8) {
func (a *_APCI) getApduMaxResp() *uint8 {
return a.apduMaxResp
}
func (a *_APCI) setApduService(apduService *readWriteModel.BACnetConfirmedServiceChoice) {
func (a *_APCI) setApduService(apduService *uint8) {
a.apduService = apduService
}
func (a *_APCI) getApduService() *readWriteModel.BACnetConfirmedServiceChoice {
func (a *_APCI) getApduService() *uint8 {
return a.apduService
}
func (a *_APCI) setApduInvokeID(apduInvokeID *uint8) {
Expand Down
57 changes: 41 additions & 16 deletions plc4go/internal/bacnetip/apdu_APCISequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,43 @@ package bacnetip

import (
"github.com/pkg/errors"

"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)

// APCISequenceContract provides a set of functions which can be overwritten by a sub struct
type APCISequenceContract interface {
SequenceContractRequirement
}

// APCISequenceContractRequirement is needed when one want to extend using SequenceContract
type APCISequenceContractRequirement interface {
APCISequenceContract
// SetAPCISequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
SetAPCISequence(a *APCISequence)
}

// TODO: implement it...
type APCISequence struct {
*_APCI
*Sequence

_contract APCISequenceContract

tagList *TagList
}

func NewAPCISequence() (*APCISequence, error) {
func NewAPCISequence(opts ...func(*APCISequence)) (*APCISequence, error) {
a := &APCISequence{}
for _, opt := range opts {
opt(a)
}
if a._contract == nil {
a._contract = a
} else {
a._contract.(APCISequenceContractRequirement).SetAPCISequence(a)
}
a._APCI = NewAPCI(nil).(*_APCI) // TODO: what to pass up?
var err error
a.Sequence, err = NewSequence(NoKWArgs, WithSequenceContract(a))
a.Sequence, err = NewSequence(NoKWArgs, WithSequenceExtension(a._contract))
if err != nil {
return nil, errors.Wrap(err, "error creating sequence")
}
Expand All @@ -47,6 +67,12 @@ func NewAPCISequence() (*APCISequence, error) {
return a, nil
}

func WithAPCISequenceExtension(contract APCISequenceContractRequirement) func(*APCISequence) {
return func(a *APCISequence) {
a._contract = contract
}
}

func (a *APCISequence) SetSequence(sequence *Sequence) {
a.Sequence = sequence
}
Expand Down Expand Up @@ -78,18 +104,17 @@ func (a *APCISequence) Decode(apdu Arg) error {
if err := a.Update(apdu); err != nil {
return errors.Wrap(err, "error updating APDU")
}
switch pduUserData := apdu.GetRootMessage().(type) {
case model.APDUExactly:
a.tagList = NewTagList(nil)
if err := a.tagList.Decode(apdu); err != nil {
return errors.Wrap(err, "error decoding TagList")
}
// pass the taglist to the Sequence for additional decoding
if err := a.Sequence.Decode(a.tagList); err != nil {
return errors.Wrap(err, "error encoding TagList")
}

_ = pduUserData
a.tagList = NewTagList(nil)
if err := a.tagList.Decode(apdu); err != nil {
return errors.Wrap(err, "error decoding TagList")
}
// pass the taglist to the Sequence for additional decoding
if err := a.Sequence.Decode(a.tagList); err != nil {
return errors.Wrap(err, "error encoding TagList")
}

if len(a.tagList.GetTagList()) > 0 {
return errors.New("trailing unmatched tags")
}
return nil
default:
Expand Down
60 changes: 59 additions & 1 deletion plc4go/internal/bacnetip/apdu_ComplexAckSequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,72 @@

package bacnetip

import (
"github.com/pkg/errors"

readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)

// TODO: implement it...
type ComplexAckSequence struct {
*APCISequence
*ComplexAckPDU
}

// TODO: implement it...
// UnconfirmedRequestSequenceContract provides a set of functions which can be overwritten by a sub struct
type UnconfirmedRequestSequenceContract interface {
APCISequenceContractRequirement
GetServiceChoice() *readWriteModel.BACnetUnconfirmedServiceChoice
}

// UnconfirmedRequestSequenceContractRequirement is needed when one want to extend using SequenceContract
type UnconfirmedRequestSequenceContractRequirement interface {
UnconfirmedRequestSequenceContract
// SetUnconfirmedRequestSequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
SetUnconfirmedRequestSequence(urs *UnconfirmedRequestSequence)
}

type UnconfirmedRequestSequence struct {
*APCISequence
*UnconfirmedRequestPDU

_contract UnconfirmedRequestSequenceContract
}

func NewUnconfirmedRequestSequence(opts ...func(*UnconfirmedRequestSequence)) (*UnconfirmedRequestSequence, error) {
u := &UnconfirmedRequestSequence{}
for _, opt := range opts {
opt(u)
}
if u._contract == nil {
u._contract = u
} else {
u._contract.(UnconfirmedRequestSequenceContractRequirement).SetUnconfirmedRequestSequence(u)
}
var err error
u.APCISequence, err = NewAPCISequence(WithAPCISequenceExtension(u._contract))
if err != nil {
return nil, errors.Wrap(err, "error creating _APCISequence")
}
u.UnconfirmedRequestPDU, err = NewUnconfirmedRequestPDU(func(pdu *UnconfirmedRequestPDU) {
pdu.argChoice = u.GetServiceChoice()
})
if err != nil {
return nil, errors.Wrap(err, "error creating UnconfirmedRequestPDU")
}
return u, nil
}

func WithUnconfirmedRequestSequenceExtension(contract UnconfirmedRequestSequenceContractRequirement) func(*UnconfirmedRequestSequence) {
return func(a *UnconfirmedRequestSequence) {
a._contract = contract
}
}

func (u *UnconfirmedRequestSequence) GetServiceChoice() *readWriteModel.BACnetUnconfirmedServiceChoice {
return nil
}

func (u *UnconfirmedRequestSequence) SetAPCISequence(a *APCISequence) {
u.APCISequence = a
}
39 changes: 24 additions & 15 deletions plc4go/internal/bacnetip/apdu_UnconfirmedRequestPDU.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,42 @@

package bacnetip

import "github.com/pkg/errors"
import (
"github.com/pkg/errors"

readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)

// TODO: implement it...
type UnconfirmedRequestPDU struct {
*___APDU

// args
argChoice *readWriteModel.BACnetUnconfirmedServiceChoice

pduType readWriteModel.ApduType
}

func NewUnconfirmedRequestPDU() (*UnconfirmedRequestPDU, error) {
u := &UnconfirmedRequestPDU{}
func NewUnconfirmedRequestPDU(opts ...func(*UnconfirmedRequestPDU)) (*UnconfirmedRequestPDU, error) {
u := &UnconfirmedRequestPDU{
pduType: readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU,
}
for _, opt := range opts {
opt(u)
}
apdu, err := new_APDU()
if err != nil {
return nil, errors.Wrap(err, "error creating _APDU")
}
u.___APDU = apdu.(*___APDU)

u.apduType = &u.pduType
u.apduService = (*uint8)(u.argChoice)

return u, nil
}

func NewUnconfirmedRequestSequence() (*UnconfirmedRequestSequence, error) {
u := &UnconfirmedRequestSequence{}
var err error
u.APCISequence, err = NewAPCISequence()
if err != nil {
return nil, errors.Wrap(err, "error creating _APCISequence")
func WithUnconfirmedRequestPDU(choice readWriteModel.BACnetUnconfirmedServiceChoice) func(*UnconfirmedRequestPDU) {
return func(u *UnconfirmedRequestPDU) {
u.argChoice = &choice
}
u.UnconfirmedRequestPDU, err = NewUnconfirmedRequestPDU()
if err != nil {
return nil, errors.Wrap(err, "error creating UnconfirmedRequestPDU")
}
return u, nil
}
30 changes: 23 additions & 7 deletions plc4go/internal/bacnetip/apdu_WhoIsRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,42 @@
package bacnetip

import (
"fmt"

"github.com/pkg/errors"

readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)

// TODO: implement it...
type WhoIsRequest struct {
*UnconfirmedRequestSequence

serviceChoice readWriteModel.BACnetUnconfirmedServiceChoice
sequenceElements []Element
}

func NewWhoIsRequest() (*WhoIsRequest, error) {
w := &WhoIsRequest{}
w := &WhoIsRequest{
serviceChoice: readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS,
sequenceElements: []Element{
NewElement("deviceInstanceRangeLowLimit", V2E(NewUnsigned), WithElementContext(0), WithElementOptional(true)),
NewElement("deviceInstanceRangeHighLimit", V2E(NewUnsigned), WithElementContext(1), WithElementOptional(true)),
},
}
var err error
w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence()
w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(WithUnconfirmedRequestSequenceExtension(w))
if err != nil {
return nil, errors.Wrap(err, "error creating UnconfirmedRequestSequence")
}
return w, nil
}

func (r *WhoIsRequest) String() string {
return fmt.Sprintf("WhoIsRequest{%s}", r.UnconfirmedRequestSequence)
func (w *WhoIsRequest) GetServiceChoice() *readWriteModel.BACnetUnconfirmedServiceChoice {
return &w.serviceChoice
}

func (w *WhoIsRequest) GetSequenceElements() []Element {
return w.sequenceElements
}

func (w *WhoIsRequest) SetUnconfirmedRequestSequence(u *UnconfirmedRequestSequence) {
w.UnconfirmedRequestSequence = u
}
22 changes: 20 additions & 2 deletions plc4go/internal/bacnetip/constructeddata.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ type ElementKlass interface {
GetAppTag() readWriteModel.BACnetDataType
}

// V2E accepts a function which takes an Arg and maps it to a ElementKlass
func V2E[T any](b func(arg Arg) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
return func(args Args, kwargs KWArgs) (ElementKlass, error) {
var arg any
if len(args) == 1 {
arg = args[0]
}
r, err := b(arg)
return any(r).(ElementKlass), err
}
}

// TODO: finish
type _Element struct {
Name string
Expand Down Expand Up @@ -75,6 +87,12 @@ func WithElementOptional(optional bool) func(*_Element) {
}
}

func WithElementContext(context int) func(*_Element) {
return func(e *_Element) {
e.Context = &context
}
}

func (e *_Element) GetName() string {
return e.Name
}
Expand Down Expand Up @@ -105,7 +123,7 @@ type SequenceContract interface {
type SequenceContractRequirement interface {
SequenceContract
// SetSequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
SetSequence(sequence *Sequence)
SetSequence(s *Sequence)
}

// TODO: finish
Expand Down Expand Up @@ -156,7 +174,7 @@ func NewSequence(kwargs KWArgs, opts ...func(*Sequence)) (*Sequence, error) {
return s, nil
}

func WithSequenceContract(contract SequenceContractRequirement) func(*Sequence) {
func WithSequenceExtension(contract SequenceContractRequirement) func(*Sequence) {
return func(s *Sequence) {
s._contract = contract
}
Expand Down
Loading

0 comments on commit 34f29bb

Please sign in to comment.