You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2024/10/07 15:44:54 UTC
(plc4x) branch develop updated: feat(plc4go/bacnetip): partial working LocalDeviceObject
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new ab677e89d7 feat(plc4go/bacnetip): partial working LocalDeviceObject
ab677e89d7 is described below
commit ab677e89d72d9ca00088f1498ad2b965cdb5d933
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Oct 7 17:44:41 2024 +0200
feat(plc4go/bacnetip): partial working LocalDeviceObject
---
.../bacgopes/basetypes/basetypes_AddressBinding.go | 10 +-
.../basetypes/basetypes_AuditOperationFlags.go | 16 +-
.../basetypes/basetypes_COVMultipleSubscription.go | 8 +-
.../basetypes_COVMultipleSubscriptionList.go | 10 +-
...es_COVMultipleSubscriptionListOfCOVReference.go | 10 +-
.../basetypes/basetypes_COVSubscription.go | 8 +-
.../basetypes_EventParameterChangeOfBitstring.go | 2 +-
.../basetypes/basetypes_EventTransitionBits.go | 16 +-
.../basetypes/basetypes_NameValueCollection.go | 2 +-
.../basetypes/basetypes_ObjectTypesSupported.go | 17 +-
.../bacgopes/basetypes/basetypes_Recipient.go | 11 +-
.../basetypes/basetypes_ServicesSupported.go | 16 +-
.../bacgopes/basetypes/basetypes_StatusFlags.go | 17 +-
.../bacgopes/basetypes/basetypes_TimeStamp.go | 8 +-
.../bacgopes/basetypes/basetypes_VTSession.go | 10 +-
.../bacnetip/bacgopes/comp/comp_KnownKeys.go | 1 +
.../bacgopes/constructeddata/constructeddata.go | 199 +++++++++++-
.../constructeddata/constructeddata_Choice.go | 347 ++++++++++++++++++++-
.../device/device.go} | 10 +-
.../local/device/local_device_LocalDevice.go | 200 +++++++++++-
plc4go/internal/bacnetip/bacgopes/object/object.go | 144 +++++++--
.../bacgopes/object/object_BitStringValueObject.go | 2 +-
.../bacgopes/object/object_DeviceObject.go | 17 +-
.../bacgopes/object/object_ElevatorGroupObject.go | 2 +-
.../bacnetip/bacgopes/object/object_Object.go | 12 +-
.../bacnetip/bacgopes/object/object_Property.go | 30 +-
26 files changed, 1034 insertions(+), 91 deletions(-)
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AddressBinding.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AddressBinding.go
index 88f6bb1efa..5a3adc3963 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AddressBinding.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AddressBinding.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -30,13 +32,17 @@ type AddressBinding struct {
sequenceElements []Element
}
-func NewAddressBinding(arg Arg) (*AddressBinding, error) {
+func NewAddressBinding(_ Arg) (*AddressBinding, error) {
s := &AddressBinding{
sequenceElements: []Element{
NewElement("deviceObjectIdentifier", Vs2E(NewObjectIdentifier)),
NewElement("deviceAddress", V2E(NewDeviceAddress)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AuditOperationFlags.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AuditOperationFlags.go
index ff14f6acee..8a729a266d 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AuditOperationFlags.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_AuditOperationFlags.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"
)
@@ -54,6 +56,18 @@ func NewAuditOperationFlags(arg Arg) (*AuditOperationFlags, error) {
},
bitLen: 16,
}
- panic("implement me")
+ var err error
+ s.BitString, err = NewBitStringWithExtension(s, NA(arg))
+ if err != nil {
+ return nil, errors.Wrap(err, "NewBitStringWithExtension failed")
+ }
return s, nil
}
+
+func (a AuditOperationFlags) GetBitNames() map[string]int {
+ return a.bitNames
+}
+
+func (a AuditOperationFlags) GetBitLen() int {
+ return a.bitLen
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscription.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscription.go
index b6b62a15fd..173f48f72a 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscription.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscription.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -40,6 +42,10 @@ func NewCOVMultipleSubscription(arg Arg) (*COVMultipleSubscription, error) {
NewElement("listOfCOVSubscriptionSpecifications", SequenceOfE(NewCOVMultipleSubscriptionList), WithElementContext(4)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionList.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionList.go
index 15d3788f55..a2f3cf36f4 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionList.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionList.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -30,13 +32,17 @@ type COVMultipleSubscriptionList struct {
sequenceElements []Element
}
-func NewCOVMultipleSubscriptionList(arg Arg) (*COVMultipleSubscriptionList, error) {
+func NewCOVMultipleSubscriptionList(_ Arg) (*COVMultipleSubscriptionList, error) {
s := &COVMultipleSubscriptionList{
sequenceElements: []Element{
NewElement("monitoredObjectIdentifier", Vs2E(NewObjectIdentifier), WithElementContext(0)),
NewElement("listOfCOVReferences", SequenceOfE(NewCOVMultipleSubscriptionListOfCOVReference), WithElementContext(1)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionListOfCOVReference.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionListOfCOVReference.go
index 1a3c600e14..f653658196 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionListOfCOVReference.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVMultipleSubscriptionListOfCOVReference.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -30,7 +32,7 @@ type COVMultipleSubscriptionListOfCOVReference struct {
sequenceElements []Element
}
-func NewCOVMultipleSubscriptionListOfCOVReference(arg Arg) (*COVMultipleSubscriptionListOfCOVReference, error) {
+func NewCOVMultipleSubscriptionListOfCOVReference(_ Arg) (*COVMultipleSubscriptionListOfCOVReference, error) {
s := &COVMultipleSubscriptionListOfCOVReference{
sequenceElements: []Element{
NewElement("monitoredProperty", V2E(NewPropertyReference), WithElementContext(0)),
@@ -38,6 +40,10 @@ func NewCOVMultipleSubscriptionListOfCOVReference(arg Arg) (*COVMultipleSubscrip
NewElement("timestamped", V2E(NewBoolean), WithElementContext(2)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVSubscription.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVSubscription.go
index 13419975f8..fad72da6a7 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVSubscription.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_COVSubscription.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -40,6 +42,10 @@ func NewCOVSubscription(arg Arg) (*COVSubscription, error) {
NewElement("covIncrement", V2E(NewReal), WithElementContext(4), WithElementOptional(true)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventParameterChangeOfBitstring.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventParameterChangeOfBitstring.go
index b96b12e5db..c82638982d 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventParameterChangeOfBitstring.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventParameterChangeOfBitstring.go
@@ -35,7 +35,7 @@ func NewEventParameterChangeOfBitstring(arg Arg) (*EventParameterChangeOfBitstri
sequenceElements: []Element{
NewElement("timeDelay", V2E(NewUnsigned), WithElementContext(0)),
NewElement("bitmask", Vs2E(NewBitString), WithElementContext(1)),
- NewElement("listOfBitstringValues", SequenceOfsE(NewBitString), WithElementContext(2)),
+ NewElement("listOfBitstringValues", SequenceOfEs(NewBitString), WithElementContext(2)),
},
}
panic("implementchoice")
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventTransitionBits.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventTransitionBits.go
index 899477355d..c0daeb1d84 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventTransitionBits.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_EventTransitionBits.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"
)
@@ -40,6 +42,18 @@ func NewEventTransitionBits(arg Arg) (*EventTransitionBits, error) {
},
bitLen: 3,
}
- panic("implement me")
+ var err error
+ s.BitString, err = NewBitStringWithExtension(s, NA(arg))
+ if err != nil {
+ return nil, errors.Wrap(err, "NewBitStringWithExtension failed")
+ }
return s, nil
}
+
+func (e EventTransitionBits) GetBitNames() map[string]int {
+ return e.bitNames
+}
+
+func (e EventTransitionBits) GetBitLen() int {
+ return e.bitLen
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_NameValueCollection.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_NameValueCollection.go
index 36d6496e92..21a3537e24 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_NameValueCollection.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_NameValueCollection.go
@@ -32,7 +32,7 @@ type NameValueCollection struct {
func NewNameValueCollection(arg Arg) (*NameValueCollection, error) {
s := &NameValueCollection{
sequenceElements: []Element{
- NewElement("members", SequenceOfsE(NewNameValue), WithElementContext(0)),
+ NewElement("members", SequenceOfEs(NewNameValue), WithElementContext(0)),
},
}
panic("implementchoice")
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ObjectTypesSupported.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ObjectTypesSupported.go
index be1fe7e84d..5110c84b8f 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ObjectTypesSupported.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ObjectTypesSupported.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"
)
@@ -99,6 +101,19 @@ func NewObjectTypesSupported(arg Arg) (*ObjectTypesSupported, error) {
},
bitLen: 63,
}
- panic("implement me")
+
+ var err error
+ s.BitString, err = NewBitStringWithExtension(s, NA(arg))
+ if err != nil {
+ return nil, errors.Wrap(err, "NewBitStringWithExtension failed")
+ }
return s, nil
}
+
+func (o ObjectTypesSupported) GetBitNames() map[string]int {
+ return o.bitNames
+}
+
+func (o ObjectTypesSupported) GetBitLen() int {
+ return o.bitLen
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Recipient.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Recipient.go
index 7e56dfb646..5655e55ecb 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Recipient.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_Recipient.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -30,13 +32,18 @@ type Recipient struct {
choiceElements []Element
}
-func NewRecipient(arg Arg) (*Recipient, error) {
+func NewRecipient(_ Arg) (*Recipient, error) {
s := &Recipient{
choiceElements: []Element{
NewElement("device", Vs2E(NewObjectIdentifier), WithElementContext(0)),
NewElement("address", V2E(NewDeviceAddress), WithElementContext(1)),
},
}
- panic("implementchoice")
+
+ var err error
+ s.Choice, err = NewChoice(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating choice")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ServicesSupported.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ServicesSupported.go
index 350c1447fa..3c1503dd18 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ServicesSupported.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_ServicesSupported.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"
)
@@ -86,6 +88,18 @@ func NewServicesSupported(arg Arg) (*ServicesSupported, error) {
},
bitLen: 49,
}
- panic("implement me")
+ var err error
+ s.BitString, err = NewBitStringWithExtension(s, NA(arg))
+ if err != nil {
+ return nil, errors.Wrap(err, "NewBitStringWithExtension failed")
+ }
return s, nil
}
+
+func (s ServicesSupported) GetBitNames() map[string]int {
+ return s.bitNames
+}
+
+func (s ServicesSupported) GetBitLen() int {
+ return s.bitLen
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_StatusFlags.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_StatusFlags.go
index 1d0b9ffd83..203c3ae9e0 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_StatusFlags.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_StatusFlags.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"
)
@@ -41,6 +43,19 @@ func NewStatusFlags(arg Arg) (*StatusFlags, error) {
},
bitLen: 4,
}
- panic("implement me")
+
+ var err error
+ s.BitString, err = NewBitStringWithExtension(s, NA(arg))
+ if err != nil {
+ return nil, errors.Wrap(err, "NewBitStringWithExtension failed")
+ }
return s, nil
}
+
+func (s StatusFlags) GetBitNames() map[string]int {
+ return s.bitNames
+}
+
+func (s StatusFlags) GetBitLen() int {
+ return s.bitLen
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_TimeStamp.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_TimeStamp.go
index 7d25afbc56..3fdb263ce1 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_TimeStamp.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_TimeStamp.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -38,6 +40,10 @@ func NewTimeStamp(arg Arg) (*TimeStamp, error) {
NewElement("dateTime", V2E(NewDateTime), WithElementContext(2)),
},
}
- panic("implementchoice")
+ var err error
+ s.Choice, err = NewChoice(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating choice")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_VTSession.go b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_VTSession.go
index 8c1393e2ee..586e200c70 100644
--- a/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_VTSession.go
+++ b/plc4go/internal/bacnetip/bacgopes/basetypes/basetypes_VTSession.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/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
@@ -30,7 +32,7 @@ type VTSession struct {
sequenceElements []Element
}
-func NewVTSession(arg Arg) (*VTSession, error) {
+func NewVTSession(_ Arg) (*VTSession, error) {
s := &VTSession{
sequenceElements: []Element{
NewElement("localVtSessionID", V2E(NewUnsigned)),
@@ -38,6 +40,10 @@ func NewVTSession(arg Arg) (*VTSession, error) {
NewElement("remoteVtAddress", V2E(NewDeviceAddress)),
},
}
- panic("implementchoice")
+ var err error
+ s.Sequence, err = NewSequence(Nothing())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating sequence")
+ }
return s, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/comp/comp_KnownKeys.go b/plc4go/internal/bacnetip/bacgopes/comp/comp_KnownKeys.go
index 12f740c8af..7f29f085a9 100644
--- a/plc4go/internal/bacnetip/bacgopes/comp/comp_KnownKeys.go
+++ b/plc4go/internal/bacnetip/bacgopes/comp/comp_KnownKeys.go
@@ -92,4 +92,5 @@ const (
KWMaxSegmentsAccepted = KnownKey("segmentsAccepted")
KWNumberOfAPDURetries = KnownKey("numberOfAPDURetries")
KWVendorIdentifier = KnownKey("vendorIdentifier")
+ KWCls = KnownKey("cls")
)
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
index 1d3ba03321..b4deb4ed68 100644
--- a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata.go
@@ -20,19 +20,24 @@
package constructeddata
import (
+ "fmt"
+
+ "github.com/pkg/errors"
+
. "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/primitivedata"
+ readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)
var _debug = CreateDebugPrinter()
-var _sequenceOfClasses map[any]struct{}
-var _listOfClasses map[any]struct{}
-
-func init() {
- _sequenceOfClasses = make(map[any]struct{})
- _listOfClasses = make(map[any]struct{})
-}
+var _arrayOfMap = make(map[any]func(Args, KWArgs) (ElementKlass, error))
+var _listOfMap = make(map[any]func(Args, KWArgs) (ElementKlass, error))
+var _sequenceOfMap = make(map[any]func(Args, KWArgs) (ElementKlass, error))
+var _sequenceOfClasses = make(map[any]struct{})
+var _arrayOfClasses = make(map[any]struct{})
+var _listOfClasses = make(map[any]struct{})
// 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) {
@@ -54,23 +59,183 @@ func Vs2E[T any](b func(args Args) (*T, error)) func(Args, KWArgs) (ElementKlass
}
}
-// TODO: finish
-func SequenceOfE[T any](b func(arg Arg) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
- panic("finish me")
+// TODO: big WIP
+type _SequenceOf[T any] struct {
+ name string
+ subType func(Args) (*T, error)
}
-func SequenceOfsE[T any](b func(args Args) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
- panic("finish me")
+func (a _SequenceOf[T]) Encode(arg Arg) (O error) {
+ panic("implement me")
}
-// TODO: finish // convert to kwArgs and check wtf we are doing here...
-func ArrayOfE[T any](b func(arg Arg) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (ElementKlass, error) {
- panic("finish me")
+func (a _SequenceOf[T]) GetAppTag() readWriteModel.BACnetDataType {
+ panic("implement me")
+}
+
+func SequenceOfE[T any](klass func(arg Arg) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
+ return SequenceOfEs(func(args Args) (*T, error) {
+ if len(args) == 0 {
+ return klass(NoArgs)
+ }
+ if len(args) > 1 {
+ panic(fmt.Sprintf("oh no %d", len(args)))
+ }
+ return klass(args[0])
+ })
+}
+
+func SequenceOfEs[T any](klass func(args Args) (*T, error)) func(Args, KWArgs) (ElementKlass, error) {
+ elementKlass, err := klass(NoArgs)
+ if err != nil {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.Wrap(err, "can't get zero object")
+ }
+ }
+ switch any(elementKlass).(type) {
+ case IsAtomic:
+ // TODO: add prototype check...
+ default:
+ // TODO: add check
+ }
+
+ // if this has already been built, return the cached one
+ if v, ok := _sequenceOfMap[fmt.Sprintf("%T", elementKlass)]; ok {
+ return v
+ }
+
+ // no SequenceOf(SequenceOf(...)) allowed
+ if _, ok := _sequenceOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.New("nested sequences disallowed")
+ }
+ }
+ // no SequenceOf(Array(...)) allowed
+ if _, ok := _arrayOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.New("sequence of ArrayOf disallowed")
+ }
+ }
+
+ // define a generic class for arrays
+ _sequenceOf := struct {
+ *_SequenceOf[T]
+ }{&_SequenceOf[T]{}}
+
+ // constrain it to a list of a specific type of item
+ _sequenceOf.subType = klass
+
+ // update the name
+ _sequenceOf.name = "SequenceOf" + fmt.Sprintf("%T", elementKlass)
+
+ // cache this type
+ _sequenceOfMap[fmt.Sprintf("%T", elementKlass)] = func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return _sequenceOf, nil
+ }
+ _sequenceOfClasses[fmt.Sprintf("%T", _sequenceOf)] = struct{}{}
+
+ return func(args Args, kwArgs KWArgs) (ElementKlass, error) {
+ return _sequenceOf, nil
+ }
+}
+
+// TODO: big WIP
+type _ArrayOf[T any] struct {
+ name string
+ subType func(Args) (*T, error)
+ fixedLength int
+ prototype any
+}
+
+var _ ElementKlass = (*_ArrayOf[any])(nil)
+
+func (a *_ArrayOf[T]) GetAppTag() readWriteModel.BACnetDataType {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (a *_ArrayOf[T]) Encode(arg Arg) (O error) {
+ panic("implement me")
+}
+
+func ArrayOfE[T any](klass func(arg Arg) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (ElementKlass, error) {
+ return ArrayOfEs(func(args Args) (*T, error) {
+ if len(args) == 0 {
+ return klass(NoArgs)
+ }
+ if len(args) > 1 {
+ panic(fmt.Sprintf("oh no %d", len(args)))
+ }
+ return klass(args[0])
+ }, fixedLength, prototype)
}
// TODO: finish // convert to kwArgs and check wtf we are doing here...
-func ArrayOfsE[T any](b func(args Args) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (ElementKlass, error) {
- panic("finish me")
+func ArrayOfEs[T any](klass func(args Args) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (ElementKlass, error) {
+ elementKlass, err := klass(NoArgs)
+ if err != nil {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.Wrap(err, "can't get zero object")
+ }
+ }
+ switch any(elementKlass).(type) {
+ case IsAtomic:
+ // TODO: add prototype check...
+ default:
+ // TODO: add check
+ }
+
+ // build a signature of the parameters
+ arraySignature := struct {
+ string
+ int
+ any
+ }{
+ fmt.Sprintf("%T", elementKlass),
+ fixedLength,
+ prototype,
+ }
+
+ // if this has already been built, return the cached one
+ if v, ok := _arrayOfMap[arraySignature]; ok {
+ return v
+ }
+
+ // no ArrayOf(ArrayOf(...)) allowed
+ if _, ok := _arrayOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.New("nested arrays disallowed")
+ }
+ }
+ // no ArrayOf(SequenceOf(...)) allowed
+ if _, ok := _sequenceOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return nil, errors.New("arrays of SequenceOf disallowed")
+ }
+ }
+
+ // define a generic class for arrays
+ _arrayOf := struct {
+ *_ArrayOf[T]
+ }{&_ArrayOf[T]{}}
+
+ // constrain it to a list of a specific type of item
+ _arrayOf.subType = klass
+ _arrayOf.fixedLength = fixedLength
+ _arrayOf.prototype = prototype
+
+ // update the name
+ _arrayOf.name = "ArrayOf" + fmt.Sprintf("%T", elementKlass)
+
+ // cache this type
+ _arrayOfMap[arraySignature] = func(_ Args, _ KWArgs) (ElementKlass, error) {
+ return _arrayOf, nil
+ }
+ _arrayOfClasses[fmt.Sprintf("%T", _arrayOf)] = struct{}{}
+
+ return func(args Args, kwArgs KWArgs) (ElementKlass, error) {
+ return _arrayOf, nil
+ }
}
// TODO: finish // convert to kwArgs and check wtf we are doing here...
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
index 7c84560a75..2275ccedbf 100644
--- a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
+++ b/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
@@ -19,6 +19,351 @@
package constructeddata
-// TODO: finish
+import (
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ . "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/primitivedata"
+ readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+// ChoiceContract provides a set of functions which can be overwritten by a sub struct
+type ChoiceContract interface {
+ GetChoiceElements() []Element
+}
+
+// ChoiceContractRequirement is needed when one want to extend using ChoiceContract
+type ChoiceContractRequirement interface {
+ ChoiceContract
+ // SetChoice 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....
+ SetChoice(s *Choice)
+}
+
type Choice struct {
+ _contract ChoiceContract
+ choiceElements []Element
+ attr map[string]any
+}
+
+func NewChoice(args Args, kwArgs KWArgs, options ...Option) (*Choice, error) {
+ c := new(Choice)
+ ApplyAppliers(options, c)
+ if c._contract == nil {
+ c._contract = c
+ } else {
+ c._contract.(ChoiceContractRequirement).SetChoice(c)
+ }
+ if _debug != nil {
+ _debug("__init__ %r %r", args, kwArgs)
+ }
+
+ var myKWArgs = make(KWArgs)
+ var otherKWArgs = make(KWArgs)
+ for _, element := range c._contract.GetChoiceElements() {
+ 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)
+ }
+
+ // set the attribute/property values for the ones provided
+ for _, element := range c._contract.GetChoiceElements() {
+ a, ok := myKWArgs[KnownKey(element.GetName())]
+ if ok {
+ c.attr[element.GetName()] = a
+ }
+ }
+ return c, nil
+}
+
+func WithChoiceExtension(contract ChoiceContractRequirement) GenericApplier[*Choice] {
+ return WrapGenericApplier(func(s *Choice) { s._contract = contract })
+}
+
+func (c *Choice) GetChoiceElements() []Element {
+ return c.choiceElements
+}
+
+func (c *Choice) GetAttr(key string) (any, bool) {
+ v, ok := c.attr[key]
+ return v, ok
+}
+
+func (c *Choice) Encode(arg Arg) error {
+ tagList, ok := arg.(*TagList)
+ if !ok {
+ return errors.New("arg is not a TagList")
+ }
+ if _debug != nil {
+ _debug("encode %r", tagList)
+ }
+
+ for _, element := range c._contract.GetChoiceElements() {
+ value, ok := c.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(), c)
+ }
+ elementKlass, err := element.GetKlass()(Nothing())
+ if err != nil {
+ return errors.Wrap(err, "can't get zero object")
+ }
+ _, elementInSequenceOfClasses := _sequenceOfClasses[fmt.Sprintf("%T", elementKlass)]
+ _, elementInListOfClasses := _listOfClasses[fmt.Sprintf("%T", 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 (c *Choice) Decode(arg Arg) error {
+ tagList, ok := arg.(*TagList)
+ if !ok {
+ return errors.New("arg is not a TagList")
+ }
+ if _debug != nil {
+ _debug("decode %r", tagList)
+ }
+
+ for _, element := range c._contract.GetChoiceElements() {
+ tag := tagList.Peek()
+ if _debug != nil {
+ _debug(" - element, tag: %r, %r", element, tag)
+ }
+
+ elementKlass, err := element.GetKlass()(Nothing())
+ if err != nil {
+ return errors.Wrap(err, "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
+ c.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(), c)
+ }
+ } else if tag.GetTagClass() == TagClosingTagClass {
+ if !element.IsOptional() {
+ return errors.Errorf("%s is a missing required element of %T", element.GetName(), c)
+ }
+
+ // 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")
+ }
+ c.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
+}
+
+func (c *Choice) PrintDebugContents(indent int, file io.Writer, _ids []uintptr) {
+ for _, element := range c.choiceElements {
+ value, ok := c.GetAttr(element.GetName())
+ if element.IsOptional() && !ok {
+ continue
+ } else if !element.IsOptional() && !ok {
+ _, _ = fmt.Fprintf(file, "%s%s is a missing required element of %s\n", strings.Repeat(" ", indent), element.GetName(), StructName())
+ continue
+ }
+
+ elementKlass, err := element.GetKlass()(Nothing())
+ if err != nil {
+ if _debug != nil {
+ _debug("can't get zero object. %w", err)
+ }
+ return
+ }
+ _, elementInSequenceOfClasses := _sequenceOfClasses[elementKlass]
+ _, elementInListOfClasses := _listOfClasses[elementKlass]
+ isAtomic := false
+ isAnyAtomic := false
+ switch elementKlass.(type) {
+ case IsAtomic:
+ isAtomic = true
+ case IsAnyAtomic:
+ isAnyAtomic = true
+ }
+ isValueSubOfElementKlass := false // TODO: how to figure that out??
+ if elementInSequenceOfClasses || elementInListOfClasses {
+ _, _ = fmt.Fprintf(file, "%s%s\n", strings.Repeat(" ", indent), element.GetName())
+ helper, err := element.GetKlass()(NA(value), NoKWArgs())
+ if err != nil {
+ if _debug != nil {
+ _debug(" - helper class %s, err: %v", element.GetName(), err)
+ }
+ return
+ }
+ helper.(DebugContentPrinter).PrintDebugContents(indent+1, file, _ids)
+ } else if isAtomic || isAnyAtomic {
+ printVerb := VerbForType(value, 'r')
+ _, _ = fmt.Fprintf(file, "%s%s = "+string(printVerb)+"\n", strings.Repeat(" ", indent), element.GetName(), value)
+ } else if isValueSubOfElementKlass {
+ value.(DebugContentPrinter).PrintDebugContents(indent+1, file, _ids)
+ } else {
+ _, _ = fmt.Fprintf(file, "%s%s must be a %T\n", strings.Repeat(" ", indent), element.GetName(), element.GetKlass())
+ }
+ }
}
diff --git a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go b/plc4go/internal/bacnetip/bacgopes/local/device/device.go
similarity index 85%
copy from plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
copy to plc4go/internal/bacnetip/bacgopes/local/device/device.go
index 7c84560a75..5d63ed2c09 100644
--- a/plc4go/internal/bacnetip/bacgopes/constructeddata/constructeddata_Choice.go
+++ b/plc4go/internal/bacnetip/bacgopes/local/device/device.go
@@ -17,8 +17,10 @@
* under the License.
*/
-package constructeddata
+package device
-// TODO: finish
-type Choice struct {
-}
+import (
+ . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
+)
+
+var _debug = CreateDebugPrinter()
diff --git a/plc4go/internal/bacnetip/bacgopes/local/device/local_device_LocalDevice.go b/plc4go/internal/bacnetip/bacgopes/local/device/local_device_LocalDevice.go
index f6ba59c869..b5427c5719 100644
--- a/plc4go/internal/bacnetip/bacgopes/local/device/local_device_LocalDevice.go
+++ b/plc4go/internal/bacnetip/bacgopes/local/device/local_device_LocalDevice.go
@@ -21,13 +21,17 @@ package device
import (
"fmt"
+ "io"
+ "strings"
"github.com/pkg/errors"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
+ . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/local/object"
. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/object"
+ . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
)
@@ -48,18 +52,10 @@ type LocalDeviceObject interface {
SetObjectList([]string)
}
-type _LocalDeviceObject struct {
- *CurrentPropertyListMixIn
- *DeviceObject
- *DefaultRFormatter
-
- properties []Property
- defaultProperties map[string]any
-
- App any `ignore:"true"` // TODO: is *Application but creates a circular dependency. figure out what is a smart way
-}
-
-func NewLocalDeviceObject(args Args, kwArgs KWArgs, options ...Option) (LocalDeviceObject, error) {
+func NewLocalDeviceObject(_ Args, kwArgs KWArgs, options ...Option) (LocalDeviceObject, error) {
+ if _debug != nil {
+ _debug("__init__ %r", kwArgs)
+ }
l := &_LocalDeviceObject{
DefaultRFormatter: NewDefaultRFormatter(),
properties: []Property{
@@ -82,9 +78,144 @@ func NewLocalDeviceObject(args Args, kwArgs KWArgs, options ...Option) (LocalDev
if err != nil {
return nil, errors.Wrap(err, "error creating mixing")
}
+ l.DeviceObject, err = NewDeviceObject(nil)
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating device object")
+ }
+
+ // start with an empty dictionary of device object properties
+ initArgs := make(KWArgs)
+ iniArg, _ := KWO[KWArgs](kwArgs, "ini", nil)
+ if _debug != nil {
+ _debug(" - ini_arg: %r", iniArg)
+ }
+
+ if _, ok := RegisteredObjectTypes[fmt.Sprintf("%T", l)]; !ok {
+ if _debug != nil {
+ _debug(" - unregistered", kwArgs)
+ }
+ vendorIdentifier, ok := KWO(kwArgs, KWVendorIdentifier, -1)
+ if _debug != nil {
+ _debug(" - keyword vendor identifier: %r", vendorIdentifier)
+ }
+
+ if !ok {
+ vendorIdentifier, ok = KWO[int](iniArg, "vendorIdentifier", -1)
+ _debug(" - INI vendor identifier: %r", vendorIdentifier)
+ }
+
+ if !ok {
+ return nil, errors.New("vendorIdentifier required to auto-register the LocalDeviceObject class")
+ }
+
+ if _, err := RegisterObjectType(NKW(KWCls, l, KWVendorIdentifier, vendorIdentifier)); err != nil {
+ return nil, errors.Wrap(err, "error register object type")
+ }
+ }
+
+ // look for properties, fill in values from the keyword arguments or
+ // the INI parameter (converted to a proper value) if it was provided
+ for propid, prop := range l.DeviceObject.Get_Properties() {
+ // special processing for object identifier
+ if propid == "objectIdentifier" {
+ continue
+ }
+
+ // use keyword argument if it was provided
+ var propValue any
+ var propDataType any
+ if v, ok := kwArgs[KnownKey(propid)]; ok {
+ propValue = v
+ } else {
+ propValue, ok = KWO[any](iniArg, KnownKey(strings.ToLower(propid)), nil)
+ if !ok {
+ continue
+ }
+
+ propDataType = prop.GetDataType()
+ // TODO: convert
+ _ = propDataType
+ // at long last
+ initArgs[KnownKey(propid)] = propValue
+ }
+ }
+ // check for object identifier as a keyword parameter or in the INI file,
+ // and it might be just an int, so make it a tuple if necessary
+ var objectIdentifier any
+ if v, ok := KWO[any](kwArgs, "objectIdentifier", nil); ok {
+ objectIdentifier = v
+ if vint, ok := v.(int); ok {
+ objectIdentifier = ObjectIdentifierTuple{Left: "device", Right: vint}
+ }
+ } else if v, ok = KWO[any](iniArg, "objectidentifier", nil); ok {
+ objectIdentifier = ObjectIdentifierTuple{Left: "device", Right: v.(int)}
+ } else {
+ return nil, errors.New("objectIdentifier required")
+ }
+ initArgs["objectIdentifier"] = objectIdentifier
+ if _debug != nil {
+ _debug(" - object identifier: %r", objectIdentifier)
+ }
+
+ // fill in default property values not in init_args
+ for attr, value := range l.defaultProperties {
+ if _, ok := initArgs[KnownKey(attr)]; !ok {
+ initArgs[KnownKey(attr)] = value
+ }
+ }
+
+ // check for properties this class implements
+ if _, ok := initArgs[KnownKey("localDate")]; ok {
+ return nil, errors.New("localDate is provided by LocalDeviceObject and cannot be overridden")
+ }
+ if _, ok := initArgs[KnownKey("localTime")]; ok {
+ return nil, errors.New("localTime is provided by LocalDeviceObject and cannot be overridden")
+ }
+ if _, ok := initArgs[KnownKey("protocolServicesSupported")]; ok {
+ return nil, errors.New("protocolServicesSupported is provided by LocalDeviceObject and cannot be overridden")
+ }
+
+ // the object list is provided
+ if _, ok := initArgs[KnownKey("objectList")]; ok {
+ return nil, errors.New("objectList is provided by LocalDeviceObject and cannot be overridden")
+ }
+ initArgs["objectList"] = ArrayOfEs[ObjectIdentifier](NewObjectIdentifier, 0, nil)
+
+ // check for a minimum value
+ if v, ok := KWO[int](kwArgs, "maxApduLengthAccepted", 0); ok && v < 50 {
+ return nil, errors.New("invalid max APDU length accepted")
+ }
+
+ // dump the updated attributes
+ if _debug != nil {
+ _debug(" - init_args: %r", initArgs)
+ }
+
+ // proceed as usual
+ // TODO: how?
+
+ // pass along special property values that are not BACnet properties
+ for key, value := range kwArgs {
+ if strings.HasPrefix(string(key), "_") {
+ l.DeviceObject.SetAttr(string(key), value)
+ }
+ }
return l, nil
}
+type _LocalDeviceObject struct {
+ *CurrentPropertyListMixIn
+ *DeviceObject
+ *DefaultRFormatter
+
+ properties []Property
+ defaultProperties map[string]any
+
+ App any `ignore:"true"` // TODO: is *Application but creates a circular dependency. figure out what is a smart way
+}
+
+var _ Object = (*_LocalDeviceObject)(nil)
+
func (l *_LocalDeviceObject) GetObjectIdentifier() string {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("objectIdentifier")
if !ok {
@@ -172,3 +303,48 @@ func (l *_LocalDeviceObject) GetObjectList() []string {
func (l *_LocalDeviceObject) SetObjectList(strings []string) {
l.CurrentPropertyListMixIn.SetAttr("objectList", strings)
}
+
+func (l *_LocalDeviceObject) GetAttr(name string) (any, bool) {
+ // ambiguous selector avoidance
+ return l.DeviceObject.GetAttr(name)
+}
+
+func (l *_LocalDeviceObject) SetAttr(name string, value any) {
+ // ambiguous selector avoidance
+ l.DeviceObject.SetAttr(name, value)
+}
+
+func (l *_LocalDeviceObject) AddProperty(prop Property) {
+ // ambiguous selector avoidance
+ l.DeviceObject.AddProperty(prop)
+}
+
+func (l *_LocalDeviceObject) ReadProperty(args Args, kwArgs KWArgs) error {
+ // ambiguous selector avoidance
+ return l.DeviceObject.ReadProperty(args, kwArgs)
+}
+
+func (l *_LocalDeviceObject) WriteProperty(args Args, kwArgs KWArgs) error {
+ // ambiguous selector avoidance
+ return l.DeviceObject.WriteProperty(args, kwArgs)
+}
+
+func (l *_LocalDeviceObject) DeleteProperty(prop string) {
+ // ambiguous selector avoidance
+ l.DeviceObject.DeleteProperty(prop)
+}
+
+func (l *_LocalDeviceObject) Get_Properties() map[string]Property {
+ // ambiguous selector avoidance
+ return l.DeviceObject.Get_Properties()
+}
+
+func (l *_LocalDeviceObject) Set_Properties(_properties map[string]Property) {
+ // ambiguous selector avoidance
+ l.DeviceObject.Set_Properties(_properties)
+}
+
+func (l *_LocalDeviceObject) PrintDebugContents(indent int, file io.Writer, _ids []uintptr) {
+ // ambiguous selector avoidance
+ l.DeviceObject.PrintDebugContents(indent, file, _ids)
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object.go b/plc4go/internal/bacnetip/bacgopes/object/object.go
index 5c58a24da2..3d9df31245 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object.go
@@ -32,22 +32,49 @@ import (
var _debug = CreateDebugPrinter()
-var _arrayOfMap map[any]func(Args, KWArgs) (PropertyKlass, error)
-var _arrayOfClasses map[any]struct{}
-var _sequenceOfClasses map[any]struct{}
-var _listOfClasses map[any]struct{}
-
-func init() {
- _arrayOfMap = make(map[any]func(Args, KWArgs) (PropertyKlass, error))
- _arrayOfClasses = make(map[any]struct{})
- _sequenceOfClasses = make(map[any]struct{})
- _listOfClasses = make(map[any]struct{})
-}
+var _arrayOfMap = make(map[any]func(Args, KWArgs) (PropertyKlass, error))
+var _listOfMap = make(map[any]func(Args, KWArgs) (PropertyKlass, error))
+var _arrayOfClasses = make(map[any]struct{})
+var _sequenceOfClasses = make(map[any]struct{})
+var _listOfClasses = make(map[any]struct{})
+
+var RegisteredObjectTypes = make(map[any]struct{})
+
+func RegisterObjectType(kwargs KWArgs) (any, error) {
+ cls, aCls := KWO[any](kwargs, KWCls, nil)
+ vendorId, _ := KWO[int](kwargs, KWVendorIdentifier, 0)
+
+ if _debug != nil {
+ _debug("register_object_type %r vendor_id=%s", cls, vendorId)
+ }
+
+ if !aCls {
+ panic("implement me")
+ }
+
+ // make sure it's an Object derived class
+ if _, ok := cls.(Object); !ok {
+ return nil, errors.New("Object derived struct required")
+ }
-var registeredObjectTypes map[any]struct{}
+ // build a property dictionary by going through the class and all its parents
+ _properties := map[string]Property{}
+ // TODO: how?
-func init() {
- registeredObjectTypes = make(map[any]struct{})
+ // if the object type hasn't been provided, make an immutable one
+ if _, ok := _properties["objectType"]; ok {
+ _properties["objectType"] = NewReadableProperty("objectType", func(args Args, _ KWArgs) (PropertyKlass, error) { return NewObjectType(args) }, WithPropertyMutable(false))
+ }
+
+ // store it in the struct
+ cls.(interface {
+ Set_Properties(_properties map[string]Property)
+ }).Set_Properties(_properties)
+
+ RegisteredObjectTypes[cls] = struct{}{} // TODO: key needs to be objectType + vendor id
+
+ // return the struct as decorator
+ return cls, nil
}
type PropertyError struct {
@@ -95,23 +122,25 @@ type _ArrayOf[T any] struct {
prototype any
}
-func (a _ArrayOf[T]) Encode(arg Arg) (O error) {
+var _ PropertyKlass = (*_ArrayOf[any])(nil)
+
+func (a *_ArrayOf[T]) Encode(arg Arg) (O error) {
panic("implement me")
}
-func ArrayOfP[T any](b func(arg Arg) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (PropertyKlass, error) {
- return ArrayOfsP(func(args Args) (*T, error) {
+func ArrayOfP[T any](klass func(arg Arg) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (PropertyKlass, error) {
+ return ArrayOfPs(func(args Args) (*T, error) {
if len(args) == 0 {
- return b(NoArgs)
+ return klass(NoArgs)
}
if len(args) > 1 {
panic(fmt.Sprintf("oh no %d", len(args)))
}
- return b(args[0])
+ return klass(args[0])
}, fixedLength, prototype)
}
-func ArrayOfsP[T any](klass func(args Args) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (PropertyKlass, error) {
+func ArrayOfPs[T any](klass func(args Args) (*T, error), fixedLength int, prototype any) func(Args, KWArgs) (PropertyKlass, error) {
elementKlass, err := klass(NoArgs)
if err != nil {
return func(_ Args, _ KWArgs) (PropertyKlass, error) {
@@ -178,7 +207,78 @@ func ArrayOfsP[T any](klass func(args Args) (*T, error), fixedLength int, protot
}
}
-// TODO: finish // convert to kwArgs and check wtf we are doing here...
+// TODO: big WIP
+type _ListOf[T any] struct {
+ name string
+ subType func(Args) (*T, error)
+}
+
+func (a _ListOf[T]) Encode(arg Arg) (O error) {
+ panic("implement me")
+}
+
func ListOfP[T any](b func(arg Arg) (*T, error)) func(Args, KWArgs) (PropertyKlass, error) {
- panic("finish me")
+ return ListOfPs(func(args Args) (*T, error) {
+ if len(args) == 0 {
+ return b(NoArgs)
+ }
+ if len(args) > 1 {
+ panic(fmt.Sprintf("oh no %d", len(args)))
+ }
+ return b(args[0])
+ })
+}
+
+func ListOfPs[T any](klass func(args Args) (*T, error)) func(Args, KWArgs) (PropertyKlass, error) {
+ elementKlass, err := klass(NoArgs)
+ if err != nil {
+ return func(_ Args, _ KWArgs) (PropertyKlass, error) {
+ return nil, errors.Wrap(err, "can't get zero object")
+ }
+ }
+ switch any(elementKlass).(type) {
+ case IsAtomic:
+ // TODO: add prototype check...
+ default:
+ // TODO: add check
+ }
+
+ // if this has already been built, return the cached one
+ if v, ok := _listOfMap[fmt.Sprintf("%T", elementKlass)]; ok {
+ return v
+ }
+
+ // no ArrayOf(ArrayOf(...)) allowed
+ if _, ok := _listOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (PropertyKlass, error) {
+ return nil, errors.New("nested lists disallowed")
+ }
+ }
+ // no ArrayOf(SequenceOf(...)) allowed
+ if _, ok := _arrayOfClasses[fmt.Sprintf("%T", elementKlass)]; ok {
+ return func(_ Args, _ KWArgs) (PropertyKlass, error) {
+ return nil, errors.New("list of arrays disallowed")
+ }
+ }
+
+ // define a generic class for lists
+ _listOf := struct {
+ *_ListOf[T]
+ }{&_ListOf[T]{}}
+
+ // constrain it to a list of a specific type of item
+ _listOf.subType = klass
+
+ // update the name
+ _listOf.name = "ListOf" + fmt.Sprintf("%T", elementKlass)
+
+ // cache this type
+ _listOfMap[fmt.Sprintf("%T", elementKlass)] = func(_ Args, _ KWArgs) (PropertyKlass, error) {
+ return _listOf, nil
+ }
+ _listOfClasses[fmt.Sprintf("%T", _listOf)] = struct{}{}
+
+ return func(args Args, kwArgs KWArgs) (PropertyKlass, error) {
+ return _listOf, nil
+ }
}
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object_BitStringValueObject.go b/plc4go/internal/bacnetip/bacgopes/object/object_BitStringValueObject.go
index 2135ee6022..1f41bf4b95 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object_BitStringValueObject.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object_BitStringValueObject.go
@@ -46,7 +46,7 @@ func NewBitStringValueObject(arg Arg) (*BitStringValueObject, error) {
NewOptionalProperty("relinquishDefault", Vs2P(NewBitString)),
NewOptionalProperty("timeDelay", V2P(NewUnsigned)),
NewOptionalProperty("notificationClass", V2P(NewUnsigned)),
- NewOptionalProperty("alarmValues", ArrayOfsP(NewBitString, 0, 0)),
+ NewOptionalProperty("alarmValues", ArrayOfPs(NewBitString, 0, 0)),
NewOptionalProperty("bitMask", Vs2P(NewBitString)),
NewOptionalProperty("eventEnable", V2P(NewEventTransitionBits)),
NewOptionalProperty("ackedTransitions", V2P(NewEventTransitionBits)),
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object_DeviceObject.go b/plc4go/internal/bacnetip/bacgopes/object/object_DeviceObject.go
index ae84ffea2a..bedb16d345 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object_DeviceObject.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object_DeviceObject.go
@@ -20,6 +20,8 @@
package object
import (
+ "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/primitivedata"
@@ -47,8 +49,8 @@ func NewDeviceObject(arg Arg) (*DeviceObject, error) {
NewReadableProperty("protocolRevision", V2P(NewUnsigned)),
NewReadableProperty("protocolServicesSupported", V2P(NewServicesSupported)),
NewReadableProperty("protocolObjectTypesSupported", V2P(NewObjectTypesSupported)),
- NewReadableProperty("objectList", ArrayOfsP(NewObjectIdentifier, 0, 0)),
- NewOptionalProperty("structuredObjectList", ArrayOfsP(NewObjectIdentifier, 0, 0)),
+ NewReadableProperty("objectList", ArrayOfPs(NewObjectIdentifier, 0, 0)),
+ NewOptionalProperty("structuredObjectList", ArrayOfPs(NewObjectIdentifier, 0, 0)),
NewReadableProperty("maxApduLengthAccepted", V2P(NewUnsigned)),
NewReadableProperty("segmentationSupported", V2P(NewSegmentation)),
NewOptionalProperty("vtClassesSupported", ListOfP(NewVTClass)),
@@ -65,7 +67,7 @@ func NewDeviceObject(arg Arg) (*DeviceObject, error) {
NewOptionalProperty("maxInfoFrames", V2P(NewUnsigned)),
NewReadableProperty("deviceAddressBinding", ListOfP(NewAddressBinding)),
NewReadableProperty("databaseRevision", V2P(NewUnsigned)),
- NewOptionalProperty("configurationFiles", ArrayOfsP(NewObjectIdentifier, 0, 0)),
+ NewOptionalProperty("configurationFiles", ArrayOfPs(NewObjectIdentifier, 0, 0)),
NewOptionalProperty("lastRestoreTime", V2P(NewTimeStamp)),
NewOptionalProperty("backupFailureTimeout", V2P(NewUnsigned)),
NewOptionalProperty("backupPreparationTime", V2P(NewUnsigned)),
@@ -104,6 +106,13 @@ func NewDeviceObject(arg Arg) (*DeviceObject, error) {
NewOptionalProperty("deployedProfileLocation", V2P(NewCharacterString)),
},
}
- // TODO: @register_object_type
+ var err error
+ o.Object, err = NewObject(NoKWArgs())
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating object")
+ }
+ if _, err := RegisterObjectType(NKW(KWCls, o)); err != nil {
+ return nil, errors.Wrap(err, "error registering object type")
+ }
return o, nil
}
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object_ElevatorGroupObject.go b/plc4go/internal/bacnetip/bacgopes/object/object_ElevatorGroupObject.go
index 7a4c85b3e5..d8c1038d21 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object_ElevatorGroupObject.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object_ElevatorGroupObject.go
@@ -38,7 +38,7 @@ func NewElevatorGroupObject(arg Arg) (*ElevatorGroupObject, error) {
properties: []Property{
NewReadableProperty("machineRoomID", Vs2P(NewObjectIdentifier)),
NewReadableProperty("groupID", V2P(NewUnsigned8)),
- NewReadableProperty("groupMembers", ArrayOfsP(NewObjectIdentifier, 0, 0)),
+ NewReadableProperty("groupMembers", ArrayOfPs(NewObjectIdentifier, 0, 0)),
NewOptionalProperty("groupMode", V2P(NewLiftGroupMode)),
NewOptionalProperty("landingCalls", ListOfP(NewLandingCallStatus)),
NewOptionalProperty("landingCallControl", V2P(NewLandingCallStatus)),
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object_Object.go b/plc4go/internal/bacnetip/bacgopes/object/object_Object.go
index 93d8d0f325..cffcbf1ea0 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object_Object.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object_Object.go
@@ -39,6 +39,8 @@ type Object interface {
DeleteProperty(prop string)
ReadProperty(Args, KWArgs) error
WriteProperty(Args, KWArgs) error
+ Set_Properties(_properties map[string]Property)
+ Get_Properties() map[string]Property
}
type _Object struct {
@@ -64,7 +66,7 @@ func NewObject(kwArgs KWArgs, options ...Option) (Object, error) {
NewReadableProperty("propertyList", ArrayOfP(NewPropertyIdentifier, 0, 0)),
NewOptionalProperty("auditLevel", V2P(NewAuditLevel)),
NewOptionalProperty("auditableOperations", V2P(NewAuditOperationFlags)),
- NewOptionalProperty("tags", ArrayOfsP(NewNameValue, 0, 0)),
+ NewOptionalProperty("tags", ArrayOfPs(NewNameValue, 0, 0)),
NewOptionalProperty("profileLocation", V2P(NewCharacterString)),
NewOptionalProperty("profileName", V2P(NewCharacterString)),
},
@@ -136,6 +138,14 @@ func WithObject_Properties(_properties map[string]Property) GenericApplier[*_Obj
})
}
+func (o *_Object) Set_Properties(_properties map[string]Property) {
+ o._properties = _properties
+}
+
+func (o *_Object) Get_Properties() map[string]Property {
+ return o._properties
+}
+
func (o *_Object) PrintDebugContents(indent int, file io.Writer, _ids []uintptr) {
//TODO implement me
panic("implement me")
diff --git a/plc4go/internal/bacnetip/bacgopes/object/object_Property.go b/plc4go/internal/bacnetip/bacgopes/object/object_Property.go
index 5abdb3c705..c75c01b122 100644
--- a/plc4go/internal/bacnetip/bacgopes/object/object_Property.go
+++ b/plc4go/internal/bacnetip/bacgopes/object/object_Property.go
@@ -25,6 +25,7 @@ import . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
type Property interface {
ReadProperty(args Args, kwArgs KWArgs) error
WriteProperty(args Args, kwArgs KWArgs) error
+ GetDataType() any
IsOptional() bool
Get_Default() any
IsMutable() bool
@@ -34,21 +35,30 @@ type PropertyKlass interface {
Encode(Arg) error
}
-func NewProperty(name string, klass func(Args, KWArgs) (PropertyKlass, error), options ...Option) Property {
+func NewProperty(identifier string, datatype func(Args, KWArgs) (PropertyKlass, error), options ...Option) Property {
i := &_Property{
- name: name,
- klass: klass,
+ // keep the arguments
+ identifier: identifier,
+ dataType: datatype,
}
ApplyAppliers(options, i)
+
+ // check the datatype
+ dataType, _ := i.dataType(Nothing())
+ switch dataType.(type) {
+ default:
+ // TODO: check for Atomic, Sequence, Choice, Array, List, AnyAtomic
+ }
+
return i
}
type _Property struct {
- name string
- klass func(Args, KWArgs) (PropertyKlass, error)
- optional bool
- _default any
- mutable bool
+ identifier string
+ dataType func(Args, KWArgs) (PropertyKlass, error)
+ optional bool
+ _default any
+ mutable bool
}
var _ Property = (*_Property)(nil)
@@ -65,6 +75,10 @@ func WithPropertyMutable(mutable bool) GenericApplier[*_Property] {
return WrapGenericApplier(func(e *_Property) { e.mutable = mutable })
}
+func (p *_Property) GetDataType() any {
+ return p.dataType
+}
+
func (p *_Property) IsOptional() bool {
return p.optional
}