Skip to content

Commit

Permalink
optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
sdghchj committed Jun 20, 2020
1 parent ef215a1 commit 82842e8
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 46 deletions.
35 changes: 23 additions & 12 deletions encoding/appdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,28 @@ func (e *Encoder) date(dt bactype.Date) {
e.write(uint8(dt.DayOfWeek))
}

func (d *Decoder) date(dt *bactype.Date) {
var year, month, day, dayOfWeek uint8
func (d *Decoder) date(dt *bactype.Date, length int) {
if length <= 0 {
return
}
data := make([]byte, length)
_, d.err = d.Read(data)
if d.err != nil {
return
}
if len(data) < 4 {
return
}

if dt.Year != bactype.UnspecifiedTime {
dt.Year = int(year) + epochYear
dt.Year = int(data[0]) + epochYear
} else {
dt.Year = int(year)
dt.Year = int(data[0])
}

dt.Month = int(month)
dt.Day = int(day)
dt.DayOfWeek = bactype.DayOfWeek(dayOfWeek)
dt.Month = int(data[1])
dt.Day = int(data[2])
dt.DayOfWeek = bactype.DayOfWeek(data[3])
}

func (e *Encoder) time(t bactype.Time) {
Expand Down Expand Up @@ -242,10 +252,7 @@ func (e *Encoder) AppData(i interface{}) error {
return nil
}

func (d *Decoder) AppData() (interface{}, error) {
tag, _, lenvalue := d.tagNumberAndValue()
len := int(lenvalue)

func (d *Decoder) AppDataOfTag(tag uint8, len int) (interface{}, error) {
switch tag {
case tagNull:
return bactype.Null{}, nil
Expand Down Expand Up @@ -281,7 +288,7 @@ func (d *Decoder) AppData() (interface{}, error) {
return d.enumerated(len), d.Error()
case tagDate:
var date bactype.Date
d.date(&date)
d.date(&date, len)
return date, d.Error()
case tagTime:
var t bactype.Time
Expand All @@ -297,3 +304,7 @@ func (d *Decoder) AppData() (interface{}, error) {
return nil, fmt.Errorf("Unsupported tag: %d", tag)
}
}
func (d *Decoder) AppData() (interface{}, error) {
tag, _, lenvalue := d.tagNumberAndValue()
return d.AppDataOfTag(tag, int(lenvalue))
}
142 changes: 142 additions & 0 deletions encoding/context_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package encoding

import "github.com/alexbeltran/gobacnet/types"

/* returns the fixed tag type for certain context tagged properties */
func tagTypeInContext(property types.PropertyType, tagNumber uint8) uint8 {
var tag uint8 = tagNumber
switch property {
case types.PROP_ACTUAL_SHED_LEVEL:
case types.PROP_REQUESTED_SHED_LEVEL:
case types.PROP_EXPECTED_SHED_LEVEL:
switch tagNumber {
case 0:
case 1:
tag = tagUint
break
case 2:
tag = tagReal
break
default:
break
}
break
case types.PROP_ACTION:
switch tagNumber {
case 0:
case 1:
tag = tagObjectID
break
case 2:
tag = tagEnumerated
break
case 3:
case 5:
case 6:
tag = tagUint
break
case 7:
case 8:
tag = tagBool
break
case 4: /* propertyValue: abstract syntax */
default:
break
}
break
case types.PROP_LIST_OF_GROUP_MEMBERS:
/* Sequence of ReadAccessSpecification */
switch tagNumber {
case 0:
tag = tagObjectID
break
default:
break
}
break
case types.PROP_EXCEPTION_SCHEDULE:
switch tagNumber {
case 1:
tag = tagObjectID
break
case 3:
tag = tagUint
break
case 0: /* calendarEntry: abstract syntax + context */
case 2: /* list of BACnetTimeValue: abstract syntax */
default:
break
}
break
case types.PROP_LOG_DEVICE_OBJECT_PROPERTY:
switch tagNumber {
case 0: /* Object ID */
case 3: /* Device ID */
tag = tagObjectID
break
case 1: /* Property ID */
tag = tagEnumerated
break
case 2: /* Array index */
tag = tagUint
break
default:
break
}
break
case types.PROP_SUBORDINATE_LIST:
/* BACnetARRAY[N] of BACnetDeviceObjectReference */
switch tagNumber {
case 0: /* Optional Device ID */
case 1: /* Object ID */
tag = tagObjectID
break
default:
break
}
break

case types.PROP_RECIPIENT_LIST:
/* List of BACnetDestination */
switch tagNumber {
case 0: /* Device Object ID */
tag = tagObjectID
break
case 1:
/* 2015.08.22 EKH 135-2012 pg 708
todo - Context 1 in Recipient list would be a BACnetAddress, not coded yet...
BACnetRecipient::= CHOICE {
device [0] BACnetObjectIdentifier,
address [1] BACnetAddress
}
*/
break
default:
break
}
break
case types.PROP_ACTIVE_COV_SUBSCRIPTIONS:
/* BACnetCOVSubscription */
switch tagNumber {
case 0: /* BACnetRecipientProcess */
case 1: /* BACnetObjectPropertyReference */
break
case 2: /* issueConfirmedNotifications */
tag = tagBool
break
case 3: /* timeRemaining */
tag = tagUint
break
case 4: /* covIncrement */
tag = tagReal
break
default:
break
}
break
default:
break
}

return tag
}
4 changes: 4 additions & 0 deletions encoding/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func (d *Decoder) ReadByte() (byte, error) {
return d.buff.ReadByte()
}

func (d *Decoder) Read(data []byte) (int, error) {
return d.buff.Read(data)
}

func (d *Decoder) UnreadByte() error {
return d.buff.UnreadByte()
}
Expand Down
84 changes: 51 additions & 33 deletions encoding/readmultipleack.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,40 +102,33 @@ func (d *Decoder) objectsWithData(objects *[]bactype.Object) error {
obj.Properties = []bactype.Property{}

// Tag 0 - Object ID
var expectedTag uint8
tag, meta, length := d.tagNumberAndValue()
objType, instance := d.objectId()

if tag != expectedTag {
return &ErrorIncorrectTag{Expected: expectedTag, Given: tag}
}
if !meta.isContextSpecific() {
if tag != 0 {
return &ErrorIncorrectTag{Expected: 0, Given: tag}
} else if !meta.isContextSpecific() {
return &ErrorWrongTagType{ContextTag}
}

obj.ID.Type = objType
obj.ID.Instance = instance
obj.ID.Type, obj.ID.Instance = d.objectId()

// Tag 1 - Opening Tag
expectedTag++
tag, meta = d.tagNumber()
if tag != expectedTag {
return &ErrorIncorrectTag{Expected: expectedTag, Given: tag}
}
if !meta.isOpening() {
if tag != 1 {
return &ErrorIncorrectTag{Expected: 1, Given: tag}
} else if !meta.isOpening() {
return &ErrorWrongTagType{OpeningTag}
}

// Tag 2 - Property Tag
tag, meta, length = d.tagNumberAndValue()
if tag != 2 {
return &ErrorIncorrectTag{Expected: 2, Given: tag}
}

for d.len() > 0 && tag == 2 && !meta.isClosing() {
expectedTag = 2
if !meta.isContextSpecific() {
return &ErrorWrongTagType{ContextTag}
}
if tag != expectedTag {
return &ErrorIncorrectTag{Expected: expectedTag, Given: tag}
}

prop := bactype.Property{}
prop.Type = bactype.PropertyType(d.enumerated(int(length)))

Expand All @@ -154,31 +147,47 @@ func (d *Decoder) objectsWithData(objects *[]bactype.Object) error {
}

// Tag 4 - Opening Tag
expectedTag = 4
if tag == expectedTag && meta.isOpening() {
if tag == 4 && meta.isOpening() {
var array []interface{}
tag, meta = d.tagNumber()
_ = d.UnreadByte()
if d.err != nil {
return d.err
}
for {
if meta.isContextSpecific() {
tag, meta = d.tagNumber()
if d.err != nil {
return d.err
}
if !meta.isClosing() {
//TODO to be done
if meta.isClosing() {
_ = d.UnreadByte()
} else {
// TODO how to parse it in Context???
*objects = append(*objects, obj)
return nil

lenValue := d.value(meta)
tag = tagTypeInContext(prop.Type, tag)
if tag == maxTag {
//skip unknown type
if lenValue > 0 {
if _, err := d.Read(make([]byte, lenValue)); err != nil {
return err
}
}
} else {
data, err := d.AppDataOfTag(tag, int(lenValue))
if err != nil {
return err
}
array = append(array, data)
}
}
} else {
data, err := d.AppData()
data, err := d.AppDataOfTag(tag, int(d.value(meta)))
if err != nil {
return err
}
array = append(array, data)
}
tag, meta = d.tagNumber()
if tag == expectedTag && meta.isClosing() {
if meta.isClosing() { //tag 4
//
break
} else {
Expand All @@ -193,22 +202,31 @@ func (d *Decoder) objectsWithData(objects *[]bactype.Object) error {
obj.Properties = append(obj.Properties, prop)

tag, meta = d.tagNumber()
} else if tag == expectedTag+1 && meta.isOpening() {
} else if tag == 5 && meta.isOpening() {
//Tag 5 error
var class, code uint32
err := d.bacError(&class, &code)
if err != nil {
return err
}
tag, meta = d.tagNumber()
if tag == expectedTag+1 && meta.isClosing() {
if tag == 5 && meta.isClosing() {
//
}
return fmt.Errorf("Class %d Code %d", class, code)
} else {
return &ErrorIncorrectTag{Expected: expectedTag, Given: tag}
return &ErrorIncorrectTag{Expected: 4, Given: tag}
}
}

// Tag 1 - Closing Tag
tag, meta = d.tagNumber()
if tag != 1 {
return &ErrorIncorrectTag{Expected: 1, Given: tag}
} else if !meta.isClosing() {
return &ErrorWrongTagType{OpeningTag}
}

*objects = append(*objects, obj)
}
return d.Error()
Expand Down
2 changes: 1 addition & 1 deletion types/bitstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func NewBitString(bufferSize int) *BitString {

func (bs *BitString) Value() []bool {
value := make([]bool, bs.bitUsed)
for i := uint8(0); i <= bs.bitUsed; i++ {
for i := uint8(0); i < bs.bitUsed; i++ {
if bs.Bit(i) {
value[i] = true
} else {
Expand Down
1 change: 1 addition & 0 deletions types/property.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
PropUnits PropertyType = 117
PropPriorityArray PropertyType = 87

//from github.com/bacnet-stack/bacnet-stack
PROP_ACKED_TRANSITIONS PropertyType = 0
PROP_ACK_REQUIRED PropertyType = 1
PROP_ACTION PropertyType = 2
Expand Down

0 comments on commit 82842e8

Please sign in to comment.