plc4go/internal/bacnetip/bacgopes/local/device/local_device_LocalDevice.go (278 lines of code) (raw):
/*
* 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 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"
)
type LocalDeviceObject interface {
fmt.Stringer
fmt.Formatter
GetObjectIdentifier() string
GetMaximumApduLengthAccepted() *readWriteModel.MaxApduLengthAccepted
GetSegmentationSupported() *readWriteModel.BACnetSegmentation
GetVendorIdentifier() any
GetNumberOfAPDURetries() *uint
GetAPDUTimeout() *uint
SetApp(a any)
GetAPDUSegmentTimeout() *uint
GetObjectName() string
GetMaxSegmentsAccepted() *readWriteModel.MaxSegmentsAccepted
GetObjectList() []string
SetObjectList([]string)
}
func NewLocalDeviceObject(_ Args, kwArgs KWArgs, options ...Option) (LocalDeviceObject, error) {
if _debug != nil {
_debug("__init__ %r", kwArgs)
}
l := &_LocalDeviceObject{
DefaultRFormatter: NewDefaultRFormatter(),
properties: []Property{
NewCurrentLocalTime(),
NewCurrentLocalDate(),
NewCurrentProtocolServicesSupported(),
},
defaultProperties: map[string]any{
"maxApduLengthAccepted": 1024,
"segmentationSupported": "segmentedBoth",
"maxSegmentsAccepted": 16,
"apduSegmentTimeout": 5000,
"apduTimeout": 3000,
"numberOfApduRetries": 3,
},
}
options = AddSharedSuperIfAbundant[Object](options)
var err error
l.CurrentPropertyListMixIn, err = NewCurrentPropertyListMixIn(options...)
if err != nil {
return nil, errors.Wrap(err, "error creating mixing")
}
l.DeviceObject, err = NewDeviceObject(options...)
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
if err := l.DeviceObject.Init(NoArgs, initArgs); err != nil {
return nil, errors.Wrap(err, "error creating device object")
}
// 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 {
return ""
}
return attr.(string)
}
func (l *_LocalDeviceObject) GetMaximumApduLengthAccepted() *readWriteModel.MaxApduLengthAccepted {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("maximumApduLengthAccepted")
if !ok {
return nil
}
return attr.(*readWriteModel.MaxApduLengthAccepted)
}
func (l *_LocalDeviceObject) GetSegmentationSupported() *readWriteModel.BACnetSegmentation {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("segmentationSupported")
if !ok {
return nil
}
return attr.(*readWriteModel.BACnetSegmentation)
}
func (l *_LocalDeviceObject) GetVendorIdentifier() any {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("vendorIdentifier")
if !ok {
return 0
}
return attr.(int)
}
func (l *_LocalDeviceObject) GetNumberOfAPDURetries() *uint {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("numberOfAPDURetries")
if !ok {
return nil
}
return attr.(*uint)
}
func (l *_LocalDeviceObject) GetAPDUTimeout() *uint {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("apduTimeout")
if !ok {
return nil
}
return attr.(*uint)
}
func (l *_LocalDeviceObject) SetApp(a any) {
l.App = a
}
func (l *_LocalDeviceObject) GetAPDUSegmentTimeout() *uint {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("apduSegmentTimeout")
if !ok {
return nil
}
return attr.(*uint)
}
func (l *_LocalDeviceObject) GetObjectName() string {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("objectName")
if !ok {
return ""
}
return attr.(string)
}
func (l *_LocalDeviceObject) GetMaxSegmentsAccepted() *readWriteModel.MaxSegmentsAccepted {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("maxSegmentsAccepted")
if !ok {
return nil
}
return attr.(*readWriteModel.MaxSegmentsAccepted)
}
func (l *_LocalDeviceObject) GetObjectList() []string {
attr, ok := l.CurrentPropertyListMixIn.GetAttr("objectList")
if !ok {
return nil
}
return attr.([]string)
}
func (l *_LocalDeviceObject) SetObjectList(strings []string) {
l.CurrentPropertyListMixIn.SetAttr("objectList", strings)
}
func (l *_LocalDeviceObject) Init(args Args, kwArgs KWArgs) error {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.Init(args, kwArgs)
}
func (l *_LocalDeviceObject) GetObjectType() string {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.GetObjectType()
}
func (l *_LocalDeviceObject) GetAttr(name string) (any, bool) {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.GetAttr(name)
}
func (l *_LocalDeviceObject) SetAttr(name string, value any) {
// ambiguous selector avoidance
l.CurrentPropertyListMixIn.SetAttr(name, value)
}
func (l *_LocalDeviceObject) AddProperty(prop Property) {
// ambiguous selector avoidance
l.CurrentPropertyListMixIn.AddProperty(prop)
}
func (l *_LocalDeviceObject) ReadProperty(args Args, kwArgs KWArgs) error {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.ReadProperty(args, kwArgs)
}
func (l *_LocalDeviceObject) WriteProperty(args Args, kwArgs KWArgs) error {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.WriteProperty(args, kwArgs)
}
func (l *_LocalDeviceObject) DeleteProperty(prop string) {
// ambiguous selector avoidance
l.CurrentPropertyListMixIn.DeleteProperty(prop)
}
func (l *_LocalDeviceObject) GetProperties() []Property {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.GetProperties()
}
func (l *_LocalDeviceObject) Get_Properties() map[string]Property {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.Get_Properties()
}
func (l *_LocalDeviceObject) Get_PropertiesMonitors() map[string][]func(old, new any) {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.Get_PropertiesMonitors()
}
func (l *_LocalDeviceObject) Get_Values() map[string]any {
// ambiguous selector avoidance
return l.CurrentPropertyListMixIn.Get_Values()
}
func (l *_LocalDeviceObject) Set_Properties(_properties map[string]Property) {
// ambiguous selector avoidance
l.CurrentPropertyListMixIn.Set_Properties(_properties)
}
func (l *_LocalDeviceObject) PrintDebugContents(indent int, file io.Writer, _ids []uintptr) {
// ambiguous selector avoidance
l.CurrentPropertyListMixIn.PrintDebugContents(indent, file, _ids)
}