Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion examples/rp-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,17 @@ func ReadPropertyClientExample(cmd *cobra.Command, args []string) {
replyRaw := make([]byte, 1024)
sentRequests := 0
for {
listenConn.SetDeadline(time.Now().Add(5 * time.Second))
if _, err := listenConn.WriteTo(mReadProperty, remoteUDPAddr); err != nil {
log.Fatalf("Failed to write the request: %s\n", err)
}

log.Printf("sent: %x", mReadProperty)

nBytes, remoteAddr, err := listenConn.ReadFrom(replyRaw)
if err != nil {
log.Fatalf("error reading incoming packet: %v\n", err)
}

log.Printf("read %d bytes from %s: %x\n", nBytes, remoteAddr, replyRaw[:nBytes])

Expand All @@ -87,7 +91,7 @@ func ReadPropertyClientExample(cmd *cobra.Command, args []string) {
}

log.Printf(
"decoded CACK reply:\n\tObject Type: %d\n\tInstance Id: %d\n\tProperty Id: %d\n\tValue: %f\n",
"decoded CACK reply:\n\tObject Type: %d\n\tInstance Id: %d\n\tProperty Id: %d\n\tValue: %v\f",
decodedCACK.ObjectType, decodedCACK.InstanceId, decodedCACK.PropertyId, decodedCACK.PresentValue,
)

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/google/go-cmp v0.5.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.7.0
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
Expand Down
21 changes: 17 additions & 4 deletions objects/objects.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package objects

import (
"fmt"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

Expand Down Expand Up @@ -33,14 +36,21 @@ const objLenMin int = 2
// UnmarshalBinary sets the values retrieved from byte sequence in a Object frame.
func (o *Object) UnmarshalBinary(b []byte) error {
if l := len(b); l < objLenMin {
return common.ErrTooShortToParse
return errors.Wrap(
common.ErrTooShortToParse,
fmt.Sprintf("failed to unmarshal - binary %x - too short", b),
)
}

o.TagNumber = b[0] >> 4
o.TagClass = common.IntToBool(int(b[0]) & 0x8 >> 3)
o.Length = b[0] & 0x7

if l := len(b); l < int(o.Length) {
return common.ErrTooShortToParse
return errors.Wrap(
common.ErrTooShortToParse,
fmt.Sprintf("failed to unmarshal object - binary %x - marshal length too short", b),
)
}

o.Data = b[1:o.Length]
Expand All @@ -52,7 +62,7 @@ func (o *Object) UnmarshalBinary(b []byte) error {
func (o *Object) MarshalBinary() ([]byte, error) {
b := make([]byte, o.MarshalLen())
if err := o.MarshalTo(b); err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to marshal object")
}

return b, nil
Expand All @@ -61,7 +71,10 @@ func (o *Object) MarshalBinary() ([]byte, error) {
// MarshalTo puts the byte sequence in the byte array given as b.
func (o *Object) MarshalTo(b []byte) error {
if len(b) < o.MarshalLen() {
return common.ErrTooShortToMarshalBinary
return errors.Wrap(
common.ErrTooShortToMarshalBinary,
fmt.Sprintf("failed to marshal object - binary %x - marshal length too short", b),
)
}
b[0] = o.TagNumber<<4 | uint8(common.BoolToInt(o.TagClass))<<3 | o.Length
if o.Length > 0 {
Expand Down
7 changes: 4 additions & 3 deletions objects/oid.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package objects
import (
"encoding/binary"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

Expand All @@ -16,17 +17,17 @@ func DecObjectIdentifier(rawPayload APDUPayload) (ObjectIdentifier, error) {

rawObject, ok := rawPayload.(*Object)
if !ok {
return decObjectId, common.ErrWrongPayload
return decObjectId, errors.Wrap(common.ErrWrongPayload, "failed to decode ObjectID")
}

switch rawObject.TagClass {
case true:
if rawObject.Length != 4 {
return decObjectId, common.ErrWrongStructure
return decObjectId, errors.Wrap(common.ErrWrongStructure, "failed to decode ObjectID - wrong binary length")
}
case false:
if rawObject.Length != 4 || rawObject.TagNumber != TagBACnetObjectIdentifier {
return decObjectId, common.ErrWrongStructure
return decObjectId, errors.Wrap(common.ErrWrongStructure, "failed to decode ObjectID - wrong tag number")
}
}

Expand Down
52 changes: 42 additions & 10 deletions objects/primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ package objects

import (
"encoding/binary"
"fmt"
"math"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

func DecUnisgnedInteger(rawPayload APDUPayload) (uint32, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return 0, common.ErrWrongPayload
return 0, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode UnsignedInteger - %v", rawPayload),
)
}

if rawObject.TagNumber != TagUnsignedInteger || rawObject.TagClass {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode UnsignedInteger - wrong tag number - %v", rawObject.TagNumber),
)
}

switch rawObject.Length {
Expand All @@ -28,7 +36,10 @@ func DecUnisgnedInteger(rawPayload APDUPayload) (uint32, error) {
return binary.BigEndian.Uint32(rawObject.Data), nil
}

return 0, common.ErrNotImplemented
return 0, errors.Wrap(
common.ErrNotImplemented,
fmt.Sprintf("failed to decode UnsignedInteger - %v", rawObject.Data),
)
}

func EncUnsignedInteger16(value uint16) *Object {
Expand All @@ -48,11 +59,17 @@ func EncUnsignedInteger16(value uint16) *Object {
func DecEnumerated(rawPayload APDUPayload) (uint32, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return 0, common.ErrWrongPayload
return 0, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode EnumObject - %v", rawPayload),
)
}

if rawObject.TagNumber != TagEnumerated || rawObject.TagClass {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode EnumObject - wrong tag number - %v", rawObject.TagNumber),
)
}

switch rawObject.Length {
Expand All @@ -66,7 +83,10 @@ func DecEnumerated(rawPayload APDUPayload) (uint32, error) {
return binary.BigEndian.Uint32(rawObject.Data), nil
}

return 0, common.ErrNotImplemented
return 0, errors.Wrap(
common.ErrNotImplemented,
fmt.Sprintf("failed to decode EnumObject - %v", rawObject.Data),
)
}

func EncEnumerated(value uint8) *Object {
Expand All @@ -86,11 +106,17 @@ func EncEnumerated(value uint8) *Object {
func DecReal(rawPayload APDUPayload) (float32, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return 0, common.ErrWrongPayload
return 0, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode Real - %v", rawPayload),
)
}

if rawObject.TagNumber != TagReal {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode real - wrong tag number - %v", rawObject.TagNumber),
)
}

return math.Float32frombits(binary.BigEndian.Uint32(rawObject.Data)), nil
Expand All @@ -113,11 +139,17 @@ func EncReal(value float32) *Object {
func DecNull(rawPayload APDUPayload) (bool, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return false, common.ErrWrongPayload
return false, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode Null - %v", rawPayload),
)
}

if rawObject.TagNumber != TagReal {
return false, common.ErrWrongStructure
return false, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode Null - wrong tag number - %v", rawObject.TagNumber),
)
}

return rawObject.TagNumber == TagNull && !rawObject.TagClass && rawObject.Length == 0, nil
Expand Down
17 changes: 14 additions & 3 deletions objects/priority.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
package objects

import (
"fmt"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

func DecPriority(rawPayload APDUPayload) (uint8, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return 0, common.ErrWrongPayload
return 0, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode Priority Object - %v", rawPayload),
)
}

switch rawObject.TagClass {
case true:
if rawObject.Length != 1 {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode Priority Object - wrong binary length - %x", rawObject.Data),)
}
case false:
if rawObject.Length != 1 || !rawObject.TagClass {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode Priority Object - wrong tag number - %v", rawObject.TagNumber),
)
}
}

Expand Down
18 changes: 15 additions & 3 deletions objects/property.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
package objects

import (
"fmt"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

func DecPropertyIdentifier(rawPayload APDUPayload) (uint8, error) {
rawObject, ok := rawPayload.(*Object)
if !ok {
return 0, common.ErrWrongPayload
return 0, errors.Wrap(
common.ErrWrongPayload,
fmt.Sprintf("failed to decode PropertyID - %v", rawPayload),
)
}

switch rawObject.TagClass {
case true:
if rawObject.Length != 1 {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode PropertyID - wrong binary length - %x", rawObject.Data),
)
}
case false:
if rawObject.Length != 1 || !rawObject.TagClass {
return 0, common.ErrWrongStructure
return 0, errors.Wrap(
common.ErrWrongStructure,
fmt.Sprintf("failed to decode PropertyID - wrong tag number - %v", rawObject.TagNumber),
)
}
}

Expand Down
21 changes: 15 additions & 6 deletions objects/tags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package objects

import (
"fmt"

"github.com/pkg/errors"
"github.com/ulbios/bacnet/common"
)

Expand All @@ -20,14 +23,20 @@ func NewNamedTag(number uint8, class bool, name uint8) *NamedTag {

func (n *NamedTag) UnmarshalBinary(b []byte) error {
if l := len(b); l < objLenMin {
return common.ErrTooShortToParse
return errors.Wrap(
common.ErrTooShortToParse,
fmt.Sprintf("failed to unmarshal NamedTag - binary too short - %x", b),
)
}
n.TagNumber = b[0] >> 4
n.TagClass = common.IntToBool(int(b[0]) & 0x8 >> 3)
n.Name = b[0] & 0x7

if l := len(b); l < 1 {
return common.ErrTooShortToParse
return errors.Wrap(
common.ErrTooShortToParse,
fmt.Sprintf("failed to unmarshal NamedTag - missing data - %v", n),
)
}

return nil
Expand All @@ -36,15 +45,15 @@ func (n *NamedTag) UnmarshalBinary(b []byte) error {
func (n *NamedTag) MarshalBinary() ([]byte, error) {
b := make([]byte, n.MarshalLen())
if err := n.MarshalTo(b); err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to marshal binary")
}

return b, nil
}

func (n *NamedTag) MarshalTo(b []byte) error {
if len(b) < n.MarshalLen() {
return common.ErrTooShortToMarshalBinary
return errors.Wrap(common.ErrTooShortToMarshalBinary, "failed to marshall NamedTag - marshal length too short")
}
b[0] = n.TagNumber<<4 | uint8(common.BoolToInt(n.TagClass))<<3 | n.Name

Expand All @@ -58,7 +67,7 @@ func (n *NamedTag) MarshalLen() int {
func DecOpeningTab(rawPayload APDUPayload) (bool, error) {
rawTag, ok := rawPayload.(*NamedTag)
if !ok {
return false, common.ErrWrongPayload
return false, errors.Wrap(common.ErrWrongPayload, "failed to decode OpeningTab")
}
return rawTag.Name == 0x6 && rawTag.TagClass, nil
}
Expand All @@ -76,7 +85,7 @@ func EncOpeningTag(tagN uint8) *NamedTag {
func DecClosingTab(rawPayload APDUPayload) (bool, error) {
rawTag, ok := rawPayload.(*NamedTag)
if !ok {
return false, common.ErrWrongPayload
return false, errors.Wrap(common.ErrWrongPayload, "failed to decode ClosingTab")
}
return rawTag.Name == 0x7 && rawTag.TagClass, nil
}
Expand Down
Loading