Skip to content

Commit

Permalink
feat(plc4go/bacnetip): add sequence support
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Aug 29, 2024
1 parent ca0f656 commit b076cf9
Show file tree
Hide file tree
Showing 19 changed files with 413 additions and 88 deletions.
33 changes: 25 additions & 8 deletions plc4go/internal/bacnetip/constructeddata.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,49 @@ func init() {

type Element interface {
GetName() string
GetKlass() func(Args, KWArgs) (interface{ Encode(Arg) error }, error)
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) (interface{ Encode(Arg) error }, error)
Klass func(Args, KWArgs) (ElementKlass, error)
Context *int
Optional bool
}

func NewElement(name string, klass func(Args, KWArgs) (interface{ Encode(Arg) error }, error)) Element {
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 (e *_Element) GetName() string {
return e.Name
}

func (e *_Element) GetKlass() func(Args, KWArgs) (interface{ Encode(Arg) error }, error) {
func (e *_Element) GetKlass() func(Args, KWArgs) (ElementKlass, error) {
return e.Klass
}

Expand Down Expand Up @@ -309,21 +323,24 @@ func (a *Sequence) Decode(arg Arg) error {
} else if isAtomic {
// convert it to application encoding
if context := element.GetContext(); context != nil {
if tag.GetTagClass() != readWriteModel.TagClass_CONTEXT_SPECIFIC_TAGS { // TODO: store the application tag klass into Boolean for example so we can inspect that here
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)
return errors.Errorf("%s expected context tag %d", element.GetName(), *context)
} else {
// TODO: we don't do this
//a.attr[element.GetName()] = nil
continue
}
}
tag, err = tag.ContextToApp(uint(readWriteModel.BACnetDataType_BOOLEAN)) // TODO: store the application tag klass into Boolean for example so we can inspect that here
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 { // TODO: store the application tag klass into Boolean for example so we can inspect that here
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 {
Expand Down
12 changes: 11 additions & 1 deletion plc4go/internal/bacnetip/primitivedata_Atomic.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@

package bacnetip

import "cmp"
import (
"cmp"

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

type ComparableAndOrdered interface {
comparable
Expand Down Expand Up @@ -48,6 +52,8 @@ type Atomic[T ComparableAndOrdered] struct {
AtomicContract[T]
atomicRequirements AtomicRequirements

_appTag readWriteModel.BACnetDataType

value T
}

Expand All @@ -68,6 +74,10 @@ func (a *Atomic[T]) isAtomic() bool {
return true
}

func (a *Atomic[T]) GetAppTag() readWriteModel.BACnetDataType {
return a._appTag
}

func (a *Atomic[T]) Compare(other any) int {
otherValue := other.(AtomicContract[T]).GetValue()
// now compare the values
Expand Down
11 changes: 9 additions & 2 deletions plc4go/internal/bacnetip/primitivedata_BitString.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type BitStringExtension interface {
}

type BitString struct {
_appTag model.BACnetDataType

bitStringExtension BitStringExtension
value []bool
}
Expand All @@ -46,6 +48,7 @@ func NewBitString(args Args) (*BitString, error) {

func NewBitStringWithExtension(bitStringExtension BitStringExtension, args Args) (*BitString, error) {
b := &BitString{
_appTag: model.BACnetDataType_BIT_STRING,
bitStringExtension: bitStringExtension,
}
if len(args) == 0 {
Expand Down Expand Up @@ -92,12 +95,16 @@ func NewBitStringWithExtension(bitStringExtension BitStringExtension, args Args)
return b, nil
}

func (b *BitString) GetAppTag() model.BACnetDataType {
return b._appTag
}

func (b *BitString) Decode(arg Arg) error {
tag, ok := arg.(Tag)
if !ok {
return errors.Errorf("%T is not a Tag", arg)
}
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(model.BACnetDataType_BIT_STRING) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(b._appTag) {
return errors.New("bit string application tag required")
}
if len(tag.GetTagData()) == 0 {
Expand Down Expand Up @@ -157,7 +164,7 @@ func (b *BitString) Encode(arg Arg) error {
data = append(data, x)
}

tag.setAppData(uint(model.BACnetDataType_BIT_STRING), data)
tag.setAppData(uint(b._appTag), data)
return nil
}

Expand Down
14 changes: 11 additions & 3 deletions plc4go/internal/bacnetip/primitivedata_Boolean.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ import (

type Boolean struct {
*Atomic[int] //Note we need int as bool can't be used

_appTag model.BACnetDataType
}

func NewBoolean(arg Arg) (*Boolean, error) {
b := &Boolean{}
b := &Boolean{
_appTag: model.BACnetDataType_BOOLEAN,
}
b.Atomic = NewAtomic[int](b)

if arg == nil {
Expand Down Expand Up @@ -66,12 +70,16 @@ func NewBoolean(arg Arg) (*Boolean, error) {
return b, nil
}

func (b *Boolean) GetAppTag() model.BACnetDataType {
return b._appTag
}

func (b *Boolean) Encode(arg Arg) error {
tag, ok := arg.(Tag)
if !ok {
return errors.Errorf("%T is not a Tag", arg)
} //TODO: move tag number into member variable
tag.set(NewArgs(model.TagClass_APPLICATION_TAGS, model.BACnetDataType_BOOLEAN, b.value, []byte{}))
tag.set(NewArgs(model.TagClass_APPLICATION_TAGS, b._appTag, b.value, []byte{}))
return nil
}

Expand All @@ -80,7 +88,7 @@ func (b *Boolean) 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(model.BACnetDataType_BOOLEAN) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(b._appTag) {
return errors.New("boolean application tag required")
}
if tag.GetTagLvt() > 1 {
Expand Down
14 changes: 11 additions & 3 deletions plc4go/internal/bacnetip/primitivedata_CharacterString.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ type CharacterString struct {
*Atomic[string]
*CommonMath

_appTag model.BACnetDataType

strEncoding byte
strValue []byte
}

func NewCharacterString(arg Arg) (*CharacterString, error) {
c := &CharacterString{}
c := &CharacterString{
_appTag: model.BACnetDataType_CHARACTER_STRING,
}
c.Atomic = NewAtomic[string](c)

if arg == nil {
Expand All @@ -63,12 +67,16 @@ func NewCharacterString(arg Arg) (*CharacterString, error) {
return c, nil
}

func (c *CharacterString) GetAppTag() model.BACnetDataType {
return c._appTag
}

func (c *CharacterString) Encode(arg Arg) error {
tag, ok := arg.(Tag)
if !ok {
return errors.Errorf("%T is not a Tag", arg)
}
tag.setAppData(uint(model.BACnetDataType_CHARACTER_STRING), append([]byte{c.strEncoding}, c.strValue...))
tag.setAppData(uint(c._appTag), append([]byte{c.strEncoding}, c.strValue...))
return nil
}

Expand All @@ -77,7 +85,7 @@ func (c *CharacterString) 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(model.BACnetDataType_CHARACTER_STRING) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(c._appTag) {
return errors.New("CharacterString application tag required")
}
if len(tag.GetTagData()) == 0 {
Expand Down
14 changes: 11 additions & 3 deletions plc4go/internal/bacnetip/primitivedata_Date.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ type DateTuple struct {

type Date struct {
value DateTuple

_appTag model.BACnetDataType
}

func NewDate(arg Arg, args Args) (*Date, error) {
d := &Date{}
d := &Date{
_appTag: model.BACnetDataType_DATE,
}
year := 255
if len(args) > 0 {
year = args[0].(int)
Expand Down Expand Up @@ -245,6 +249,10 @@ func NewDate(arg Arg, args Args) (*Date, error) {
return d, nil
}

func (d *Date) GetAppTag() model.BACnetDataType {
return d._appTag
}

func (d *Date) calcDayOfWeek() {
year, month, day, dayOfWeek := d.value.Year, d.value.Month, d.value.Day, d.value.DayOfWeek

Expand Down Expand Up @@ -281,7 +289,7 @@ func (d *Date) Encode(arg Arg) error {
if !ok {
return errors.Errorf("%T is not a Tag", arg)
}
tag.setAppData(uint(model.BACnetDataType_DATE), []byte{byte(d.value.Year), byte(d.value.Month), byte(d.value.Day), byte(d.value.DayOfWeek)})
tag.setAppData(uint(d._appTag), []byte{byte(d.value.Year), byte(d.value.Month), byte(d.value.Day), byte(d.value.DayOfWeek)})

return nil
}
Expand All @@ -291,7 +299,7 @@ func (d *Date) 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(model.BACnetDataType_DATE) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(d._appTag) {
return errors.New("Date application tag required")
}
if len(tag.GetTagData()) != 4 {
Expand Down
14 changes: 11 additions & 3 deletions plc4go/internal/bacnetip/primitivedata_Double.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ import (
type Double struct {
*Atomic[float64]
*CommonMath

_appTag model.BACnetDataType
}

func NewDouble(arg Arg) (*Double, error) {
b := &Double{}
b := &Double{
_appTag: model.BACnetDataType_DOUBLE,
}
b.Atomic = NewAtomic[float64](b)

if arg == nil {
Expand Down Expand Up @@ -63,14 +67,18 @@ func NewDouble(arg Arg) (*Double, error) {
return b, nil
}

func (d *Double) GetAppTag() model.BACnetDataType {
return d._appTag
}

func (d *Double) Encode(arg Arg) error {
tag, ok := arg.(Tag)
if !ok {
return errors.Errorf("%T is not a Tag", arg)
}
var _b = make([]byte, 8)
binary.BigEndian.PutUint64(_b, math.Float64bits(d.value))
tag.setAppData(uint(model.BACnetDataType_DOUBLE), _b)
tag.setAppData(uint(d._appTag), _b)
return nil
}

Expand All @@ -79,7 +87,7 @@ func (d *Double) 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(model.BACnetDataType_DOUBLE) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(d._appTag) {
return errors.New("Double application tag required")
}
if len(tag.GetTagData()) != 8 {
Expand Down
14 changes: 11 additions & 3 deletions plc4go/internal/bacnetip/primitivedata_Enumeration.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ type Enumerated struct {
*Atomic[uint64]
EnumeratedContract

_appTag model.BACnetDataType

_xlateTable map[any]any

valueString string
}

func NewEnumerated(args ...any) (*Enumerated, error) {
e := &Enumerated{}
e := &Enumerated{
_appTag: model.BACnetDataType_ENUMERATED,
}
e.EnumeratedContract = e
e.Atomic = NewAtomic[uint64](e)

Expand Down Expand Up @@ -131,6 +135,10 @@ func NewEnumerated(args ...any) (*Enumerated, error) {
return e, nil
}

func (e *Enumerated) GetAppTag() model.BACnetDataType {
return e._appTag
}

func (e *Enumerated) GetEnumerations() map[string]uint64 {
return make(map[string]uint64)
}
Expand Down Expand Up @@ -191,7 +199,7 @@ func (e *Enumerated) 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(model.BACnetDataType_ENUMERATED) {
if tag.GetTagClass() != model.TagClass_APPLICATION_TAGS || tag.GetTagNumber() != uint(e._appTag) {
return errors.New("bit string application tag required")
}
if len(tag.GetTagData()) == 0 {
Expand Down Expand Up @@ -234,7 +242,7 @@ func (e *Enumerated) Encode(arg Arg) error {
}

// encode the tag
tag.setAppData(uint(model.BACnetDataType_ENUMERATED), data)
tag.setAppData(uint(e._appTag), data)
return nil
}

Expand Down
Loading

0 comments on commit b076cf9

Please sign in to comment.