diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go
index dee252b16e5..9702ae7984c 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go
@@ -21,19 +21,22 @@ package apdu
 
 import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
+var _debug = CreateDebugPrinter()
+
 var APDUTypes map[readWriteModel.ApduType]func() Decoder
 
 func init() {
 	APDUTypes = map[readWriteModel.ApduType]func() Decoder{
 		readWriteModel.ApduType_CONFIRMED_REQUEST_PDU: func() Decoder {
-			pdu, _ := NewConfirmedRequestPDU(nil)
+			pdu, _ := NewConfirmedRequestPDU(Nothing())
 			return pdu
 		},
 		readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU: func() Decoder {
-			pdu, _ := NewUnconfirmedRequestPDU(nil)
+			pdu, _ := NewUnconfirmedRequestPDU(Nothing())
 			return pdu
 		},
 		readWriteModel.ApduType_SIMPLE_ACK_PDU: func() Decoder {
@@ -110,7 +113,7 @@ func init() {
 			panic("implement me")
 		},
 		readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS: func() Decoder {
-			request, _ := NewWhoIsRequest()
+			request, _ := NewWhoIsRequest(Nothing())
 			return request
 		},
 		readWriteModel.BACnetUnconfirmedServiceChoice_UTC_TIME_SYNCHRONIZATION: func() Decoder {
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go
index d17ef0b0f2e..50bc8c84ac7 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go
@@ -28,7 +28,6 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
@@ -93,17 +92,16 @@ type _APCI struct {
 
 var _ APCI = (*_APCI)(nil)
 
-func NewAPCI(apdu readWriteModel.APDU) APCI {
+func NewAPCI(args Args, kwArgs KWArgs) APCI {
+	if _debug != nil {
+		_debug("__init__ %r %r", args, kwArgs)
+	}
 	a := &_APCI{}
 	a.DebugContents = NewDebugContents(a, "apduType", "apduSeg", "apduMor", "apduSA", "apduSrv",
 		"apduNak", "apduSeq", "apduWin", "apduMaxSegs", "apduMaxResp",
 		"apduService", "apduInvokeID", "apduAbortRejectReason")
-	a.PCI = NewPCI(NoArgs, NKW(KWCompRootMessage, apdu)) // TODO: convert to args so we can solve all those todos
+	a.PCI = NewPCI(args, kwArgs)
 	a.AddExtraPrinters(a.PCI.(DebugContentPrinter))
-	if apdu != nil {
-		apduType := apdu.GetApduType()
-		a.apduType = &apduType
-	}
 	return a
 }
 
@@ -112,14 +110,29 @@ func (a *_APCI) GetDebugAttr(attr string) any {
 	case "apduType":
 		return a.apduType
 	case "apduSeg":
+		if !a.apduSeg {
+			return nil
+		}
 		return a.apduSeq
 	case "apduMor":
+		if !a.apduMor {
+			return nil
+		}
 		return a.apduMor
 	case "apduSA":
+		if !a.apduSA {
+			return nil
+		}
 		return a.apduSA
 	case "apduSrv":
+		if !a.apduSrv {
+			return nil
+		}
 		return a.apduSrv
 	case "apduNak":
+		if !a.apduNak {
+			return nil
+		}
 		return a.apduNak
 	case "apduSeq":
 		if a.apduSeq != nil {
@@ -149,7 +162,6 @@ func (a *_APCI) GetDebugAttr(attr string) any {
 		if a.apduAbortRejectReason != nil {
 			return *a.apduAbortRejectReason
 		}
-		panic("implement me")
 	default:
 		return nil
 	}
@@ -265,6 +277,9 @@ func (a *_APCI) Update(apci Arg) error {
 }
 
 func (a *_APCI) Encode(pdu Arg) error {
+	if _debug != nil {
+		_debug("encode %r", pdu)
+	}
 	switch pdu := pdu.(type) {
 	case PCI:
 		if err := pdu.GetPCI().Update(a); err != nil {
@@ -363,6 +378,9 @@ func (a *_APCI) Encode(pdu Arg) error {
 }
 
 func (a *_APCI) Decode(pdu Arg) error {
+	if _debug != nil {
+		_debug("decode %r", pdu)
+	}
 	if err := a.PCI.Update(pdu); err != nil {
 		return errors.Wrap(err, "error updating pdu")
 	}
@@ -486,27 +504,22 @@ func (a *_APCI) deepCopy() *_APCI {
 }
 
 func (a *_APCI) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("APCI{%s}", a.PCI) // TODO: add other fields
-	} else {
-		sname := fmt.Sprintf("%T", a)
-
-		// expand the type if possible
-
-		stype := ""
-		if a.apduType != nil {
-			if v, ok := APDUTypes[*a.apduType]; ok {
-				stype = fmt.Sprintf("%T", v)
-			} else {
-				stype = "?"
-			}
+	sname := StructName()
+
+	// expand the type if possible
+	stype := ""
+	if a.apduType != nil {
+		if v, ok := APDUTypes[*a.apduType]; ok {
+			stype = fmt.Sprintf("%T", v)
+		} else {
+			stype = "?"
 		}
+	}
 
-		// add the invoke ID if it has one
-		if a.apduInvokeID != nil {
-			stype += ", " + strconv.Itoa(int(*a.apduInvokeID))
-		}
-		// put it together
-		return fmt.Sprintf("<%s(%s instance at %p)>", sname, stype, a)
+	// add the invoke ID if it has one
+	if a.apduInvokeID != nil {
+		stype += ", " + strconv.Itoa(int(*a.apduInvokeID))
 	}
+	// put it together
+	return fmt.Sprintf("<%s(%s instance at %p)>", sname, stype, a)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go
index 2f30ab1f832..b53173486e3 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go
@@ -26,7 +26,6 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
 // APCISequenceContract provides a set of functions which can be overwritten by a sub struct
@@ -60,8 +59,7 @@ func NewAPCISequence(args Args, kwArgs KWArgs, opts ...func(*APCISequence)) (*AP
 	} else {
 		a._contract.(APCISequenceContractRequirement).SetAPCISequence(a)
 	}
-	apdu := GA[readWriteModel.APDU](args, 0) // TODO: might break but should be fine as we are a GA*
-	a._APCI = NewAPCI(apdu).(*_APCI)
+	a._APCI = NewAPCI(args, kwArgs).(*_APCI)
 	var err error
 	a.Sequence, err = NewSequence(args, kwArgs, WithSequenceExtension(a._contract))
 	if err != nil {
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go
index b319bb74864..b41a3f00798 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go
@@ -28,7 +28,6 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi"
@@ -43,43 +42,25 @@ type APDU interface {
 type __APDU struct {
 	*_APCI
 	PDUData
-
-	// post construct function
-	_postConstruct []func()
 }
 
 var _ APDU = (*__APDU)(nil)
 
-// TODO: optimize with options and smart non-recoding...
-func NewAPDU(apdu readWriteModel.APDU, opts ...func(*__APDU)) (APDU, error) {
-	a := &__APDU{}
-	for _, opt := range opts {
-		opt(a)
+func NewAPDU(args Args, kwArgs KWArgs) (APDU, error) {
+	if _debug != nil {
+		_debug("__init__ %r %r", args, kwArgs)
 	}
-	a._APCI = NewAPCI(apdu).(*_APCI)
-	a.PDUData = NewPDUData(NoArgs, NoKWArgs())
+	a := &__APDU{}
+	a._APCI = NewAPCI(args, kwArgs).(*_APCI)
+	a.PDUData = NewPDUData(args, kwArgs)
 	a.AddExtraPrinters(a.PDUData.(DebugContentPrinter))
-	// Do a post construct for a bit more easy initialization
-	for _, f := range a._postConstruct {
-		f()
-	}
-	a._postConstruct = nil
-	if a.GetRootMessage() != nil {
-		data, _ := a.GetRootMessage().Serialize()
-		a.SetPduData(data)
-	}
 	return a, nil
 }
 
-func WithAPDUUserData(userData spi.Message) func(*__APDU) {
-	return func(apdu *__APDU) {
-		apdu._postConstruct = append(apdu._postConstruct, func() {
-			apdu.SetPDUUserData(userData)
-		})
-	}
-}
-
 func (a *__APDU) Encode(pdu Arg) error {
+	if _debug != nil {
+		_debug("encode %s", pdu)
+	}
 	if err := a._APCI.Encode(pdu); err != nil {
 		return errors.Wrap(err, "error encoding APCI")
 	}
@@ -91,11 +72,16 @@ func (a *__APDU) Encode(pdu Arg) error {
 }
 
 func (a *__APDU) Decode(pdu Arg) error {
+	if _debug != nil {
+		_debug("decode %s", pdu)
+	}
 	var rootMessage spi.Message
 	switch pdu := pdu.(type) { // Save a root message as long as we have enough data
 	case PDUData:
 		data := pdu.GetPduData()
-		rootMessage, _ = readWriteModel.APDUParse[readWriteModel.APDU](context.Background(), data, uint16(len(data)))
+		rootMessage, _ = Try1(func() (readWriteModel.APDU, error) {
+			return readWriteModel.APDUParse[readWriteModel.APDU](context.Background(), data, uint16(len(data)))
+		})
 	}
 	switch pdu := pdu.(type) {
 	case IPCI:
@@ -147,10 +133,9 @@ func (a *__APDU) DeepCopy() any {
 }
 
 func (a *__APDU) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("APDU{%s}", a.PCI)
-	} else {
+	if IsDebuggingActive() {
 		pci := "\t" + strings.Join(strings.Split(a.PCI.String(), "\n"), "\n\t")
 		return fmt.Sprintf("<APDU instance at %p>\n%s\n\tpduData = x'%s'", a, pci, Btox(a.GetPduData(), "."))
 	}
+	return fmt.Sprintf("APDU{%s}", a.PCI)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go
index d81ef0b36c8..bffa3f078c1 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go
@@ -22,4 +22,10 @@ package apdu
 // TODO: implement it...
 type AbortPDU struct {
 	*___APDU
+
+	apduSrv any
+}
+
+func (a *AbortPDU) GetAPDUSrv() any {
+	panic("implement me")
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go
index 948b03a37b5..a8bd3b18551 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go
@@ -30,7 +30,6 @@ import (
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
-// TODO: implement it...
 type ConfirmedPrivateTransferRequest struct {
 	*ConfirmedRequestSequence
 
@@ -38,7 +37,7 @@ type ConfirmedPrivateTransferRequest struct {
 	sequenceElements []Element
 }
 
-func NewConfirmedPrivateTransferRequest(_ Args, _ KWArgs) (*ConfirmedPrivateTransferRequest, error) {
+func NewConfirmedPrivateTransferRequest(args Args, kwArgs KWArgs) (*ConfirmedPrivateTransferRequest, error) {
 	c := &ConfirmedPrivateTransferRequest{
 		serviceChoice: readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_PRIVATE_TRANSFER,
 		sequenceElements: []Element{
@@ -47,17 +46,16 @@ func NewConfirmedPrivateTransferRequest(_ Args, _ KWArgs) (*ConfirmedPrivateTran
 			NewElement("serviceParameters", Vs2E(NewAny), WithElementContext(2), WithElementOptional(true)),
 		},
 	}
-	var err error
-	c.ConfirmedRequestSequence, err = NewConfirmedRequestSequence(
-		readWriteModel.NewBACnetConfirmedServiceRequestConfirmedPrivateTransfer(
-			readWriteModel.CreateBACnetVendorIdContextTagged(0, 0),
-			readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0),
+	if _, ok := kwArgs[KWCompRootMessage]; !ok {
+		kwArgs[KWCompRootMessage] = readWriteModel.NewBACnetConfirmedServiceRequestConfirmedPrivateTransfer(
+			readWriteModel.CreateBACnetVendorIdContextTagged(0, 0),     // TODO: get right values
+			readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0), // TODO: get right values
 			nil,
 			0,
-		),
-		NoKWArgs(),
-		WithConfirmedRequestSequenceExtension(c),
-	)
+		)
+	}
+	var err error
+	c.ConfirmedRequestSequence, err = NewConfirmedRequestSequence(args, kwArgs, WithConfirmedRequestSequenceExtension(c))
 	if err != nil {
 		return nil, errors.Wrap(err, "error building confirmed request")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go
index 553d40f5773..29a98d9e259 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go
@@ -22,6 +22,7 @@ package apdu
 import (
 	"github.com/pkg/errors"
 
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
@@ -33,26 +34,32 @@ type ConfirmedRequestPDU struct {
 
 var _ readWriteModel.APDUConfirmedRequest = (*ConfirmedRequestPDU)(nil)
 
-func NewConfirmedRequestPDU(serviceRequest readWriteModel.BACnetConfirmedServiceRequest, opts ...func(*ConfirmedRequestPDU)) (*ConfirmedRequestPDU, error) {
-	u := &ConfirmedRequestPDU{
-		serviceRequest: serviceRequest,
+func NewConfirmedRequestPDU(args Args, kwArgs KWArgs) (*ConfirmedRequestPDU, error) {
+	c := &ConfirmedRequestPDU{}
+	choice, ok := KWO[*readWriteModel.BACnetConfirmedServiceChoice](kwArgs, KWConfirmedServiceChoice, nil)
+	if _debug != nil {
+		_debug("__init__ %r %r %r", choice, args, kwArgs)
 	}
-	for _, opt := range opts {
-		opt(u)
-	}
-	apdu, err := new_APDU(nil)
+	apdu, err := New_APDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating _APDU")
 	}
-	u.___APDU = apdu.(*___APDU)
-	if serviceRequest != nil {
-		serviceChoice := uint8(serviceRequest.GetServiceChoice())
-		u.apduService = &serviceChoice
+	c.___APDU = apdu.(*___APDU)
+	c.apduType = ToPtr(readWriteModel.ApduType_CONFIRMED_REQUEST_PDU)
+	if ok {
+		serviceChoice := uint8(*choice)
+		c.apduService = &serviceChoice
+	}
+	c.SetExpectingReply(true)
+	switch rm := c.GetRootMessage().(type) {
+	case readWriteModel.BACnetConfirmedServiceRequest:
+		c.serviceRequest = rm
+		serviceChoice := rm.GetServiceChoice()
+		c.apduService = ToPtr(uint8(serviceChoice))
 	}
-	u.SetExpectingReply(true)
-	u.SetRootMessage(u.buildConfirmedRequest(serviceRequest))
+	c.SetRootMessage(c.buildConfirmedRequest(c.serviceRequest))
 
-	return u, nil
+	return c, nil
 }
 
 func (c *ConfirmedRequestPDU) buildConfirmedRequest(serviceRequest readWriteModel.BACnetConfirmedServiceRequest) readWriteModel.APDUConfirmedRequest {
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go
index 6c6dc5096ba..2346bd16d77 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go
@@ -46,7 +46,7 @@ type ConfirmedRequestSequence struct {
 	_contract ConfirmedRequestSequenceContract
 }
 
-func NewConfirmedRequestSequence(serviceRequest /*TODO: breaks a bit the consistency, maybe we just convert it to args to be flexible*/ model.BACnetConfirmedServiceRequest, kwArgs KWArgs, opts ...func(*ConfirmedRequestSequence)) (*ConfirmedRequestSequence, error) {
+func NewConfirmedRequestSequence(args Args, kwArgs KWArgs, opts ...func(*ConfirmedRequestSequence)) (*ConfirmedRequestSequence, error) {
 	u := &ConfirmedRequestSequence{}
 	for _, opt := range opts {
 		opt(u)
@@ -57,16 +57,25 @@ func NewConfirmedRequestSequence(serviceRequest /*TODO: breaks a bit the consist
 		u._contract.(ConfirmedRequestSequenceContractRequirement).SetConfirmedRequestSequence(u)
 	}
 	var err error
-	u.APCISequence, err = NewAPCISequence(NA(model.NewAPDUConfirmedRequest(false, false, false, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS, model.MaxApduLengthAccepted_NUM_OCTETS_1476, 0, nil, nil, serviceRequest, nil, nil, 0)), kwArgs, WithAPCISequenceExtension(u._contract))
+	kwArgs[KWConfirmedServiceChoice] = u._contract.GetServiceChoice()
+	u.ConfirmedRequestPDU, err = NewConfirmedRequestPDU(args, kwArgs)
 	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APCISequence")
+		return nil, errors.Wrap(err, "error creating ConfirmedRequestPDU")
 	}
-	u.ConfirmedRequestPDU, err = NewConfirmedRequestPDU(serviceRequest)
+	u.APCISequence, err = NewAPCISequence(args, kwArgs, WithAPCISequenceExtension(u._contract))
 	if err != nil {
-		return nil, errors.Wrap(err, "error creating ConfirmedRequestPDU")
+		return nil, errors.Wrap(err, "error creating _APCISequence")
 	}
 	// We need to set the APCI to the same objects...
 	u.APCISequence._APCI = u.ConfirmedRequestPDU._APCI
+	if u.GetRootMessage() == nil {
+		panic("this should be set by NewConfirmedRequestPDU")
+		serviceRequest, _ := GAO[model.BACnetConfirmedServiceRequest](args, 0, nil)
+		if serviceRequest != nil {
+			apduConfirmedRequest := model.NewAPDUConfirmedRequest(false, false, false, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS, model.MaxApduLengthAccepted_NUM_OCTETS_1476, 0, nil, nil, serviceRequest, nil, nil, 0)
+			u.SetRootMessage(apduConfirmedRequest)
+		}
+	}
 	return u, nil
 }
 
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go
index 331186e003b..2e54198fdc2 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go
@@ -19,6 +19,41 @@
 
 package apdu
 
-// TODO: implement it...
+import (
+	"fmt"
+
+	"github.com/pkg/errors"
+
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/basetypes"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
+)
+
 type Error struct {
+	*ErrorSequence
+}
+
+func NewError(args Args, kwArgs KWArgs) (*Error, error) {
+	e := &Error{}
+	var err error
+	e.ErrorSequence, err = NewErrorSequence(args, kwArgs, WithErrorSequenceExtension(e))
+	if err != nil {
+		return e, errors.Wrap(err, "Error creating new ErrorSequence")
+	}
+	return e, nil
+}
+
+func (e *Error) SetErrorSequence(es *ErrorSequence) {
+	e.ErrorSequence = es
+}
+
+func (e *Error) GetSequenceElements() []Element {
+	errorType, _ := basetypes.NewErrorType(nil) // TODO: check if is meant to be like that
+	return errorType.GetSequenceElements()
+}
+
+func (e *Error) String() string {
+	errorClass, _ := e.GetAttr("errorClass")
+	errorCode, _ := e.GetAttr("errorCode")
+	return fmt.Sprintf("%s:%s", errorClass, errorCode)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go
index a83f15e7c1f..433a5c5b113 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go
@@ -19,7 +19,146 @@
 
 package apdu
 
-// TODO: implement it...
+import (
+	"github.com/pkg/errors"
+
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
 type ErrorPDU struct {
 	*___APDU
+
+	bacnetError readWriteModel.BACnetError
+}
+
+var _ readWriteModel.APDUError = (*ErrorPDU)(nil)
+
+func NewErrorPDU(args Args, kwArgs KWArgs) (*ErrorPDU, error) {
+	e := &ErrorPDU{}
+	choice, ok := KWO[*readWriteModel.BACnetConfirmedServiceChoice](kwArgs, KWConfirmedServiceChoice, nil)
+	invokeID, ok := KWO[*uint8](kwArgs, KWInvokedID, nil)
+	context, ok := KWO[APDU](kwArgs, KWContext, nil)
+	if _debug != nil {
+		_debug("__init__ %r %r %r %r %r", choice, invokeID, context, args, kwArgs)
+	}
+	apdu, err := New_APDU(args, kwArgs)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating _APDU")
+	}
+	e.___APDU = apdu.(*___APDU)
+	e.apduType = ToPtr(readWriteModel.ApduType_ERROR_PDU)
+	if ok {
+		serviceChoice := uint8(*choice)
+		e.apduService = &serviceChoice
+	}
+	e.apduInvokeID = invokeID
+
+	// use the context to fill in most of the fields
+	if context != nil {
+		e.apduService = context.getApduService()
+		e.SetContext(context)
+	}
+
+	switch rm := e.GetRootMessage().(type) {
+	case readWriteModel.BACnetError:
+		e.bacnetError = rm
+		serviceChoice := rm.GetErrorChoice()
+		e.apduService = ToPtr(uint8(serviceChoice))
+	}
+	e.SetRootMessage(e.buildConfirmedRequest(e.bacnetError))
+
+	return e, nil
+}
+
+func (e *ErrorPDU) buildConfirmedRequest(bacnetError readWriteModel.BACnetError) readWriteModel.APDUError {
+	if bacnetError == nil {
+		return nil
+	}
+	invokeID := uint8(0)
+	if e.apduInvokeID != nil {
+		invokeID = *e.apduInvokeID
+	}
+	return readWriteModel.NewAPDUError(
+		invokeID,
+		e.GetErrorChoice(),
+		e.bacnetError,
+		0,
+	)
+}
+
+func (e *ErrorPDU) GetSegmentedMessage() bool {
+	return e.apduSeg
+}
+
+func (e *ErrorPDU) GetMoreFollows() bool {
+	return e.apduMor
+}
+
+func (e *ErrorPDU) GetSegmentedResponseAccepted() bool {
+	return e.apduSA
+}
+
+func (e *ErrorPDU) GetMaxSegmentsAccepted() readWriteModel.MaxSegmentsAccepted {
+	if e.apduMaxSegs != nil {
+		return readWriteModel.MaxSegmentsAccepted(*e.apduMaxSegs)
+	}
+	return readWriteModel.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS
+}
+
+func (e *ErrorPDU) GetMaxApduLengthAccepted() readWriteModel.MaxApduLengthAccepted {
+	if e.apduMaxResp != nil {
+		return readWriteModel.MaxApduLengthAccepted(*e.apduMaxResp)
+	}
+	return readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476
+}
+
+func (e *ErrorPDU) GetInvokeId() uint8 {
+	if e.apduInvokeID != nil {
+		return *e.apduInvokeID
+	}
+	return 0
+}
+
+func (e *ErrorPDU) GetSequenceNumber() *uint8 {
+	return e.apduSeq
+}
+
+func (e *ErrorPDU) GetProposedWindowSize() *uint8 {
+	return e.apduWin
+}
+
+func (e *ErrorPDU) GetSegment() []byte {
+	return nil
+}
+
+func (e *ErrorPDU) GetApduHeaderReduction() uint16 {
+	return 0
+}
+
+func (e *ErrorPDU) GetSegmentReduction() uint16 {
+	return 0
+}
+
+func (e *ErrorPDU) GetOriginalInvokeId() uint8 {
+	invokeID := e.apduInvokeID
+	if invokeID != nil {
+		return *invokeID
+	}
+	return 0
+}
+
+func (e *ErrorPDU) GetErrorChoice() readWriteModel.BACnetConfirmedServiceChoice {
+	service := e.apduService
+	if service != nil {
+		return readWriteModel.BACnetConfirmedServiceChoice(*service)
+	}
+	return 0
+}
+
+func (e *ErrorPDU) GetError() readWriteModel.BACnetError {
+	return e.bacnetError
+}
+
+func (e *ErrorPDU) IsAPDUError() {
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go
index 0521ae9a165..2d09e95b341 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go
@@ -19,8 +19,76 @@
 
 package apdu
 
-// TODO: implement it...
+import (
+	"github.com/pkg/errors"
+
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+// ErrorSequenceContract provides a set of functions which can be overwritten by a sub struct
+type ErrorSequenceContract interface {
+	APCISequenceContractRequirement
+	GetErrorChoice() *model.BACnetConfirmedServiceChoice
+}
+
+// ErrorSequenceContractRequirement is needed when one want to extend using SequenceContract
+type ErrorSequenceContractRequirement interface {
+	ErrorSequenceContract
+	// SetErrorSequence 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....
+	SetErrorSequence(es *ErrorSequence)
+}
+
 type ErrorSequence struct {
 	*APCISequence
 	*ErrorPDU
+
+	_contract ErrorSequenceContract
+}
+
+func NewErrorSequence(args Args, kwArgs KWArgs, opts ...func(*ErrorSequence)) (*ErrorSequence, error) {
+	e := &ErrorSequence{}
+	for _, opt := range opts {
+		opt(e)
+	}
+	if e._contract == nil {
+		e._contract = e
+	} else {
+		e._contract.(ErrorSequenceContractRequirement).SetErrorSequence(e)
+	}
+	var err error
+	kwArgs[KWConfirmedServiceChoice] = e._contract.GetErrorChoice()
+	e.ErrorPDU, err = NewErrorPDU(args, kwArgs)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating ErrorPDU")
+	}
+	e.APCISequence, err = NewAPCISequence(args, kwArgs, WithAPCISequenceExtension(e._contract))
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating _APCISequence")
+	}
+	// We need to set the APCI to the same objects...
+	e.APCISequence._APCI = e.ErrorPDU._APCI
+	return e, nil
+}
+
+func WithErrorSequenceExtension(contract ErrorSequenceContractRequirement) func(*ErrorSequence) {
+	return func(a *ErrorSequence) {
+		a._contract = contract
+	}
+}
+
+func (u *ErrorSequence) SetAPCISequence(a *APCISequence) {
+	u.APCISequence = a
+}
+
+func (*ErrorSequence) GetErrorChoice() *model.BACnetConfirmedServiceChoice {
+	return nil
+}
+
+func (u *ErrorSequence) DeepCopy() any {
+	panic("implement me")
+}
+
+func (u *ErrorSequence) String() string {
+	return u.APCISequence.String()
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go
index 983d76e87bf..269d92133d3 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go
@@ -36,7 +36,7 @@ type IAmRequest struct {
 	sequenceElements []Element
 }
 
-func NewIAmRequest(_ Args, kwArgs KWArgs) (*IAmRequest, error) {
+func NewIAmRequest(args Args, kwArgs KWArgs) (*IAmRequest, error) {
 	w := &IAmRequest{
 		serviceChoice: readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS,
 		sequenceElements: []Element{
@@ -46,18 +46,17 @@ func NewIAmRequest(_ Args, kwArgs KWArgs) (*IAmRequest, error) {
 			NewElement("vendorID", V2E(NewUnsigned)),
 		},
 	}
-	var err error
-	w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(
-		readWriteModel.NewBACnetUnconfirmedServiceRequestIAm(
-			readWriteModel.CreateBACnetApplicationTagObjectIdentifier(0, 0),
-			readWriteModel.CreateBACnetApplicationTagUnsignedInteger(0),
-			readWriteModel.NewBACnetSegmentationTagged(readWriteModel.CreateBACnetTagHeaderBalanced(false, 0, 0), 0, 0, 0),
-			readWriteModel.CreateBACnetVendorIdApplicationTagged(0),
+	if _, ok := kwArgs[KWCompRootMessage]; !ok {
+		kwArgs[KWCompRootMessage] = readWriteModel.NewBACnetUnconfirmedServiceRequestIAm(
+			readWriteModel.CreateBACnetApplicationTagObjectIdentifier(0, 0),                                                // TODO: get right values
+			readWriteModel.CreateBACnetApplicationTagUnsignedInteger(0),                                                    // TODO: get right values
+			readWriteModel.NewBACnetSegmentationTagged(readWriteModel.CreateBACnetTagHeaderBalanced(false, 0, 0), 0, 0, 0), // TODO: get right values
+			readWriteModel.CreateBACnetVendorIdApplicationTagged(0),                                                        // TODO: get right values
 			0,
-		),
-		kwArgs,
-		WithUnconfirmedRequestSequenceExtension(w),
-	)
+		)
+	}
+	var err error
+	w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(args, kwArgs, WithUnconfirmedRequestSequenceExtension(w))
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating UnconfirmedRequestSequence")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go
index 3c5fac04763..eb913c61ff6 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go
@@ -23,3 +23,7 @@ package apdu
 type SegmentAckPDU struct {
 	*___APDU
 }
+
+func (s *SegmentAckPDU) GetServer() any {
+	panic("implement me")
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestPDU.go
index d6b09aa3890..16c834580a7 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestPDU.go
@@ -20,6 +20,9 @@
 package apdu
 
 import (
+	"github.com/pkg/errors"
+
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
@@ -31,23 +34,33 @@ type UnconfirmedRequestPDU struct {
 
 var _ readWriteModel.APDUUnconfirmedRequest = (*UnconfirmedRequestPDU)(nil)
 
-func NewUnconfirmedRequestPDU(serviceRequest readWriteModel.BACnetUnconfirmedServiceRequest, opts ...func(*UnconfirmedRequestPDU)) (*UnconfirmedRequestPDU, error) {
-	u := &UnconfirmedRequestPDU{
-		serviceRequest: serviceRequest,
+func NewUnconfirmedRequestPDU(args Args, kwArgs KWArgs) (*UnconfirmedRequestPDU, error) {
+	u := &UnconfirmedRequestPDU{}
+	choice, ok := KWO[*readWriteModel.BACnetUnconfirmedServiceChoice](kwArgs, KWUnconfirmedServiceChoice, nil)
+	if _debug != nil {
+		_debug("__init__ %r %r %r", choice, args, kwArgs)
 	}
-	for _, opt := range opts {
-		opt(u)
+	apdu, err := New_APDU(args, kwArgs)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating _APDU")
 	}
-	apdu, _ := new_APDU(buildUnconfirmedServiceRequest(serviceRequest))
 	u.___APDU = apdu.(*___APDU)
-	if serviceRequest != nil {
-		serviceChoice := uint8(serviceRequest.GetServiceChoice())
+	u.apduType = ToPtr(readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU)
+	if ok {
+		serviceChoice := uint8(*choice)
 		u.apduService = &serviceChoice
 	}
+	switch rm := u.GetRootMessage().(type) {
+	case readWriteModel.BACnetUnconfirmedServiceRequest:
+		u.serviceRequest = rm
+		serviceChoice := rm.GetServiceChoice()
+		u.apduService = ToPtr(uint8(serviceChoice))
+	}
+	u.SetRootMessage(u.buildUnconfirmedServiceRequest(u.serviceRequest))
 	return u, nil
 }
 
-func buildUnconfirmedServiceRequest(serviceRequest readWriteModel.BACnetUnconfirmedServiceRequest) readWriteModel.APDUUnconfirmedRequest {
+func (u *UnconfirmedRequestPDU) buildUnconfirmedServiceRequest(serviceRequest readWriteModel.BACnetUnconfirmedServiceRequest) readWriteModel.APDUUnconfirmedRequest {
 	if serviceRequest == nil {
 		return nil
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestSequence.go
index 557b63683f8..63eb0ba3396 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestSequence.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedRequestSequence.go
@@ -46,7 +46,7 @@ type UnconfirmedRequestSequence struct {
 	_contract UnconfirmedRequestSequenceContract
 }
 
-func NewUnconfirmedRequestSequence(serviceRequest /*TODO: breaks a bit the consistency, maybe we just convert it to args to be flexible*/ model.BACnetUnconfirmedServiceRequest, kwArgs KWArgs, opts ...func(*UnconfirmedRequestSequence)) (*UnconfirmedRequestSequence, error) {
+func NewUnconfirmedRequestSequence(args Args, kwArgs KWArgs, opts ...func(*UnconfirmedRequestSequence)) (*UnconfirmedRequestSequence, error) {
 	u := &UnconfirmedRequestSequence{}
 	for _, opt := range opts {
 		opt(u)
@@ -57,16 +57,25 @@ func NewUnconfirmedRequestSequence(serviceRequest /*TODO: breaks a bit the consi
 		u._contract.(UnconfirmedRequestSequenceContractRequirement).SetUnconfirmedRequestSequence(u)
 	}
 	var err error
-	u.APCISequence, err = NewAPCISequence(NA(model.NewAPDUUnconfirmedRequest(serviceRequest, 0)), kwArgs, WithAPCISequenceExtension(u._contract))
+	kwArgs[KWUnconfirmedServiceChoice] = u._contract.GetServiceChoice()
+	u.UnconfirmedRequestPDU, err = NewUnconfirmedRequestPDU(args, kwArgs)
 	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APCISequence")
+		return nil, errors.Wrap(err, "error creating UnconfirmedRequestPDU")
 	}
-	u.UnconfirmedRequestPDU, err = NewUnconfirmedRequestPDU(serviceRequest)
+	u.APCISequence, err = NewAPCISequence(args, kwArgs, WithAPCISequenceExtension(u._contract))
 	if err != nil {
-		return nil, errors.Wrap(err, "error creating UnconfirmedRequestPDU")
+		return nil, errors.Wrap(err, "error creating _APCISequence")
 	}
 	// We need to set the APCI to the same objects...
 	u.APCISequence._APCI = u.UnconfirmedRequestPDU._APCI
+	if u.GetRootMessage() == nil {
+		panic("this should be set by NewConfirmedRequestPDU")
+		serviceRequest, _ := GAO[model.BACnetConfirmedServiceRequest](args, 0, nil)
+		if serviceRequest != nil {
+			apduConfirmedRequest := model.NewAPDUConfirmedRequest(false, false, false, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS, model.MaxApduLengthAccepted_NUM_OCTETS_1476, 0, nil, nil, serviceRequest, nil, nil, 0)
+			u.SetRootMessage(apduConfirmedRequest)
+		}
+	}
 	return u, nil
 }
 
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_WhoIsRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_WhoIsRequest.go
index 2a2ac86e568..ed77da177cd 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_WhoIsRequest.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_WhoIsRequest.go
@@ -35,7 +35,9 @@ type WhoIsRequest struct {
 	sequenceElements []Element
 }
 
-func NewWhoIsRequest() (*WhoIsRequest, error) {
+var _ readWriteModel.APDUUnconfirmedRequest = (*WhoIsRequest)(nil)
+
+func NewWhoIsRequest(args Args, kwArgs KWArgs) (*WhoIsRequest, error) {
 	w := &WhoIsRequest{
 		serviceChoice: readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS,
 		sequenceElements: []Element{
@@ -43,20 +45,25 @@ func NewWhoIsRequest() (*WhoIsRequest, error) {
 			NewElement("deviceInstanceRangeHighLimit", V2E(NewUnsigned), WithElementContext(1), WithElementOptional(true)),
 		},
 	}
-	var err error
-	w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(
-		readWriteModel.NewBACnetUnconfirmedServiceRequestWhoIs(
-			readWriteModel.CreateBACnetContextTagUnsignedInteger(0, 0),
-			readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0),
+	if _, ok := kwArgs[KWCompRootMessage]; !ok {
+		kwArgs[KWCompRootMessage] = readWriteModel.NewBACnetUnconfirmedServiceRequestWhoIs(
+			readWriteModel.CreateBACnetContextTagUnsignedInteger(0, 0), // TODO: set the right values
+			readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0), // TODO: set the right values
 			0,
-		),
-		NoKWArgs(),
-		WithUnconfirmedRequestSequenceExtension(w),
-	)
+		)
+	}
+	var err error
+	w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(args, kwArgs, WithUnconfirmedRequestSequenceExtension(w))
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating UnconfirmedRequestSequence")
 	}
-
+	if w.GetRootMessage() == nil {
+		w.SetRootMessage(readWriteModel.NewBACnetUnconfirmedServiceRequestWhoIs(
+			readWriteModel.CreateBACnetContextTagUnsignedInteger(0, 0), // TODO: set the right values
+			readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0), // TODO: set the right values
+			0,
+		))
+	}
 	return w, nil
 }
 
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu__APDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu__APDU.go
index 4f23e7d3836..04c0fb3c669 100644
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu__APDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/apdu/apdu__APDU.go
@@ -26,9 +26,7 @@ import (
 	"github.com/pkg/errors"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
 // _APDU masks the Encode() and Decode() functions of the APDU
@@ -44,13 +42,10 @@ type ___APDU struct {
 
 var _ _APDU = (*___APDU)(nil)
 
-func new_APDU(rootMessage readWriteModel.APDU, opts ...func(*___APDU)) (_APDU, error) {
+func New_APDU(args Args, kwArgs KWArgs) (_APDU, error) {
 	i := &___APDU{}
-	for _, opt := range opts {
-		opt(i)
-	}
 	var err error
-	apdu, err := NewAPDU(rootMessage)
+	apdu, err := NewAPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating APDU")
 	}
@@ -59,8 +54,11 @@ func new_APDU(rootMessage readWriteModel.APDU, opts ...func(*___APDU)) (_APDU, e
 }
 
 func (a *___APDU) Encode(pdu Arg) error {
+	if _debug != nil {
+		_debug("encode %r", pdu)
+	}
 	switch pdu := pdu.(type) {
-	case APCI:
+	case PCI:
 		if err := pdu.Update(a); err != nil {
 			return errors.Wrap(err, "error updating PDU")
 		}
@@ -73,17 +71,37 @@ func (a *___APDU) Encode(pdu Arg) error {
 }
 
 func (a *___APDU) Decode(pdu Arg) error {
+	if _debug != nil {
+		_debug("decode %r", pdu)
+	}
 	if err := a._APCI.Update(pdu); err != nil {
 		return errors.Wrap(err, "error updating pdu")
 	}
-	a.SetPduData(pdu.(PDUData).GetPduData())
+	switch pdu := pdu.(type) {
+	case PDUData:
+		data, err := pdu.GetData(len(pdu.GetPduData()))
+		if err != nil {
+			return errors.Wrap(err, "error getting data")
+		}
+		a.SetPduData(data)
+	}
 	return nil
 }
 
-func (a *___APDU) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("_APDU{%s}", a.__APDU)
-	} else {
+func (a *___APDU) SetContext(context APDU) {
+	if _debug != nil {
+		_debug("set_context %r", context)
+	}
+	a.SetPDUUserData(context.GetPDUUserData())
+	a.SetPDUDestination(context.GetPDUSource())
+	a.SetExpectingReply(false)
+	a.SetNetworkPriority(context.GetNetworkPriority())
+	a.apduInvokeID = context.GetApduInvokeID()
+}
+
+func (a *___APDU) Format(s fmt.State, v rune) {
+	switch v {
+	case 'v', 's', 'r':
 		sname := fmt.Sprintf("%T", a)
 
 		// the type is the service
@@ -99,6 +117,6 @@ func (a *___APDU) String() string {
 			stype += ", " + strconv.Itoa(int(*a.apduInvokeID))
 		}
 		// put it together
-		return fmt.Sprintf("<%s(%s) instance at %p>", sname, stype, a)
+		_, _ = fmt.Fprintf(s, "<%s(%s) instance at %p>", sname, stype, a)
 	}
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/app/app.go b/plc4go/internal/bacnetip/bacgopes/app/app.go
index 2671d7d88d9..af091f03548 100644
--- a/plc4go/internal/bacnetip/bacgopes/app/app.go
+++ b/plc4go/internal/bacnetip/bacgopes/app/app.go
@@ -18,3 +18,7 @@
  */
 
 package app
+
+import "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
+
+var _debug = debugging.CreateDebugPrinter()
diff --git a/plc4go/internal/bacnetip/bacgopes/app/app_Application.go b/plc4go/internal/bacnetip/bacgopes/app/app_Application.go
index 629bf79215e..d86a8e8085f 100644
--- a/plc4go/internal/bacnetip/bacgopes/app/app_Application.go
+++ b/plc4go/internal/bacnetip/bacgopes/app/app_Application.go
@@ -26,7 +26,7 @@ import (
 	"github.com/rs/zerolog"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/apdu"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/appservice"
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/appservice"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/capability"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
@@ -48,7 +48,8 @@ type Application struct {
 	objectName       map[string]*LocalDeviceObject
 	objectIdentifier map[string]*LocalDeviceObject
 	localDevice      *LocalDeviceObject
-	deviceInfoCache  *DeviceInfoCache
+	localAddress     *Address
+	deviceInfoCache  *appservice.DeviceInfoCache
 	controllers      map[string]any
 	helpers          map[string]func(apdu APDU) error `ignore:"true"`
 
@@ -61,7 +62,7 @@ type Application struct {
 	log zerolog.Logger
 }
 
-func NewApplication(localLog zerolog.Logger, localDevice *LocalDeviceObject, opts ...func(*Application)) (*Application, error) {
+func NewApplication(localLog zerolog.Logger, opts ...func(*Application)) (*Application, error) {
 	a := &Application{
 		log:     localLog,
 		helpers: map[string]func(apdu APDU) error{},
@@ -70,10 +71,13 @@ func NewApplication(localLog zerolog.Logger, localDevice *LocalDeviceObject, opt
 		opt(a)
 	}
 	localLog.Debug().
-		Stringer("localDevice", localDevice).
+		Stringer("localDevice", a.localDevice).
 		Stringer("deviceInfoCache", a.deviceInfoCache).
 		Interface("aseID", a.argAseID).
 		Msg("NewApplication")
+	if _debug != nil {
+		_debug("__init__ %r %r deviceInfoCache=%r aseID=%r", a.localDevice, a.localAddress, a.deviceInfoCache, a.argAse)
+	}
 	var err error
 	a.ApplicationServiceElementContract, err = NewApplicationServiceElement(localLog, OptionalOption2(a.argAseID, a.argAse, WithApplicationServiceElementAseID))
 	if err != nil {
@@ -85,20 +89,18 @@ func NewApplication(localLog zerolog.Logger, localDevice *LocalDeviceObject, opt
 	a.objectIdentifier = map[string]*LocalDeviceObject{}
 
 	// keep track of the local device
-	if localDevice != nil {
-		a.localDevice = localDevice
-
+	if a.localDevice != nil {
 		// bind the device object to this application
-		localDevice.App = a
+		a.localDevice.App = a
 
 		// local objects by ID and name
-		a.objectName[localDevice.ObjectName] = localDevice
-		a.objectName[localDevice.ObjectIdentifier] = localDevice
+		a.objectName[a.localDevice.ObjectName] = a.localDevice
+		a.objectName[a.localDevice.ObjectIdentifier] = a.localDevice
 	}
 
 	// use the provided cache or make a default one
 	if a.deviceInfoCache == nil {
-		a.deviceInfoCache = NewDeviceInfoCache(localLog)
+		a.deviceInfoCache = appservice.NewDeviceInfoCache(localLog)
 	}
 
 	// controllers for managing confirmed requests as a client
@@ -112,6 +114,9 @@ func NewApplication(localLog zerolog.Logger, localDevice *LocalDeviceObject, opt
 	// if starting up is enabled, find all the startup functions
 	if !a._startupDisabled {
 		for fn := range a.CapabilityFunctions("startup") {
+			if _debug != nil {
+				_debug("    - startup fn: %t", fn != nil)
+			}
 			localLog.Debug().Interface("fn", fn).Msg("startup fn")
 			Deferred(fn, NoArgs, NoKWArgs())
 		}
@@ -119,6 +124,12 @@ func NewApplication(localLog zerolog.Logger, localDevice *LocalDeviceObject, opt
 	return a, nil
 }
 
+func WithApplicationLocalDeviceObject(localDevice *LocalDeviceObject) func(*Application) {
+	return func(a *Application) {
+		a.localDevice = localDevice
+	}
+}
+
 func WithApplicationAseID(aseID int, ase ApplicationServiceElement) func(*Application) {
 	return func(a *Application) {
 		a.argAseID = &aseID
@@ -126,19 +137,22 @@ func WithApplicationAseID(aseID int, ase ApplicationServiceElement) func(*Applic
 	}
 }
 
-func WithApplicationDeviceInfoCache(deviceInfoCache *DeviceInfoCache) func(*Application) {
+func WithApplicationDeviceInfoCache(deviceInfoCache *appservice.DeviceInfoCache) func(*Application) {
 	return func(a *Application) {
 		a.deviceInfoCache = deviceInfoCache
 	}
 }
 
-func (a *Application) GetDeviceInfoCache() *DeviceInfoCache {
+func (a *Application) GetDeviceInfoCache() *appservice.DeviceInfoCache {
 	return a.deviceInfoCache
 }
 
 // AddObject adds an object to the local collection
 func (a *Application) AddObject(obj *LocalDeviceObject) error {
 	a.log.Debug().Stringer("obj", obj).Msg("AddObject")
+	if _debug != nil {
+		_debug("add_object %r", obj)
+	}
 
 	// extract the object name and identifier
 	objectName := obj.ObjectName
@@ -176,6 +190,9 @@ func (a *Application) AddObject(obj *LocalDeviceObject) error {
 // DeleteObject deletes an object from the local collection
 func (a *Application) DeleteObject(obj *LocalDeviceObject) error {
 	a.log.Debug().Stringer("obj", obj).Msg("DeleteObject")
+	if _debug != nil {
+		_debug("delete_object %r", obj)
+	}
 
 	// extract the object name and identifier
 	objectName := obj.ObjectName
@@ -229,6 +246,9 @@ func (a *Application) IterObjects() []*LocalDeviceObject {
 //
 // TODO: match that with readWriteModel.BACnetServicesSupported
 func (a *Application) GetServicesSupported() []string {
+	if _debug != nil {
+		_debug("get_services_supported")
+	}
 	servicesSupported := make([]string, 0, len(a.helpers))
 	for key := range a.helpers {
 		servicesSupported = append(servicesSupported, key)
@@ -238,10 +258,13 @@ func (a *Application) GetServicesSupported() []string {
 
 func (a *Application) Request(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("Request")
-	pdu := GA[PDU](args, 0)
+	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("request %r", apdu)
+	}
 
 	// double-check the input is the right kind of APDU
-	switch pdu.GetRootMessage().(type) {
+	switch apdu.GetRootMessage().(type) {
 	case readWriteModel.APDUUnconfirmedRequest, readWriteModel.APDUConfirmedRequest:
 	default:
 		return errors.New("APDU expected")
@@ -252,6 +275,9 @@ func (a *Application) Request(args Args, kwArgs KWArgs) error {
 func (a *Application) Indication(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("Indication")
 	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("indication %r", apdu)
+	}
 
 	// get a helper function
 	helperName := fmt.Sprintf("Do_%T", apdu)
@@ -260,6 +286,9 @@ func (a *Application) Indication(args Args, kwArgs KWArgs) error {
 		Str("helperName", helperName).
 		Bool("helperFn", helperFn != nil).
 		Msg("working with helper")
+	if _debug != nil {
+		_debug("    - helperFn: %t", helperFn != nil)
+	}
 
 	// send back a reject for unrecognized services
 	if helperFn == nil {
@@ -271,10 +300,15 @@ func (a *Application) Indication(args Args, kwArgs KWArgs) error {
 
 	if err := helperFn(apdu); err != nil {
 		a.log.Debug().Err(err).Msg("err result")
-		panic("do it")
 		// TODO: do proper mapping
-		if err := a.Response(NA(NewPDU(NoArgs, NKW(KWCompRootMessage, readWriteModel.NewAPDUError(0, readWriteModel.BACnetConfirmedServiceChoice_CREATE_OBJECT, nil, 0)))), NoKWArgs()); err != nil {
-			return err
+		if _, ok := apdu.(readWriteModel.APDUConfirmedRequest); ok {
+			resp, err := NewError(NoArgs, NKW(KWErrorClass, "device", KWErrorCode, "operationalProblem", KWContext, apdu))
+			if err != nil {
+				return errors.Wrap(err, "error creating error")
+			}
+			if err := a.Response(NA(resp), NoKWArgs()); err != nil {
+				return errors.Wrap(err, "error sending response")
+			}
 		}
 	}
 
diff --git a/plc4go/internal/bacnetip/bacgopes/app/app_ApplicationIOController.go b/plc4go/internal/bacnetip/bacgopes/app/app_ApplicationIOController.go
index 1460c434c13..f0837030a29 100644
--- a/plc4go/internal/bacnetip/bacgopes/app/app_ApplicationIOController.go
+++ b/plc4go/internal/bacnetip/bacgopes/app/app_ApplicationIOController.go
@@ -23,7 +23,7 @@ import (
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
 
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/appservice"
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/appservice"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/iocb"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/local/device"
@@ -39,8 +39,8 @@ type ApplicationIOController struct {
 	queueByAddress map[string]*SieveQueue
 
 	// pass through args
-	argDeviceInfoCache *DeviceInfoCache `ignore:"true"`
-	argAseID           *int             `ignore:"true"`
+	argDeviceInfoCache *appservice.DeviceInfoCache `ignore:"true"`
+	argAseID           *int                        `ignore:"true"`
 
 	log zerolog.Logger
 }
@@ -59,7 +59,8 @@ func NewApplicationIOController(localLog zerolog.Logger, localDevice *LocalDevic
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating io controller")
 	}
-	a.Application, err = NewApplication(localLog, localDevice, func(application *Application) {
+	a.Application, err = NewApplication(localLog, func(application *Application) {
+		application.localDevice = localDevice
 		application.deviceInfoCache = a.argDeviceInfoCache
 		application.argAseID = a.argAseID
 	})
@@ -69,7 +70,7 @@ func NewApplicationIOController(localLog zerolog.Logger, localDevice *LocalDevic
 	return a, nil
 }
 
-func WithApplicationIOControllerDeviceInfoCache(deviceInfoCache *DeviceInfoCache) func(*ApplicationIOController) {
+func WithApplicationIOControllerDeviceInfoCache(deviceInfoCache *appservice.DeviceInfoCache) func(*ApplicationIOController) {
 	return func(a *ApplicationIOController) {
 		a.argDeviceInfoCache = deviceInfoCache
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/app/app_Application_plc4xgen.go b/plc4go/internal/bacnetip/bacgopes/app/app_Application_plc4xgen.go
index 66bc5097fcd..b7fbe1b10a0 100644
--- a/plc4go/internal/bacnetip/bacgopes/app/app_Application_plc4xgen.go
+++ b/plc4go/internal/bacnetip/bacgopes/app/app_Application_plc4xgen.go
@@ -117,11 +117,30 @@ func (d *Application) SerializeWithWriteBuffer(ctx context.Context, writeBuffer
 			}
 		}
 	}
-	if d.deviceInfoCache != nil {
+	if d.localAddress != nil {
 		{
-			_value := fmt.Sprintf("%v", d.deviceInfoCache)
+			_value := fmt.Sprintf("%v", d.localAddress)
 
-			if err := writeBuffer.WriteString("deviceInfoCache", uint32(len(_value)*8), _value); err != nil {
+			if err := writeBuffer.WriteString("localAddress", uint32(len(_value)*8), _value); err != nil {
+				return err
+			}
+		}
+	}
+
+	if d.deviceInfoCache != nil {
+		if serializableField, ok := any(d.deviceInfoCache).(utils.Serializable); ok {
+			if err := writeBuffer.PushContext("deviceInfoCache"); err != nil {
+				return err
+			}
+			if err := serializableField.SerializeWithWriteBuffer(ctx, writeBuffer); err != nil {
+				return err
+			}
+			if err := writeBuffer.PopContext("deviceInfoCache"); err != nil {
+				return err
+			}
+		} else {
+			stringValue := fmt.Sprintf("%v", d.deviceInfoCache)
+			if err := writeBuffer.WriteString("deviceInfoCache", uint32(len(stringValue)*8), stringValue); err != nil {
 				return err
 			}
 		}
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfo.go b/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfo.go
index f9b8e0e989b..1f34f5c8c41 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfo.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfo.go
@@ -24,6 +24,8 @@ import (
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
+// NOTE: needs to reside here otherwise there is a circular dependency
+
 //go:generate plc4xGenerator -type=DeviceInfo -prefix=app_
 type DeviceInfo struct {
 	DeviceIdentifier readWriteModel.BACnetTagPayloadObjectIdentifier
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfoCache.go b/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfoCache.go
index 553d1f58443..665f3ed6417 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfoCache.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/app_DeviceInfoCache.go
@@ -31,6 +31,8 @@ import (
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
+// NOTE: needs to reside here otherwise there is a circular dependency
+
 // DeviceInfoCacheKey caches by either Instance, PduSource of both
 type DeviceInfoCacheKey struct {
 	Instance  *uint32
@@ -58,6 +60,9 @@ type DeviceInfoCache struct {
 }
 
 func NewDeviceInfoCache(localLog zerolog.Logger) *DeviceInfoCache {
+	if _debug != nil {
+		_debug("__init__")
+	}
 	return &DeviceInfoCache{
 		cache: make(map[uint32]DeviceInfo),
 		log:   localLog,
@@ -66,6 +71,9 @@ func NewDeviceInfoCache(localLog zerolog.Logger) *DeviceInfoCache {
 
 // HasDeviceInfo Return true if cache has information about the device.
 func (d *DeviceInfoCache) HasDeviceInfo(key DeviceInfoCacheKey) bool {
+	if _debug != nil {
+		_debug("has_device_info %r", key)
+	}
 	_, ok := d.cache[key.HashKey()]
 	return ok
 }
@@ -73,6 +81,9 @@ func (d *DeviceInfoCache) HasDeviceInfo(key DeviceInfoCacheKey) bool {
 // IAmDeviceInfo Create a device information record based on the contents of an IAmRequest and put it in the cache.
 func (d *DeviceInfoCache) IAmDeviceInfo(iAm readWriteModel.BACnetUnconfirmedServiceRequestIAm, pduSource Address) {
 	d.log.Debug().Stringer("iAm", iAm).Msg("IAmDeviceInfo")
+	if _debug != nil {
+		_debug("iam_device_info %r", iAm)
+	}
 
 	deviceIdentifier := iAm.GetDeviceIdentifier()
 	// Get the device instance
@@ -106,10 +117,16 @@ func (d *DeviceInfoCache) IAmDeviceInfo(iAm readWriteModel.BACnetUnconfirmedServ
 // GetDeviceInfo gets a DeviceInfo from cache
 func (d *DeviceInfoCache) GetDeviceInfo(key DeviceInfoCacheKey) (DeviceInfo, bool) {
 	d.log.Debug().Stringer("key", key).Msg("GetDeviceInfo %s")
+	if _debug != nil {
+		_debug("get_device_info %r", key)
+	}
 
 	// get the info if it's there
 	deviceInfo, ok := d.cache[key.HashKey()]
 	d.log.Debug().Stringer("deviceInfo", &deviceInfo).Msg("deviceInfo")
+	if _debug != nil {
+		_debug("    - device_info: %r", deviceInfo)
+	}
 
 	return deviceInfo, ok
 }
@@ -120,16 +137,25 @@ func (d *DeviceInfoCache) GetDeviceInfo(key DeviceInfoCacheKey) (DeviceInfo, boo
 //	opportunity to update the database.
 func (d *DeviceInfoCache) UpdateDeviceInfo(deviceInfo DeviceInfo) {
 	d.log.Debug().Stringer("deviceInfo", &deviceInfo).Msg("UpdateDeviceInfo")
+	if _debug != nil {
+		_debug("update_device_info %r", deviceInfo)
+	}
 
 	// get the current key
 	cacheKey := deviceInfo._cacheKey
 	if cacheKey.Instance != nil && deviceInfo.DeviceIdentifier.GetInstanceNumber() != *cacheKey.Instance {
+		if _debug != nil {
+			_debug("    - device identifier updated")
+		}
 		instanceNumber := deviceInfo.DeviceIdentifier.GetInstanceNumber()
 		cacheKey.Instance = &instanceNumber
 		delete(d.cache, cacheKey.HashKey())
 		d.cache[DeviceInfoCacheKey{Instance: &instanceNumber}.HashKey()] = deviceInfo
 	}
 	if !deviceInfo.Address.Equals(cacheKey.PduSource) {
+		if _debug != nil {
+			_debug("    - device address updated")
+		}
 		cacheKey.PduSource = &deviceInfo.Address
 		delete(d.cache, cacheKey.HashKey())
 		d.cache[DeviceInfoCacheKey{PduSource: cacheKey.PduSource}.HashKey()] = deviceInfo
@@ -149,18 +175,31 @@ func (d *DeviceInfoCache) UpdateDeviceInfo(deviceInfo DeviceInfo) {
 //	machine.
 func (d *DeviceInfoCache) Acquire(key DeviceInfoCacheKey) (DeviceInfo, bool) {
 	d.log.Debug().Stringer("key", key).Msg("Acquire")
+	if _debug != nil {
+		_debug("acquire %r", key)
+	}
 
 	deviceInfo, ok := d.cache[key.HashKey()]
 	if ok {
+		if _debug != nil {
+			_debug("    - reference bump")
+		}
 		deviceInfo._refCount++
 		d.cache[key.HashKey()] = deviceInfo
 	}
 
+	if _debug != nil {
+		_debug("    - device_info: %r", deviceInfo)
+	}
+
 	return deviceInfo, ok
 }
 
 // Release This function is called by the segmentation state machine when it has finished with the device information.
 func (d *DeviceInfoCache) Release(deviceInfo DeviceInfo) error {
+	if _debug != nil {
+		_debug("release %r", deviceInfo)
+	}
 
 	//this information record might be used by more than one SSM
 	if deviceInfo._refCount == 0 {
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/appservice.go b/plc4go/internal/bacnetip/bacgopes/appservice/appservice.go
index dd5e44ba8a7..4cec12569f3 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/appservice.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/appservice.go
@@ -18,3 +18,7 @@
  */
 
 package appservice
+
+import . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
+
+var _debug = CreateDebugPrinter()
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ApplicationServiceAccessPoint.go b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ApplicationServiceAccessPoint.go
index 0969a5f86a3..743a696a7b8 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ApplicationServiceAccessPoint.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ApplicationServiceAccessPoint.go
@@ -20,12 +20,15 @@
 package appservice
 
 import (
+	"fmt"
+
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/apdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
@@ -34,6 +37,7 @@ import (
 type ApplicationServiceAccessPoint struct {
 	ApplicationServiceElementContract
 	ServiceAccessPointContract
+	*DefaultRFormatter `ignore:"true"`
 
 	// pass through args
 	argAseID        *int                       `ignore:"true"`
@@ -46,11 +50,15 @@ type ApplicationServiceAccessPoint struct {
 
 func NewApplicationServiceAccessPoint(localLog zerolog.Logger, opts ...func(*ApplicationServiceAccessPoint)) (*ApplicationServiceAccessPoint, error) {
 	a := &ApplicationServiceAccessPoint{
-		log: localLog,
+		DefaultRFormatter: NewDefaultRFormatter(),
+		log:               localLog,
 	}
 	for _, opt := range opts {
 		opt(a)
 	}
+	if _debug != nil {
+		_debug("__init__ aseID=%r sapID=%r", a.argAseID, a.argSapID)
+	}
 	var err error
 	a.ApplicationServiceElementContract, err = NewApplicationServiceElement(localLog, OptionalOption2(a.argAseID, a.argASEExtension, WithApplicationServiceElementAseID))
 	if err != nil {
@@ -80,6 +88,9 @@ func WithApplicationServiceAccessPointSapID(sapID int, sap ServiceAccessPoint) f
 func (a *ApplicationServiceAccessPoint) Indication(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("Indication")
 	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("indication %r", apdu)
+	}
 
 	switch _apdu := apdu.GetRootMessage().(type) {
 	case readWriteModel.APDUConfirmedRequest:
@@ -97,6 +108,9 @@ func (a *ApplicationServiceAccessPoint) Indication(args Args, kwArgs KWArgs) err
 		cr, ok := ConfirmedRequestTypes[apduService]
 		if !ok {
 			a.log.Debug().Stringer("apduService", apduService).Msg("unknown service type")
+			if _debug != nil {
+				_debug("    - no confirmed request decoder")
+			}
 			errorFound = errors.New("unrecognized service")
 		}
 
@@ -108,6 +122,9 @@ func (a *ApplicationServiceAccessPoint) Indication(args Args, kwArgs KWArgs) err
 				// TODO: add advanced error check for  reject and abort
 				panic("do it")
 				errorFound = err
+				if _debug != nil {
+					_debug("    - no decoding error")
+				}
 			}
 		}
 
@@ -159,15 +176,17 @@ func (a *ApplicationServiceAccessPoint) Indication(args Args, kwArgs KWArgs) err
 // TODO: big WIP
 func (a *ApplicationServiceAccessPoint) SapIndication(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("SapIndication")
-
 	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("sap_indication %r", apdu)
+	}
 
 	isConfirmed := false
 	var xpdu APDU
-	switch apdu.GetRootMessage().(type) {
+	switch apdu.(type) {
 	case readWriteModel.APDUConfirmedRequest:
 		var err error
-		xpdu, err = NewConfirmedRequestPDU(nil)
+		xpdu, err = NewConfirmedRequestPDU(Nothing())
 		if err != nil {
 			return errors.Wrap(err, "error creating unconfirmed request")
 		}
@@ -177,7 +196,7 @@ func (a *ApplicationServiceAccessPoint) SapIndication(args Args, kwArgs KWArgs)
 		isConfirmed = true
 	case readWriteModel.APDUUnconfirmedRequest:
 		var err error
-		xpdu, err = NewUnconfirmedRequestPDU(nil)
+		xpdu, err = NewUnconfirmedRequestPDU(Nothing())
 		if err != nil {
 			return errors.Wrap(err, "error creating unconfirmed request")
 		}
@@ -205,6 +224,10 @@ func (a *ApplicationServiceAccessPoint) SapIndication(args Args, kwArgs KWArgs)
 // TODO: big WIP
 func (a *ApplicationServiceAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("Confirmation")
+	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("confirmation %r", apdu)
+	}
 
 	// TODO: check if we need to check apdu here
 
@@ -215,8 +238,19 @@ func (a *ApplicationServiceAccessPoint) Confirmation(args Args, kwArgs KWArgs) e
 // TODO: big WIP
 func (a *ApplicationServiceAccessPoint) SapConfirmation(args Args, kwArgs KWArgs) error {
 	a.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("SapConfirmation")
+	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("sap_confirmation %r", apdu)
+	}
 
 	// TODO: check if we need to check apdu here
 
 	return a.Response(args, kwArgs)
 }
+
+func (a *ApplicationServiceAccessPoint) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", a), true
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ClientSSM.go b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ClientSSM.go
index 864e47aedf2..b87b8563c4a 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ClientSSM.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_ClientSSM.go
@@ -25,6 +25,7 @@ import (
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
 
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/apdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
@@ -43,6 +44,9 @@ func NewClientSSM(localLog zerolog.Logger, sap SSMSAPRequirements, pduAddress *A
 	c := &ClientSSM{
 		log: localLog,
 	}
+	if _debug != nil {
+		_debug("__init__ %s %r", sap, pduAddress)
+	}
 	ssm, err := NewSSM(localLog, struct {
 		SSMSAPRequirements
 		SSMProcessingRequirements
@@ -50,10 +54,13 @@ func NewClientSSM(localLog zerolog.Logger, sap SSMSAPRequirements, pduAddress *A
 	if err != nil {
 		return nil, err
 	}
-	// TODO: if deviceEntry is not there get it now...
-	if ssm.deviceInfo == nil {
-		// TODO: get entry for device, store it in inventory
+	// acquire the device info
+	if ssm.deviceInfo != nil {
+		if _debug != nil {
+			_debug("    - acquire device information")
+		}
 		localLog.Debug().Msg("Accquire device information")
+		c.ssmSAP.GetDeviceInfoCache().Acquire(c.deviceInfo._cacheKey)
 	}
 	c.SSM = ssm
 	return c, nil
@@ -95,7 +102,7 @@ func (c *ClientSSM) Request(args Args, kwArgs KWArgs) error {
 //	rolling
 func (c *ClientSSM) Indication(args Args, kwArgs KWArgs) error {
 	c.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("indication")
-	apdu := GA[PDU](args, 0)
+	apdu := GA[APDU](args, 0)
 	// make sure we're getting confirmed requests
 	var apduConfirmedRequest readWriteModel.APDUConfirmedRequest
 	if apduCasted, ok := apdu.GetRootMessage().(readWriteModel.APDUConfirmedRequest); !ok {
diff --git a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_StateMachineAccessPoint.go b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_StateMachineAccessPoint.go
index d0d4e717b54..eadb4e49022 100644
--- a/plc4go/internal/bacnetip/bacgopes/appservice/appservice_StateMachineAccessPoint.go
+++ b/plc4go/internal/bacnetip/bacgopes/appservice/appservice_StateMachineAccessPoint.go
@@ -20,12 +20,15 @@
 package appservice
 
 import (
+	"fmt"
+
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
 
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/apdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/local/device"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
@@ -35,6 +38,7 @@ import (
 type StateMachineAccessPoint struct {
 	ClientContract
 	ServiceAccessPointContract
+	*DefaultRFormatter `ignore:"true"`
 
 	localDevice           *LocalDeviceObject
 	deviceInfoCache       *DeviceInfoCache
@@ -61,6 +65,7 @@ type StateMachineAccessPoint struct {
 
 func NewStateMachineAccessPoint(localLog zerolog.Logger, localDevice *LocalDeviceObject, opts ...func(*StateMachineAccessPoint)) (*StateMachineAccessPoint, error) {
 	s := &StateMachineAccessPoint{
+		DefaultRFormatter: NewDefaultRFormatter(),
 		// save a reference to the device information cache
 		localDevice: localDevice,
 
@@ -94,14 +99,15 @@ func NewStateMachineAccessPoint(localLog zerolog.Logger, localDevice *LocalDevic
 	for _, opt := range opts {
 		opt(s)
 	}
-	if LogAppService {
-		s.log.Debug().
-			Stringer("localDevice", localDevice).
-			Stringer("deviceInfoCache", s.deviceInfoCache).
-			Interface("sapID", s.argSapID).
-			Interface("cid", s.argCid).
-			Msg("NewStateMachineAccessPoint")
+	if _debug != nil {
+		_debug("__init__ localDevice=%r deviceInfoCache=%r sap=%r cid=%r", localDevice, s.deviceInfoCache, s.argSap, s.argCid)
 	}
+	s.log.Debug().
+		Stringer("localDevice", localDevice).
+		Stringer("deviceInfoCache", s.deviceInfoCache).
+		Interface("sapID", s.argSapID).
+		Interface("cid", s.argCid).
+		Msg("NewStateMachineAccessPoint")
 	// basic initialization
 	var err error
 	s.ClientContract, err = NewClient(s.log, OptionalOption2(s.argCid, ToPtr[ClientRequirements](s), WithClientCID))
@@ -112,9 +118,6 @@ func NewStateMachineAccessPoint(localLog zerolog.Logger, localDevice *LocalDevic
 	if err != nil {
 		return nil, errors.Wrapf(err, "error building serviceAccessPoint for %d", s.argSapID)
 	}
-	if !LogAppService {
-		s.log = zerolog.Nop()
-	}
 	return s, nil
 }
 
@@ -139,6 +142,9 @@ func WithStateMachineAccessPointCid(cid int) func(*StateMachineAccessPoint) {
 
 // getNextInvokeId Called by clients to get an unused invoke ID
 func (s *StateMachineAccessPoint) getNextInvokeId(address Address) (uint8, error) {
+	if _debug != nil {
+		_debug("get_next_invoke_id")
+	}
 	s.log.Debug().Msg("getNextInvokeId")
 
 	initialID := s.nextInvokeId
@@ -188,42 +194,77 @@ func (s *StateMachineAccessPoint) GetDefaultMaximumApduLengthAccepted() readWrit
 // Confirmation Packets coming up the stack are APDU's
 func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error { // TODO: note we need a special method here as we don't contain src in the apdu
 	s.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("Confirmation")
-	apdu := GA[PDU](args, 0)
+	pdu := GA[PDU](args, 0)
+	if _debug != nil {
+		_debug("confirmation %r", pdu)
+	}
 
 	// check device communication control
 	switch s.dccEnableDisable {
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_ENABLE:
+		if _debug != nil {
+			_debug("    - communications enabled")
+		}
 		s.log.Debug().Msg("communications enabled")
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_DISABLE:
-		apduType := apdu.GetRootMessage().(interface {
+		apduType := pdu.GetRootMessage().(interface {
 			GetApduType() readWriteModel.ApduType
 		}).GetApduType()
 		switch {
 		case apduType == readWriteModel.ApduType_CONFIRMED_REQUEST_PDU &&
-			apdu.GetRootMessage().(readWriteModel.APDUConfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetConfirmedServiceChoice_DEVICE_COMMUNICATION_CONTROL:
+			pdu.GetRootMessage().(readWriteModel.APDUConfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetConfirmedServiceChoice_DEVICE_COMMUNICATION_CONTROL:
+			if _debug != nil {
+				_debug("    - continue with DCC request")
+			}
 			s.log.Debug().Msg("continue with DCC request")
 		case apduType == readWriteModel.ApduType_CONFIRMED_REQUEST_PDU &&
-			apdu.GetRootMessage().(readWriteModel.APDUConfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetConfirmedServiceChoice_REINITIALIZE_DEVICE:
+			pdu.GetRootMessage().(readWriteModel.APDUConfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetConfirmedServiceChoice_REINITIALIZE_DEVICE:
+			if _debug != nil {
+				_debug("    - continue with reinitialize device")
+			}
 			s.log.Debug().Msg("continue with reinitialize device")
 		case apduType == readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU &&
-			apdu.GetRootMessage().(readWriteModel.APDUUnconfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS:
+			pdu.GetRootMessage().(readWriteModel.APDUUnconfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS:
+			if _debug != nil {
+				_debug("    - continue with Who-Is")
+			}
 			s.log.Debug().Msg("continue with Who-Is")
 		default:
+			if _debug != nil {
+				_debug("    - not a Who-Is, dropped")
+			}
 			s.log.Debug().Msg("not a Who-Is, dropped")
 			return nil
 		}
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_DISABLE_INITIATION:
+		if _debug != nil {
+			_debug("    - initiation disabled")
+		}
 		s.log.Debug().Msg("initiation disabled")
 	}
 
-	var pduSource = apdu.GetPDUSource()
+	// make a more focused interpretation
+	atype := APDUTypes[pdu.(APDU).GetApduType()] // TODO: why are we suddenly assuming apdu now here...
+	if atype == nil {
+		s.log.Warn().Msgf("    - unknown apduType: %s", pdu.(APDU).GetApduType())
+		return nil
+	}
 
-	switch _apdu := apdu.GetRootMessage().(type) {
-	case readWriteModel.APDUConfirmedRequest:
+	// decode it
+	apdu := atype()
+	if err := apdu.Decode(pdu); err != nil {
+		return errors.Wrap(err, "apdu decode failed")
+	}
+	if _debug != nil {
+		_debug("    - apdu: %r", apdu)
+	}
+
+	switch apdu := apdu.(type) {
+	case *ConfirmedRequestPDU:
 		// Find duplicates of this request
 		var tr *ServerSSM
 		for _, serverTransactionElement := range s.serverTransactions {
-			if _apdu.GetInvokeId() == serverTransactionElement.invokeId && pduSource.Equals(serverTransactionElement.pduAddress) {
+			if apdu.GetInvokeId() == serverTransactionElement.invokeId && apdu.GetPDUSource().Equals(serverTransactionElement.pduAddress) {
 				tr = serverTransactionElement
 				break
 			}
@@ -231,7 +272,7 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		if tr == nil {
 			// build a server transaction
 			var err error
-			tr, err = NewServerSSM(s.log, s, pduSource)
+			tr, err = NewServerSSM(s.log, s, apdu.GetPDUSource())
 			if err != nil {
 				return errors.Wrap(err, "Error building server ssm")
 			}
@@ -242,7 +283,7 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		if err := tr.Indication(NA(apdu), NoKWArgs()); err != nil {
 			return errors.Wrap(err, "error runnning indication")
 		}
-	case readWriteModel.APDUUnconfirmedRequest:
+	case *UnconfirmedRequestPDU:
 		// deliver directly to the application
 		if err := s.SapRequest(NA(apdu), NoKWArgs()); err != nil {
 			s.log.Debug().Err(err).Msg("error sending request")
@@ -251,7 +292,7 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		// find the client transaction this is acking
 		var tr *ClientSSM
 		for _, _tr := range s.clientTransactions {
-			if _apdu.(interface{ GetOriginalInvokeId() uint8 }).GetOriginalInvokeId() == _tr.invokeId && pduSource.Equals(_tr.pduAddress) {
+			if apdu.(interface{ GetInvokeId() uint8 }).GetInvokeId() == _tr.invokeId && apdu.(interface{ GetPDUSource() *Address }).GetPDUSource().Equals(_tr.pduAddress) {
 				tr = _tr
 				break
 			}
@@ -265,12 +306,12 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		if err := tr.Confirmation(NA(apdu), NoKWArgs()); err != nil {
 			return errors.Wrap(err, "error running confirmation")
 		}
-	case readWriteModel.APDUAbort:
+	case *AbortPDU:
 		// find the transaction being aborted
-		if _apdu.GetServer() {
+		if apdu.GetAPDUSrv() != nil {
 			var tr *ClientSSM
 			for _, tr := range s.clientTransactions {
-				if apdu.(interface{ GetOriginalInvokeId() uint8 }).GetOriginalInvokeId() == tr.invokeId && pduSource.Equals(tr.pduAddress) {
+				if *apdu.GetApduInvokeID() == tr.invokeId && apdu.GetPDUSource().Equals(tr.pduAddress) {
 					break
 				}
 			}
@@ -286,7 +327,7 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		} else {
 			var tr *ServerSSM
 			for _, serverTransactionElement := range s.serverTransactions {
-				if _apdu.GetOriginalInvokeId() == serverTransactionElement.invokeId && pduSource.Equals(serverTransactionElement.pduAddress) {
+				if *apdu.GetApduInvokeID() == serverTransactionElement.invokeId && apdu.GetPDUSource().Equals(serverTransactionElement.pduAddress) {
 					tr = serverTransactionElement
 					break
 				}
@@ -301,12 +342,12 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 				return errors.Wrap(err, "error running indication")
 			}
 		}
-	case readWriteModel.APDUSegmentAck:
+	case *SegmentAckPDU:
 		// find the transaction being aborted
-		if _apdu.GetServer() {
+		if apdu.GetServer() != nil {
 			var tr *ClientSSM
 			for _, tr := range s.clientTransactions {
-				if apdu.(interface{ GetOriginalInvokeId() uint8 }).GetOriginalInvokeId() == tr.invokeId && pduSource.Equals(tr.pduAddress) {
+				if *apdu.GetApduInvokeID() == tr.invokeId && apdu.GetPDUSource().Equals(tr.pduAddress) {
 					break
 				}
 			}
@@ -322,7 +363,7 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 		} else {
 			var tr *ServerSSM
 			for _, serverTransactionElement := range s.serverTransactions {
-				if _apdu.GetOriginalInvokeId() == serverTransactionElement.invokeId && pduSource.Equals(serverTransactionElement.pduAddress) {
+				if *apdu.GetApduInvokeID() == serverTransactionElement.invokeId && apdu.GetPDUSource().Equals(serverTransactionElement.pduAddress) {
 					tr = serverTransactionElement
 					break
 				}
@@ -346,7 +387,10 @@ func (s *StateMachineAccessPoint) Confirmation(args Args, kwArgs KWArgs) error {
 // SapIndication This function is called when the application is requesting a new transaction as a client.
 func (s *StateMachineAccessPoint) SapIndication(args Args, kwArgs KWArgs) error {
 	s.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("SapIndication")
-	apdu := GA[PDU](args, 0)
+	apdu := GA[APDU](args, 0)
+	if _debug != nil {
+		_debug("sap_indication %r", apdu)
+	}
 
 	pduDestination := apdu.GetPDUDestination()
 
@@ -354,21 +398,36 @@ func (s *StateMachineAccessPoint) SapIndication(args Args, kwArgs KWArgs) error
 	switch s.dccEnableDisable {
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_ENABLE:
 		s.log.Debug().Msg("communications enabled")
+		if _debug != nil {
+			_debug("    - communications enabled")
+		}
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_DISABLE:
 		s.log.Debug().Msg("communications disabled")
+		if _debug != nil {
+			_debug("    - communications disabled")
+		}
 		return nil
 	case readWriteModel.BACnetConfirmedServiceRequestDeviceCommunicationControlEnableDisable_DISABLE_INITIATION:
+		if _debug != nil {
+			_debug("    - initiation disabled")
+		}
 		s.log.Debug().Msg("initiation disabled")
 		// TODO: this should be quarded
 		if apdu.GetRootMessage().(readWriteModel.APDU).GetApduType() == readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU && apdu.(readWriteModel.APDUUnconfirmedRequest).GetServiceRequest().GetServiceChoice() == readWriteModel.BACnetUnconfirmedServiceChoice_I_AM {
 			s.log.Debug().Msg("continue with I-Am")
+			if _debug != nil {
+				_debug("    - continue with I-Am")
+			}
 		} else {
 			s.log.Debug().Msg("not an I-Am")
+			if _debug != nil {
+				_debug("    - not an I-Am")
+			}
 			return nil
 		}
 	}
 
-	switch _apdu := apdu.GetRootMessage().(type) {
+	switch _apdu := apdu.(type) {
 	case readWriteModel.APDUUnconfirmedRequest:
 		// deliver to the device
 		if err := s.Request(NA(apdu), NoKWArgs()); err != nil {
@@ -392,6 +451,9 @@ func (s *StateMachineAccessPoint) SapIndication(args Args, kwArgs KWArgs) error
 		if err != nil {
 			return errors.Wrap(err, "error creating client ssm")
 		}
+		if _debug != nil {
+			_debug("    - client segmentation state machine: %r", tr)
+		}
 
 		// add it to our transactions to track it
 		s.clientTransactions = append(s.clientTransactions, tr)
@@ -413,6 +475,10 @@ func (s *StateMachineAccessPoint) SapIndication(args Args, kwArgs KWArgs) error
 func (s *StateMachineAccessPoint) SapConfirmation(args Args, kwArgs KWArgs) error {
 	s.log.Debug().Stringer("Args", args).Stringer("KWArgs", kwArgs).Msg("SapConfirmation")
 	apdu := GA[PDU](args, 0)
+	if _debug != nil {
+		_debug("sap_confirmation %r", apdu)
+	}
+
 	pduDestination := apdu.GetPDUDestination()
 	switch apdu.GetRootMessage().(type) {
 	case readWriteModel.APDUSimpleAck, readWriteModel.APDUComplexAck, readWriteModel.APDUError, readWriteModel.APDUReject:
@@ -487,3 +553,10 @@ func (s *StateMachineAccessPoint) RemoveServerTransaction(sssm *ServerSSM) {
 func (s *StateMachineAccessPoint) GetApplicationTimeout() uint {
 	return s.applicationTimeout
 }
+
+func (s *StateMachineAccessPoint) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", s), true
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Segmentation.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Segmentation.go
index ce6f3a6886a..3c8a420ca78 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Segmentation.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Segmentation.go
@@ -20,6 +20,8 @@
 package basetypes
 
 import (
+	"github.com/pkg/errors"
+
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
 )
@@ -32,12 +34,21 @@ type Segmentation struct {
 
 func NewSegmentation(arg Arg) (*Segmentation, error) {
 	s := &Segmentation{
-		enumerations: map[string]uint64{"segmentedBoth": 0,
+		enumerations: map[string]uint64{
+			"segmentedBoth":     0,
 			"segmentedTransmit": 1,
 			"segmentedReceive":  2,
 			"noSegmentation":    3,
 		},
 	}
-	panic("enumeratedimplementme")
+	var err error
+	args := NoArgs
+	if !IsNil(arg) {
+		args = append(args, arg)
+	}
+	s.Enumerated, err = NewEnumerated(args)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to create enumerated")
+	}
 	return s, nil
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLCI.go b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLCI.go
index b7e531b59db..5c1421a2b6e 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLCI.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLCI.go
@@ -54,7 +54,7 @@ type _BVLCI struct {
 	PCI
 	*DebugContents
 
-	requirements BVLCIRequirements
+	_requirements BVLCIRequirements
 
 	bvlciType     uint8
 	bvlciFunction uint8
@@ -66,18 +66,19 @@ type _BVLCI struct {
 
 var _ BVLCI = (*_BVLCI)(nil)
 
-func NewBVLCI(args Args, kwArgs KWArgs) BVLCI {
+func NewBVLCI(requirements BVLCIRequirements, args Args, kwArgs KWArgs) BVLCI {
 	if _debug != nil {
 		_debug("__init__ %r %r", args, kwArgs)
 	}
 	b := &_BVLCI{
-		bvlciType:    0x81,
-		requirements: KW[BVLCIRequirements](kwArgs, KWCompBVLCIRequirements),
+		_requirements: requirements,
+
+		bvlciType: 0x81,
 	}
 	b.DebugContents = NewDebugContents(b, "bvlciType", "bvlciFunction", "bvlciLength")
 	b.PCI = NewPCI(args, kwArgs)
 	b.AddExtraPrinters(b.PCI.(DebugContentPrinter))
-	if bvlc := KWO[readWriteModel.BVLC](kwArgs, KWCompRootMessage, nil); bvlc != nil {
+	if bvlc, ok := KWO[readWriteModel.BVLC](kwArgs, KWCompRootMessage, nil); ok {
 		b.bvlciFunction = bvlc.GetBvlcFunction()
 		b.bvlciLength = bvlc.GetLengthInBytes(context.Background())
 	}
@@ -126,8 +127,8 @@ func (b *_BVLCI) Encode(pdu Arg) error {
 		pdu.Put(b.bvlciType)
 		pdu.Put(b.bvlciFunction)
 
-		if int(b.bvlciLength) != len(b.requirements.GetPduData())+4 {
-			return errors.Errorf("invalid BVLCI length %d != %d", b.bvlciLength, len(b.requirements.GetPduData())+4)
+		if int(b.bvlciLength) != len(b._requirements.GetPduData())+4 {
+			return errors.Errorf("invalid BVLCI length %d != %d", b.bvlciLength, len(b._requirements.GetPduData())+4)
 		}
 
 		pdu.PutShort(b.bvlciLength)
diff --git a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLPDU.go b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLPDU.go
index 97e12e7b9bb..b96af069c51 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_BVLPDU.go
@@ -49,8 +49,7 @@ func NewBVLPDU(args Args, kwArgs KWArgs) BVLPDU {
 		_debug("__init__ %r %r", args, kwArgs)
 	}
 	b := &_BVLPDU{}
-	kwArgs[KWCompBVLCIRequirements] = b
-	b._BVLCI = NewBVLCI(args, kwArgs).(*_BVLCI)
+	b._BVLCI = NewBVLCI(b, args, kwArgs).(*_BVLCI)
 	b.PDUData = NewPDUData(args, kwArgs)
 	b.AddExtraPrinters(b.PDUData.(DebugContentPrinter))
 	if b.GetRootMessage() != nil {
diff --git a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_DistributeBroadcastToNetwork.go b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_DistributeBroadcastToNetwork.go
index e86e4ab0a4d..2ed4bcf05a9 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvll/bvll_DistributeBroadcastToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvll/bvll_DistributeBroadcastToNetwork.go
@@ -54,6 +54,7 @@ func (d *DistributeBroadcastToNetwork) produceInnerNPDU(inNpdu readWriteModel.NP
 }
 
 func (d *DistributeBroadcastToNetwork) Encode(bvlpdu Arg) error {
+	d.bvlciLength = uint16(4 + len(d.GetPduData()))
 	switch bvlpdu := bvlpdu.(type) {
 	case BVLCI:
 		if err := bvlpdu.getBVLCI().Update(d); err != nil {
@@ -83,7 +84,11 @@ func (d *DistributeBroadcastToNetwork) Decode(bvlpdu Arg) error {
 	}
 	switch bvlpdu := bvlpdu.(type) {
 	case PDUData:
-		d.SetPduData(bvlpdu.GetPduData())
+		data, err := bvlpdu.GetData(len(bvlpdu.GetPduData()))
+		if err != nil {
+			return errors.Wrap(err, "error getting data")
+		}
+		d.SetPduData(data)
 	}
 	return nil
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_AnnexJCodec.go b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_AnnexJCodec.go
index 03c2730fca6..35756f72b60 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_AnnexJCodec.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_AnnexJCodec.go
@@ -32,9 +32,9 @@ import (
 
 //go:generate plc4xGenerator -type=AnnexJCodec -prefix=bvllservice_
 type AnnexJCodec struct {
-	*DefaultRFormatter `ignore:"true"`
 	ClientContract
 	ServerContract
+	*DefaultRFormatter `ignore:"true"`
 
 	// pass through args
 	argCid *int `ignore:"true"`
diff --git a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPForeign.go b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPForeign.go
index a1497aa1407..1515064f4ec 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPForeign.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPForeign.go
@@ -185,7 +185,7 @@ func (b *BIPForeign) Indication(args Args, kwArgs KWArgs) error {
 		}
 
 		// make an original broadcast _PDU
-		xpdu, err := NewOriginalBroadcastNPDU(NA(pdu), NKW(KWCPCIDestination, b.bbmdAddress, KWCPCIUserData, pdu.GetPDUUserData()))
+		xpdu, err := NewDistributeBroadcastToNetwork(NA(pdu), NKW(KWCPCIDestination, b.bbmdAddress, KWCPCIUserData, pdu.GetPDUUserData()))
 		if err != nil {
 			return errors.Wrap(err, "error creating original unicast NPDU")
 		}
diff --git a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSAP.go b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSAP.go
index cdc8d668ccc..2866b2a51e7 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSAP.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSAP.go
@@ -37,8 +37,9 @@ type BIPSAPRequirements interface {
 }
 
 type BIPSAP struct {
-	*DefaultRFormatter `ignore:"true"`
 	ServiceAccessPointContract
+	*DefaultRFormatter `ignore:"true"`
+
 	requirements BIPSAPRequirements
 
 	// pass through args
diff --git a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSimple.go b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSimple.go
index 983797af25f..ed1e6256b53 100644
--- a/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSimple.go
+++ b/plc4go/internal/bacnetip/bacgopes/bvllservice/bvllservice_BIPSimple.go
@@ -26,6 +26,7 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/bvll"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
@@ -35,6 +36,7 @@ type BIPSimple struct {
 	*BIPSAP
 	ClientContract
 	ServerContract
+	*debugging.DefaultRFormatter `ignore:"true"`
 
 	// pass through args
 	argSapID *int `ignore:"true"`
@@ -46,7 +48,8 @@ type BIPSimple struct {
 
 func NewBIPSimple(localLog zerolog.Logger, opts ...func(simple *BIPSimple)) (*BIPSimple, error) {
 	b := &BIPSimple{
-		log: localLog,
+		DefaultRFormatter: debugging.NewDefaultRFormatter(),
+		log:               localLog,
 	}
 	for _, opt := range opts {
 		opt(b)
diff --git a/plc4go/internal/bacnetip/bacgopes/comm/comm_PDU.go b/plc4go/internal/bacnetip/bacgopes/comm/comm_PDU.go
index 10309b15375..be2adf123c3 100644
--- a/plc4go/internal/bacnetip/bacgopes/comm/comm_PDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/comm/comm_PDU.go
@@ -23,7 +23,7 @@ import (
 	"fmt"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	"github.com/apache/plc4x/plc4go/spi"
 )
@@ -47,9 +47,9 @@ func NewCPDU(data any, kwArgs KWArgs) CPDU {
 	}
 
 	// pick up some optional kwArgs
-	userData := KWO[spi.Message](kwArgs, KWCPCIUserData, nil)
-	source := KWO[*Address](kwArgs, KWCPCISource, nil)
-	destination := KWO[*Address](kwArgs, KWCPCIDestination, nil)
+	userData, _ := KWO[spi.Message](kwArgs, KWCPCIUserData, nil)
+	source, _ := KWO[*Address](kwArgs, KWCPCISource, nil)
+	destination, _ := KWO[*Address](kwArgs, KWCPCIDestination, nil)
 
 	// carry source and destination from another PDU
 	// so this can act like a copy constructor
@@ -82,8 +82,8 @@ func (p *_PDU) GetName() string {
 }
 
 func (p *_PDU) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("_PDU{%s}", p.PCI)
+	if debugging.IsDebuggingActive() {
+		return fmt.Sprintf("<%T %s -> %s : %s>", p, p.GetPDUSource(), p.GetPDUDestination(), p.PDUData)
 	}
-	return fmt.Sprintf("<%T %s -> %s : %s>", p, p.GetPDUSource(), p.GetPDUDestination(), p.PDUData)
+	return fmt.Sprintf("_PDU{%s}", p.PCI)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/comm/comm_bind.go b/plc4go/internal/bacnetip/bacgopes/comm/comm_bind.go
index 8ce110c3d10..04231fa0a75 100644
--- a/plc4go/internal/bacnetip/bacgopes/comm/comm_bind.go
+++ b/plc4go/internal/bacnetip/bacgopes/comm/comm_bind.go
@@ -139,10 +139,10 @@ func Bind(localLog zerolog.Logger, args ...any) error {
 				Msg("cast states")
 			return errors.New("Bind() requires a client and a server")
 		}
+		if _debug != nil {
+			_debug("    - bound")
+		}
+		localLog.Trace().Msg("bound")
 	}
-	if _debug != nil {
-		_debug("    - bound")
-	}
-	localLog.Trace().Msg("bound")
 	return nil
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/comp/comp.go b/plc4go/internal/bacnetip/bacgopes/comp/comp.go
index fdebc1ffe6d..e3bd05410c7 100644
--- a/plc4go/internal/bacnetip/bacgopes/comp/comp.go
+++ b/plc4go/internal/bacnetip/bacgopes/comp/comp.go
@@ -79,18 +79,25 @@ func GAO[T any](args Args, index int, defaultValue T) (T, bool) {
 
 func (a Args) Format(s fmt.State, verb rune) {
 	switch verb {
-	case 's', 'v', 'r':
+	case 'r':
+		_, _ = fmt.Fprintf(s, "(%s)", a.string(false, false)[1:len(a.string(false, false))-1])
+	case 's', 'v':
 		_, _ = fmt.Fprintf(s, "(%s)", a.String()[1:len(a.String())-1])
 	}
 }
 
 func (a Args) String() string {
+	return a.string(true, true)
+}
+func (a Args) string(printIndex bool, printType bool) string {
 	r := ""
 	for i, ea := range a {
 		eat := fmt.Sprintf("%T", ea)
 		switch tea := ea.(type) {
 		case []byte:
 			ea = Btox(tea, ".")
+		case string:
+			ea = "'" + tea + "'"
 		case fmt.Stringer:
 			if !IsNil(tea) {
 				teaString := tea.String()
@@ -100,7 +107,14 @@ func (a Args) String() string {
 				}
 			}
 		}
-		r += fmt.Sprintf("%d: %v (%s), ", i, ea, eat)
+		if printIndex {
+			r += fmt.Sprintf("%d: ", i)
+		}
+		r += fmt.Sprintf("%v", ea)
+		if printType {
+			r += fmt.Sprintf(" (%s)", eat)
+		}
+		r += ", "
 	}
 	if r != "" {
 		r = r[:len(r)-2]
@@ -141,7 +155,7 @@ func (k KWArgs) String() string {
 	r := ""
 	for kk, ea := range k {
 		switch kk {
-		case KWCompRootMessage, KWCompBVLCIRequirements:
+		case KWCompRootMessage:
 			// TODO: figure out if we want to control that for the %r above and do something different here
 			continue
 		}
@@ -149,6 +163,9 @@ func (k KWArgs) String() string {
 		case []byte:
 			ea = Btox(tea, ".")
 		}
+		if IsNil(ea) {
+			ea = fmt.Sprintf("<nil>(%T)", ea)
+		}
 		r += fmt.Sprintf("'%s'=%v, ", kk, ea)
 	}
 	if r != "" {
@@ -163,20 +180,22 @@ func KW[T any](kwArgs KWArgs, key KnownKey) T {
 	if !ok {
 		panic(fmt.Sprintf("key %v not found in kwArgs", key))
 	}
+	delete(kwArgs, key) // usually that means this argument was consumed so we get rid of it
 	return r.(T)
 }
 
 // KWO gets a value from KWArgs and if not present returns the supplied default value
-func KWO[T any](kwArgs KWArgs, key KnownKey, defaultValue T) T {
+func KWO[T any](kwArgs KWArgs, key KnownKey, defaultValue T) (T, bool) {
 	r, ok := kwArgs[key]
 	if !ok {
-		return defaultValue
+		return defaultValue, false
 	}
 	v, ok := r.(T)
 	if !ok {
-		return defaultValue
+		return defaultValue, false
 	}
-	return v
+	delete(kwArgs, key) // usually that means this argument was consumed so we get rid of it
+	return v, true
 }
 
 type KnownKey string
@@ -234,11 +253,22 @@ const (
 	KWBvlciTimeToLive = KnownKey("bvlciTimeToLive")
 	KWBvlciFDT        = KnownKey("bvlciFDT")
 
+	////
+	// APDU keys
+
+	KWConfirmedServiceChoice   = KnownKey("choice")
+	KWUnconfirmedServiceChoice = KnownKey("choice")
+	KWErrorClass               = KnownKey("errorClass")
+	KWErrorCode                = KnownKey("errorCode")
+	KWContext                  = KnownKey("context")
+	KWInvokedID                = KnownKey("invokeID")
+
 	////
 	// Compability layer keys
 
-	KWCompRootMessage       = KnownKey("compRootMessage")
-	KWCompBVLCIRequirements = KnownKey("compBVLCIRequirements")
+	KWCompRootMessage = KnownKey("compRootMessage")
+	KWCompNLM         = KnownKey("compNLM")
+	KWCompAPDU        = KnownKey("compAPDU")
 )
 
 // Nothing give NoArgs and NoKWArgs()
@@ -473,7 +503,7 @@ func Try1[T any](f func() (T, error)) (v T, err error) {
 	return f()
 }
 
-// IsNil when nil checks aren'T enough
+// IsNil when nil checks aren't enough
 func IsNil(v interface{}) bool {
 	if v == nil {
 		return true
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
index 277449e6df7..9fd3caef0d4 100644
--- a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
@@ -20,15 +20,12 @@
 package constructeddata
 
 import (
-	"reflect"
-
-	"github.com/pkg/errors"
-
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 )
 
+var _debug = CreateDebugPrinter()
+
 var _sequenceOfClasses map[any]struct{}
 var _listOfClasses map[any]struct{}
 
@@ -37,19 +34,6 @@ func init() {
 	_listOfClasses = make(map[any]struct{})
 }
 
-type Element interface {
-	GetName() string
-	GetKlass() func(Args, KWArgs) (ElementKlass, error)
-	GetContext() *int
-	IsOptional() bool
-	Encode(tagList Arg) error
-}
-
-type ElementKlass interface {
-	Encode(Arg) error
-	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) {
@@ -70,334 +54,6 @@ func Vs2E[T any](b func(args Args) (*T, error)) func(Args, KWArgs) (ElementKlass
 	}
 }
 
-// TODO: finish
-type _Element struct {
-	Name     string
-	Klass    func(Args, KWArgs) (ElementKlass, error)
-	Context  *int
-	Optional bool
-}
-
-func NewElement(name string, klass func(Args, KWArgs) (ElementKlass, error), opts ...func(*_Element)) Element {
-	e := &_Element{
-		Name:  name,
-		Klass: klass,
-	}
-	for _, opt := range opts {
-		opt(e)
-	}
-	return e
-}
-
-var _ Element = (*_Element)(nil)
-
-func WithElementOptional(optional bool) func(*_Element) {
-	return func(e *_Element) {
-		e.Optional = optional
-	}
-}
-
-func WithElementContext(context int) func(*_Element) {
-	return func(e *_Element) {
-		e.Context = &context
-	}
-}
-
-func (e *_Element) GetName() string {
-	return e.Name
-}
-
-func (e *_Element) GetKlass() func(Args, KWArgs) (ElementKlass, error) {
-	return e.Klass
-}
-
-func (e *_Element) GetContext() *int {
-	return e.Context
-}
-
-func (e *_Element) IsOptional() bool {
-	return e.Optional
-}
-
-func (e *_Element) Encode(tagList Arg) error {
-	//TODO implement me
-	panic("implement me")
-}
-
-// SequenceContract provides a set of functions which can be overwritten by a sub struct
-type SequenceContract interface {
-	GetSequenceElements() []Element
-}
-
-// SequenceContractRequirement is needed when one want to extend using SequenceContract
-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(s *Sequence)
-}
-
-// TODO: finish
-type Sequence struct {
-	_contract        SequenceContract
-	sequenceElements []Element
-	attr             map[string]any
-}
-
-// NewSequence Create a sequence element, optionally providing attribute/property values.
-func NewSequence(args Args, kwArgs KWArgs, opts ...func(*Sequence)) (*Sequence, error) {
-	s := &Sequence{
-		attr: make(map[string]any),
-	}
-	for _, opt := range opts {
-		opt(s)
-	}
-	if s._contract == nil {
-		s._contract = s
-	} else {
-		s._contract.(SequenceContractRequirement).SetSequence(s)
-	}
-
-	var myKWArgs = make(KWArgs)
-	var otherKWArgs = make(KWArgs)
-	for _, element := range s._contract.GetSequenceElements() {
-		if a, ok := kwArgs[KnownKey(element.GetName())]; ok {
-			myKWArgs[KnownKey(element.GetName())] = a
-		}
-	}
-	for key, a := range kwArgs {
-		if _, ok := myKWArgs[key]; !ok {
-			otherKWArgs[key] = a
-		}
-	}
-
-	if len(otherKWArgs) > 0 {
-		return nil, errors.Errorf("invalid arguments %v", otherKWArgs)
-	}
-
-	// set the attribute/property values for the ones provided
-	for _, element := range s._contract.GetSequenceElements() {
-		a, ok := myKWArgs[KnownKey(element.GetName())]
-		if ok {
-			s.attr[element.GetName()] = a
-		}
-	}
-	return s, nil
-}
-
-func WithSequenceExtension(contract SequenceContractRequirement) func(*Sequence) {
-	return func(s *Sequence) {
-		s._contract = contract
-	}
-}
-
-func (a *Sequence) GetSequenceElements() []Element {
-	return a.sequenceElements
-}
-
-func (a *Sequence) Encode(arg Arg) error {
-	tagList, ok := arg.(*TagList)
-	if !ok {
-		return errors.New("arg is not a TagList")
-	}
-
-	for _, element := range a._contract.GetSequenceElements() {
-		value, ok := a.attr[element.GetName()]
-		if element.IsOptional() && !ok {
-			continue
-		}
-		if !element.IsOptional() && !ok {
-			return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
-		}
-		elementKlass, err := element.GetKlass()(Nothing())
-		if err != nil {
-			return errors.New("can't get zero object")
-		}
-		_, elementInSequenceOfClasses := _sequenceOfClasses[elementKlass]
-		_, elementInListOfClasses := _listOfClasses[elementKlass]
-		isAtomic := false
-		switch elementKlass.(type) {
-		case IsAtomic, IsAnyAtomic:
-			isAtomic = true
-		}
-		isValue := reflect.TypeOf(value) == reflect.TypeOf(elementKlass)
-
-		if elementInSequenceOfClasses || elementInListOfClasses {
-			// might need to encode an opening tag
-			if element.GetContext() != nil {
-				openingTag, err := NewOpeningTag(*element.GetContext())
-				if err != nil {
-					return errors.Wrap(err, "error creating opening tag")
-				}
-				tagList.Append(openingTag)
-			}
-
-			helper, err := element.GetKlass()(NA(value), NoKWArgs())
-			if err != nil {
-				return errors.Wrap(err, "error klass element")
-			}
-
-			// encode the value
-			if err := helper.Encode(tagList); err != nil {
-				return errors.Wrap(err, "error encoding tag list")
-			}
-
-			// might need to encode a closing tag
-			if element.GetContext() != nil {
-				closingTag, err := NewClosingTag(*element.GetContext())
-				if err != nil {
-					return errors.Wrap(err, "error creating closing tag")
-				}
-				tagList.Append(closingTag)
-			}
-		} else if isAtomic {
-			helper, err := element.GetKlass()(NA(value), NoKWArgs())
-			if err != nil {
-				return errors.Wrap(err, "error klass element")
-			}
-
-			// build a tag and encode the data into it
-			tag, err := NewTag(nil)
-			if err != nil {
-				return errors.Wrap(err, "error creating tag")
-			}
-			// encode the value
-			if err := helper.Encode(tag); err != nil {
-				return errors.Wrap(err, "error encoding tag list")
-			}
-
-			// convert it to context encoding if necessary
-			if element.GetContext() != nil {
-				tag, err = tag.AppToContext(uint(*element.GetContext()))
-				if err != nil {
-					return errors.Wrap(err, "error converting tag to context")
-				}
-			}
-			tagList.Append(tag)
-		} else if isValue {
-			// might need to encode an opening tag
-			if element.GetContext() != nil {
-				openingTag, err := NewOpeningTag(*element.GetContext())
-				if err != nil {
-					return errors.Wrap(err, "error creating opening tag")
-				}
-				tagList.Append(openingTag)
-			}
-
-			// encode the tag
-			if err := value.(interface{ Encode(Arg) error }).Encode(tagList); err != nil { // TODO: ugly case, need a encode interface soon
-				return errors.Wrap(err, "error encoding tag list")
-			}
-
-			// might need to encode a closing tag
-			if element.GetContext() != nil {
-				closingTag, err := NewClosingTag(*element.GetContext())
-				if err != nil {
-					return errors.Wrap(err, "error creating closing tag")
-				}
-				tagList.Append(closingTag)
-			}
-		}
-	}
-	return nil
-}
-
-func (a *Sequence) Decode(arg Arg) error {
-	tagList, ok := arg.(*TagList)
-	if !ok {
-		return errors.New("arg is not a TagList")
-	}
-
-	for _, element := range a._contract.GetSequenceElements() {
-		tag := tagList.Peek()
-
-		elementKlass, err := element.GetKlass()(Nothing())
-		if err != nil {
-			return errors.New("can't get zero object")
-		}
-		_, elementInSequenceOfClasses := _sequenceOfClasses[elementKlass]
-		_, elementInListOfClasses := _listOfClasses[elementKlass]
-		isAtomic := false
-		isAnyAtomic := false
-		switch elementKlass.(type) {
-		case IsAtomic:
-			isAtomic = true
-		case IsAnyAtomic:
-			isAnyAtomic = true
-		}
-		// no more elements
-		if tag == nil {
-			if element.IsOptional() {
-				// ommited optional element
-				a.attr[element.GetName()] = nil
-			} else if elementInSequenceOfClasses || elementInListOfClasses {
-				// empty list
-				//a.attr[element.GetName()] = nil // TODO: what to do???
-			} else {
-				return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
-			}
-		} else if tag.GetTagClass() == TagClosingTagClass {
-			if !element.IsOptional() {
-				return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
-			}
-
-			// ommited optional element
-			// a.attr[element.GetName()] = nil // TODO: don't set it for now as we use _,ok:=
-		} else if elementInSequenceOfClasses {
-			// check for context encoding
-			panic("finish me") // TODO: finish me
-		} else if isAnyAtomic {
-			// convert it to application encoding
-			panic("finish me") // TODO: finish me
-		} else if isAtomic {
-			// convert it to application encoding
-			if context := element.GetContext(); context != nil {
-				if tag.GetTagClass() != readWriteModel.TagClass_CONTEXT_SPECIFIC_TAGS && tag.GetTagNumber() != uint(*context) {
-					if !element.IsOptional() {
-						return errors.Errorf("%s expected context tag %d", element.GetName(), *context)
-					} else {
-						// TODO: we don't do this
-						//a.attr[element.GetName()] = nil
-						continue
-					}
-				}
-				atomicTag := tag.(interface {
-					GetAppTag() readWriteModel.BACnetDataType
-				})
-				tag, err = tag.ContextToApp(uint(atomicTag.GetAppTag()))
-				if err != nil {
-					return errors.Wrap(err, "error converting tag")
-				}
-			} else {
-				if tag.GetTagClass() != readWriteModel.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(elementKlass.GetAppTag()) {
-					if !element.IsOptional() {
-						return errors.Errorf("%s expected context tag %d", element.GetName(), context)
-					} else {
-						// TODO: we don't do this
-						//a.attr[element.GetName()] = nil
-						continue
-					}
-				}
-			}
-
-			// consume the tag
-			tagList.Pop()
-
-			// a helper cooperates between the atomic value and the tag
-			helper, err := element.GetKlass()(NA(tag), NoKWArgs())
-			if err != nil {
-				return errors.Wrap(err, "error creating helper")
-			}
-			a.attr[element.GetName()] = helper
-		} else if isAnyAtomic { // TODO: what is upstream doing here??? how???
-			// convert it to application encoding
-			panic("finish me") // TODO: finish me
-		} else {
-			panic("finish me") // TODO: finish me
-		}
-	}
-	return nil
-}
-
 // TODO: finish
 func SequenceOf[T any](b func(arg Arg) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
 	panic("finish me")
@@ -411,142 +67,3 @@ func SequenceOfs[T any](b func(args Args) (*T, error)) func(Args, KWArgs) (Eleme
 func ArrayOf[T any](b func(arg Arg) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (ElementKlass, error) {
 	panic("finish me")
 }
-
-// TODO: finish
-type List struct {
-}
-
-// TODO: finish
-type Array struct {
-}
-
-// TODO: finish
-type Choice struct {
-}
-
-type AnyContract interface {
-	Encode(taglist TagList) error
-	Decode(taglist TagList) error
-	castIn(arg Arg) error
-	castOut(arg Arg) error
-}
-
-type Any struct {
-	_contract AnyContract // TODO: finish
-
-	tagList TagList
-}
-
-func NewAny(args Args) (*Any, error) {
-	a := &Any{}
-
-	// cast the args
-	for _, arg := range args {
-		if err := a.castIn(arg); err != nil {
-			return nil, errors.Wrapf(err, "error casting arg %v", arg)
-		}
-	}
-	return a, nil
-}
-
-func WithAnyContract(contract AnyContract) func(*Any) {
-	return func(a *Any) {
-		a._contract = contract
-	}
-}
-
-func (a *Any) Encode(tagList TagList) error {
-	a.tagList.Extend(tagList.GetTagList()...)
-	return nil
-}
-
-func (a *Any) Decode(tagList TagList) error {
-	lvl := 0
-	for len(tagList.GetTagList()) != 0 {
-		tag := tagList.Peek()
-		if tag.GetTagClass() == TagOpeningTagClass {
-			lvl++
-		} else if tag.GetTagClass() == TagClosingTagClass {
-			lvl--
-			if lvl < 0 {
-				break
-			}
-		}
-		a.tagList.Append(tagList.Pop())
-	}
-
-	// make sure everything balances
-	if lvl > 0 {
-		return errors.New("mismatched open/close tags")
-	}
-	return nil
-}
-
-func (a *Any) castIn(element Arg) error {
-	t := NewTagList(nil)
-	switch element.(type) {
-	case IsAtomic:
-		tag, err := NewTag(nil)
-		if err != nil {
-			return errors.New("error creating empty tag")
-		}
-		if err := element.(interface{ Encode(arg Arg) error }).Encode(tag); err != nil {
-			return errors.New("error encoding element")
-		}
-		t.Append(tag)
-	case IsAnyAtomic:
-		tag, err := NewTag(nil)
-		if err != nil {
-			return errors.New("error creating empty tag")
-		}
-		if err := element.(interface{ GetValue() any }).GetValue().(interface{ Encode(Tag) error }).Encode(tag); err != nil {
-			return errors.New("error encoding element")
-		}
-		t.Append(tag)
-	default:
-		if err := element.(interface{ Encode(arg Arg) error }).Encode(t); err != nil {
-			return errors.New("error encoding element")
-		}
-	}
-	a.tagList.Extend(t.GetTagList()...)
-	return nil
-}
-
-func (a *Any) castOut(element Arg) error {
-	panic("implement me")
-	return nil
-}
-
-type IsAnyAtomic interface {
-	isAnyAtomic() bool
-}
-
-// TODO: finish me
-type AnyAtomic struct {
-	value any
-}
-
-var _ IsAnyAtomic = (*AnyAtomic)(nil)
-
-func NewAnyAtomic(args Args) (*AnyAtomic, error) {
-	a := &AnyAtomic{}
-	return a, nil
-}
-
-func (a *AnyAtomic) isAnyAtomic() bool {
-	return true
-}
-
-func (a *AnyAtomic) GetValue() any {
-	return a.value
-}
-
-func (a *AnyAtomic) Encode(arg Arg) {}
-
-func (a *AnyAtomic) Decode(arg Arg) error {
-	return nil
-}
-
-// TODO: finish
-type SequenceOfAny struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Any.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Any.go
new file mode 100644
index 00000000000..d26bbfe1336
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Any.go
@@ -0,0 +1,120 @@
+/*
+ * 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 constructeddata
+
+import (
+	"github.com/pkg/errors"
+
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
+)
+
+type AnyContract interface {
+	Encode(taglist TagList) error
+	Decode(taglist TagList) error
+	castIn(arg Arg) error
+	castOut(arg Arg) error
+}
+
+type Any struct {
+	_contract AnyContract // TODO: finish
+
+	tagList TagList
+}
+
+func NewAny(args Args) (*Any, error) {
+	a := &Any{}
+
+	// cast the args
+	for _, arg := range args {
+		if err := a.castIn(arg); err != nil {
+			return nil, errors.Wrapf(err, "error casting arg %v", arg)
+		}
+	}
+	return a, nil
+}
+
+func WithAnyContract(contract AnyContract) func(*Any) {
+	return func(a *Any) {
+		a._contract = contract
+	}
+}
+
+func (a *Any) Encode(tagList TagList) error {
+	a.tagList.Extend(tagList.GetTagList()...)
+	return nil
+}
+
+func (a *Any) Decode(tagList TagList) error {
+	lvl := 0
+	for len(tagList.GetTagList()) != 0 {
+		tag := tagList.Peek()
+		if tag.GetTagClass() == TagOpeningTagClass {
+			lvl++
+		} else if tag.GetTagClass() == TagClosingTagClass {
+			lvl--
+			if lvl < 0 {
+				break
+			}
+		}
+		a.tagList.Append(tagList.Pop())
+	}
+
+	// make sure everything balances
+	if lvl > 0 {
+		return errors.New("mismatched open/close tags")
+	}
+	return nil
+}
+
+func (a *Any) castIn(element Arg) error {
+	t := NewTagList(nil)
+	switch element.(type) {
+	case IsAtomic:
+		tag, err := NewTag(nil)
+		if err != nil {
+			return errors.New("error creating empty tag")
+		}
+		if err := element.(interface{ Encode(arg Arg) error }).Encode(tag); err != nil {
+			return errors.New("error encoding element")
+		}
+		t.Append(tag)
+	case IsAnyAtomic:
+		tag, err := NewTag(nil)
+		if err != nil {
+			return errors.New("error creating empty tag")
+		}
+		if err := element.(interface{ GetValue() any }).GetValue().(interface{ Encode(Tag) error }).Encode(tag); err != nil {
+			return errors.New("error encoding element")
+		}
+		t.Append(tag)
+	default:
+		if err := element.(interface{ Encode(arg Arg) error }).Encode(t); err != nil {
+			return errors.New("error encoding element")
+		}
+	}
+	a.tagList.Extend(t.GetTagList()...)
+	return nil
+}
+
+func (a *Any) castOut(element Arg) error {
+	panic("implement me")
+	return nil
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_AnyAtomic.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_AnyAtomic.go
new file mode 100644
index 00000000000..7e4561ce4e5
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_AnyAtomic.go
@@ -0,0 +1,54 @@
+/*
+ * 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 constructeddata
+
+import (
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+)
+
+type IsAnyAtomic interface {
+	isAnyAtomic() bool
+}
+
+// TODO: finish me
+type AnyAtomic struct {
+	value any
+}
+
+var _ IsAnyAtomic = (*AnyAtomic)(nil)
+
+func NewAnyAtomic(args Args) (*AnyAtomic, error) {
+	a := &AnyAtomic{}
+	return a, nil
+}
+
+func (a *AnyAtomic) isAnyAtomic() bool {
+	return true
+}
+
+func (a *AnyAtomic) GetValue() any {
+	return a.value
+}
+
+func (a *AnyAtomic) Encode(arg Arg) {}
+
+func (a *AnyAtomic) Decode(arg Arg) error {
+	return nil
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/globals/settings.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Array.go
similarity index 60%
rename from plc4go/internal/bacnetip/bacgopes/globals/settings.go
rename to plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Array.go
index 19143e235f2..23c054e8736 100644
--- a/plc4go/internal/bacnetip/bacgopes/globals/settings.go
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Array.go
@@ -17,23 +17,8 @@
  * under the License.
  */
 
-package globals
+package constructeddata
 
-import "os"
-
-var (
-	// ExtendedGeneralOutput switches extended output on for general items
-	ExtendedGeneralOutput bool
-
-	// ExtendedPDUOutput switches the PDU output to an extended format for debugging
-	ExtendedPDUOutput bool
-
-	// LogAppService enables logging for application services
-	LogAppService bool
-)
-
-func init() {
-	ExtendedGeneralOutput = os.Getenv("ExtendedGeneralOutput") == "true"
-	ExtendedPDUOutput = os.Getenv("ExtendedPDUOutput") == "true"
-	LogAppService = os.Getenv("LogAppService") == "true"
+// TODO: finish
+type Array struct {
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
new file mode 100644
index 00000000000..7c84560a750
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
@@ -0,0 +1,24 @@
+/*
+ * 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 constructeddata
+
+// TODO: finish
+type Choice struct {
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Element.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Element.go
new file mode 100644
index 00000000000..f920980a914
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Element.go
@@ -0,0 +1,92 @@
+/*
+ * 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 constructeddata
+
+import (
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+type Element interface {
+	GetName() string
+	GetKlass() func(Args, KWArgs) (ElementKlass, error)
+	GetContext() *int
+	IsOptional() bool
+	Encode(tagList Arg) error
+}
+
+type ElementKlass interface {
+	Encode(Arg) error
+	GetAppTag() readWriteModel.BACnetDataType
+}
+
+// TODO: finish
+type _Element struct {
+	Name     string
+	Klass    func(Args, KWArgs) (ElementKlass, error)
+	Context  *int
+	Optional bool
+}
+
+func NewElement(name string, klass func(Args, KWArgs) (ElementKlass, error), opts ...func(*_Element)) Element {
+	e := &_Element{
+		Name:  name,
+		Klass: klass,
+	}
+	for _, opt := range opts {
+		opt(e)
+	}
+	return e
+}
+
+var _ Element = (*_Element)(nil)
+
+func WithElementOptional(optional bool) func(*_Element) {
+	return func(e *_Element) {
+		e.Optional = optional
+	}
+}
+
+func WithElementContext(context int) func(*_Element) {
+	return func(e *_Element) {
+		e.Context = &context
+	}
+}
+
+func (e *_Element) GetName() string {
+	return e.Name
+}
+
+func (e *_Element) GetKlass() func(Args, KWArgs) (ElementKlass, error) {
+	return e.Klass
+}
+
+func (e *_Element) GetContext() *int {
+	return e.Context
+}
+
+func (e *_Element) IsOptional() bool {
+	return e.Optional
+}
+
+func (e *_Element) Encode(tagList Arg) error {
+	//TODO implement me
+	panic("implement me")
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_List.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_List.go
new file mode 100644
index 00000000000..5db25ae10cf
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_List.go
@@ -0,0 +1,24 @@
+/*
+ * 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 constructeddata
+
+// TODO: finish
+type List struct {
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Sequence.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Sequence.go
new file mode 100644
index 00000000000..9800e971a6a
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Sequence.go
@@ -0,0 +1,318 @@
+/*
+ * 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 constructeddata
+
+import (
+	"reflect"
+
+	"github.com/pkg/errors"
+
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+// SequenceContract provides a set of functions which can be overwritten by a sub struct
+type SequenceContract interface {
+	GetSequenceElements() []Element
+}
+
+// SequenceContractRequirement is needed when one want to extend using SequenceContract
+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(s *Sequence)
+}
+
+// TODO: finish
+type Sequence struct {
+	_contract        SequenceContract
+	sequenceElements []Element
+	attr             map[string]any
+}
+
+// NewSequence Create a sequence element, optionally providing attribute/property values.
+func NewSequence(args Args, kwArgs KWArgs, opts ...func(*Sequence)) (*Sequence, error) {
+	s := &Sequence{
+		attr: make(map[string]any),
+	}
+	for _, opt := range opts {
+		opt(s)
+	}
+	if s._contract == nil {
+		s._contract = s
+	} else {
+		s._contract.(SequenceContractRequirement).SetSequence(s)
+	}
+	if _debug != nil {
+		_debug("__init__ %r %r", args, kwArgs)
+	}
+
+	var myKWArgs = make(KWArgs)
+	var otherKWArgs = make(KWArgs)
+	for _, element := range s._contract.GetSequenceElements() {
+		if a, ok := kwArgs[KnownKey(element.GetName())]; ok {
+			myKWArgs[KnownKey(element.GetName())] = a
+		}
+	}
+	for key, a := range kwArgs {
+		if _, ok := myKWArgs[key]; !ok {
+			otherKWArgs[key] = a
+		}
+	}
+
+	if _debug != nil {
+		_debug("    - my_kwargs: %r", myKWArgs)
+	}
+	if _debug != nil {
+		_debug("    - other_kwargs: %r", otherKWArgs)
+	}
+	if len(otherKWArgs) > 0 {
+		return nil, errors.Errorf("invalid arguments %v", otherKWArgs)
+	}
+
+	// set the attribute/property values for the ones provided
+	for _, element := range s._contract.GetSequenceElements() {
+		a, ok := myKWArgs[KnownKey(element.GetName())]
+		if ok {
+			s.attr[element.GetName()] = a
+		}
+	}
+	return s, nil
+}
+
+func WithSequenceExtension(contract SequenceContractRequirement) func(*Sequence) {
+	return func(s *Sequence) {
+		s._contract = contract
+	}
+}
+
+func (a *Sequence) GetSequenceElements() []Element {
+	return a.sequenceElements
+}
+
+func (a *Sequence) GetAttr(key string) (any, bool) {
+	v, ok := a.attr[key]
+	return v, ok
+}
+
+func (a *Sequence) Encode(arg Arg) error {
+	tagList, ok := arg.(*TagList)
+	if !ok {
+		return errors.New("arg is not a TagList")
+	}
+
+	for _, element := range a._contract.GetSequenceElements() {
+		value, ok := a.attr[element.GetName()]
+		if element.IsOptional() && !ok {
+			continue
+		}
+		if !element.IsOptional() && !ok {
+			return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
+		}
+		elementKlass, err := element.GetKlass()(Nothing())
+		if err != nil {
+			return errors.New("can't get zero object")
+		}
+		_, elementInSequenceOfClasses := _sequenceOfClasses[elementKlass]
+		_, elementInListOfClasses := _listOfClasses[elementKlass]
+		isAtomic := false
+		switch elementKlass.(type) {
+		case IsAtomic, IsAnyAtomic:
+			isAtomic = true
+		}
+		isValue := reflect.TypeOf(value) == reflect.TypeOf(elementKlass)
+
+		if elementInSequenceOfClasses || elementInListOfClasses {
+			// might need to encode an opening tag
+			if element.GetContext() != nil {
+				openingTag, err := NewOpeningTag(*element.GetContext())
+				if err != nil {
+					return errors.Wrap(err, "error creating opening tag")
+				}
+				tagList.Append(openingTag)
+			}
+
+			helper, err := element.GetKlass()(NA(value), NoKWArgs())
+			if err != nil {
+				return errors.Wrap(err, "error klass element")
+			}
+
+			// encode the value
+			if err := helper.Encode(tagList); err != nil {
+				return errors.Wrap(err, "error encoding tag list")
+			}
+
+			// might need to encode a closing tag
+			if element.GetContext() != nil {
+				closingTag, err := NewClosingTag(*element.GetContext())
+				if err != nil {
+					return errors.Wrap(err, "error creating closing tag")
+				}
+				tagList.Append(closingTag)
+			}
+		} else if isAtomic {
+			helper, err := element.GetKlass()(NA(value), NoKWArgs())
+			if err != nil {
+				return errors.Wrap(err, "error klass element")
+			}
+
+			// build a tag and encode the data into it
+			tag, err := NewTag(nil)
+			if err != nil {
+				return errors.Wrap(err, "error creating tag")
+			}
+			// encode the value
+			if err := helper.Encode(tag); err != nil {
+				return errors.Wrap(err, "error encoding tag list")
+			}
+
+			// convert it to context encoding if necessary
+			if element.GetContext() != nil {
+				tag, err = tag.AppToContext(uint(*element.GetContext()))
+				if err != nil {
+					return errors.Wrap(err, "error converting tag to context")
+				}
+			}
+			tagList.Append(tag)
+		} else if isValue {
+			// might need to encode an opening tag
+			if element.GetContext() != nil {
+				openingTag, err := NewOpeningTag(*element.GetContext())
+				if err != nil {
+					return errors.Wrap(err, "error creating opening tag")
+				}
+				tagList.Append(openingTag)
+			}
+
+			// encode the tag
+			if err := value.(interface{ Encode(Arg) error }).Encode(tagList); err != nil { // TODO: ugly case, need a encode interface soon
+				return errors.Wrap(err, "error encoding tag list")
+			}
+
+			// might need to encode a closing tag
+			if element.GetContext() != nil {
+				closingTag, err := NewClosingTag(*element.GetContext())
+				if err != nil {
+					return errors.Wrap(err, "error creating closing tag")
+				}
+				tagList.Append(closingTag)
+			}
+		}
+	}
+	return nil
+}
+
+func (a *Sequence) Decode(arg Arg) error {
+	tagList, ok := arg.(*TagList)
+	if !ok {
+		return errors.New("arg is not a TagList")
+	}
+
+	for _, element := range a._contract.GetSequenceElements() {
+		tag := tagList.Peek()
+
+		elementKlass, err := element.GetKlass()(Nothing())
+		if err != nil {
+			return errors.New("can't get zero object")
+		}
+		_, elementInSequenceOfClasses := _sequenceOfClasses[elementKlass]
+		_, elementInListOfClasses := _listOfClasses[elementKlass]
+		isAtomic := false
+		isAnyAtomic := false
+		switch elementKlass.(type) {
+		case IsAtomic:
+			isAtomic = true
+		case IsAnyAtomic:
+			isAnyAtomic = true
+		}
+		// no more elements
+		if tag == nil {
+			if element.IsOptional() {
+				// ommited optional element
+				a.attr[element.GetName()] = nil
+			} else if elementInSequenceOfClasses || elementInListOfClasses {
+				// empty list
+				//a.attr[element.GetName()] = nil // TODO: what to do???
+			} else {
+				return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
+			}
+		} else if tag.GetTagClass() == TagClosingTagClass {
+			if !element.IsOptional() {
+				return errors.Errorf("%s is a missing required element of %T", element.GetName(), a)
+			}
+
+			// ommited optional element
+			// a.attr[element.GetName()] = nil // TODO: don't set it for now as we use _,ok:=
+		} else if elementInSequenceOfClasses {
+			// check for context encoding
+			panic("finish me") // TODO: finish me
+		} else if isAnyAtomic {
+			// convert it to application encoding
+			panic("finish me") // TODO: finish me
+		} else if isAtomic {
+			// convert it to application encoding
+			if context := element.GetContext(); context != nil {
+				if tag.GetTagClass() != readWriteModel.TagClass_CONTEXT_SPECIFIC_TAGS && tag.GetTagNumber() != uint(*context) {
+					if !element.IsOptional() {
+						return errors.Errorf("%s expected context tag %d", element.GetName(), *context)
+					} else {
+						// TODO: we don't do this
+						//a.attr[element.GetName()] = nil
+						continue
+					}
+				}
+				atomicTag := tag.(interface {
+					GetAppTag() readWriteModel.BACnetDataType
+				})
+				tag, err = tag.ContextToApp(uint(atomicTag.GetAppTag()))
+				if err != nil {
+					return errors.Wrap(err, "error converting tag")
+				}
+			} else {
+				if tag.GetTagClass() != readWriteModel.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(elementKlass.GetAppTag()) {
+					if !element.IsOptional() {
+						return errors.Errorf("%s expected context tag %d", element.GetName(), context)
+					} else {
+						// TODO: we don't do this
+						//a.attr[element.GetName()] = nil
+						continue
+					}
+				}
+			}
+
+			// consume the tag
+			tagList.Pop()
+
+			// a helper cooperates between the atomic value and the tag
+			helper, err := element.GetKlass()(NA(tag), NoKWArgs())
+			if err != nil {
+				return errors.Wrap(err, "error creating helper")
+			}
+			a.attr[element.GetName()] = helper
+		} else if isAnyAtomic { // TODO: what is upstream doing here??? how???
+			// convert it to application encoding
+			panic("finish me") // TODO: finish me
+		} else {
+			panic("finish me") // TODO: finish me
+		}
+	}
+	return nil
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_SequenceOfAny.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_SequenceOfAny.go
new file mode 100644
index 00000000000..ec45b7b8964
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_SequenceOfAny.go
@@ -0,0 +1,24 @@
+/*
+ * 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 constructeddata
+
+// TODO: finish
+type SequenceOfAny struct {
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/debugging/debugging.go b/plc4go/internal/bacnetip/bacgopes/debugging/debugging.go
index 231db5e85a0..76026621ba3 100644
--- a/plc4go/internal/bacnetip/bacgopes/debugging/debugging.go
+++ b/plc4go/internal/bacnetip/bacgopes/debugging/debugging.go
@@ -34,6 +34,7 @@ import (
 	"unsafe"
 )
 
+var _isDebuggingActive = false
 var _debug = CreateDebugPrinter()
 
 func Btox(data []byte, sep string) string {
@@ -107,15 +108,16 @@ func (d *DebugContents) Format(s fmt.State, v rune) {
 		// TODO: check if that hacky hacky makes sense
 		if len(d.debuggables) > 0 {
 			debuggable := d.debuggables[0]
-			_, _ = fmt.Fprintf(s, "<%s at %p>", TypeName(debuggable), debuggable)
+			_, _ = fmt.Fprintf(s, "<%s at %p>", QualifiedTypeName(debuggable), debuggable)
 		}
 	case 'r':
 		// TODO: check if that hacky hacky makes sense
 		if len(d.debuggables) > 0 {
 			debuggable := d.debuggables[0]
-			_, _ = fmt.Fprintf(s, "<%s at %p>\n", TypeName(debuggable), debuggable)
+			_, _ = fmt.Fprintf(s, "<%s at %p>\n", QualifiedTypeName(debuggable), debuggable)
+			_, _ = fmt.Fprintf(s, "    <%s at %p>\n", QualifiedTypeName(debuggable), debuggable) // TODO: why is this duplicated?
 		}
-		d.PrintDebugContents(0, s, nil)
+		d.PrintDebugContents(2, s, nil)
 	}
 }
 
@@ -199,7 +201,7 @@ func (d *DebugContents) PrintDebugContents(indent int, file io.Writer, _ids []ui
 		value := debuggable.GetDebugAttr(attr)
 
 		// skip nil
-		if value == nil {
+		if isNil(value) {
 			continue
 		}
 
@@ -225,7 +227,27 @@ func (d *DebugContents) PrintDebugContents(indent int, file io.Writer, _ids []ui
 			indent -= 1
 			_, _ = fmt.Fprintf(file, "%s    ]\n", strings.Repeat("    ", indent))
 		} else if goListDict && isDict(value) {
-			panic("add support for map") // TODO: add map support
+			_map, ok := toMap(value)
+			if !ok {
+				panic("impossible")
+			}
+			_, _ = fmt.Fprintf(file, "%s%s = {\n", strings.Repeat("    ", indent), attr)
+			indent += 1
+			for key, elem := range _map {
+				keyPrintVerb := verbForType(key, 'r')
+				elemPrintVerb := verbForType(elem, 'r')
+				_, _ = fmt.Fprintf(file, "%s"+string(keyPrintVerb)+" : "+string(elemPrintVerb)+"\n", strings.Repeat("    ", indent), key, elem)
+				if deepDebugContent, ok := elem.(interface {
+					DebugContents(int, io.Writer, []uintptr)
+				}); goDeep && ok {
+					if slices.Contains(_ids, uintptr(unsafe.Pointer(&deepDebugContent))) {
+						_ids = append(_ids, uintptr(unsafe.Pointer(&deepDebugContent)))
+						deepDebugContent.DebugContents(indent+1, file, _ids)
+					}
+				}
+			}
+			indent -= 1
+			_, _ = fmt.Fprintf(file, "%s    }\n", strings.Repeat("    ", indent))
 		} else if goHexed && isString(value) { // TODO: add support
 			panic("add support")
 		} else {
@@ -312,6 +334,18 @@ func TypeName(anything any) string {
 	return typeOf.Name()
 }
 
+func QualifiedTypeName(anything any) string {
+	typeOf := reflect.TypeOf(anything)
+	if typeOf.Kind() == reflect.Ptr {
+		typeOf = typeOf.Elem()
+	}
+	typeNameString := "bacgopes." + typeOf.String()
+	if customProjectName != "" {
+		typeNameString = strings.ReplaceAll(typeNameString, projectName, customProjectName)
+	}
+	return typeNameString
+}
+
 // TODO: migrate comp debug logger to here...
 type LoggingFormatter struct {
 	// TODO: implement me
@@ -334,8 +368,13 @@ func NewDefaultRFormatter(extraPrinters ...DebugContentPrinter) *DefaultRFormatt
 	base := path.Base(file)
 	prefix := strings.TrimSuffix(base, ".go")
 	prefix = strings.TrimPrefix(prefix, dirPrefix)
+	qualifier := strings.ReplaceAll(dirPrefix, "_", ".")
+	header := fmt.Sprintf("<%s at 0x%x>", "bacgopes."+qualifier+prefix, pc)
+	if customProjectName != "" {
+		header = strings.ReplaceAll(header, projectName, customProjectName)
+	}
 	return &DefaultRFormatter{
-		header:        fmt.Sprintf("<%s at 0x%x>", prefix, pc),
+		header:        header,
 		extraPrinters: extraPrinters,
 	}
 }
@@ -406,6 +445,7 @@ func CreateDebugPrinter() DebugPrinter {
 
 	bacgopesDebug := os.Getenv("BACGOPES_DEBUG")
 	if strings.Contains(bacgopesDebug, qualifier) {
+		_isDebuggingActive = true
 		return func(format string, a ...any) {
 			pc, file, _, ok := runtime.Caller(1)
 			if !ok {
@@ -440,6 +480,10 @@ func CreateDebugPrinter() DebugPrinter {
 	return nil
 }
 
+func IsDebuggingActive() bool {
+	return _isDebuggingActive
+}
+
 func cleanupFormatString(s string) string {
 	// TODO: investigate via comm.comm is happening
 	s = strings.ReplaceAll(s, ".comm.comm:", ".comm:")
@@ -492,3 +536,17 @@ func verbForType(value any, printVerb rune) rune {
 	}
 	return printVerb
 }
+
+// clone from comp to avoid circular dependencies // TODO: maybe move Btox somewhere else or come up with something smarter there
+func isNil(v interface{}) bool {
+	if v == nil {
+		return true
+	}
+	valueOf := reflect.ValueOf(v)
+	switch valueOf.Kind() {
+	case reflect.Ptr, reflect.Interface, reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
+		return valueOf.IsNil()
+	default:
+		return false
+	}
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkAdapter.go b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkAdapter.go
index 7ab3ca7bfc2..cc1a03d3b4d 100644
--- a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkAdapter.go
+++ b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkAdapter.go
@@ -20,11 +20,14 @@
 package netservice
 
 import (
+	"fmt"
+
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/npdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 )
@@ -32,6 +35,8 @@ import (
 //go:generate plc4xGenerator -type=NetworkAdapter -prefix=netservice_
 type NetworkAdapter struct {
 	ClientContract
+	*DebugContents `ignore:"true"`
+
 	adapterSAP           *NetworkServiceAccessPoint `asPtr:"true"`
 	adapterNet           *uint16
 	adapterAddr          *Address
@@ -54,6 +59,7 @@ func NewNetworkAdapter(localLog zerolog.Logger, sap *NetworkServiceAccessPoint,
 	for _, opt := range opts {
 		opt(n)
 	}
+	n.DebugContents = NewDebugContents(n, "adapterSAP-", "adapterNet", "adapterAddr", "adapterNetConfigured")
 	n.log.Trace().Stringer("sap", sap).Interface("net", net).Stringer("addr", addr).Interface("cid", n.argCid).Msg("NewNetworkAdapter")
 	var err error
 	n.ClientContract, err = NewClient(n.log, OptionalOption2(n.argCid, ToPtr[ClientRequirements](n), WithClientCID))
@@ -74,6 +80,30 @@ func WithNetworkAdapterCid(cid int) func(*NetworkAdapter) {
 	}
 }
 
+func (n *NetworkAdapter) GetDebugAttr(attr string) any {
+	switch attr {
+	case "adapterSAP":
+		if n.adapterSAP != nil {
+			return fmt.Sprintf("%s", n.adapterSAP) // TODO: we call format here directly to avoid endless loop
+		}
+	case "adapterNet":
+		if n.adapterNet != nil {
+			return *n.adapterNet
+		}
+	case "adapterAddr":
+		if n.adapterAddr != nil {
+			return n.adapterAddr
+		}
+	case "adapterNetConfigured":
+		if n.adapterNetConfigured != nil {
+			return *n.adapterNetConfigured
+		}
+	default:
+		return nil
+	}
+	return nil
+}
+
 // Confirmation Decode upstream PDUs and pass them up to the service access point.
 func (n *NetworkAdapter) Confirmation(args Args, kwArgs KWArgs) error {
 	n.log.Debug().
@@ -83,11 +113,10 @@ func (n *NetworkAdapter) Confirmation(args Args, kwArgs KWArgs) error {
 
 	pdu := GA[PDU](args, 0)
 
-	npdu, err := NewNPDU(nil, nil)
+	npdu, err := NewNPDU(NoArgs, NKW(KWCPCIUserData, pdu.GetPDUUserData()))
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
-	npdu.SetPDUUserData(pdu.GetPDUUserData())
 	if err := npdu.Decode(pdu); err != nil {
 		return errors.Wrap(err, "error decoding NPDU")
 	}
@@ -115,3 +144,10 @@ func (n *NetworkAdapter) EstablishConnectionToNetwork(net any) error {
 func (n *NetworkAdapter) DisconnectConnectionToNetwork(net any) error {
 	panic("not implemented yet")
 }
+
+func (n *NetworkAdapter) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", n), true // Delegate to debugging format
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceAccessPoint.go b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceAccessPoint.go
index f213c1c585b..bca8eaa69e6 100644
--- a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceAccessPoint.go
+++ b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceAccessPoint.go
@@ -21,6 +21,7 @@ package netservice
 
 import (
 	"bytes"
+	"fmt"
 
 	"github.com/pkg/errors"
 	"github.com/rs/zerolog"
@@ -29,6 +30,7 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/apdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/npdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
@@ -38,6 +40,8 @@ import (
 type NetworkServiceAccessPoint struct {
 	ServiceAccessPointContract
 	ServerContract
+	*DebugContents `ignore:"true"`
+
 	adapters        map[netKey]*NetworkAdapter
 	routerInfoCache *RouterInfoCache `stringer:"true"`
 	pendingNets     map[netKey][]NPDU
@@ -55,6 +59,7 @@ func NewNetworkServiceAccessPoint(localLog zerolog.Logger, opts ...func(*Network
 	n := &NetworkServiceAccessPoint{
 		log: localLog,
 	}
+	n.DebugContents = NewDebugContents(n, "adapters++", "pending_nets", "local_adapter-")
 	for _, opt := range opts {
 		opt(n)
 	}
@@ -101,6 +106,19 @@ func WithNetworkServiceAccessPointRouterSID(sid int) func(*NetworkServiceAccessP
 	}
 }
 
+func (n *NetworkServiceAccessPoint) GetDebugAttr(attr string) any {
+	switch attr {
+	case "adapters":
+		return n.adapters
+	case "pending_nets":
+		return n.pendingNets
+	case "local_adapter":
+		return n.localAdapter
+	default:
+		return nil
+	}
+}
+
 /*
 Bind creates a network adapter object and bind.
 
@@ -212,7 +230,7 @@ func (n *NetworkServiceAccessPoint) Indication(args Args, kwArgs KWArgs) error {
 	n.log.Debug().Stringer("localAdapter", localAdapter).Msg("localAdapter")
 
 	// build a generic APDU
-	apdu, err := NewAPDU(nil, WithAPDUUserData(pdu.GetPDUUserData())) // Note: upstream makes a _APDU instance which looks like a programming error as this class is only useful in an extension context...
+	apdu, err := NewAPDU(nil, NKW(KWCPCIUserData, pdu.GetPDUUserData())) // Note: upstream makes a _APDU instance which looks like a programming error as this class is only useful in an extension context...
 	if err != nil {
 		return errors.Wrap(err, "error creating _APDU")
 	}
@@ -222,7 +240,7 @@ func (n *NetworkServiceAccessPoint) Indication(args Args, kwArgs KWArgs) error {
 	n.log.Debug().Stringer("_APDU", apdu).Msg("apdu")
 
 	// build an NPDU specific to where it is going
-	npdu, err := NewNPDU(nil, nil)
+	npdu, err := NewNPDU(NoArgs, NKW(KWCPCIUserData, pdu.GetPDUUserData()))
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
@@ -349,7 +367,7 @@ func (n *NetworkServiceAccessPoint) Indication(args Args, kwArgs KWArgs) error {
 		n.pendingNets[nk(dnet)] = netList
 
 		// build a request for the network and send it to all the adapters
-		xnpdu, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(*dnet))
+		xnpdu, err := NewWhoIsRouterToNetwork(NoArgs, NoKWArgs(), WithWhoIsRouterToNetworkNet(*dnet))
 		if err != nil {
 			return errors.Wrap(err, "error building WhoIsRouterToNetwork")
 		}
@@ -444,11 +462,10 @@ func (n *NetworkServiceAccessPoint) ProcessNPDU(adapter *NetworkAdapter, npdu NP
 		if processLocally && n.HasServerPeer() {
 			n.log.Trace().Msg("processing APDU locally")
 			// decode as a generic APDU
-			apdu, err := NewAPDU(nil)
+			apdu, err := NewAPDU(NoArgs, NKW(KWCPCIUserData, npdu.GetPDUUserData()))
 			if err != nil {
 				return errors.Wrap(err, "error creating APDU")
 			}
-			apdu.SetPDUUserData(npdu.GetPDUUserData()) // TODO: upstream does this inline
 			if err := apdu.Decode(DeepCopy[NPDU](npdu)); err != nil {
 				return errors.Wrap(err, "error decoding APDU")
 			}
@@ -679,14 +696,14 @@ func (n *NetworkServiceAccessPoint) SapIndication(args Args, kwArgs KWArgs) erro
 	npdu := GA[NPDU](args, 1)
 
 	// encode it as a generic NPDU
-	xpdu, err := NewNPDU(nil, nil) // TODO: add with user data thingy...
+	xpdu, err := NewNPDU(NoArgs, NKW(KWCPCIUserData, npdu.GetPDUUserData()))
 	if err != nil {
 		return errors.Wrap(err, "error building NPDU")
 	}
 	if err := npdu.Encode(xpdu); err != nil {
 		return errors.Wrap(err, "error encoding NPDU")
 	}
-	// npdu._xpdu = xpdu
+	// npdu._xpdu = xpdu // TODO: what does that mean?
 
 	// tell the adapter to process the NPDU
 	return adapter.ProcessNPDU(xpdu)
@@ -698,14 +715,21 @@ func (n *NetworkServiceAccessPoint) SapConfirmation(args Args, kwArgs KWArgs) er
 	npdu := GA[NPDU](args, 1)
 
 	// encode it as a generic NPDU
-	xpdu, err := NewNPDU(nil, nil) // TODO: add with user data thingy...
+	xpdu, err := NewNPDU(NoArgs, NKW(KWCPCIUserData, npdu.GetPDUUserData()))
 	if err != nil {
 		return errors.Wrap(err, "error building NPDU")
 	}
 	if err := npdu.Encode(xpdu); err != nil {
 		return errors.Wrap(err, "error encoding NPDU")
 	}
-	// npdu._xpdu = xpdu
+	// npdu._xpdu = xpdu // TODO: what does this mean
 
 	return adapter.ProcessNPDU(xpdu)
 }
+
+func (n *NetworkServiceAccessPoint) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", n), true // Delegate to the format method
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceElement.go b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceElement.go
index 3000458dba3..4f519b222d4 100644
--- a/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceElement.go
+++ b/plc4go/internal/bacnetip/bacgopes/netservice/netservice_NetworkServiceElement.go
@@ -20,6 +20,7 @@
 package netservice
 
 import (
+	"fmt"
 	"slices"
 	"time"
 
@@ -29,6 +30,7 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/core"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/npdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
@@ -37,6 +39,7 @@ import (
 //go:generate plc4xGenerator -type=NetworkServiceElement -prefix=netservice_
 type NetworkServiceElement struct {
 	ApplicationServiceElementContract
+	*DefaultRFormatter `ignore:"true"`
 
 	networkNumberIsTask time.Time
 
@@ -52,7 +55,8 @@ type NetworkServiceElement struct {
 
 func NewNetworkServiceElement(localLog zerolog.Logger, opts ...func(*NetworkServiceElement)) (*NetworkServiceElement, error) {
 	n := &NetworkServiceElement{
-		log: localLog,
+		DefaultRFormatter: NewDefaultRFormatter(),
+		log:               localLog,
 	}
 	for _, opt := range opts {
 		opt(n)
@@ -147,7 +151,7 @@ func (n *NetworkServiceElement) Indication(args Args, kwArgs KWArgs) error {
 	case model.NPDU:
 		switch nlm := message.GetNlm().(type) {
 		case model.NLMWhoIsRouterToNetwork:
-			return n.WhoIsRouteToNetwork(adapter, npdu, nlm)
+			return n.WhoIsRouterToNetwork(adapter, npdu, nlm)
 		case model.NLMIAmRouterToNetwork:
 			return n.IAmRouterToNetwork(adapter, npdu, nlm)
 		case model.NLMICouldBeRouterToNetwork:
@@ -189,7 +193,7 @@ func (n *NetworkServiceElement) Confirmation(args Args, kwArgs KWArgs) error {
 	case model.NPDU:
 		switch nlm := message.GetNlm().(type) {
 		case model.NLMWhoIsRouterToNetwork:
-			return n.WhoIsRouteToNetwork(adapter, npdu, nlm)
+			return n.WhoIsRouterToNetwork(adapter, npdu, nlm)
 		case model.NLMIAmRouterToNetwork:
 			return n.IAmRouterToNetwork(adapter, npdu, nlm)
 		case model.NLMICouldBeRouterToNetwork:
@@ -320,7 +324,7 @@ func (n *NetworkServiceElement) iamRouterToNetwork(args Args, _ KWArgs) error {
 		}
 
 		// build a response
-		iamrtn, err := NewIAmRouterToNetwork()
+		iamrtn, err := NewIAmRouterToNetwork(Nothing())
 		if err != nil {
 			return errors.Wrap(err, "error creating IAM router to network")
 		}
@@ -336,7 +340,7 @@ func (n *NetworkServiceElement) iamRouterToNetwork(args Args, _ KWArgs) error {
 	return nil
 }
 
-func (n *NetworkServiceElement) WhoIsRouteToNetwork(adapter *NetworkAdapter, npdu NPDU, nlm model.NLMWhoIsRouterToNetwork) error {
+func (n *NetworkServiceElement) WhoIsRouterToNetwork(adapter *NetworkAdapter, npdu NPDU, nlm model.NLMWhoIsRouterToNetwork) error {
 	n.log.Debug().Stringer("adapter", adapter).Stringer("npdu", npdu).Stringer("nlm", nlm).Msg("WhoIsRouteToNetwork")
 
 	// reference the service access point
@@ -370,11 +374,10 @@ func (n *NetworkServiceElement) WhoIsRouteToNetwork(adapter *NetworkAdapter, npd
 			n.log.Debug().Uints16("netlist", netlist).Msg("found these")
 
 			// build a response
-			iamrtn, err := NewIAmRouterToNetwork(WithIAmRouterToNetworkNetworkList(netlist...))
+			iamrtn, err := NewIAmRouterToNetwork(NoArgs, NewKWArgs(KWCPCIUserData, npdu.GetPDUUserData()), WithIAmRouterToNetworkNetworkList(netlist...))
 			if err != nil {
 				return errors.Wrap(err, "error building IAmRouterToNetwork")
 			}
-			iamrtn.SetPDUUserData(npdu.GetPDUUserData()) // TODO: upstream does this inline
 			iamrtn.SetPDUDestination(npdu.GetPDUSource())
 
 			// send it back
@@ -399,11 +402,10 @@ func (n *NetworkServiceElement) WhoIsRouteToNetwork(adapter *NetworkAdapter, npd
 			}
 
 			// build a response
-			iamrtn, err := NewIAmRouterToNetwork(WithIAmRouterToNetworkNetworkList(dnet))
+			iamrtn, err := NewIAmRouterToNetwork(NoArgs, NewKWArgs(KWCPCIUserData, npdu.GetPDUUserData()), WithIAmRouterToNetworkNetworkList(dnet))
 			if err != nil {
 				return errors.Wrap(err, "error building IAmRouterToNetwork")
 			}
-			iamrtn.SetPDUUserData(npdu.GetPDUUserData()) // TODO: upstream does this inline
 			iamrtn.SetPDUDestination(npdu.GetPDUSource())
 
 			// send it back
@@ -432,11 +434,10 @@ func (n *NetworkServiceElement) WhoIsRouteToNetwork(adapter *NetworkAdapter, npd
 			}
 
 			// build a response
-			iamrtn, err := NewIAmRouterToNetwork(WithIAmRouterToNetworkNetworkList(dnet))
+			iamrtn, err := NewIAmRouterToNetwork(NoArgs, NewKWArgs(KWCPCIUserData, npdu.GetPDUUserData()), WithIAmRouterToNetworkNetworkList(dnet))
 			if err != nil {
 				return errors.Wrap(err, "error building IAmRouterToNetwork")
 			}
-			iamrtn.SetPDUUserData(npdu.GetPDUUserData()) // TODO: upstream does this inline
 			iamrtn.SetPDUDestination(npdu.GetPDUSource())
 
 			// send it back
@@ -444,11 +445,10 @@ func (n *NetworkServiceElement) WhoIsRouteToNetwork(adapter *NetworkAdapter, npd
 		} else {
 			n.log.Trace().Msg("forwarding to other adapters")
 
-			whoisrtn, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(dnet))
+			whoisrtn, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIUserData, npdu.GetPDUUserData()), WithWhoIsRouterToNetworkNet(dnet))
 			if err != nil {
 				return errors.Wrap(err, "error building WhoIsRouterToNetwork")
 			}
-			whoisrtn.SetPDUUserData(npdu.GetPDUUserData()) // TODO: upstream does this inline
 			whoisrtn.SetPDUDestination(NewLocalBroadcast(nil))
 
 			// if the request had a source forward it along
@@ -495,7 +495,7 @@ func (n *NetworkServiceElement) IAmRouterToNetwork(adapter *NetworkAdapter, npdu
 		n.log.Trace().Msg("forwarding other adapters")
 
 		// Build a broadcast announcement
-		iamrtn, err := NewIAmRouterToNetwork(WithIAmRouterToNetworkNetworkList(nlm.GetDestinationNetworkAddresses()...))
+		iamrtn, err := NewIAmRouterToNetwork(NoArgs, NoKWArgs(), WithIAmRouterToNetworkNetworkList(nlm.GetDestinationNetworkAddresses()...))
 		if err != nil {
 			return errors.Wrap(err, "error building IAmRouterToNetwork")
 		}
@@ -577,3 +577,10 @@ func (n *NetworkServiceElement) WhatIsNetworkNumber(adapter *NetworkAdapter, nlm
 func (n *NetworkServiceElement) NetworkNumberIs(adapter *NetworkAdapter, nlm model.NLMNetworkNumberIs) error {
 	panic("not implemented") // TODO: implement me
 }
+
+func (n *NetworkServiceElement) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", n), true // Delegate to format
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu.go
index 2d07171ef88..c853ea82bbc 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu.go
@@ -29,43 +29,43 @@ var NPDUTypes map[uint8]func() Decoder
 func init() {
 	NPDUTypes = map[uint8]func() Decoder{
 		0x00: func() Decoder {
-			v, _ := NewWhoIsRouterToNetwork()
+			v, _ := NewWhoIsRouterToNetwork(Nothing())
 			return v
 		},
 		0x01: func() Decoder {
-			v, _ := NewIAmRouterToNetwork()
+			v, _ := NewIAmRouterToNetwork(Nothing())
 			return v
 		},
 		0x02: func() Decoder {
-			v, _ := NewICouldBeRouterToNetwork()
+			v, _ := NewICouldBeRouterToNetwork(Nothing())
 			return v
 		},
 		0x03: func() Decoder {
-			v, _ := NewRejectMessageToNetwork()
+			v, _ := NewRejectMessageToNetwork(Nothing())
 			return v
 		},
 		0x04: func() Decoder {
-			v, _ := NewRouterBusyToNetwork()
+			v, _ := NewRouterBusyToNetwork(Nothing())
 			return v
 		},
 		0x05: func() Decoder {
-			v, _ := NewRouterAvailableToNetwork()
+			v, _ := NewRouterAvailableToNetwork(Nothing())
 			return v
 		},
 		0x06: func() Decoder {
-			v, _ := NewInitializeRoutingTable()
+			v, _ := NewInitializeRoutingTable(Nothing())
 			return v
 		},
 		0x07: func() Decoder {
-			v, _ := NewInitializeRoutingTableAck()
+			v, _ := NewInitializeRoutingTableAck(Nothing())
 			return v
 		},
 		0x08: func() Decoder {
-			v, _ := NewEstablishConnectionToNetwork()
+			v, _ := NewEstablishConnectionToNetwork(Nothing())
 			return v
 		},
 		0x09: func() Decoder {
-			v, _ := NewDisconnectConnectionToNetwork()
+			v, _ := NewDisconnectConnectionToNetwork(Nothing())
 			return v
 		},
 		// 0x0A: NewChallengeRequest, // TODO: not present upstream
@@ -77,11 +77,11 @@ func init() {
 		// 0x10: NewRequestMasterKey, // TODO: not present upstream
 		// 0x11: NewSetMasterKey, // TODO: not present upstream
 		0x12: func() Decoder {
-			v, _ := NewWhatIsNetworkNumber()
+			v, _ := NewWhatIsNetworkNumber(Nothing())
 			return v
 		},
 		0x13: func() Decoder {
-			v, _ := NewNetworkNumberIs()
+			v, _ := NewNetworkNumberIs(Nothing())
 			return v
 		},
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_DisconnectConnectionToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_DisconnectConnectionToNetwork.go
index 05a59aae7c4..1d61ca984cb 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_DisconnectConnectionToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_DisconnectConnectionToNetwork.go
@@ -37,14 +37,17 @@ type DisconnectConnectionToNetwork struct {
 	dctnDNET uint16
 }
 
-func NewDisconnectConnectionToNetwork(opts ...func(*DisconnectConnectionToNetwork)) (*DisconnectConnectionToNetwork, error) {
+func NewDisconnectConnectionToNetwork(args Args, kwArgs KWArgs, opts ...func(*DisconnectConnectionToNetwork)) (*DisconnectConnectionToNetwork, error) {
 	i := &DisconnectConnectionToNetwork{
 		messageType: 0x09,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMDisconnectConnectionToNetwork(i.dctnDNET, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMDisconnectConnectionToNetwork(i.dctnDNET, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_EstablishConnectionToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_EstablishConnectionToNetwork.go
index 836a1ec6b3d..aec813db889 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_EstablishConnectionToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_EstablishConnectionToNetwork.go
@@ -38,14 +38,17 @@ type EstablishConnectionToNetwork struct {
 	ectnTerminationTime uint8
 }
 
-func NewEstablishConnectionToNetwork(opts ...func(*EstablishConnectionToNetwork)) (*EstablishConnectionToNetwork, error) {
+func NewEstablishConnectionToNetwork(args Args, kwArgs KWArgs, opts ...func(*EstablishConnectionToNetwork)) (*EstablishConnectionToNetwork, error) {
 	i := &EstablishConnectionToNetwork{
 		messageType: 0x08,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMEstablishConnectionToNetwork(i.ectnDNET, i.ectnTerminationTime, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMEstablishConnectionToNetwork(i.ectnDNET, i.ectnTerminationTime, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_IAmRouterToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_IAmRouterToNetwork.go
index 6a091b94ec6..629464bb4cf 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_IAmRouterToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_IAmRouterToNetwork.go
@@ -37,14 +37,17 @@ type IAmRouterToNetwork struct {
 	iartnNetworkList []uint16
 }
 
-func NewIAmRouterToNetwork(opts ...func(*IAmRouterToNetwork)) (*IAmRouterToNetwork, error) {
+func NewIAmRouterToNetwork(args Args, kwArgs KWArgs, opts ...func(*IAmRouterToNetwork)) (*IAmRouterToNetwork, error) {
 	i := &IAmRouterToNetwork{
 		messageType: 0x01,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMIAmRouterToNetwork(i.iartnNetworkList, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMIAmRouterToNetwork(i.iartnNetworkList, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_ICouldBeRouterToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_ICouldBeRouterToNetwork.go
index 3bf088d855c..36943dbb51b 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_ICouldBeRouterToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_ICouldBeRouterToNetwork.go
@@ -38,14 +38,17 @@ type ICouldBeRouterToNetwork struct {
 	icbrtnPerformanceIndex uint8
 }
 
-func NewICouldBeRouterToNetwork(opts ...func(*ICouldBeRouterToNetwork)) (*ICouldBeRouterToNetwork, error) {
+func NewICouldBeRouterToNetwork(args Args, kwArgs KWArgs, opts ...func(*ICouldBeRouterToNetwork)) (*ICouldBeRouterToNetwork, error) {
 	i := &ICouldBeRouterToNetwork{
 		messageType: 0x02,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMICouldBeRouterToNetwork(i.icbrtnNetwork, i.icbrtnPerformanceIndex, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMICouldBeRouterToNetwork(i.icbrtnNetwork, i.icbrtnPerformanceIndex, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTable.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTable.go
index 1da5ef132c4..20b2b444087 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTable.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTable.go
@@ -37,14 +37,17 @@ type InitializeRoutingTable struct {
 	irtTable []*RoutingTableEntry
 }
 
-func NewInitializeRoutingTable(opts ...func(*InitializeRoutingTable)) (*InitializeRoutingTable, error) {
+func NewInitializeRoutingTable(args Args, kwArgs KWArgs, opts ...func(*InitializeRoutingTable)) (*InitializeRoutingTable, error) {
 	i := &InitializeRoutingTable{
 		messageType: 0x06,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMInitializeRoutingTable(i.produceNLMInitializeRoutingTablePortMapping()), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMInitializeRoutingTable(i.produceNLMInitializeRoutingTablePortMapping())
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTableAck.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTableAck.go
index 0b75989b259..2db11b28f16 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTableAck.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_InitializeRoutingTableAck.go
@@ -37,14 +37,17 @@ type InitializeRoutingTableAck struct {
 	irtaTable []*RoutingTableEntry
 }
 
-func NewInitializeRoutingTableAck(opts ...func(*InitializeRoutingTableAck)) (*InitializeRoutingTableAck, error) {
+func NewInitializeRoutingTableAck(args Args, kwArgs KWArgs, opts ...func(*InitializeRoutingTableAck)) (*InitializeRoutingTableAck, error) {
 	i := &InitializeRoutingTableAck{
 		messageType: 0x07,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMInitializeRoutingTableAck(i.produceNLMInitializeRoutingTableAckPortMapping()), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMInitializeRoutingTableAck(i.produceNLMInitializeRoutingTableAckPortMapping())
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPCI.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPCI.go
index 2dc01778ce5..89793061a5f 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPCI.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPCI.go
@@ -29,7 +29,6 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
@@ -78,19 +77,22 @@ type _NPCI struct {
 
 var _ NPCI = (*_NPCI)(nil)
 
-func NewNPCI(nlm readWriteModel.NLM, apdu readWriteModel.APDU) NPCI {
+func NewNPCI(args Args, kwArgs KWArgs) NPCI {
 	n := &_NPCI{
 		npduVersion: 1,
 	}
 	n.DebugContents = NewDebugContents(n, "npduVersion", "npduControl", "npduDADR", "npduSADR",
 		"npduHopCount", "npduNetMessage", "npduVendorID")
-	npdu, _ := n.buildNPDU(0, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE, nlm, apdu)
-	nkw := NKW(KWCompRootMessage, npdu)
-	if npdu == nil {
-		nkw = NoKWArgs()
-	}
-	n.PCI = NewPCI(NoArgs, nkw) // TODO: convert to args so we can solve all those todos
+	n.PCI = NewPCI(args, kwArgs)
 	n.AddExtraPrinters(n.PCI.(DebugContentPrinter))
+	if n.GetRootMessage() == nil {
+		nlm, nlmOk := KWO[readWriteModel.NLM](kwArgs, KWCompNLM, nil)
+		apdu, apduOk := KWO[readWriteModel.APDU](kwArgs, KWCompAPDU, nil)
+		if nlmOk || apduOk {
+			npdu, _ := n.buildNPDU(0, nil, nil, false, readWriteModel.NPDUNetworkPriority_NORMAL_MESSAGE, nlm, apdu)
+			n.SetRootMessage(npdu)
+		}
+	}
 	return n
 }
 
@@ -521,9 +523,7 @@ func (n *_NPCI) DeepCopy() any {
 }
 
 func (n *_NPCI) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("NPCI{%s}", n.PCI)
-	} else {
+	if IsDebuggingActive() {
 		npduDADRStr := ""
 		if n.npduDADR != nil {
 			npduDADRStr = "\nnpduDADR = " + n.npduDADR.String()
@@ -557,4 +557,5 @@ func (n *_NPCI) String() string {
 			npduVendorIDStr,
 		)
 	}
+	return fmt.Sprintf("NPCI{%s}", n.PCI)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPDU.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPDU.go
index b9301af40d1..99447705a83 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NPDU.go
@@ -28,7 +28,6 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi"
@@ -48,10 +47,9 @@ type _NPDU struct {
 
 var _ = (NPDU)(nil)
 
-// TODO: optimize with options and smart non-recoding...
-func NewNPDU(nlm readWriteModel.NLM, apdu readWriteModel.APDU) (NPDU, error) {
+func NewNPDU(args Args, kwArgs KWArgs) (NPDU, error) {
 	n := &_NPDU{}
-	n._NPCI = NewNPCI(nlm, apdu).(*_NPCI)
+	n._NPCI = NewNPCI(args, kwArgs).(*_NPCI)
 	n.PDUData = NewPDUData(NoArgs, NoKWArgs())
 	n.AddExtraPrinters(n.PDUData.(DebugContentPrinter))
 	if n.GetRootMessage() != nil {
@@ -229,10 +227,9 @@ func (n *_NPDU) DeepCopy() any {
 }
 
 func (n *_NPDU) String() string {
-	if ExtendedPDUOutput {
-		return fmt.Sprintf("NPDU{%s}", n._NPCI)
-	} else {
+	if IsDebuggingActive() {
 		npci := "\t" + strings.Join(strings.Split(n._NPCI.String(), "\n"), "\n\t")
 		return fmt.Sprintf("<NPDU instance at %p>%s\n\tpduData = %s", n, npci, Btox(n.GetPduData(), "."))
 	}
+	return fmt.Sprintf("NPDU{%s}", n._NPCI)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NetworkNumberIs.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NetworkNumberIs.go
index d7a03657db3..e2693692eb0 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NetworkNumberIs.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_NetworkNumberIs.go
@@ -38,14 +38,17 @@ type NetworkNumberIs struct {
 	nniFlag bool
 }
 
-func NewNetworkNumberIs(opts ...func(*NetworkNumberIs)) (*NetworkNumberIs, error) {
+func NewNetworkNumberIs(args Args, kwArgs KWArgs, opts ...func(*NetworkNumberIs)) (*NetworkNumberIs, error) {
 	n := &NetworkNumberIs{
 		messageType: 0x13,
 	}
 	for _, opt := range opts {
 		opt(n)
 	}
-	npdu, err := NewNPDU(model.NewNLMNetworkNumberIs(n.nniNet, n.nniFlag, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMNetworkNumberIs(n.nniNet, n.nniFlag, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RejectMessageToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RejectMessageToNetwork.go
index 1af39298711..013ff409824 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RejectMessageToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RejectMessageToNetwork.go
@@ -38,14 +38,17 @@ type RejectMessageToNetwork struct {
 	rmtnDNET            uint16
 }
 
-func NewRejectMessageToNetwork(opts ...func(*RejectMessageToNetwork)) (*RejectMessageToNetwork, error) {
+func NewRejectMessageToNetwork(args Args, kwArgs KWArgs, opts ...func(*RejectMessageToNetwork)) (*RejectMessageToNetwork, error) {
 	i := &RejectMessageToNetwork{
 		messageType: 0x03,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMRejectMessageToNetwork(i.rmtnRejectionReason, i.rmtnDNET, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMRejectMessageToNetwork(i.rmtnRejectionReason, i.rmtnDNET, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterAvailableToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterAvailableToNetwork.go
index d870f7d2a62..7db1061c2c1 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterAvailableToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterAvailableToNetwork.go
@@ -37,14 +37,17 @@ type RouterAvailableToNetwork struct {
 	ratnNetworkList []uint16
 }
 
-func NewRouterAvailableToNetwork(opts ...func(*RouterAvailableToNetwork)) (*RouterAvailableToNetwork, error) {
+func NewRouterAvailableToNetwork(args Args, kwArgs KWArgs, opts ...func(*RouterAvailableToNetwork)) (*RouterAvailableToNetwork, error) {
 	i := &RouterAvailableToNetwork{
 		messageType: 0x05,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMRouterAvailableToNetwork(i.ratnNetworkList, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMRouterAvailableToNetwork(i.ratnNetworkList, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterBusyToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterBusyToNetwork.go
index 019a01067bc..9de984eb0ca 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterBusyToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_RouterBusyToNetwork.go
@@ -37,14 +37,17 @@ type RouterBusyToNetwork struct {
 	rbtnNetworkList []uint16
 }
 
-func NewRouterBusyToNetwork(opts ...func(*RouterBusyToNetwork)) (*RouterBusyToNetwork, error) {
+func NewRouterBusyToNetwork(args Args, kwArgs KWArgs, opts ...func(*RouterBusyToNetwork)) (*RouterBusyToNetwork, error) {
 	i := &RouterBusyToNetwork{
 		messageType: 0x04,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMRouterBusyToNetwork(i.rbtnNetworkList, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMRouterBusyToNetwork(i.rbtnNetworkList, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhatIsNetworkNumber.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhatIsNetworkNumber.go
index e0eebcb1885..5d48540b921 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhatIsNetworkNumber.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhatIsNetworkNumber.go
@@ -35,14 +35,17 @@ type WhatIsNetworkNumber struct {
 	messageType uint8
 }
 
-func NewWhatIsNetworkNumber(opts ...func(*WhatIsNetworkNumber)) (*WhatIsNetworkNumber, error) {
+func NewWhatIsNetworkNumber(args Args, kwArgs KWArgs, opts ...func(*WhatIsNetworkNumber)) (*WhatIsNetworkNumber, error) {
 	i := &WhatIsNetworkNumber{
 		messageType: 0x12,
 	}
 	for _, opt := range opts {
 		opt(i)
 	}
-	npdu, err := NewNPDU(model.NewNLMWhatIsNetworkNumber(0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMWhatIsNetworkNumber(0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhoIsRouterToNetwork.go b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhoIsRouterToNetwork.go
index c285e461d98..b11fff9a640 100644
--- a/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhoIsRouterToNetwork.go
+++ b/plc4go/internal/bacnetip/bacgopes/npdu/npdu_WhoIsRouterToNetwork.go
@@ -37,14 +37,17 @@ type WhoIsRouterToNetwork struct {
 	wirtnNetwork *uint16
 }
 
-func NewWhoIsRouterToNetwork(opts ...func(network *WhoIsRouterToNetwork)) (*WhoIsRouterToNetwork, error) {
+func NewWhoIsRouterToNetwork(args Args, kwArgs KWArgs, opts ...func(network *WhoIsRouterToNetwork)) (*WhoIsRouterToNetwork, error) {
 	w := &WhoIsRouterToNetwork{
 		messageType: 0x00,
 	}
 	for _, opt := range opts {
 		opt(w)
 	}
-	npdu, err := NewNPDU(model.NewNLMWhoIsRouterToNetwork(w.wirtnNetwork, 0), nil)
+	if _, ok := kwArgs[KWCompNLM]; ok {
+		kwArgs[KWCompNLM] = model.NewNLMWhoIsRouterToNetwork(w.wirtnNetwork, 0)
+	}
+	npdu, err := NewNPDU(args, kwArgs)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/pdu/comm_PCI.go b/plc4go/internal/bacnetip/bacgopes/pdu/comm_PCI.go
index 0e1d79e9621..e5fbff192bf 100644
--- a/plc4go/internal/bacnetip/bacgopes/pdu/comm_PCI.go
+++ b/plc4go/internal/bacnetip/bacgopes/pdu/comm_PCI.go
@@ -21,6 +21,7 @@ package pdu
 
 import (
 	"context"
+	"fmt"
 
 	"github.com/pkg/errors"
 
@@ -60,9 +61,8 @@ func new__PCI(args Args, kwArgs KWArgs) *__PCI {
 	if _debug != nil {
 		_debug("__init__ %r %r", args, kwArgs)
 	}
-	i := &__PCI{
-		rootMessage: KWO[spi.Message](kwArgs, KWCompRootMessage, nil),
-	}
+	i := &__PCI{}
+	i.rootMessage, _ = KWO[spi.Message](kwArgs, KWCompRootMessage, nil)
 	delete(kwArgs, KWCompRootMessage)
 	i.DebugContents = NewDebugContents(i, "pduUserData+", "pduSource", "pduDestination")
 	var myKwargs = make(KWArgs)
@@ -78,15 +78,15 @@ func new__PCI(args Args, kwArgs KWArgs) *__PCI {
 		}
 	}
 	if _debug != nil {
-		_debug("    - my_kwArgs: %r", myKwargs)
+		_debug("    - my_kwargs: %r", myKwargs)
 	}
 	if _debug != nil {
-		_debug("    - other_kwArgs: %r", otherKwargs)
+		_debug("    - other_kwargs: %r", otherKwargs)
 	}
 
-	i.pduUserData = KWO[spi.Message](kwArgs, KWCPCIUserData, nil)
-	i.pduSource = KWO[*Address](kwArgs, KWCPCISource, nil)
-	i.pduDestination = KWO[*Address](kwArgs, KWCPCIDestination, nil)
+	i.pduUserData, _ = KWO[spi.Message](kwArgs, KWCPCIUserData, nil)
+	i.pduSource, _ = KWO[*Address](kwArgs, KWCPCISource, nil)
+	i.pduDestination, _ = KWO[*Address](kwArgs, KWCPCIDestination, nil)
 	return i
 }
 
@@ -205,5 +205,8 @@ func (p *__PCI) String() string {
 	if p.rootMessage == nil {
 		return "_PCI<nil>"
 	}
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", p) // Delegate
+	}
 	return p.rootMessage.String()
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_Address.go b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_Address.go
index 7be77949885..6146143ffcc 100644
--- a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_Address.go
+++ b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_Address.go
@@ -794,6 +794,10 @@ func (a *Address) Equals(other any) bool {
 }
 
 func (a *Address) Format(s fmt.State, v rune) {
+	if a == nil {
+		_, _ = fmt.Fprint(s, "<nil>")
+		return
+	}
 	switch v {
 	case 'r':
 		_, _ = fmt.Fprintf(s, "<%s %s>", StructName(), a.String())
@@ -802,108 +806,6 @@ func (a *Address) Format(s fmt.State, v rune) {
 	}
 }
 
-func (a *Address) AlternateString() (string, bool) {
-	if a == nil {
-		return "None", true
-	}
-	result := ""
-	if a.AddrType == NULL_ADDRESS {
-		result = "Null"
-	} else if a.AddrType == LOCAL_BROADCAST_ADDRESS {
-		result = "*"
-	} else if a.AddrType == LOCAL_STATION_ADDRESS {
-		if a.AddrLen != nil && *a.AddrLen == 1 {
-			result += fmt.Sprintf("%v", a.AddrAddress[0])
-		} else {
-			port := binary.BigEndian.Uint16(a.AddrAddress[len(a.AddrAddress)-2:])
-			if len(a.AddrAddress) == 6 && port >= 47808 && port <= 47823 {
-				var octests = make([]string, 4)
-				for i, address := range a.AddrAddress[0:4] {
-					octests[i] = fmt.Sprintf("%d", address)
-				}
-				result += fmt.Sprintf("%v", strings.Join(octests, "."))
-				if port != 47808 {
-					result += fmt.Sprintf(":%v", port)
-				}
-			} else {
-				result += fmt.Sprintf("0x%x", a.AddrAddress)
-			}
-		}
-	} else if a.AddrType == REMOTE_BROADCAST_ADDRESS {
-		result = fmt.Sprintf("%d:*", *a.AddrNet)
-	} else if a.AddrType == REMOTE_STATION_ADDRESS {
-		result = fmt.Sprintf("%d:", *a.AddrNet)
-		if a.AddrLen != nil && *a.AddrLen == 1 {
-			result += fmt.Sprintf("%v", a.AddrAddress[0])
-		} else {
-			port := binary.BigEndian.Uint16(a.AddrAddress[len(a.AddrAddress)-2:])
-			if len(a.AddrAddress) == 6 && port >= 47808 && port <= 47823 {
-				var octests = make([]string, 4)
-				for i, address := range a.AddrAddress[0:4] {
-					octests[i] = fmt.Sprintf("%d", address)
-				}
-				result += fmt.Sprintf("%v", strings.Join(octests, "."))
-				if port != 47808 {
-					result += fmt.Sprintf(":%v", port)
-				}
-			} else {
-				result += fmt.Sprintf("0x%x", a.AddrAddress)
-			}
-		}
-	} else if a.AddrType == GLOBAL_BROADCAST_ADDRESS {
-		result = "*:*"
-	} else {
-		panic("Unknown address type: " + a.AddrType.String())
-	}
-
-	if a.AddrRoute != nil {
-		result += fmt.Sprintf("@%s", a.AddrRoute)
-	}
-	return result, true
-}
-
-func (a *Address) GoString() string { //TODO: not valid yet, needs adjustments to have proper output syntax
-	if a == nil {
-		return "<nil>"
-	}
-	var sb strings.Builder
-	sb.WriteString(a.AddrType.String())
-	if a.AddrNet != nil {
-		_, _ = fmt.Fprintf(&sb, ", net: %d", *a.AddrNet)
-	}
-	if len(a.AddrAddress) > 0 {
-		_, _ = fmt.Fprintf(&sb, ", address: %d", a.AddrAddress)
-	}
-	if a.AddrLen != nil {
-		_, _ = fmt.Fprintf(&sb, " with len %d", *a.AddrLen)
-	}
-	if a.AddrRoute != nil {
-		_, _ = fmt.Fprintf(&sb, ", route: %s", a.AddrRoute)
-	}
-	if a.AddrIP != nil {
-		_, _ = fmt.Fprintf(&sb, ", ip: %d", *a.AddrIP)
-	}
-	if a.AddrMask != nil {
-		_, _ = fmt.Fprintf(&sb, ", mask: %d", *a.AddrMask)
-	}
-	if a.AddrHost != nil {
-		_, _ = fmt.Fprintf(&sb, ", host: %d", *a.AddrHost)
-	}
-	if a.AddrSubnet != nil {
-		_, _ = fmt.Fprintf(&sb, ", subnet: %d", *a.AddrSubnet)
-	}
-	if a.AddrPort != nil {
-		_, _ = fmt.Fprintf(&sb, ", port: %d", *a.AddrPort)
-	}
-	if a.AddrTuple != nil {
-		_, _ = fmt.Fprintf(&sb, ", tuple: %s", a.AddrTuple)
-	}
-	if a.AddrBroadcastTuple != nil {
-		_, _ = fmt.Fprintf(&sb, ", broadcast tuple: %s", a.AddrBroadcastTuple)
-	}
-	return sb.String()
-}
-
 func (a *Address) deepCopy() *Address {
 	if a == nil {
 		return nil
@@ -927,3 +829,66 @@ func (a *Address) deepCopy() *Address {
 func (a *Address) DeepCopy() any {
 	return a.deepCopy()
 }
+
+func (a *Address) AlternateString() (string, bool) {
+	if IsDebuggingActive() || true { // TODO: figure out what to do when we want the below string in testing etc...
+		if a == nil {
+			return "<nil>", true
+		}
+		result := ""
+		if a.AddrType == NULL_ADDRESS {
+			result = "Null"
+		} else if a.AddrType == LOCAL_BROADCAST_ADDRESS {
+			result = "*"
+		} else if a.AddrType == LOCAL_STATION_ADDRESS {
+			if a.AddrLen != nil && *a.AddrLen == 1 {
+				result += fmt.Sprintf("%v", a.AddrAddress[0])
+			} else {
+				port := binary.BigEndian.Uint16(a.AddrAddress[len(a.AddrAddress)-2:])
+				if len(a.AddrAddress) == 6 && port >= 47808 && port <= 47823 {
+					var octests = make([]string, 4)
+					for i, address := range a.AddrAddress[0:4] {
+						octests[i] = fmt.Sprintf("%d", address)
+					}
+					result += fmt.Sprintf("%v", strings.Join(octests, "."))
+					if port != 47808 {
+						result += fmt.Sprintf(":%v", port)
+					}
+				} else {
+					result += fmt.Sprintf("0x%x", a.AddrAddress)
+				}
+			}
+		} else if a.AddrType == REMOTE_BROADCAST_ADDRESS {
+			result = fmt.Sprintf("%d:*", *a.AddrNet)
+		} else if a.AddrType == REMOTE_STATION_ADDRESS {
+			result = fmt.Sprintf("%d:", *a.AddrNet)
+			if a.AddrLen != nil && *a.AddrLen == 1 {
+				result += fmt.Sprintf("%v", a.AddrAddress[0])
+			} else {
+				port := binary.BigEndian.Uint16(a.AddrAddress[len(a.AddrAddress)-2:])
+				if len(a.AddrAddress) == 6 && port >= 47808 && port <= 47823 {
+					var octests = make([]string, 4)
+					for i, address := range a.AddrAddress[0:4] {
+						octests[i] = fmt.Sprintf("%d", address)
+					}
+					result += fmt.Sprintf("%v", strings.Join(octests, "."))
+					if port != 47808 {
+						result += fmt.Sprintf(":%v", port)
+					}
+				} else {
+					result += fmt.Sprintf("0x%x", a.AddrAddress)
+				}
+			}
+		} else if a.AddrType == GLOBAL_BROADCAST_ADDRESS {
+			result = "*:*"
+		} else {
+			panic("Unknown address type: " + a.AddrType.String())
+		}
+
+		if a.AddrRoute != nil {
+			result += fmt.Sprintf("@%s", a.AddrRoute)
+		}
+		return result, true
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PCI.go b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PCI.go
index 52dcc2753d3..90f1f4dc9b4 100644
--- a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PCI.go
+++ b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PCI.go
@@ -62,15 +62,17 @@ func NewPCI(args Args, kwArgs KWArgs) *_PCI {
 		}
 	}
 	if _debug != nil {
-		_debug("    - my_kwArgs: %r", myKwargs)
+		_debug("    - my_kwargs: %r", myKwargs)
 	}
 	if _debug != nil {
-		_debug("    - other_kwArgs: %r", otherKwargs)
+		_debug("    - other_kwargs: %r", otherKwargs)
 	}
+	expectingReply, _ := KWO(kwArgs, KWPCIExpectingReply, false)
+	networkPriority, _ := KWO(kwArgs, KWPCINetworkPriority, model.NPDUNetworkPriority_NORMAL_MESSAGE)
 	i := &_PCI{
-		new__PCI(args, otherKwargs),
-		KWO(myKwargs, KWPCIExpectingReply, false),
-		KWO(myKwargs, KWPCINetworkPriority, model.NPDUNetworkPriority_NORMAL_MESSAGE),
+		new__PCI(args, kwArgs),
+		expectingReply,
+		networkPriority,
 	}
 	i.AddDebugContents(i, "pduExpectingReply", "pduNetworkPriority")
 	return i
diff --git a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PDU.go b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PDU.go
index e72e6c8628b..96c9a492720 100644
--- a/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PDU.go
+++ b/plc4go/internal/bacnetip/bacgopes/pdu/pdu_PDU.go
@@ -34,9 +34,9 @@ type PDU interface {
 }
 
 type _PDU struct {
-	*DefaultRFormatter
 	*_PCI
 	*_PDUData
+	*DefaultRFormatter
 }
 
 func NewPDU(args Args, kwArgs KWArgs) PDU {
@@ -55,7 +55,7 @@ func (p *_PDU) GetRootMessage() spi.Message {
 }
 
 func (p *_PDU) deepCopy() *_PDU {
-	pduCopy := &_PDU{p.DefaultRFormatter, p._PCI.deepCopy(), p._PDUData.deepCopy()}
+	pduCopy := &_PDU{p._PCI.deepCopy(), p._PDUData.deepCopy(), p.DefaultRFormatter}
 	return pduCopy
 }
 
@@ -73,5 +73,5 @@ func (p *_PDU) Format(s fmt.State, v rune) {
 }
 
 func (p *_PDU) String() string {
-	return fmt.Sprintf("<%T %s -> %s : %s>", p, p.GetPDUSource(), p.GetPDUDestination(), p._PDUData)
+	return fmt.Sprintf("<%s %s -> %s : %s>", StructName(), p.GetPDUSource(), p.GetPDUDestination(), p._PDUData)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/primitivedata/primitivedata_Unsigned.go b/plc4go/internal/bacnetip/bacgopes/primitivedata/primitivedata_Unsigned.go
index 6dcd7aef1e9..f481dd66182 100644
--- a/plc4go/internal/bacnetip/bacgopes/primitivedata/primitivedata_Unsigned.go
+++ b/plc4go/internal/bacnetip/bacgopes/primitivedata/primitivedata_Unsigned.go
@@ -28,19 +28,19 @@ import (
 	"github.com/pkg/errors"
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
 type Unsigned struct {
 	*Atomic[uint32]
 	*CommonMath
 
-	_appTag model.BACnetDataType
+	_appTag readWriteModel.BACnetDataType
 }
 
 func NewUnsigned(arg Arg) (*Unsigned, error) {
 	i := &Unsigned{
-		_appTag: model.BACnetDataType_UNSIGNED_INTEGER,
+		_appTag: readWriteModel.BACnetDataType_UNSIGNED_INTEGER,
 	}
 	i.Atomic = NewAtomic[uint32](i)
 
@@ -54,6 +54,10 @@ func NewUnsigned(arg Arg) (*Unsigned, error) {
 			return nil, errors.Wrap(err, "error decoding")
 		}
 		return i, nil
+	case uint8:
+		i.value = uint32(arg)
+	case uint16:
+		i.value = uint32(arg)
 	case uint32:
 		i.value = arg
 	case uint:
@@ -73,6 +77,10 @@ func NewUnsigned(arg Arg) (*Unsigned, error) {
 		i.value = uint32(arg)
 	case *Unsigned:
 		i.value = arg.value
+	case *readWriteModel.MaxApduLengthAccepted:
+		if arg != nil {
+			i.value = uint32(*arg)
+		}
 	default:
 		return nil, errors.Errorf("invalid constructor datatype: %T", arg)
 	}
@@ -80,7 +88,7 @@ func NewUnsigned(arg Arg) (*Unsigned, error) {
 	return i, nil
 }
 
-func (u *Unsigned) GetAppTag() model.BACnetDataType {
+func (u *Unsigned) GetAppTag() readWriteModel.BACnetDataType {
 	return u._appTag
 }
 
@@ -106,7 +114,7 @@ func (u *Unsigned) Decode(arg Arg) error {
 	if !ok {
 		return errors.Errorf("%T is not a Tag", arg)
 	}
-	if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(u._appTag) {
+	if tag.GetTagClass() != readWriteModel.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(u._appTag) {
 		return errors.New("Unsigned application tag required")
 	}
 	if len(tag.GetTagData()) == 0 {
diff --git a/plc4go/internal/bacnetip/bacgopes/service/service.go b/plc4go/internal/bacnetip/bacgopes/service/service.go
new file mode 100644
index 00000000000..51d0c69c679
--- /dev/null
+++ b/plc4go/internal/bacnetip/bacgopes/service/service.go
@@ -0,0 +1,24 @@
+/*
+ * 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 service
+
+import . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
+
+var _debug = CreateDebugPrinter()
diff --git a/plc4go/internal/bacnetip/bacgopes/service/service_device_WhoIsIAmServices.go b/plc4go/internal/bacnetip/bacgopes/service/service_device_WhoIsIAmServices.go
index 05577400ee7..f2fe1ee98e7 100644
--- a/plc4go/internal/bacnetip/bacgopes/service/service_device_WhoIsIAmServices.go
+++ b/plc4go/internal/bacnetip/bacgopes/service/service_device_WhoIsIAmServices.go
@@ -30,6 +30,7 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/local/device"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
+	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
@@ -56,10 +57,16 @@ func NewWhoIsIAmServices(localLog zerolog.Logger, whoIsIAmServicesRequirements W
 	for _, opt := range opts {
 		opt(w)
 	}
+	if _debug != nil {
+		_debug("__init__")
+	}
 	w.Capability = NewCapability()
 	if err := w._requirements.RegisterHelperFn(fmt.Sprintf("Do_%T", &WhoIsRequest{}), w.DoWhoIsRequest); err != nil {
 		return nil, errors.Wrap(err, "registering function failed")
 	}
+	if err := w._requirements.RegisterHelperFn(fmt.Sprintf("Do_%T", &IAmRequest{}), w.DoIAmRequest); err != nil {
+		return nil, errors.Wrap(err, "registering function failed")
+	}
 	return w, nil
 }
 
@@ -70,6 +77,9 @@ func WithWhoIsIAmServicesLocalDevice(localDevice *LocalDeviceObject) func(*WhoIs
 }
 
 func (w *WhoIsIAmServices) Startup() error {
+	if _debug != nil {
+		_debug("startup")
+	}
 	w.log.Debug().Msg("Startup")
 
 	// send a global broadcast I-Am
@@ -77,6 +87,9 @@ func (w *WhoIsIAmServices) Startup() error {
 }
 
 func (w *WhoIsIAmServices) WhoIs(lowLimit, highLimit *uint, address *Address) error {
+	if _debug != nil {
+		_debug("who_is")
+	}
 	w.log.Debug().Msg("WhoIs")
 
 	var deviceInstanceRangeLowLimit, deviceInstanceRangeHighLimit uint
@@ -106,6 +119,9 @@ func (w *WhoIsIAmServices) WhoIs(lowLimit, highLimit *uint, address *Address) er
 	// Build a request
 	whoIs := readWriteModel.NewBACnetUnconfirmedServiceRequestWhoIs(readWriteModel.CreateBACnetContextTagUnsignedInteger(0, deviceInstanceRangeLowLimit), readWriteModel.CreateBACnetContextTagUnsignedInteger(1, deviceInstanceRangeHighLimit), 0)
 
+	if _debug != nil {
+		_debug("    - whoIs: %r", whoIs)
+	}
 	w.log.Debug().Stringer("whoIs", whoIs).Msg("WhoIs")
 
 	return w._requirements.Request(NA(NewPDU(NoArgs, NKW(KWCompRootMessage, whoIs, KWCPCIDestination, address))), NoKWArgs())
@@ -113,11 +129,18 @@ func (w *WhoIsIAmServices) WhoIs(lowLimit, highLimit *uint, address *Address) er
 
 // DoWhoIsRequest respond to a Who-Is request.
 func (w *WhoIsIAmServices) DoWhoIsRequest(apdu APDU) error {
+	if _debug != nil {
+		_debug("do_WhoIsRequest %r", apdu)
+	}
 	w.log.Debug().Stringer("apdu", apdu).Msg("DoWhoIsRequest")
 
 	// ignore this if there's no local device
 	if w.localDevice == nil {
+		if _debug != nil {
+			_debug("    - no local device")
+		}
 		w.log.Debug().Msg("No local device")
+		return nil
 	}
 
 	// TODO: ugly hacky hacky, better feat from the orginal api
@@ -168,10 +191,16 @@ func (w *WhoIsIAmServices) DoWhoIsRequest(apdu APDU) error {
 }
 
 func (w *WhoIsIAmServices) IAm(address *Address) error {
+	if _debug != nil {
+		_debug("i_am")
+	}
 	w.log.Debug().Msg("IAm")
 
 	// this requires a local device
 	if w.localDevice == nil {
+		if _debug != nil {
+			_debug("    - no local device")
+		}
 		w.log.Debug().Msg("no local device")
 		return nil
 	}
@@ -194,13 +223,48 @@ func (w *WhoIsIAmServices) IAm(address *Address) error {
 		address = NewGlobalBroadcast(nil)
 	}
 	iAm.SetPDUDestination(address)
+	if _debug != nil {
+		_debug("    - iAm: %r", iAm)
+	}
 	w.log.Debug().Stringer("iAm", iAm).Msg("IAm")
 
-	return w._requirements.Request(NA(NewPDU(NoArgs, NKW(KWCompRootMessage, iAm, KWCPCIDestination, address))), NoKWArgs())
+	return w._requirements.Request(NA(iAm), NoKWArgs())
 }
 
 // DoIAmRequest responds to an I-Am request.
-func (w *WhoIsIAmServices) DoIAmRequest(apdu PDU) error {
-	// TODO: implement me... upstream impl empty
+func (w *WhoIsIAmServices) DoIAmRequest(apdu APDU) error {
+	if _debug != nil {
+		_debug("do_IAmRequest %r", apdu)
+	}
+	iam := apdu.(*IAmRequest)
+	// check for required parameters
+	if _, ok := iam.GetAttr("iAmDeviceIdentifier"); !ok {
+		return MissingRequiredParameter{Message: "iAmDeviceIdentifier required"}
+	}
+	if _, ok := iam.GetAttr("maxAPDULengthAccepted"); !ok {
+		return MissingRequiredParameter{Message: "maxAPDULengthAccepted required"}
+	}
+	if _, ok := iam.GetAttr("segmentationSupported"); !ok {
+		return MissingRequiredParameter{Message: "segmentationSupported required"}
+	}
+	if _, ok := iam.GetAttr("vendorID"); !ok {
+		return MissingRequiredParameter{Message: "vendorID required"}
+	}
+
+	// extract the device instance number
+	deviceIdentifier, _ := iam.GetAttr("iAmDeviceIdentifier")
+	deviceInstance := deviceIdentifier.(*primitivedata.ObjectIdentifier).GetValue().Right
+	if _debug != nil {
+		_debug("    - device_instance: %r", deviceInstance)
+	}
+
+	// extract the source address
+	deviceAddress := apdu.GetPDUSource()
+	if _debug != nil {
+		_debug("    - device_address: %r", deviceAddress)
+	}
+
+	////// check to see if the application is looking for this device
+	////// and update the device info cache if it is
 	return nil
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/quick/apdu.go b/plc4go/internal/bacnetip/bacgopes/tests/quick/apdu.go
index aa3b6409337..562fe3ababa 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/quick/apdu.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/quick/apdu.go
@@ -33,7 +33,7 @@ func ConfirmedPrivateTransferRequest(kwArgs KWArgs) *apdu.ConfirmedPrivateTransf
 }
 
 func WhoIsRequest(kwArgs KWArgs) *apdu.WhoIsRequest {
-	whoIsRequest, err := apdu.NewWhoIsRequest()
+	whoIsRequest, err := apdu.NewWhoIsRequest(NoArgs, kwArgs)
 	if err != nil {
 		panic(err)
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/quick/npdu.go b/plc4go/internal/bacnetip/bacgopes/tests/quick/npdu.go
index 6a4cf76bb91..a3059eaeb1a 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/quick/npdu.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/quick/npdu.go
@@ -20,12 +20,13 @@
 package quick
 
 import (
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/npdu"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 )
 
 func WhoIsRouterToNetwork(net uint16) *npdu.WhoIsRouterToNetwork {
-	network, err := npdu.NewWhoIsRouterToNetwork(npdu.WithWhoIsRouterToNetworkNet(net))
+	network, err := npdu.NewWhoIsRouterToNetwork(NoArgs, NoKWArgs(), npdu.WithWhoIsRouterToNetworkNet(net))
 	if err != nil {
 		panic(err)
 	}
@@ -33,7 +34,7 @@ func WhoIsRouterToNetwork(net uint16) *npdu.WhoIsRouterToNetwork {
 }
 
 func IAmRouterToNetwork(netList ...uint16) *npdu.IAmRouterToNetwork {
-	network, err := npdu.NewIAmRouterToNetwork(npdu.WithIAmRouterToNetworkNetworkList(netList...))
+	network, err := npdu.NewIAmRouterToNetwork(NoArgs, NoKWArgs(), npdu.WithIAmRouterToNetworkNetworkList(netList...))
 	if err != nil {
 		panic(err)
 	}
@@ -41,7 +42,7 @@ func IAmRouterToNetwork(netList ...uint16) *npdu.IAmRouterToNetwork {
 }
 
 func ICouldBeRouterToNetwork(net uint16, perf uint8) *npdu.ICouldBeRouterToNetwork {
-	network, err := npdu.NewICouldBeRouterToNetwork(npdu.WithICouldBeRouterToNetworkNetwork(net), npdu.WithICouldBeRouterToNetworkPerformanceIndex(perf))
+	network, err := npdu.NewICouldBeRouterToNetwork(NoArgs, NoKWArgs(), npdu.WithICouldBeRouterToNetworkNetwork(net), npdu.WithICouldBeRouterToNetworkPerformanceIndex(perf))
 	if err != nil {
 		panic(err)
 	}
@@ -49,7 +50,7 @@ func ICouldBeRouterToNetwork(net uint16, perf uint8) *npdu.ICouldBeRouterToNetwo
 }
 
 func RejectMessageToNetwork(reason uint8, dnet uint16) *npdu.RejectMessageToNetwork {
-	network, err := npdu.NewRejectMessageToNetwork(npdu.WithRejectMessageToNetworkRejectionReason(readWriteModel.NLMRejectMessageToNetworkRejectReason(reason)), npdu.WithRejectMessageToNetworkDnet(dnet))
+	network, err := npdu.NewRejectMessageToNetwork(NoArgs, NoKWArgs(), npdu.WithRejectMessageToNetworkRejectionReason(readWriteModel.NLMRejectMessageToNetworkRejectReason(reason)), npdu.WithRejectMessageToNetworkDnet(dnet))
 	if err != nil {
 		panic(err)
 	}
@@ -57,7 +58,7 @@ func RejectMessageToNetwork(reason uint8, dnet uint16) *npdu.RejectMessageToNetw
 }
 
 func RouterBusyToNetwork(netList ...uint16) *npdu.RouterBusyToNetwork {
-	network, err := npdu.NewRouterBusyToNetwork(npdu.WithRouterBusyToNetworkDnet(netList))
+	network, err := npdu.NewRouterBusyToNetwork(NoArgs, NoKWArgs(), npdu.WithRouterBusyToNetworkDnet(netList))
 	if err != nil {
 		panic(err)
 	}
@@ -65,7 +66,7 @@ func RouterBusyToNetwork(netList ...uint16) *npdu.RouterBusyToNetwork {
 }
 
 func RouterAvailableToNetwork(netList ...uint16) *npdu.RouterAvailableToNetwork {
-	network, err := npdu.NewRouterAvailableToNetwork(npdu.WithRouterAvailableToNetworkDnet(netList))
+	network, err := npdu.NewRouterAvailableToNetwork(NoArgs, NoKWArgs(), npdu.WithRouterAvailableToNetworkDnet(netList))
 	if err != nil {
 		panic(err)
 	}
@@ -73,7 +74,7 @@ func RouterAvailableToNetwork(netList ...uint16) *npdu.RouterAvailableToNetwork
 }
 
 func InitializeRoutingTable(irtTable ...*npdu.RoutingTableEntry) *npdu.InitializeRoutingTable {
-	network, err := npdu.NewInitializeRoutingTable(npdu.WithInitializeRoutingTableIrtTable(irtTable...))
+	network, err := npdu.NewInitializeRoutingTable(NoArgs, NoKWArgs(), npdu.WithInitializeRoutingTableIrtTable(irtTable...))
 	if err != nil {
 		panic(err)
 	}
@@ -89,7 +90,7 @@ func RoutingTableEntry(address uint16, portId uint8, portInfo []byte) *npdu.Rout
 }
 
 func InitializeRoutingTableAck(irtaTable ...*npdu.RoutingTableEntry) *npdu.InitializeRoutingTableAck {
-	network, err := npdu.NewInitializeRoutingTableAck(npdu.WithInitializeRoutingTableAckIrtaTable(irtaTable...))
+	network, err := npdu.NewInitializeRoutingTableAck(NoArgs, NoKWArgs(), npdu.WithInitializeRoutingTableAckIrtaTable(irtaTable...))
 	if err != nil {
 		panic(err)
 	}
@@ -97,7 +98,7 @@ func InitializeRoutingTableAck(irtaTable ...*npdu.RoutingTableEntry) *npdu.Initi
 }
 
 func EstablishConnectionToNetwork(dnet uint16, terminationTime uint8) *npdu.EstablishConnectionToNetwork {
-	network, err := npdu.NewEstablishConnectionToNetwork(npdu.WithEstablishConnectionToNetworkDNET(dnet), npdu.WithEstablishConnectionToNetworkTerminationTime(terminationTime))
+	network, err := npdu.NewEstablishConnectionToNetwork(NoArgs, NoKWArgs(), npdu.WithEstablishConnectionToNetworkDNET(dnet), npdu.WithEstablishConnectionToNetworkTerminationTime(terminationTime))
 	if err != nil {
 		panic(err)
 	}
@@ -105,7 +106,7 @@ func EstablishConnectionToNetwork(dnet uint16, terminationTime uint8) *npdu.Esta
 }
 
 func DisconnectConnectionToNetwork(dnet uint16) *npdu.DisconnectConnectionToNetwork {
-	network, err := npdu.NewDisconnectConnectionToNetwork(npdu.WithDisconnectConnectionToNetworkDNET(dnet))
+	network, err := npdu.NewDisconnectConnectionToNetwork(NoArgs, NoKWArgs(), npdu.WithDisconnectConnectionToNetworkDNET(dnet))
 	if err != nil {
 		panic(err)
 	}
@@ -113,7 +114,7 @@ func DisconnectConnectionToNetwork(dnet uint16) *npdu.DisconnectConnectionToNetw
 }
 
 func WhatIsNetworkNumber(dnet uint16) *npdu.WhatIsNetworkNumber {
-	network, err := npdu.NewWhatIsNetworkNumber()
+	network, err := npdu.NewWhatIsNetworkNumber(NoArgs, NoKWArgs()) // TODO: something is odd here...
 	if err != nil {
 		panic(err)
 	}
@@ -121,7 +122,7 @@ func WhatIsNetworkNumber(dnet uint16) *npdu.WhatIsNetworkNumber {
 }
 
 func NetworkNumberIs(net uint16, flag bool) *npdu.NetworkNumberIs {
-	network, err := npdu.NewNetworkNumberIs(npdu.WithNetworkNumberIsNET(net), npdu.WithNetworkNumberIsTerminationConfigured(flag))
+	network, err := npdu.NewNetworkNumberIs(NoArgs, NoKWArgs(), npdu.WithNetworkNumberIsNET(net), npdu.WithNetworkNumberIsTerminationConfigured(flag))
 	if err != nil {
 		panic(err)
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_ClientStateMachine.go b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_ClientStateMachine.go
index 69bb4d7efd0..d70e75f9b31 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_ClientStateMachine.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_ClientStateMachine.go
@@ -27,7 +27,7 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
+	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 )
 
@@ -116,8 +116,8 @@ func (s *ClientStateMachine) Confirmation(args Args, kwArgs KWArgs) error {
 }
 
 func (s *ClientStateMachine) AlternateString() (string, bool) {
-	if ExtendedGeneralOutput {
-		return "", false
+	if IsDebuggingActive() {
+		return s.StateMachineContract.String(), true
 	}
-	return s.StateMachineContract.String(), true
+	return "", false
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_State.go b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_State.go
index 6d57d2c6744..c23df81494e 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_State.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_State.go
@@ -28,7 +28,6 @@ import (
 
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/globals"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/task"
 )
@@ -574,9 +573,8 @@ func (s *state) String() string {
 	if s == nil {
 		return "<nil>(*state)"
 	}
-	if ExtendedGeneralOutput {
-		return fmt.Sprintf("state(doc: %s, successState: %t, isFailState: %t)", s.docString, s.isSuccessState, s.isFailState)
-	} else {
-		return fmt.Sprintf("<%T(%s) at %p>", s, s.docString, s)
+	if IsDebuggingActive() {
+		return fmt.Sprintf("%s", s) // Delegate to format
 	}
+	return fmt.Sprintf("state(doc: %s, successState: %t, isFailState: %t)", s.docString, s.isSuccessState, s.isFailState)
 }
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_StateMachine.go b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_StateMachine.go
index bde4a2af9bc..922de8f1dbd 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_StateMachine.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_StateMachine.go
@@ -86,7 +86,7 @@ type StateMachineRequirements interface {
 type stateMachine struct {
 	requirements StateMachineRequirements `ignore:"true"`
 
-	interceptor    StateInterceptor
+	interceptor    StateInterceptor `asPtr:"true"`
 	stateDecorator func(state State) State
 
 	states                 []State
@@ -841,26 +841,6 @@ func (s *stateMachine) IsFailState() bool {
 	return *s.isFailState
 }
 
-func (s *stateMachine) AlternateString() (string, bool) {
-	var stateText = ""
-	if s.currentState == nil {
-		stateText = "not started"
-	} else if s.isSuccessState != nil && *s.isSuccessState {
-		stateText = "success"
-	} else if s.isFailState != nil && *s.isFailState {
-		stateText = "fail"
-	} else if !s.running {
-		stateText = "idle"
-	} else {
-		stateText = "in"
-	}
-	if s.currentState != nil {
-		stateText += " " + s.currentState.String()
-	}
-
-	return fmt.Sprintf("<%s(%s) %s at %p>", TypeName(s.requirements), s.name, stateText, s), true
-}
-
 func (s *stateMachine) Format(state fmt.State, verb rune) {
 	switch verb {
 	case 's', 'v':
@@ -870,3 +850,26 @@ func (s *stateMachine) Format(state fmt.State, verb rune) {
 		_, _ = state.Write([]byte(alternateString))
 	}
 }
+
+func (s *stateMachine) AlternateString() (string, bool) {
+	if IsDebuggingActive() {
+		var stateText = ""
+		if s.currentState == nil {
+			stateText = "not started"
+		} else if s.isSuccessState != nil && *s.isSuccessState {
+			stateText = "success"
+		} else if s.isFailState != nil && *s.isFailState {
+			stateText = "fail"
+		} else if !s.running {
+			stateText = "idle"
+		} else {
+			stateText = "in"
+		}
+		if s.currentState != nil {
+			stateText += " " + s.currentState.String()
+		}
+
+		return fmt.Sprintf("<%s(%s) %s at %p>", TypeName(s.requirements), s.name, stateText, s), true
+	}
+	return "", false
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_stateMachine_plc4xgen.go b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_stateMachine_plc4xgen.go
index abf92d3be15..3e53cdecf77 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_stateMachine_plc4xgen.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/state_machine/state_machine_stateMachine_plc4xgen.go
@@ -48,12 +48,9 @@ func (d *stateMachine) SerializeWithWriteBuffer(ctx context.Context, writeBuffer
 	if err := writeBuffer.PushContext("stateMachine"); err != nil {
 		return err
 	}
-	{
-		_value := fmt.Sprintf("%v", d.interceptor)
 
-		if err := writeBuffer.WriteString("interceptor", uint32(len(_value)*8), _value); err != nil {
-			return err
-		}
+	if err := writeBuffer.WriteString("interceptor", uint32(len(fmt.Sprintf("%p", d.interceptor))*8), fmt.Sprintf("%p", d.interceptor)); err != nil {
+		return err
 	}
 
 	if err := writeBuffer.WriteBit("stateDecorator", d.stateDecorator != nil); err != nil {
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDApplication.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDApplication.go
index 45f8b3288ac..3e539aa7481 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDApplication.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDApplication.go
@@ -80,7 +80,7 @@ func NewBIPBBMDApplication(localLog zerolog.Logger, address string, vlan *IPNetw
 	}
 
 	// continue with initialization
-	b.Application, err = NewApplication(localLog, localDevice.LocalDeviceObject) //TODO: this is a indirection that wasn't intended... we don't use the annotation yet so that might be fine
+	b.Application, err = NewApplication(localLog, WithApplicationLocalDeviceObject(localDevice.LocalDeviceObject)) //TODO: this is a indirection that wasn't intended... we don't use the annotation yet so that might be fine
 	if err != nil {
 		return nil, errors.Wrap(err, "error building application")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDStateMachine.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDStateMachine.go
index e7becd8aee5..dcf4ea16b72 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDStateMachine.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_BIPBBMDStateMachine.go
@@ -70,6 +70,9 @@ func NewBIPBBMDStateMachine(localLog zerolog.Logger, address string, vlan *IPNet
 
 	// build an address, full mask
 	bdtAddress := fmt.Sprintf("%s/32:%d", b.address.AddrTuple.Left, b.address.AddrTuple.Right)
+	if _debug != nil {
+		_debug("    - bdt_address: %r", bdtAddress)
+	}
 	b.log.Debug().Str("bdtAddress", bdtAddress).Msg("bdtAddress")
 
 	// add itself as the first entry in the BDT
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_FauxMultiplexer.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_FauxMultiplexer.go
index 17c805d75eb..257f6932ca1 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_FauxMultiplexer.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_FauxMultiplexer.go
@@ -32,9 +32,9 @@ import (
 
 //go:generate plc4xGenerator -type=FauxMultiplexer -prefix=helpers_
 type FauxMultiplexer struct {
-	*DefaultRFormatter `ignore:"true"`
 	ClientContract
 	ServerContract
+	*DefaultRFormatter `ignore:"true"`
 
 	address        *Address
 	unicastTuple   *AddressTuple[string, uint16]
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_SnifferStateMachine.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_SnifferStateMachine.go
index f7059f5fc46..4ba2502bbf5 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_SnifferStateMachine.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/helpers_SnifferStateMachine.go
@@ -26,14 +26,12 @@ import (
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/bvllservice"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comm"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/tests/state_machine"
 	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/vlan"
 )
 
 type SnifferStateMachine struct {
-	*DefaultRFormatter `ignore:"true"`
 	*ClientStateMachine
 
 	address *Address
@@ -45,8 +43,7 @@ type SnifferStateMachine struct {
 
 func NewSnifferStateMachine(localLog zerolog.Logger, address string, vlan *IPNetwork) (*SnifferStateMachine, error) {
 	s := &SnifferStateMachine{
-		DefaultRFormatter: NewDefaultRFormatter(),
-		log:               localLog,
+		log: localLog,
 	}
 	if _debug != nil {
 		_debug("__init__ %r %r", address, vlan)
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_codec_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_codec_test.go
index 6b35f9da90b..75fc190bd72 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_codec_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_codec_test.go
@@ -396,7 +396,6 @@ func (suite *TestAnnexJCodecSuite) TestDeleteForeignDeviceTableEntry() {
 
 func (suite *TestAnnexJCodecSuite) TestDeleteForeignDeviceTableAck() {
 	// TODO: implement me
-	suite.T().Skip()
 }
 
 func (suite *TestAnnexJCodecSuite) TestDistributeBroadcastToNetwork() {
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_foreign_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_foreign_test.go
index 82b366375eb..ee814225595 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_foreign_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_bvll/test_foreign_test.go
@@ -264,7 +264,6 @@ func TestForeign(t *testing.T) {
 		tnet.Run(0)
 	})
 	t.Run("test_broadcast", func(t *testing.T) { //Test a broadcast message from TD to IUT.
-		t.Skip("needs more work before it can do something") // TODO: implement me
 		ExclusiveGlobalTimeMachine(t)
 		testingLogger := testutils.ProduceTestingLogger(t)
 
@@ -280,7 +279,7 @@ func TestForeign(t *testing.T) {
 		tnet.fd.GetStartState().Doc("4-1-0").
 			Call(func(args Args, _ KWArgs) error {
 				return tnet.fd.bip.Register(args[0].(*Address), args[1].(uint16))
-			}, NA(tnet.bbmd.address, 60), NoKWArgs()).Doc("4-1-1").
+			}, NA(tnet.bbmd.address, uint16(60)), NoKWArgs()).Doc("4-1-1").
 			WaitEvent("4-registered", nil).Doc("4-1-2").
 			Send(pdu, nil).Doc("4-1-3").
 			Success("")
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers.go
index c80b75f977d..73b7326ffd1 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers.go
@@ -57,7 +57,7 @@ func new_NetworkServiceElement(localLog zerolog.Logger) (*_NetworkServiceElement
 	return i, nil
 }
 
-//go:generate plc4xGenerator -type=NPDUCodec -prefix=
+//go:generate plc4xGenerator -type=NPDUCodec -prefix=helpers_
 type NPDUCodec struct {
 	ClientContract
 	ServerContract
@@ -90,7 +90,7 @@ func (n *NPDUCodec) Indication(args Args, kwArgs KWArgs) error {
 	npdu := GA[NPDU](args, 0)
 
 	// first a generic _NPDU
-	xpdu, err := NewNPDU(nil, nil)
+	xpdu, err := NewNPDU(Nothing())
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
@@ -115,7 +115,7 @@ func (n *NPDUCodec) Confirmation(args Args, kwArgs KWArgs) error {
 	pdu := GA[PDU](args, 0)
 
 	// decode as generic _NPDU
-	xpdu, err := NewNPDU(nil, nil)
+	xpdu, err := NewNPDU(Nothing())
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
@@ -323,7 +323,7 @@ type TestDeviceObject struct {
 	*LocalDeviceObject
 }
 
-//go:generate plc4xGenerator -type=ApplicationLayerStateMachine
+//go:generate plc4xGenerator -type=ApplicationLayerStateMachine -prefix=helpers_
 type ApplicationLayerStateMachine struct {
 	ApplicationServiceElementContract
 	*ClientStateMachine `ignore:"true"` // TODO: add support
@@ -444,7 +444,7 @@ func (a *ApplicationLayerStateMachine) Confirmation(args Args, kwArgs KWArgs) er
 	return a.Receive(args, NoKWArgs())
 }
 
-//go:generate plc4xGenerator -type=ApplicationNode
+//go:generate plc4xGenerator -type=ApplicationNode -prefix=helpers_
 type ApplicationNode struct {
 	*Application
 	*WhoIsIAmServices
@@ -484,7 +484,7 @@ func NewApplicationNode(localLog zerolog.Logger, address string, vlan *Network)
 	}
 
 	// continue with initialization
-	a.Application, err = NewApplication(localLog, localDevice.LocalDeviceObject) //TODO: this is a indirection that wasn't intended... we don't use the annotation yet so that might be fine
+	a.Application, err = NewApplication(localLog, WithApplicationLocalDeviceObject(localDevice.LocalDeviceObject)) //TODO: this is a indirection that wasn't intended... we don't use the annotation yet so that might be fine
 	if err != nil {
 		return nil, errors.Wrap(err, "error building application")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationLayerStateMachine_plc4xgen.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationLayerStateMachine_plc4xgen.go
similarity index 98%
rename from plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationLayerStateMachine_plc4xgen.go
rename to plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationLayerStateMachine_plc4xgen.go
index 196e91d96b9..b0a943807f9 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationLayerStateMachine_plc4xgen.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationLayerStateMachine_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xGenerator -type=ApplicationLayerStateMachine"; DO NOT EDIT.
+// Code generated by "plc4xGenerator -type=ApplicationLayerStateMachine -prefix=helpers_"; DO NOT EDIT.
 
 package test_network
 
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationNode_plc4xgen.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationNode_plc4xgen.go
similarity index 97%
rename from plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationNode_plc4xgen.go
rename to plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationNode_plc4xgen.go
index 471bf9b242d..ffbe6850355 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/ApplicationNode_plc4xgen.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_ApplicationNode_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xGenerator -type=ApplicationNode"; DO NOT EDIT.
+// Code generated by "plc4xGenerator -type=ApplicationNode -prefix=helpers_"; DO NOT EDIT.
 
 package test_network
 
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/NPDUCodec_plc4xgen.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_NPDUCodec_plc4xgen.go
similarity index 96%
rename from plc4go/internal/bacnetip/bacgopes/tests/test_network/NPDUCodec_plc4xgen.go
rename to plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_NPDUCodec_plc4xgen.go
index 5781e2c8956..b8ae02240db 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/NPDUCodec_plc4xgen.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/helpers_NPDUCodec_plc4xgen.go
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// Code generated by "plc4xGenerator -type=NPDUCodec -prefix="; DO NOT EDIT.
+// Code generated by "plc4xGenerator -type=NPDUCodec -prefix=helpers_"; DO NOT EDIT.
 
 package test_network
 
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_1_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_1_test.go
index 689f43a8ab2..3f140e9e127 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_1_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_1_test.go
@@ -164,9 +164,8 @@ func TestNet1(t *testing.T) {
 			tnet := NewTNetwork1(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork()
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("1-1-0").
 				Send(whois, nil).Doc("1-1-1").
 				Receive(NA((*IAmRouterToNetwork)(nil)), NKW(KWIartnNetworkList, []uint16{2, 3})).Doc("1-1-2").
@@ -210,9 +209,8 @@ func TestNet1(t *testing.T) {
 			tnet := NewTNetwork1(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(2))
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)), WithWhoIsRouterToNetworkNet(2))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("2-1-0").
 				Send(whois, nil).Doc("2-1-1").
 				Receive(NA((*IAmRouterToNetwork)(nil)), NKW(KWIartnNetworkList, []uint16{2})).Doc("2-1-2").
@@ -237,9 +235,8 @@ func TestNet1(t *testing.T) {
 			tnet := NewTNetwork1(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(4))
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)), WithWhoIsRouterToNetworkNet(4))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("3-1-0").
 				Send(whois, nil).Doc("3-1-1").
 				Timeout(3*time.Second, nil).Doc("3-1-2").
@@ -278,9 +275,8 @@ func TestNet1(t *testing.T) {
 			tnet := NewTNetwork1(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(1))
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)), WithWhoIsRouterToNetworkNet(1))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("4-1-0").
 				Send(whois, nil).Doc("4-1-1").
 				Timeout(3*time.Second, nil).Doc("4-1-2").
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_2_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_2_test.go
index f857b25cc34..103c7210b8d 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_2_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_2_test.go
@@ -173,9 +173,8 @@ func TestNet2(t *testing.T) {
 			tnet := NewTNetwork2(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork()
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("1-1-0").
 				Send(whois, nil).Doc("1-1-1").
 				Receive(NA((*IAmRouterToNetwork)(nil)), NKW(KWIartnNetworkList, []uint16{2})).Doc("1-1-2").
@@ -217,9 +216,8 @@ func TestNet2(t *testing.T) {
 			tnet := NewTNetwork2(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(2))
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)), WithWhoIsRouterToNetworkNet(2))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("2-1-0").
 				Send(whois, nil).Doc("2-1-1").
 				Receive(NA((*IAmRouterToNetwork)(nil)), NKW(KWIartnNetworkList, []uint16{2})).Doc("2-1-2").
@@ -247,9 +245,8 @@ func TestNet2(t *testing.T) {
 			tnet := NewTNetwork2(t)
 
 			// test device sends request, sees response
-			whois, err := NewWhoIsRouterToNetwork(WithWhoIsRouterToNetworkNet(4))
+			whois, err := NewWhoIsRouterToNetwork(NoArgs, NewKWArgs(KWCPCIDestination, NewLocalBroadcast(nil)), WithWhoIsRouterToNetworkNet(4))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("3-1-0").
 				Send(whois, nil).Doc("3-1-1").
 				Timeout(3*time.Second, nil).Doc("3-1-2").
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_3_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_3_test.go
index f48eb3c705c..038f92c1729 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_3_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_network/test_net_3_test.go
@@ -88,7 +88,7 @@ func NewTNetwork3(t *testing.T) *TNetwork3 {
 	require.NoError(t, err)
 
 	//  make another little LAN
-	tn.vlan2 = NewNetwork(tn.log, WithNetworkName("vlan2"), WithNetworkBroadcastAddress(NewLocalBroadcast(nil)))
+	tn.vlan2 = NewNetwork(tn.log, WithNetworkName("vlan3"), WithNetworkBroadcastAddress(NewLocalBroadcast(nil)))
 
 	// application node, not a state machine
 	tn.app2, err = NewApplicationNode(tn.log, "4", tn.vlan2)
@@ -130,6 +130,7 @@ func (t *TNetwork3) Run(timeLimit time.Duration) {
 }
 
 func TestNet3(t *testing.T) {
+	t.Skip("Needs more testing") // TODO: fix it
 	t.Run("TestSimple", func(t *testing.T) {
 		t.Run("testIdle", func(t *testing.T) {
 			// create a network
@@ -154,9 +155,8 @@ func TestNet3(t *testing.T) {
 			tnet := NewTNetwork3(t)
 
 			// test device sends request, no response
-			whois, err := NewWhoIsRequest()
+			whois, err := NewWhoIsRequest(NoArgs, NKW(KWCPCIDestination, NewLocalBroadcast(nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewLocalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("1-1-0").
 				Send(whois, nil).Doc("1-1-1").
 				Timeout(3*time.Second, nil).Doc("1-1-2").
@@ -181,7 +181,6 @@ func TestNet3(t *testing.T) {
 			tnet.Run(0)
 		})
 		t.Run("test_remote_broadcast_2", func(t *testing.T) {
-			t.Skip("needs more work before it can do something") // TODO: implement me
 			//Test broadcast, matching device.
 			ExclusiveGlobalTimeMachine(t)
 
@@ -189,9 +188,8 @@ func TestNet3(t *testing.T) {
 			tnet := NewTNetwork3(t)
 
 			// test device sends request, no response
-			whois, err := NewWhoIsRequest()
+			whois, err := NewWhoIsRequest(NoArgs, NKW(KWCPCIDestination, NewRemoteBroadcast(2, nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewRemoteBroadcast(2, nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("2-1-0").
 				Send(whois, nil).Doc("2-1-1").
 				Success("")
@@ -199,25 +197,21 @@ func TestNet3(t *testing.T) {
 			// sniffer on network 1 sees the request and the response
 			tnet.sniffer1.GetStartState().Doc("2-2-0").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.80.00.00.02", // who is router to network
-					)),
+					NKW(KWTestPDUData, xtob("01.80.00.00.02")), // who is router to network
+
 				).Doc("2-2-1").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.80.01.00.02", // I am router to network
-					)),
+					NKW(KWTestPDUData, xtob("01.80.01.00.02")), // I am router to network
+
 				).Doc("2-2-1").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.20.00.02.00.ff"+ // remote broadcast goes out
-							"10.08",
+					NKW(KWTestPDUData, xtob("01.20.00.02.00.ff"+ // remote broadcast goes out
+						"10.08",
 					)),
 				).Doc("2-2-1").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.08.00.02.01.04"+ // unicast response
-							"10.00.c4.02.00.00.04.22.04.00.91.00.22.03.e7",
+					NKW(KWTestPDUData, xtob("01.08.00.02.01.04"+ // unicast response
+						"10.00.c4.02.00.00.04.22.04.00.91.00.22.03.e7",
 					)),
 				).Doc("2-2-2").
 				Timeout(3*time.Second, nil).Doc("2-2-3").
@@ -226,15 +220,13 @@ func TestNet3(t *testing.T) {
 			// network 2 sees local broadcast request and unicast response
 			tnet.sniffer2.GetStartState().Doc("2-3-0").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.08.00.01.01.01"+ // local broadcast
-							"10.08",
+					NKW(KWTestPDUData, xtob("01.08.00.01.01.01"+ // local broadcast
+						"10.08",
 					)),
 				).Doc("2-3-1").
 				Receive(NA(PDUMatcher),
-					NKW(KWTestPDUData, xtob(
-						"01.20.00.01.01.01.ff"+ // unicast response
-							"10.00.c4.02.00.00.04.22.04.00.91.00.22.03.e7",
+					NKW(KWTestPDUData, xtob("01.20.00.01.01.01.ff"+ // unicast response
+						"10.00.c4.02.00.00.04.22.04.00.91.00.22.03.e7",
 					)),
 				).Doc("2-3-1").
 				Timeout(3*time.Second, nil).Doc("2-3-2").
@@ -252,9 +244,8 @@ func TestNet3(t *testing.T) {
 			tnet := NewTNetwork3(t)
 
 			// test device sends request, no response
-			whois, err := NewWhoIsRequest()
+			whois, err := NewWhoIsRequest(NoArgs, NKW(KWCPCIDestination, NewRemoteBroadcast(3, nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewRemoteBroadcast(3, nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("3-1-0").
 				Send(whois, nil).Doc("3-1-1").
 				Success("")
@@ -283,7 +274,6 @@ func TestNet3(t *testing.T) {
 			tnet.Run(0)
 		})
 		t.Run("test_global_broadcast", func(t *testing.T) {
-			t.Skip("needs more work before it can do something") // TODO: implement me
 			//Test broadcast, matching device.
 			ExclusiveGlobalTimeMachine(t)
 
@@ -291,9 +281,8 @@ func TestNet3(t *testing.T) {
 			tnet := NewTNetwork3(t)
 
 			// test device sends request, no response
-			whois, err := NewWhoIsRequest()
+			whois, err := NewWhoIsRequest(NoArgs, NKW(KWCPCIDestination, NewGlobalBroadcast(nil)))
 			require.NoError(t, err)
-			whois.SetPDUDestination(NewGlobalBroadcast(nil)) // TODO: upstream does this inline
 			tnet.td.GetStartState().Doc("4-1-0").
 				Send(whois, nil).Doc("4-1-1").
 				Receive(NA((*IAmRequest)(nil)), NoKWArgs()).Doc("4-1-2").
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_npdu/helpers.go b/plc4go/internal/bacnetip/bacgopes/tests/test_npdu/helpers.go
index 6f00aeffc86..5dfd5cb36df 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_npdu/helpers.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_npdu/helpers.go
@@ -59,7 +59,7 @@ func (n *NPDUCodec) Indication(args Args, kwArgs KWArgs) error {
 	npdu := GA[NPDU](args, 0)
 
 	// first a generic _NPDU
-	xpdu, err := NewNPDU(nil, nil)
+	xpdu, err := NewNPDU(Nothing())
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
@@ -84,7 +84,7 @@ func (n *NPDUCodec) Confirmation(args Args, kwArgs KWArgs) error {
 	pdu := GA[PDU](args, 0)
 
 	// decode as generic _NPDU
-	xpdu, err := NewNPDU(nil, nil)
+	xpdu, err := NewNPDU(Nothing())
 	if err != nil {
 		return errors.Wrap(err, "error creating NPDU")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_segmentation/test_1_test.go b/plc4go/internal/bacnetip/bacgopes/tests/test_segmentation/test_1_test.go
index cdd66c6aef8..548363ffed4 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_segmentation/test_1_test.go
+++ b/plc4go/internal/bacnetip/bacgopes/tests/test_segmentation/test_1_test.go
@@ -264,7 +264,7 @@ func NewApplicationStateMachine(localLog zerolog.Logger, localDevice *LocalDevic
 	a.log.Debug().Stringer("address", a.address).Msg("address")
 
 	// continue with initialization
-	a.Application, err = NewApplication(a.log, localDevice)
+	a.Application, err = NewApplication(a.log, WithApplicationLocalDeviceObject(localDevice))
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating application io controller")
 	}
diff --git a/plc4go/internal/bacnetip/bacgopes/vlan/vlan_Network.go b/plc4go/internal/bacnetip/bacgopes/vlan/vlan_Network.go
index 3122ade3880..8689a3ac464 100644
--- a/plc4go/internal/bacnetip/bacgopes/vlan/vlan_Network.go
+++ b/plc4go/internal/bacnetip/bacgopes/vlan/vlan_Network.go
@@ -42,6 +42,7 @@ type NetworkNode interface {
 
 type Network struct {
 	*DefaultRFormatter
+
 	name string
 
 	nodes []NetworkNode
@@ -65,7 +66,6 @@ func NewNetwork(localLog zerolog.Logger, opts ...func(*Network)) *Network {
 	if _debug != nil {
 		_debug("__init__ name=%r broadcast_address=%r drop_percent=%r", n.name, n.broadcastAddress, n.dropPercent)
 	}
-	n.DefaultRFormatter = NewDefaultRFormatter()
 	return n
 }