From 67f2cedae82ffec689dc382c48619917eb591ffd Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 28 Aug 2023 15:42:59 +0300 Subject: [PATCH 01/24] add bacnet package Signed-off-by: SammyOina --- base.go | 35 +++++++++++++++++++++++++++++++++++ client.go | 19 +++++++++++++++++++ go.mod | 3 +++ 3 files changed, 57 insertions(+) create mode 100644 base.go create mode 100644 client.go create mode 100644 go.mod diff --git a/base.go b/base.go new file mode 100644 index 0000000..34ed666 --- /dev/null +++ b/base.go @@ -0,0 +1,35 @@ +package bacnet + +type NetworkPriority int + +const ( + LifeSafetyMessage NetworkPriority = iota + 1 + CriticalEquipmentMessage + UrgentMessage + NormalMessage +) + +type NetworkLayerMessage int + +const ( + WhoIsRouterToNetwork NetworkLayerMessage = iota + IAmRouterToNetwork + ICouldBeRouterToNetwork + RejectMessageToNetwork + RouterBusyToNetwork + RouterAvailableToNetwork + InitRtTable + InitRtTableAck + EstablishConnectionToNetwork + DisconnectConnectionToNetwork + ChallengeRequest + SecurityPayload + SecurityResponse + RequestKeyUpdate + UpdateKeySet + UpdateDistributionKey + RequestMasterKey + SetMasterKey + WhatIsNetworkNumber + NetworkNumberIs +) diff --git a/client.go b/client.go new file mode 100644 index 0000000..b639e27 --- /dev/null +++ b/client.go @@ -0,0 +1,19 @@ +package bacnet + +type client struct { + // Fields for client configuration +} + +type Client interface { + ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (Value, error) + WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value Value) error +} + +func NewClient(address string, port int) (Client, error) { +} + +func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (Value, error) { +} + +func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value Value) error { +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c8d470d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/absmach/bacnet + +go 1.21.0 From 354108bbb4bc24350758e222c3141ba7ced4d090 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 28 Aug 2023 17:04:21 +0300 Subject: [PATCH 02/24] set base types and constants Signed-off-by: SammyOina --- base.go | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/base.go b/base.go index 34ed666..28fa40f 100644 --- a/base.go +++ b/base.go @@ -9,10 +9,10 @@ const ( NormalMessage ) -type NetworkLayerMessage int +type NetworkLayerMessageType int const ( - WhoIsRouterToNetwork NetworkLayerMessage = iota + WhoIsRouterToNetwork NetworkLayerMessageType = iota IAmRouterToNetwork ICouldBeRouterToNetwork RejectMessageToNetwork @@ -33,3 +33,119 @@ const ( WhatIsNetworkNumber NetworkNumberIs ) + +type BacnetMaxSegments int + +const ( + MaxSEG0 BacnetMaxSegments = 0 + MaxSEG2 BacnetMaxSegments = 0x10 + MaxSEG4 BacnetMaxSegments = 0x20 + MaxSEG8 BacnetMaxSegments = 0x30 + MaxSEG16 BacnetMaxSegments = 0x40 + MaxSEG32 BacnetMaxSegments = 0x50 + MaxSEG64 BacnetMaxSegments = 0x60 + MaxSEG65 BacnetMaxSegments = 0x70 +) + +type BacnetMaxAdpu int + +const ( + MaxAPDU50 BacnetMaxAdpu = iota + MaxAPDU128 + MaxAPDU206 + MaxAPDU480 + MaxAPDU1024 + MaxAPDU1476 +) + +type BacnetPduTypes int + +const ( + PDUTypeConfirmedServiceRequest BacnetPduTypes = iota + Server + NegativeAck + // TODO + SegmentResponseAccepted + MORE_FOLLOWS + SEGMENTED_MESSAGE BacnetPduTypes = 8 + PDUTypeUnconfirmedServiceRequest BacnetPduTypes = 0x10 + PDUTypeSimpleAck BacnetPduTypes = 0x20 + PDUTypeComplexAck BacnetPduTypes = 0x30 + PDUTypeSegmentAck BacnetPduTypes = 0x40 + PDUTypeError BacnetPduTypes = 0x50 + PDUTypeReject BacnetPduTypes = 0x60 + PDUTypeAbort BacnetPduTypes = 0x70 + PDUTypeMask BacnetPduTypes = 0xF0 +) + +type BacnetCharacterStringEncodings int + +const ( + CharacterANSIX34 BacnetCharacterStringEncodings = 0 + CharacterUTF8 BacnetCharacterStringEncodings = 0 + CharacterMSDBCS BacnetCharacterStringEncodings = 1 + CharacterJISC6226 BacnetCharacterStringEncodings = 2 + CharacterJISX0208 BacnetCharacterStringEncodings = 2 + CharacterUCS4 BacnetCharacterStringEncodings = 3 + CharacterUCS2 BacnetCharacterStringEncodings = 4 + CharacterISO8859 BacnetCharacterStringEncodings = 5 +) + +type BACnetApplicationTag int + +const ( + Null BACnetApplicationTag = iota + Boolean + UnsignedInt + SignedInt + Real + Double + OctetString + CharacterString + BitString + Enumerated + Date + Time + BACnetObjectIdentifier + Reserve1 + Reserve2 + Reserve3 +) + +type BacnetNpduControl int + +const ( + PriorityNormalMessage BacnetNpduControl = iota + PriorityUrgentMessage + PriorityCriticalMessage + PriorityLifeSafetyMessage + ExpectingReply + SourceSpecified BacnetNpduControl = 8 + DestinationSpecified BacnetNpduControl = 32 + NetworkLayerMessage BacnetNpduControl = 128 +) + +type BacnetNetworkMessageType int + +const ( + NetworkMessageWhoIsRouterToNetwork BacnetNetworkMessageType = iota + NetworkMessageIAmRouterToNetwork + NetworkMessageICouldBeRouterToNetwork + NetworkMessageRejectMessageToNetwork + NetworkMessageRouterBusyToNetwork + NetworkMessageRouterAvailableToNetwork + NetworkMessageInitRtTable + NetworkMessageInitRtTableAck + NetworkMessageEstablishConnectionToNetwork + NetworkMessageDisconnectConnectionToNetwork + NetworkMessageChallengeRequest + NetworkMessageSecurityPayload + NetworkMessageSecurityResponse + NetworkMessageRequestKeyUpdate + NetworkMessageUpdateKeySet + NetworkMessageUpdateDistributionKey + NetworkMessageRequestMasterKey + NetworkMessageSetMasterKey + NetworkMessageWhatIsNetworkNumber + NetworkMessageNetworkNumberIs +) From c46d913b6c95cf354687089ddac59f2474b77b31 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 28 Aug 2023 17:11:42 +0300 Subject: [PATCH 03/24] add error classes and codes Signed-off-by: SammyOina --- base.go | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/base.go b/base.go index 28fa40f..88e1ac5 100644 --- a/base.go +++ b/base.go @@ -149,3 +149,161 @@ const ( NetworkMessageWhatIsNetworkNumber NetworkMessageNetworkNumberIs ) + +// ErrorClassEnum represents the error classes as constants. +type ErrorClassEnum int + +const ( + Device ErrorClassEnum = iota + Object + Property + Resources + Security + Services + VT + Communication +) + +// Error Code Enum represents the error codes as constants. +type ErrorCodeEnum int + +const ( + Other ErrorCodeEnum = iota + AuthenticationFailed + ConfigurationInProgress + DeviceBusy + DynamicCreationNotSupported + FileAccessDenied + IncompatibleSecurityLevels + InconsistentParameters + InconsistentSelectionCriterion + InvalidDataType + InvalidFileAccessMethod + InvalidFileStartPosition + InvalidOperatorName + InvalidParameterDataType + InvalidTimestamp + KeyGenerationError + MissingRequiredParameter + NoObjectsOfSpecifiedType + NoSpaceForObject + NoSpaceToAddListElement + NoSpaceToWriteProperty + NoVTSessionsAvailable + PropertyIsNotAList + ObjectDeletionNotPermitted + ObjectIdentifierAlreadyExists + OperationalProblem + PasswordFailure + ReadAccessDenied + SecurityNotSupported + ServiceRequestDenied + Timeout + UnknownObject + UnknownProperty + UnknownVTClass + UnknownVTSession + UnsupportedObjectType + ValueOutOfRange + VTSessionAlreadyClosed + VTSessionTerminationFailure + WriteAccessDenied + CharacterSetNotSupported + InvalidArrayIndex + COVSubscriptionFailed + NotCOVProperty + OptionalFunctionalityNotSupported + InvalidConfigurationData + DataTypeNotSupported + DuplicateName + DuplicateObjectID + PropertyIsNotAnArray + AbortBufferOverflow + AbortInvalidAPDUInThisState + AbortPreemptedbyHigherPriorityTask + AbortSegmentationNotSupported + AbortProprietary + AbortOther + InvalidTag + NetworkDown + RejectBufferOverflow + RejectInconsistentParameters + RejectInvalidParameterDataType + RejectInvalidTag + RejectMissingRequiredParameter + RejectParameterOutOfRange + RejectTooManyArguments + RejectUndefinedEnumeration + RejectUnrecognizedService + RejectProprietary + RejectOther + UnknownDevice + UnknownRoute + ValueNotInitialized + InvalidEventState + NoAlarmConfigured + LogBufferFull + LoggedValuePurged + NoPropertySpecified + NotConfiguredForTriggeredLogging + UnknownSubscription + ParameterOutOfRange + ListElementNotFound + Busy + CommunicationDisabled + Success + AccessDenied + BadDestinationAddress + BadDestinationDeviceID + BadSignature + BadSourceAddress + BadTimestamp + CannotUseKey + CannotVerifyMessageID + CorrectKeyRevision + DestinationDeviceIDRequired + DuplicateMessage + EncryptionNotConfigured + EncryptionRequired + IncorrectKey + InvalidKeyData + KeyUpdateInProgress + MalformedMessage + NotKeyServer + SecurityNotConfigured + SourceSecurityRequired + TooManyKeys + UnknownAuthenticationType + UnknownKey + UnknownKeyRevision + UnknownSourceMessage + NotRouterToDNET + RouterBusy + UnknownNetworkMessage + MessageTooLong + SecurityError + AddressingError + WriteBDTFailed + ReadBDTFailed + RegisterForeignDeviceFailed + ReadFDTFailed + DeleteFDTEntryFailed + DistributeBroadcastFailed + UnknownFileSize + AbortAPDUTooLong + AbortApplicationExceededReplyTime + AbortOutOfResources + AbortTSMTimeout + AbortWindowSizeOutOfRange + FileFull + InconsistentConfiguration + InconsistentObjectType + InternalError + NotConfigured + OutOfMemory + ValueTooLong + AbortInsufficientSecurity + AbortSecurityError + DuplicateEntry + InvalidValueInThisState +) From 2e6bbc487a8d7cbc38c8b4c33edc5b05eaa6c717 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Tue, 29 Aug 2023 19:47:12 +0300 Subject: [PATCH 04/24] encode integers Signed-off-by: SammyOina --- base.go | 8 +++++++ encoding.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 encoding.go diff --git a/base.go b/base.go index 88e1ac5..4032a31 100644 --- a/base.go +++ b/base.go @@ -307,3 +307,11 @@ const ( DuplicateEntry InvalidValueInThisState ) + +type ObjectIdentifier struct { + Type ObjectType + Instance int +} + +func (oi *ObjectIdentifier) ASN1decode() { +} diff --git a/encoding.go b/encoding.go new file mode 100644 index 0000000..51ec325 --- /dev/null +++ b/encoding.go @@ -0,0 +1,63 @@ +package bacnet + +import ( + "bytes" + "encoding/binary" +) + +const ( + MaxObject = 0x3FF + InstanceBits = 22 + MaxInstance = 0x3FFFFF + MaxBitstringBytes = 15 + ArrayAll = 0xFFFFFFFF + NoPriority = 0 + MinPriority = 1 + MaxPriority = 16 +) + +func encodeUnsigned(value uint32) []byte { + switch { + case value < 0x100: + buf := make([]byte, 1) + buf[0] = uint8(value) + return buf + case value < 0x10000: + buf := make([]byte, 2) + binary.BigEndian.PutUint16(buf, uint16(value)) + return buf + case value < 0x1000000: + buf := make([]byte, 3) + buf[0] = byte((value & 0xff0000) >> 16) + buf[1] = byte((value & 0x00ff00) >> 8) + buf[2] = byte(value & 0x0000ff) + return buf + default: + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, value) + return buf + } +} + +func encodeSigned(value int32) []byte { + switch { + case value < 0x100: + buf := new(bytes.Buffer) + binary.Write(buf, binary.BigEndian, uint8(value)) + return buf.Bytes() + case value < 0x10000: + buf := new(bytes.Buffer) + binary.Write(buf, binary.BigEndian, uint16(value)) + return buf.Bytes() + case value < 0x1000000: + buf := make([]byte, 3) + buf[0] = byte((value & 0xff0000) >> 16) + buf[1] = byte((value & 0x00ff00) >> 8) + buf[2] = byte(value & 0x0000ff) + return buf + default: + buf := new(bytes.Buffer) + binary.Write(buf, binary.BigEndian, value) + return buf.Bytes() + } +} From 6c17e28e99e5dc847aef2217775e3fa6905c0013 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Tue, 29 Aug 2023 22:16:44 +0300 Subject: [PATCH 05/24] add objects Signed-off-by: SammyOina --- base.go | 29 ------ client.go | 8 +- encoding/decoding.go | 9 ++ encoding.go => encoding/encoding.go | 6 +- encoding/tags.go | 134 ++++++++++++++++++++++++++++ object.go | 51 +++++++++++ 6 files changed, 201 insertions(+), 36 deletions(-) create mode 100644 encoding/decoding.go rename encoding.go => encoding/encoding.go (92%) create mode 100644 encoding/tags.go create mode 100644 object.go diff --git a/base.go b/base.go index 4032a31..2184703 100644 --- a/base.go +++ b/base.go @@ -91,27 +91,6 @@ const ( CharacterISO8859 BacnetCharacterStringEncodings = 5 ) -type BACnetApplicationTag int - -const ( - Null BACnetApplicationTag = iota - Boolean - UnsignedInt - SignedInt - Real - Double - OctetString - CharacterString - BitString - Enumerated - Date - Time - BACnetObjectIdentifier - Reserve1 - Reserve2 - Reserve3 -) - type BacnetNpduControl int const ( @@ -307,11 +286,3 @@ const ( DuplicateEntry InvalidValueInThisState ) - -type ObjectIdentifier struct { - Type ObjectType - Instance int -} - -func (oi *ObjectIdentifier) ASN1decode() { -} diff --git a/client.go b/client.go index b639e27..0b78fc5 100644 --- a/client.go +++ b/client.go @@ -5,15 +5,15 @@ type client struct { } type Client interface { - ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (Value, error) - WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value Value) error + ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (interface{}, error) + WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value interface{}) error } func NewClient(address string, port int) (Client, error) { } -func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (Value, error) { +func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (interface{}, error) { } -func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value Value) error { +func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value interface{}) error { } diff --git a/encoding/decoding.go b/encoding/decoding.go new file mode 100644 index 0000000..a3c36c5 --- /dev/null +++ b/encoding/decoding.go @@ -0,0 +1,9 @@ +package encoding + +func DecodeUnsigned(buffer []byte, offset, len int) (int, uint32) { + value := uint32(0) + for i := 0; i < len; i++ { + value += uint32(buffer[offset+i]) << uint(8*(len-i-1)) + } + return len, value +} diff --git a/encoding.go b/encoding/encoding.go similarity index 92% rename from encoding.go rename to encoding/encoding.go index 51ec325..2188e7a 100644 --- a/encoding.go +++ b/encoding/encoding.go @@ -1,4 +1,4 @@ -package bacnet +package encoding import ( "bytes" @@ -16,7 +16,7 @@ const ( MaxPriority = 16 ) -func encodeUnsigned(value uint32) []byte { +func EncodeUnsigned(value uint32) []byte { switch { case value < 0x100: buf := make([]byte, 1) @@ -39,7 +39,7 @@ func encodeUnsigned(value uint32) []byte { } } -func encodeSigned(value int32) []byte { +func EncodeSigned(value int32) []byte { switch { case value < 0x100: buf := new(bytes.Buffer) diff --git a/encoding/tags.go b/encoding/tags.go new file mode 100644 index 0000000..b5888de --- /dev/null +++ b/encoding/tags.go @@ -0,0 +1,134 @@ +package encoding + +type BACnetApplicationTag int + +const ( + Null BACnetApplicationTag = iota + Boolean + UnsignedInt + SignedInt + Real + Double + OctetString + CharacterString + BitString + Enumerated + Date + Time + BACnetObjectIdentifier + Reserve1 + Reserve2 + Reserve3 +) + +func isExtendedTagNumber(b byte) bool { + return (b & 0xF0) == 0xF0 +} + +func isExtendedValue(b byte) bool { + return (b & 0x07) == 5 +} + +func isOpeningTag(b byte) bool { + return (b & 0x07) == 6 +} + +func isClosingTag(b byte) bool { + return (b & 0x07) == 7 +} + +func isContextSpecific(b byte) bool { + return (b & 0x8) == 0x8 +} + +func decodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { + len = 1 + + if isExtendedTagNumber(buf[offset]) { + return len + 1, buf[offset+len] + } + return len, buf[offset] >> 4 +} + +func DecodeIsCOntextTag(buf []byte, offset int, tagNum byte) bool { + _, myTagNum := decodeTagNumber(buf, offset) + return isContextSpecific(buf[offset]) && myTagNum == tagNum + +} + +func DecodeIsCOntextTagWithLength(buf []byte, offset int, tagNum byte) (int, bool) { + tagLen, myTagNum := decodeTagNumber(buf, offset) + return tagLen, isContextSpecific(buf[offset]) && myTagNum == tagNum +} + +func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val uint32) { + len, tagNum = decodeTagNumber(buf, offset) + + switch { + case isExtendedValue(buf[offset]): + switch buf[offset+len] { + case 255: + len += 1 + len1, val1 := DecodeUnsigned(buf, offset+len, 4) + len += len1 + val = val1 + case 254: + len += 1 + len1, val1 := DecodeUnsigned(buf, offset+len, 2) + len += len1 + val = val1 + default: + val = uint32(buf[offset+len]) + len += 1 + } + case isOpeningTag(buf[offset]), isClosingTag(buf[offset]): + val = 0 + default: + val = uint32(buf[offset] & 0x07) + } + return len, tagNum, val + +} + +func DecodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { + len = 1 + if isExtendedTagNumber(buf[offset]) { + return len + 1, buf[offset+len] + } + return len, buf[offset] >> 4 +} + +func EncodeTag(tagNum BACnetApplicationTag, ctxSpecific bool, lenVal int) []byte { + tag := []byte{} + value := byte(0) + + if ctxSpecific { + value = 0x8 + } + + if tagNum <= 14 { + value += byte(tagNum) << 4 + tag = append(tag, value) + } else { + value += 0xF0 + tag = append(tag, value) + tag = append(tag, byte(tagNum)) + } + + if lenVal <= 4 { + tag[0] += byte(lenVal) + return tag + } + tag[0] += 5 + switch { + case lenVal <= 253: + tag = append(tag, byte(lenVal)) + return tag + case lenVal <= 65535: + tag = append(tag, 254) + return append(tag, EncodeUnsigned(uint32(lenVal))...) + default: + tag = append(tag, 255) + return append(tag, EncodeUnsigned(uint32(lenVal))...) + } +} diff --git a/object.go b/object.go new file mode 100644 index 0000000..9c2beba --- /dev/null +++ b/object.go @@ -0,0 +1,51 @@ +package bacnet + +import ( + "encoding/binary" + + "github.com/absmach/bacnet/encoding" +) + +type ObjectInstance uint32 + +type ObjectType uint16 + +type ObjectIdentifier struct { + Type ObjectType + Instance ObjectInstance +} + +func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdu_len int) int { + len, val := encoding.DecodeUnsigned(buf, offset, 4) + oi.Instance = ObjectInstance(val) & ObjectInstance(encoding.MaxInstance) + oi.Type = ObjectType(val >> encoding.InstanceBits & encoding.MaxObject) + return len +} + +func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdu_len int, tagNumber byte) int { + len := 0 + if encoding.DecodeIsCOntextTag(buf, offset+len, tagNumber) { + len1, _, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+len) + len += len1 + len += oi.Decode(buf, offset+len1, int(lenVal)) + return len + } + return -1 +} + +func (oi *ObjectIdentifier) Encode() []byte { + value := uint32(oi.Type)&encoding.MaxObject< Date: Wed, 30 Aug 2023 01:13:24 +0300 Subject: [PATCH 06/24] encoding date time and init property value Signed-off-by: SammyOina --- base.go | 477 ++++++++++++++++++++++++++++++++++++++++++ client.go | 3 + encoding/date_time.go | 100 +++++++++ property.go | 8 + 4 files changed, 588 insertions(+) create mode 100644 encoding/date_time.go create mode 100644 property.go diff --git a/base.go b/base.go index 2184703..f44a793 100644 --- a/base.go +++ b/base.go @@ -286,3 +286,480 @@ const ( DuplicateEntry InvalidValueInThisState ) + +// BACnetPropertyIdentifier represents BACnet property identifiers. +type PropertyIdentifier int + +const ( + AckedTransitions PropertyIdentifier = 0 + AckRequired PropertyIdentifier = 1 + Action PropertyIdentifier = 2 + ActionText PropertyIdentifier = 3 + ActiveText PropertyIdentifier = 4 + ActiveVtSessions PropertyIdentifier = 5 + AlarmValue PropertyIdentifier = 6 + AlarmValues PropertyIdentifier = 7 + All PropertyIdentifier = 8 + AllWritesSuccessful PropertyIdentifier = 9 + ApduSegmentTimeout PropertyIdentifier = 10 + ApduTimeout PropertyIdentifier = 11 + ApplicationSoftwareVersion PropertyIdentifier = 12 + Archive PropertyIdentifier = 13 + Bias PropertyIdentifier = 14 + ChangeOfStateCount PropertyIdentifier = 15 + ChangeOfStateTime PropertyIdentifier = 16 + NotificationClass PropertyIdentifier = 17 + Blank1 PropertyIdentifier = 18 + ControlledVariableReference PropertyIdentifier = 19 + ControlledVariableUnits PropertyIdentifier = 20 + ControlledVariableValue PropertyIdentifier = 21 + CovIncrement PropertyIdentifier = 22 + DateList PropertyIdentifier = 23 + DaylightSavingsStatus PropertyIdentifier = 24 + Deadband PropertyIdentifier = 25 + DerivativeConstant PropertyIdentifier = 26 + DerivativeConstantUnits PropertyIdentifier = 27 + Description PropertyIdentifier = 28 + DescriptionOfHalt PropertyIdentifier = 29 + DeviceAddressBinding PropertyIdentifier = 30 + DeviceType PropertyIdentifier = 31 + EffectivePeriod PropertyIdentifier = 32 + ElapsedActiveTime PropertyIdentifier = 33 + ErrorLimit PropertyIdentifier = 34 + EventEnable PropertyIdentifier = 35 + EventState PropertyIdentifier = 36 + EventType PropertyIdentifier = 37 + ExceptionSchedule PropertyIdentifier = 38 + FaultValues PropertyIdentifier = 39 + FeedbackValue PropertyIdentifier = 40 + FileAccessMethod PropertyIdentifier = 41 + FileSize PropertyIdentifier = 42 + FileType PropertyIdentifier = 43 + FirmwareRevision PropertyIdentifier = 44 + HighLimit PropertyIdentifier = 45 + InactiveText PropertyIdentifier = 46 + InProcess PropertyIdentifier = 47 + InstanceOf PropertyIdentifier = 48 + IntegralConstant PropertyIdentifier = 49 + IntegralConstantUnits PropertyIdentifier = 50 + IssueConfirmedNotifications PropertyIdentifier = 51 + LimitEnable PropertyIdentifier = 52 + ListOfGroupMembers PropertyIdentifier = 53 + ListOfObjectPropertyReferences PropertyIdentifier = 54 + ListOfSessionKeys PropertyIdentifier = 55 + LocalDate PropertyIdentifier = 56 + LocalTime PropertyIdentifier = 57 + Location PropertyIdentifier = 58 + LowLimit PropertyIdentifier = 59 + ManipulatedVariableReference PropertyIdentifier = 60 + MaximumOutput PropertyIdentifier = 61 + MaxApduLengthAccepted PropertyIdentifier = 62 + MaxInfoFrames PropertyIdentifier = 63 + MaxMaster PropertyIdentifier = 64 + MaxPresValue PropertyIdentifier = 65 + MinimumOffTime PropertyIdentifier = 66 + MinimumOnTime PropertyIdentifier = 67 + MinimumOutput PropertyIdentifier = 68 + MinPresValue PropertyIdentifier = 69 + ModelName PropertyIdentifier = 70 + ModificationDate PropertyIdentifier = 71 + NotifyType PropertyIdentifier = 72 + NumberOfApduRetries PropertyIdentifier = 73 + NumberOfStates PropertyIdentifier = 74 + ObjectIdentifierPI PropertyIdentifier = 75 + ObjectList PropertyIdentifier = 76 + ObjectName PropertyIdentifier = 77 + ObjectPropertyReference PropertyIdentifier = 78 + ObjectTypePI PropertyIdentifier = 79 + Optional PropertyIdentifier = 80 + OutOfService PropertyIdentifier = 81 + OutputUnits PropertyIdentifier = 82 + EventParameters PropertyIdentifier = 83 + Polarity PropertyIdentifier = 84 + PresentValue PropertyIdentifier = 85 + Priority PropertyIdentifier = 86 + PriorityArray PropertyIdentifier = 87 + PriorityForWriting PropertyIdentifier = 88 + ProcessIdentifier PropertyIdentifier = 89 + ProgramChange PropertyIdentifier = 90 + ProgramLocation PropertyIdentifier = 91 + ProgramState PropertyIdentifier = 92 + ProportionalConstant PropertyIdentifier = 93 + ProportionalConstantUnits PropertyIdentifier = 94 + ProtocolConformanceClass PropertyIdentifier = 95 + ProtocolObjectTypesSupported PropertyIdentifier = 96 + ProtocolServicesSupported PropertyIdentifier = 97 + ProtocolVersion PropertyIdentifier = 98 + ReadOnly PropertyIdentifier = 99 + ReasonForHalt PropertyIdentifier = 100 + Recipient PropertyIdentifier = 101 + RecipientList PropertyIdentifier = 102 + Reliability PropertyIdentifier = 103 + RelinquishDefault PropertyIdentifier = 104 + Required PropertyIdentifier = 105 + Resolution PropertyIdentifier = 106 + SegmentationSupported PropertyIdentifier = 107 + Setpoint PropertyIdentifier = 108 + SetpointReference PropertyIdentifier = 109 + StateText PropertyIdentifier = 110 + StatusFlags PropertyIdentifier = 111 + SystemStatus PropertyIdentifier = 112 + TimeDelay PropertyIdentifier = 113 + TimeOfActiveTimeReset PropertyIdentifier = 114 + TimeOfStateCountReset PropertyIdentifier = 115 + TimeSynchronizationRecipients PropertyIdentifier = 116 + Units PropertyIdentifier = 117 + UpdateInterval PropertyIdentifier = 118 + UtcOffset PropertyIdentifier = 119 + VendorIdentifier PropertyIdentifier = 120 + VendorName PropertyIdentifier = 121 + VtClassesSupported PropertyIdentifier = 122 + WeeklySchedule PropertyIdentifier = 123 + AttemptedSamples PropertyIdentifier = 124 + AverageValue PropertyIdentifier = 125 + BufferSize PropertyIdentifier = 126 + ClientCovIncrement PropertyIdentifier = 127 + CovResubscriptionInterval PropertyIdentifier = 128 + CurrentNotifyTime PropertyIdentifier = 129 + EventTimeStamps PropertyIdentifier = 130 + LogBuffer PropertyIdentifier = 131 + LogDeviceObjectProperty PropertyIdentifier = 132 + Enable PropertyIdentifier = 133 + LogInterval PropertyIdentifier = 134 + MaximumValue PropertyIdentifier = 135 + MinimumValue PropertyIdentifier = 136 + NotificationThreshold PropertyIdentifier = 137 + PreviousNotifyTime PropertyIdentifier = 138 + ProtocolRevision PropertyIdentifier = 139 + RecordsSinceNotification PropertyIdentifier = 140 + RecordCount PropertyIdentifier = 141 + StartTime PropertyIdentifier = 142 + StopTime PropertyIdentifier = 143 + StopWhenFull PropertyIdentifier = 144 + TotalRecordCount PropertyIdentifier = 145 + ValidSamples PropertyIdentifier = 146 + WindowInterval PropertyIdentifier = 147 + WindowSamples PropertyIdentifier = 148 + MaximumValueTimestamp PropertyIdentifier = 149 + MinimumValueTimestamp PropertyIdentifier = 150 + VarianceValue PropertyIdentifier = 151 + ActiveCovSubscriptions PropertyIdentifier = 152 + BackupFailureTimeout PropertyIdentifier = 153 + ConfigurationFiles PropertyIdentifier = 154 + DatabaseRevision PropertyIdentifier = 155 + DirectReading PropertyIdentifier = 156 + LastRestoreTime PropertyIdentifier = 157 + MaintenanceRequired PropertyIdentifier = 158 + MemberOf PropertyIdentifier = 159 + Mode PropertyIdentifier = 160 + OperationExpected PropertyIdentifier = 161 + Setting PropertyIdentifier = 162 + Silenced PropertyIdentifier = 163 + TrackingValue PropertyIdentifier = 164 + ZoneMembers PropertyIdentifier = 165 + LifeSafetyAlarmValues PropertyIdentifier = 166 + MaxSegmentsAccepted PropertyIdentifier = 167 + ProfileName PropertyIdentifier = 168 + AutoSlaveDiscovery PropertyIdentifier = 169 + ManualSlaveAddressBinding PropertyIdentifier = 170 + SlaveAddressBinding PropertyIdentifier = 171 + SlaveProxyEnable PropertyIdentifier = 172 + LastNotifyRecord PropertyIdentifier = 173 + ScheduleDefault PropertyIdentifier = 174 + AcceptedModes PropertyIdentifier = 175 + AdjustValue PropertyIdentifier = 176 + Count PropertyIdentifier = 177 + CountBeforeChange PropertyIdentifier = 178 + CountChangeTime PropertyIdentifier = 179 + CovPeriod PropertyIdentifier = 180 + InputReference PropertyIdentifier = 181 + LimitMonitoringInterval PropertyIdentifier = 182 + LoggingObject PropertyIdentifier = 183 + LoggingRecord PropertyIdentifier = 184 + Prescale PropertyIdentifier = 185 + PulseRate PropertyIdentifier = 186 + Scale PropertyIdentifier = 187 + ScaleFactor PropertyIdentifier = 188 + UpdateTime PropertyIdentifier = 189 + ValueBeforeChange PropertyIdentifier = 190 + ValueSet PropertyIdentifier = 191 + ValueChangeTime PropertyIdentifier = 192 + AlignIntervals PropertyIdentifier = 193 + IntervalOffset PropertyIdentifier = 195 + LastRestartReason PropertyIdentifier = 196 + LoggingType PropertyIdentifier = 197 + RestartNotificationRecipients PropertyIdentifier = 202 + TimeOfDeviceRestart PropertyIdentifier = 203 + TimeSynchronizationInterval PropertyIdentifier = 204 + Trigger PropertyIdentifier = 205 + UtcTimeSynchronizationRecipients PropertyIdentifier = 206 + NodeSubtype PropertyIdentifier = 207 + NodeType PropertyIdentifier = 208 + StructuredObjectList PropertyIdentifier = 209 + SubordinateAnnotations PropertyIdentifier = 210 + SubordinateList PropertyIdentifier = 211 + ActualShedLevel PropertyIdentifier = 212 + DutyWindow PropertyIdentifier = 213 + ExpectedShedLevel PropertyIdentifier = 214 + FullDutyBaseline PropertyIdentifier = 215 + RequestedShedLevel PropertyIdentifier = 218 + ShedDuration PropertyIdentifier = 219 + ShedLevelDescriptions PropertyIdentifier = 220 + ShedLevels PropertyIdentifier = 221 + StateDescription PropertyIdentifier = 222 + DoorAlarmState PropertyIdentifier = 226 + DoorExtendedPulseTime PropertyIdentifier = 227 + DoorMembers PropertyIdentifier = 228 + DoorOpenTooLongTime PropertyIdentifier = 229 + DoorPulseTime PropertyIdentifier = 230 + DoorStatus PropertyIdentifier = 231 + DoorUnlockDelayTime PropertyIdentifier = 232 + LockStatus PropertyIdentifier = 233 + MaskedAlarmValues PropertyIdentifier = 234 + SecuredStatus PropertyIdentifier = 235 + AbsenteeLimit PropertyIdentifier = 244 + AccessAlarmEvents PropertyIdentifier = 245 + AccessDoors PropertyIdentifier = 246 + AccessEvent PropertyIdentifier = 247 + AccessEventAuthenticationFactor PropertyIdentifier = 248 + AccessEventCredential PropertyIdentifier = 249 + AccessEventTime PropertyIdentifier = 250 + AccessTransactionEvents PropertyIdentifier = 251 + Accompaniment PropertyIdentifier = 252 + AccompanimentTime PropertyIdentifier = 253 + ActivationTime PropertyIdentifier = 254 + ActiveAuthenticationPolicy PropertyIdentifier = 255 + AssignedAccessRights PropertyIdentifier = 256 + AuthenticationFactors PropertyIdentifier = 257 + AuthenticationPolicyList PropertyIdentifier = 258 + AuthenticationPolicyNames PropertyIdentifier = 259 + AuthenticationStatus PropertyIdentifier = 260 + AuthorizationMode PropertyIdentifier = 261 + BelongsTo PropertyIdentifier = 262 + CredentialDisable PropertyIdentifier = 263 + CredentialStatus PropertyIdentifier = 264 + Credentials PropertyIdentifier = 265 + CredentialsInZone PropertyIdentifier = 266 + DaysRemaining PropertyIdentifier = 267 + EntryPoints PropertyIdentifier = 268 + ExitPoints PropertyIdentifier = 269 + ExpiryTime PropertyIdentifier = 270 + ExtendedTimeEnable PropertyIdentifier = 271 + FailedAttemptEvents PropertyIdentifier = 272 + FailedAttempts PropertyIdentifier = 273 + FailedAttemptsTime PropertyIdentifier = 274 + LastAccessEvent PropertyIdentifier = 275 + LastAccessPoint PropertyIdentifier = 276 + LastCredentialAdded PropertyIdentifier = 277 + LastCredentialAddedTime PropertyIdentifier = 278 + LastCredentialRemoved PropertyIdentifier = 279 + LastCredentialRemovedTime PropertyIdentifier = 280 + LastUseTime PropertyIdentifier = 281 + Lockout PropertyIdentifier = 282 + LockoutRelinquishTime PropertyIdentifier = 283 + MasterExemption PropertyIdentifier = 284 + MaxFailedAttempts PropertyIdentifier = 285 + Members PropertyIdentifier = 286 + MusterPoint PropertyIdentifier = 287 + NegativeAccessRules PropertyIdentifier = 288 + NumberOfAuthenticationPolicies PropertyIdentifier = 289 + OccupancyCount PropertyIdentifier = 290 + OccupancyCountAdjust PropertyIdentifier = 291 + OccupancyCountEnable PropertyIdentifier = 292 + OccupancyExemption PropertyIdentifier = 293 + OccupancyLowerLimit PropertyIdentifier = 294 + OccupancyLowerLimitEnforced PropertyIdentifier = 295 + OccupancyState PropertyIdentifier = 296 + OccupancyUpperLimit PropertyIdentifier = 297 + OccupancyUpperLimitEnforced PropertyIdentifier = 298 + PassbackExemption PropertyIdentifier = 299 + PassbackMode PropertyIdentifier = 300 + PassbackTimeout PropertyIdentifier = 301 + PositiveAccessRules PropertyIdentifier = 302 + ReasonForDisable PropertyIdentifier = 303 + SupportedFormats PropertyIdentifier = 304 + SupportedFormatClasses PropertyIdentifier = 305 + ThreatAuthority PropertyIdentifier = 306 + ThreatLevel PropertyIdentifier = 307 + TraceFlag PropertyIdentifier = 308 + TransactionNotificationClass PropertyIdentifier = 309 + UserExternalIdentifier PropertyIdentifier = 310 + UserInformationReference PropertyIdentifier = 311 + UserName PropertyIdentifier = 317 + UserType PropertyIdentifier = 318 + UsesRemaining PropertyIdentifier = 319 + ZoneFrom PropertyIdentifier = 320 + ZoneTo PropertyIdentifier = 321 + AccessEventTag PropertyIdentifier = 322 + GlobalIdentifier PropertyIdentifier = 323 + VerificationTime PropertyIdentifier = 326 + BaseDeviceSecurityPolicy PropertyIdentifier = 327 + DistributionKeyRevision PropertyIdentifier = 328 + DoNotHide PropertyIdentifier = 329 + KeySets PropertyIdentifier = 330 + LastKeyServer PropertyIdentifier = 331 + NetworkAccessSecurityPolicies PropertyIdentifier = 332 + PacketReorderTime PropertyIdentifier = 333 + SecurityPduTimeout PropertyIdentifier = 334 + SecurityTimeWindow PropertyIdentifier = 335 + SupportedSecurityAlgorithm PropertyIdentifier = 336 + UpdateKeySetTimeout PropertyIdentifier = 337 + BackupAndRestoreState PropertyIdentifier = 338 + BackupPreparationTime PropertyIdentifier = 339 + RestoreCompletionTime PropertyIdentifier = 340 + RestorePreparationTime PropertyIdentifier = 341 + BitMask PropertyIdentifier = 342 + BitText PropertyIdentifier = 343 + IsUtc PropertyIdentifier = 344 + GroupMembers PropertyIdentifier = 345 + GroupMemberNames PropertyIdentifier = 346 + MemberStatusFlags PropertyIdentifier = 347 + RequestedUpdateInterval PropertyIdentifier = 348 + CovuPeriod PropertyIdentifier = 349 + CovuRecipients PropertyIdentifier = 350 + EventMessageTexts PropertyIdentifier = 351 + EventMessageTextsConfig PropertyIdentifier = 352 + EventDetectionEnable PropertyIdentifier = 353 + EventAlgorithmInhibit PropertyIdentifier = 354 + EventAlgorithmInhibitRef PropertyIdentifier = 355 + TimeDelayNormal PropertyIdentifier = 356 + ReliabilityEvaluationInhibit PropertyIdentifier = 357 + FaultParameters PropertyIdentifier = 358 + FaultType PropertyIdentifier = 359 + LocalForwardingOnly PropertyIdentifier = 360 + ProcessIdentifierFilter PropertyIdentifier = 361 + SubscribedRecipients PropertyIdentifier = 362 + PortFilter PropertyIdentifier = 363 + AuthorizationExemptions PropertyIdentifier = 364 + AllowGroupDelayInhibit PropertyIdentifier = 365 + ChannelNumber PropertyIdentifier = 366 + ControlGroups PropertyIdentifier = 367 + ExecutionDelay PropertyIdentifier = 368 + LastPriority PropertyIdentifier = 369 + WriteStatus PropertyIdentifier = 370 + PropertyList PropertyIdentifier = 371 + SerialNumber PropertyIdentifier = 372 + BlinkWarnEnable PropertyIdentifier = 373 + DefaultFadeTime PropertyIdentifier = 374 + DefaultRampRate PropertyIdentifier = 375 + DefaultStepIncrement PropertyIdentifier = 376 + EgressTime PropertyIdentifier = 377 + InProgress PropertyIdentifier = 378 + InstantaneousPower PropertyIdentifier = 379 + LightingCommand PropertyIdentifier = 380 + LightingCommandDefaultPriority PropertyIdentifier = 381 + MaxActualValue PropertyIdentifier = 382 + MinActualValue PropertyIdentifier = 383 + Power PropertyIdentifier = 384 + Transition PropertyIdentifier = 385 + EgressActive PropertyIdentifier = 386 + InterfaceValue PropertyIdentifier = 387 + FaultHighLimit PropertyIdentifier = 388 + FaultLowLimit PropertyIdentifier = 389 + LowDiffLimit PropertyIdentifier = 390 + StrikeCount PropertyIdentifier = 391 + TimeOfStrikeCountReset PropertyIdentifier = 392 + DefaultTimeout PropertyIdentifier = 393 + InitialTimeout PropertyIdentifier = 394 + LastStateChange PropertyIdentifier = 395 + StateChangeValues PropertyIdentifier = 396 + TimerRunning PropertyIdentifier = 397 + TimerState PropertyIdentifier = 398 + ApduLength PropertyIdentifier = 399 + IpAddress PropertyIdentifier = 400 + IpDefaultGateway PropertyIdentifier = 401 + IpDhcpEnable PropertyIdentifier = 402 + IpDhcpLeaseTime PropertyIdentifier = 403 + IpDhcpLeaseTimeRemaining PropertyIdentifier = 404 + IpDhcpServer PropertyIdentifier = 405 + IpDnsServer PropertyIdentifier = 406 + BacnetIpGlobalAddress PropertyIdentifier = 407 + BacnetIpMode PropertyIdentifier = 408 + BacnetIpMulticastAddress PropertyIdentifier = 409 + BacnetIpNatTraversal PropertyIdentifier = 410 + IpSubnetMask PropertyIdentifier = 411 + BacnetIpUdpPort PropertyIdentifier = 412 + BbmdAcceptFdRegistrations PropertyIdentifier = 413 + BbmdBroadcastDistributionTable PropertyIdentifier = 414 + BbmdForeignDeviceTable PropertyIdentifier = 415 + ChangesPending PropertyIdentifier = 416 + Command PropertyIdentifier = 417 + FdBbmdAddress PropertyIdentifier = 418 + FdSubscriptionLifetime PropertyIdentifier = 419 + LinkSpeed PropertyIdentifier = 420 + LinkSpeeds PropertyIdentifier = 421 + LinkSpeedAutonegotiate PropertyIdentifier = 422 + MacAddress PropertyIdentifier = 423 + NetworkInterfaceName PropertyIdentifier = 424 + NetworkNumber PropertyIdentifier = 425 + NetworkNumberQuality PropertyIdentifier = 426 + NetworkType PropertyIdentifier = 427 + RoutingTable PropertyIdentifier = 428 + VirtualMacAddressTable PropertyIdentifier = 429 + CommandTimeArray PropertyIdentifier = 430 + CurrentCommandPriority PropertyIdentifier = 431 + LastCommandTime PropertyIdentifier = 432 + ValueSource PropertyIdentifier = 433 + ValueSourceArray PropertyIdentifier = 434 + BacnetIpv6Mode PropertyIdentifier = 435 + Ipv6Address PropertyIdentifier = 436 + Ipv6PrefixLength PropertyIdentifier = 437 + BacnetIpv6UdpPort PropertyIdentifier = 438 + Ipv6DefaultGateway PropertyIdentifier = 439 + BacnetIpv6MulticastAddress PropertyIdentifier = 440 + Ipv6DnsServer PropertyIdentifier = 441 + Ipv6AutoAddressingEnable PropertyIdentifier = 442 + Ipv6DhcpLeaseTime PropertyIdentifier = 443 + Ipv6DhcpLeaseTimeRemaining PropertyIdentifier = 444 + Ipv6DhcpServer PropertyIdentifier = 445 + Ipv6ZoneIndex PropertyIdentifier = 446 + AssignedLandingCalls PropertyIdentifier = 447 + CarAssignedDirection PropertyIdentifier = 448 + CarDoorCommand PropertyIdentifier = 449 + CarDoorStatus PropertyIdentifier = 450 + CarDoorText PropertyIdentifier = 451 + CarDoorZone PropertyIdentifier = 452 + CarDriveStatus PropertyIdentifier = 453 + CarLoad PropertyIdentifier = 454 + CarLoadUnits PropertyIdentifier = 455 + CarMode PropertyIdentifier = 456 + CarMovingDirection PropertyIdentifier = 457 + CarPosition PropertyIdentifier = 458 + ElevatorGroup PropertyIdentifier = 459 + EnergyMeter PropertyIdentifier = 460 + EnergyMeterRef PropertyIdentifier = 461 + EscalatorMode PropertyIdentifier = 462 + FloorText PropertyIdentifier = 464 + GroupId PropertyIdentifier = 465 + GroupMode PropertyIdentifier = 467 + HigherDeck PropertyIdentifier = 468 + InstallationId PropertyIdentifier = 469 + LandingCalls PropertyIdentifier = 470 + LandingCallControl PropertyIdentifier = 471 + LandingDoorStatus PropertyIdentifier = 472 + LowerDeck PropertyIdentifier = 473 + MachineRoomId PropertyIdentifier = 474 + MakingCarCall PropertyIdentifier = 475 + NextStoppingFloor PropertyIdentifier = 476 + OperationDirection PropertyIdentifier = 477 + PassengerAlarm PropertyIdentifier = 478 + PowerMode PropertyIdentifier = 479 + RegisteredCarCall PropertyIdentifier = 480 + ActiveCovMultipleSubscriptions PropertyIdentifier = 481 + ProtocolLevel PropertyIdentifier = 482 + ReferencePort PropertyIdentifier = 483 + DeployedProfileLocation PropertyIdentifier = 484 + ProfileLocation PropertyIdentifier = 485 + Tags PropertyIdentifier = 486 + SubordinateNodeTypes PropertyIdentifier = 487 + SubordinateRelationships PropertyIdentifier = 489 + SubordinateTags PropertyIdentifier = 488 + DefaultSubordinateRelationship PropertyIdentifier = 490 + Represents PropertyIdentifier = 491 + DefaultPresentValue PropertyIdentifier = 492 + PresentStage PropertyIdentifier = 493 + Stages PropertyIdentifier = 494 + StageNames PropertyIdentifier = 495 + TargetReferences PropertyIdentifier = 496 + FaultSignals PropertyIdentifier = 463 +) diff --git a/client.go b/client.go index 0b78fc5..98f6c67 100644 --- a/client.go +++ b/client.go @@ -10,10 +10,13 @@ type Client interface { } func NewClient(address string, port int) (Client, error) { + return &client{}, nil } func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (interface{}, error) { + return nil, nil } func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value interface{}) error { + return nil } diff --git a/encoding/date_time.go b/encoding/date_time.go new file mode 100644 index 0000000..4e561cb --- /dev/null +++ b/encoding/date_time.go @@ -0,0 +1,100 @@ +package encoding + +import "time" + +type DateTime struct { + Date time.Time +} + +func DecodeApplicationDate(buf []byte, offset int) (int, time.Time) { + len, tagNum := decodeTagNumber(buf, offset) + if tagNum == byte(Date) { + len1, date := decodeDate(buf, offset+len) + return len + len1, date + } + return -1, time.Time{} +} + +func DecodeApplicationTime(buf []byte, offset int) (int, time.Time) { + len, tagNum := decodeTagNumber(buf, offset) + if tagNum == byte(Time) { + len1, btime := decodeBACnetTime(buf, offset+len) + return len + len1, btime + } + return -1, time.Time{} +} + +func decodeDate(buf []byte, offset int) (int, time.Time) { + year := buf[offset] + month := buf[offset+1] + day := buf[offset+2] + wday := buf[offset+3] + if month == 0xFF && day == 0xFF && wday == 0xFF && year == 0xFF { + return 4, time.Time{} + } + return 4, time.Date(int(year)+1900, time.Month(month), int(day), 0, 0, 0, 0, nil) +} + +func decodeDateSafe(buf []byte, offset, lenVal int) (int, time.Time) { + if lenVal != 4 { + return lenVal, time.Time{} + } + return decodeDate(buf, offset) +} + +func decodeBACnetTime(buf []byte, offset int) (int, time.Time) { + hour := buf[offset] + min := buf[offset+1] + sec := buf[offset+2] + hundredths := buf[offset+3] + if hour == 0xFF && min == 0xFF && sec == 0xFF && hundredths == 0xFF { + return 4, time.Time{} + } + if hundredths > 100 { + hundredths = 0 + } + return 4, time.Date(0, 0, 0, int(hour), int(min), int(sec), int(hundredths*10), nil) +} + +func decodeBACnetTimeSafe(buf []byte, offset int, lenVal int) (int, time.Time) { + if lenVal != 4 { + return lenVal, time.Time{} + } + return decodeBACnetTime(buf, offset) +} + +func (dt *DateTime) Decode(buf []byte, offset int) int { + len, date := DecodeApplicationDate(buf, offset) + len1, ttime := DecodeApplicationTime(buf, offset+len) + dt.Date = ttime.AddDate(date.Year(), int(date.Month()), date.Day()) + return len + len1 +} + +func (dt *DateTime) Encode() []byte { + return append(encodeApplicationDate(dt.Date), encodeApplicationTime(dt.Date)...) +} + +func encodeApplicationDate(date time.Time) []byte { + return append(EncodeTag(Date, false, 4), encodeBacnetDate(date)...) +} +func encodeApplicationTime(date time.Time) []byte { + return append(EncodeTag(Time, false, 4), encodeBacnetTime(date)...) +} + +func encodeBacnetDate(date time.Time) []byte { + data := make([]byte, 4) + data[0] = byte(date.Year() - 1900) + data[1] = byte(date.Month()) + data[2] = byte(date.Day()) + data[3] = byte(date.Weekday()) + return data +} + +func encodeBacnetTime(date time.Time) []byte { + data := make([]byte, 4) + data[0] = byte(date.Hour()) + data[1] = byte(date.Minute()) + data[2] = byte(date.Second()) + data[3] = byte(date.Nanosecond() / 10) + return data +} diff --git a/property.go b/property.go new file mode 100644 index 0000000..08d5908 --- /dev/null +++ b/property.go @@ -0,0 +1,8 @@ +package bacnet + +type PropertyValue struct { + Identifier PropertyIdentifier + Arrayindex *uint32 + Value uint32 + Priority uint32 +} From fc6b4756d54baaee27db362c8db0b817c15702cb Mon Sep 17 00:00:00 2001 From: SammyOina Date: Wed, 30 Aug 2023 14:37:44 +0300 Subject: [PATCH 07/24] add who is Signed-off-by: SammyOina --- encoding/date_time.go | 19 ++------------- encoding/encoding.go | 15 ++++++++++++ general.go | 22 +++++++++++++++++ object.go | 6 ++--- whois.go | 55 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 general.go create mode 100644 whois.go diff --git a/encoding/date_time.go b/encoding/date_time.go index 4e561cb..a1a7250 100644 --- a/encoding/date_time.go +++ b/encoding/date_time.go @@ -2,10 +2,6 @@ package encoding import "time" -type DateTime struct { - Date time.Time -} - func DecodeApplicationDate(buf []byte, offset int) (int, time.Time) { len, tagNum := decodeTagNumber(buf, offset) if tagNum == byte(Date) { @@ -63,21 +59,10 @@ func decodeBACnetTimeSafe(buf []byte, offset int, lenVal int) (int, time.Time) { return decodeBACnetTime(buf, offset) } -func (dt *DateTime) Decode(buf []byte, offset int) int { - len, date := DecodeApplicationDate(buf, offset) - len1, ttime := DecodeApplicationTime(buf, offset+len) - dt.Date = ttime.AddDate(date.Year(), int(date.Month()), date.Day()) - return len + len1 -} - -func (dt *DateTime) Encode() []byte { - return append(encodeApplicationDate(dt.Date), encodeApplicationTime(dt.Date)...) -} - -func encodeApplicationDate(date time.Time) []byte { +func EncodeApplicationDate(date time.Time) []byte { return append(EncodeTag(Date, false, 4), encodeBacnetDate(date)...) } -func encodeApplicationTime(date time.Time) []byte { +func EncodeApplicationTime(date time.Time) []byte { return append(EncodeTag(Time, false, 4), encodeBacnetTime(date)...) } diff --git a/encoding/encoding.go b/encoding/encoding.go index 2188e7a..e7a64b2 100644 --- a/encoding/encoding.go +++ b/encoding/encoding.go @@ -61,3 +61,18 @@ func EncodeSigned(value int32) []byte { return buf.Bytes() } } + +func EncodeContextUnsigned(tagNum BACnetApplicationTag, val uint32) []byte { + len := 0 + switch { + case val < 0x100: + len = 1 + case val < 0x10000: + len = 2 + case val < 0x1000000: + len = 3 + default: + len = 4 + } + return append(EncodeTag(tagNum, true, len), EncodeUnsigned(val)...) +} diff --git a/general.go b/general.go new file mode 100644 index 0000000..3a5d08d --- /dev/null +++ b/general.go @@ -0,0 +1,22 @@ +package bacnet + +import ( + "time" + + "github.com/absmach/bacnet/encoding" +) + +type DateTime struct { + Date time.Time +} + +func (dt *DateTime) Decode(buf []byte, offset int) int { + len, date := encoding.DecodeApplicationDate(buf, offset) + len1, ttime := encoding.DecodeApplicationTime(buf, offset+len) + dt.Date = ttime.AddDate(date.Year(), int(date.Month()), date.Day()) + return len + len1 +} + +func (dt DateTime) Encode() []byte { + return append(encoding.EncodeApplicationDate(dt.Date), encoding.EncodeApplicationTime(dt.Date)...) +} diff --git a/object.go b/object.go index 9c2beba..f585e8e 100644 --- a/object.go +++ b/object.go @@ -33,19 +33,19 @@ func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdu_len int, tagN return -1 } -func (oi *ObjectIdentifier) Encode() []byte { +func (oi ObjectIdentifier) Encode() []byte { value := uint32(oi.Type)&encoding.MaxObject< length { + len1, decVal := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + length += len1 + + if decVal <= encoding.MaxInstance { + w.LowLimit = &decVal + } + + if apduLen > length { + len1, tagNum, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+length) + length += len1 + if tagNum != 1 { + return -1 + } + if apduLen > length { + len1, _ := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + length += len1 + if decVal <= encoding.MaxInstance { + w.HighLimit = &decVal + } + } else { + return -1 + } + } else { + return -1 + } + } else { + return -1 + } + return length +} + +func (w WhoIs) Encode() []byte { + if w.LowLimit != nil && *w.LowLimit <= encoding.MaxInstance && + w.HighLimit != nil && *w.HighLimit <= encoding.MaxInstance { + return append(encoding.EncodeContextUnsigned(0, *w.LowLimit), encoding.EncodeContextUnsigned(1, *w.HighLimit)...) + } + return []byte{} +} From 11555687a1e98b454ce1c700af9d86f189a859c7 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 1 Sep 2023 01:47:01 +0300 Subject: [PATCH 08/24] add npdu Signed-off-by: SammyOina --- encoding/decoding.go | 6 ++ internal/bitarray.go | 52 ++++++++++ network.go | 124 +++++++++++++++++++++++ npdu.go | 231 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 413 insertions(+) create mode 100644 internal/bitarray.go create mode 100644 network.go create mode 100644 npdu.go diff --git a/encoding/decoding.go b/encoding/decoding.go index a3c36c5..bcdeb14 100644 --- a/encoding/decoding.go +++ b/encoding/decoding.go @@ -7,3 +7,9 @@ func DecodeUnsigned(buffer []byte, offset, len int) (int, uint32) { } return len, value } + +func DecodeOctetString(buf []byte, offset, lenVal int) (int, []byte) { + tmp := make([]byte, lenVal) + copy(tmp, buf[offset:offset+lenVal]) + return len(tmp), tmp +} diff --git a/internal/bitarray.go b/internal/bitarray.go new file mode 100644 index 0000000..ff03c23 --- /dev/null +++ b/internal/bitarray.go @@ -0,0 +1,52 @@ +package internal + +import "errors" + +var errBitArrayLen = errors.New("bit array length must be 8 to convert to byte") + +type BitArray struct { + bits []bool +} + +func NewBitArray(length int) *BitArray { + return &BitArray{ + bits: make([]bool, length), + } +} + +func (ba *BitArray) Set(index int, value bool) { + if index >= 0 && index < len(ba.bits) { + ba.bits[index] = value + } +} + +func (ba *BitArray) Get(index int) bool { + if index >= 0 && index < len(ba.bits) { + return ba.bits[index] + } + return false +} + +func (ba *BitArray) ToByte() (byte, error) { + // Ensure the length of the bit array is 8 to convert to a byte. + if len(ba.bits) != 8 { + return 0, errBitArrayLen + } + + var byteValue byte + for j := 0; j < 8; j++ { + if ba.bits[j] { + byteValue |= 1 << uint(7-j) + } + } + + return byteValue, nil +} + +func NewBitArrayFromByte(byteValue byte) *BitArray { + bitArray := NewBitArray(8) + for j := 0; j < 8; j++ { + bitArray.Set(j, byteValue&(1<>8), byte(port)) + case Ethernet: + parts := strings.Split(addr1, "-") + for _, part := range parts { + val := byte(0) + fmt.Sscanf(part, "%d", &val) + addr.MacAddress = append(addr.MacAddress, val) + } + } + } + case ObjectIdentifier: + if *netType == IPV4 { + addr.MacAddress = make([]byte, 6) + binary.LittleEndian.PutUint64(addr.MacAddress, uint64(addr1.Instance)) + } + } + + return addr +} + +func (ba *BACnetAddress) IPAndPort() (string, int) { + ip := fmt.Sprintf("%d.%d.%d.%d", ba.MacAddress[0], ba.MacAddress[1], ba.MacAddress[2], ba.MacAddress[3]) + port := int(ba.MacAddress[4])<<8 + int(ba.MacAddress[5]) + return ip, port +} + +func (ba *BACnetAddress) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(UnsignedInt) { + leng += leng1 + leng1, ba.NetworkNumber = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1 + } + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(OctetString) { + leng += leng1 + leng1, ba.MacAddress = encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1 + } + + return leng +} diff --git a/npdu.go b/npdu.go new file mode 100644 index 0000000..65b7bea --- /dev/null +++ b/npdu.go @@ -0,0 +1,231 @@ +package bacnet + +import ( + "encoding/binary" + "errors" + "log" + + "github.com/absmach/bacnet/internal" +) + +type NPDU struct { + Version uint8 // Always one. + Control NPDUControlInformation + DNET uint16 + DLEN uint8 + DADR []byte + Destination *BACnetAddress + SNET uint16 + SLEN uint8 + SADR []byte + Source *BACnetAddress + MessageType byte + HopCount byte + VendorID uint16 +} + +type NPDUControlInformation struct { + control internal.BitArray +} + +func NewNPDUControlInformation() *NPDUControlInformation { + return &NPDUControlInformation{ + control: *internal.NewBitArray(8), + } +} + +func (nci *NPDUControlInformation) IsNetworkLayerMessage() bool { + return nci.control.Get(0) +} + +func (nci *NPDUControlInformation) SetNetworkLayerMessage(a bool) { + nci.control.Set(0, a) +} + +func (nci *NPDUControlInformation) IsDestinationSpecifier() bool { + return nci.control.Get(2) +} + +func (nci *NPDUControlInformation) SetDestinationSpecifier(a bool) { + nci.control.Set(2, a) +} + +func (nci *NPDUControlInformation) IsSourceSpecifier() bool { + return nci.control.Get(4) +} + +func (nci *NPDUControlInformation) SetSourceSpecifier(a bool) { + nci.control.Set(4, a) +} + +func (nci *NPDUControlInformation) IsDataExpectingReply() bool { + return nci.control.Get(5) +} + +func (nci *NPDUControlInformation) SetDataExpectingReply(a bool) { + nci.control.Set(5, a) +} + +func (nci *NPDUControlInformation) NetworkPriority() (NetworkPriority, error) { + if !nci.control.Get(6) && !nci.control.Get(7) { + return NormalMessage, nil + } else if !nci.control.Get(6) && nci.control.Get(7) { + return UrgentMessage, nil + } else if nci.control.Get(6) && !nci.control.Get(7) { + return CriticalEquipmentMessage, nil + } else if nci.control.Get(6) && nci.control.Get(7) { + return LifeSafetyMessage, nil + } + return 0, errors.New("invalid network priority") +} + +func (nci *NPDUControlInformation) SetNetworkPriority(a NetworkPriority) error { + switch a { + case NormalMessage: + nci.control.Set(6, false) + nci.control.Set(7, false) + case UrgentMessage: + nci.control.Set(6, false) + nci.control.Set(7, true) + case CriticalEquipmentMessage: + nci.control.Set(6, true) + nci.control.Set(7, false) + case LifeSafetyMessage: + nci.control.Set(6, true) + nci.control.Set(7, true) + default: + return errors.New("invalid network priority") + } + return nil +} + +func (nci *NPDUControlInformation) Encode() ([]byte, error) { + b, err := nci.control.ToByte() + if err != nil { + return []byte{}, err + } + return []byte{b}, nil +} + +func (nci *NPDUControlInformation) Decode(buffer []byte, offset int) int { + if offset < len(buffer) { + nci.control = *internal.NewBitArrayFromByte(buffer[offset]) + return 1 + } + return 0 +} + +func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount int, vendorID int) *NPDU { + npdu := &NPDU{ + Version: 1, + Control: *NewNPDUControlInformation(), + Destination: destination, + Source: source, + HopCount: uint8(hopCount), + VendorID: uint16(vendorID), + } + + if destination != nil && destination.NetworkNumber > 0 { + npdu.Control.SetDestinationSpecifier(true) + npdu.DNET = uint16(destination.NetworkNumber) + npdu.DLEN = uint8(len(destination.MacAddress)) + npdu.DADR = destination.MacAddress + } + + if source != nil && source.NetworkNumber > 0 && source.NetworkNumber < 0xFFFF { + npdu.Control.SetSourceSpecifier(true) + npdu.SNET = uint16(source.NetworkNumber) + npdu.SLEN = uint8(len(source.MacAddress)) + npdu.SADR = source.MacAddress + } + + return npdu +} + +func (npdu *NPDU) Encode() ([]byte, error) { + buffer := make([]byte, 0) + buffer = append(buffer, npdu.Version) + ctrlBuf, err := npdu.Control.Encode() + if err != nil { + return buffer, err + } + buffer = append(buffer, ctrlBuf...) + + if npdu.Control.IsDestinationSpecifier() { + buffer = append(buffer, uint8(npdu.DNET>>8), uint8(npdu.DNET&0xFF)) + if npdu.DNET == 0xFFFF { + buffer = append(buffer, 0x00) + } else { + buffer = append(buffer, npdu.DLEN) + buffer = append(buffer, npdu.DADR...) + } + } + + if npdu.Control.IsSourceSpecifier() { + buffer = append(buffer, uint8(npdu.SNET>>8), uint8(npdu.SNET&0xFF)) + buffer = append(buffer, npdu.SLEN) + buffer = append(buffer, npdu.SADR...) + } + + if npdu.Control.IsDestinationSpecifier() { + buffer = append(buffer, npdu.HopCount) + } + + if npdu.Control.IsNetworkLayerMessage() { + buffer = append(buffer, npdu.MessageType) + if npdu.MessageType >= 0x80 && npdu.MessageType <= 0xFF { + buffer = append(buffer, uint8(npdu.VendorID>>8), uint8(npdu.VendorID&0xFF)) + } + } + + return buffer, nil +} + +func (npdu *NPDU) Decode(buffer []byte, offset int) int { + length := 0 + version := buffer[offset] // always 1!!!! + length++ + if version != npdu.Version { + log.Println("Received something else!") + return -1 + } + + npdu.Control = *NewNPDUControlInformation() + length += npdu.Control.Decode(buffer, offset+length) + + if npdu.Control.IsDestinationSpecifier() { + npdu.DNET = binary.BigEndian.Uint16(buffer[offset+length : offset+length+2]) + length += 2 + npdu.DLEN = buffer[offset+length] + length++ + npdu.DADR = buffer[offset+length : offset+length+int(npdu.DLEN)] + length += int(npdu.DLEN) + npdu.Destination = NewBACnetAddress(uint32(npdu.DNET), npdu.DADR, "", nil) + } + + if npdu.Control.IsSourceSpecifier() { + npdu.SNET = binary.BigEndian.Uint16(buffer[offset+length : offset+length+2]) + length += 2 + npdu.SLEN = buffer[offset+length] + length++ + npdu.SADR = buffer[offset+length : offset+length+int(npdu.SLEN)] + length += int(npdu.SLEN) + npdu.Source = NewBACnetAddress(uint32(npdu.SNET), npdu.SADR, "", nil) + } + + if npdu.Control.IsDestinationSpecifier() { + npdu.HopCount = buffer[offset+length] + length++ + } + + if npdu.Control.IsNetworkLayerMessage() { + npdu.MessageType = buffer[offset+length] + length++ + if npdu.MessageType >= 0x80 { + npdu.VendorID = binary.BigEndian.Uint16(buffer[offset+length : offset+length+2]) + length += 2 + } + } + + return length +} From b6107649c17cb31702187e11ec01e2774abfdea0 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 4 Sep 2023 22:53:58 +0300 Subject: [PATCH 09/24] testing whoIs Signed-off-by: SammyOina --- example/whois.go | 58 ++++++++++++++++ iam.go | 170 +++++++++++++++++++++++++++++++++++++++++++++++ object.go | 68 ++++++++++++++++++- 3 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 example/whois.go create mode 100644 iam.go diff --git a/example/whois.go b/example/whois.go new file mode 100644 index 0000000..2b18b6e --- /dev/null +++ b/example/whois.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "net" + "time" + + "github.com/absmach/bacnet" +) + +func main() { + var highlim, lowLim uint32 = 4194303, 0 + whi := bacnet.WhoIs{HighLimit: &highlim, LowLimit: &lowLim} + whoIsRequest := whi.Encode() + + // Define the BACnet broadcast address (255.255.255.255:47808) + remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.255:47809") + if err != nil { + fmt.Println("Error resolving remote address:", err) + return + } + + // Create a UDP connection + conn, err := net.DialUDP("udp", nil, remoteAddr) + if err != nil { + fmt.Println("Error creating UDP connection:", err) + return + } + defer conn.Close() + + // Send the WhoIsRequest packet + _, err = conn.Write(whoIsRequest) + if err != nil { + fmt.Println("Error sending WhoIsRequest:", err) + return + } + + // Wait for responses + buffer := make([]byte, 1500) + conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // Set a timeout for responses + + for { + n, _, err := conn.ReadFromUDP(buffer) + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + // Timeout reached, no more responses + fmt.Println("No more responses received.") + break + } + fmt.Println("Error reading response:", err) + break + } + + // Process the response (you'll need to parse BACnet responses here) + response := buffer[:n] + fmt.Printf("Received response: %X\n", response) + } +} diff --git a/iam.go b/iam.go new file mode 100644 index 0000000..bfad5be --- /dev/null +++ b/iam.go @@ -0,0 +1,170 @@ +package bacnet + +/* +import ( + "errors" + + "github.com/absmach/bacnet/encoding" +) + +type IAmRequest struct { + IamDeviceIdentifier ObjectIdentifier + MaxAPDULengthAccepted uint32 + SegmentationSupported int + VendorID uint32 +} + +func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, error) { + leng := 0 + iam.IamDeviceIdentifier = ObjectIdentifier{} + // OBJECT ID - object id + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + + if tagNumber != byte(BACnetObjectIdentifier) { + return -1, errors.New("Invalid tag number") + } + + leng = iam.IamDeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + + if iam.IamDeviceIdentifier.Type != ObjectTypeDevice { + // Handle error or log message + return -1, errors.New("Got Iam from no device") + } + + // MAX APDU - unsigned + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber != byte(UnsignedInt) { + return -1, errors.New("Invalid tag number") + } + + leng1, decodedValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + iam.MaxAPDULengthAccepted = decodedValue + + // Segmentation - enumerated + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber != byte(Enumerated) { + return -1, errors.New("Invalid tag number") + } + segmentationSupported, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, SegmentationSupported) + if err != nil { + return -1, err + } + leng += leng1 + iam.SegmentationSupported = segmentationSupported + + // Vendor ID - unsigned16 + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + + if tagNumber != byte(UnsignedInt) { + return -1, errors.New("Invalid tag number") + } + + leng1, decodedValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + + leng += leng1 + if decodedValue > 0xFFFF { + return -1, errors.New("Value exceeds 0xFFFF") + } + iam.VendorID = decodedValue + + return leng, nil +} + +func (iam *IAmRequest) ASN1Encode() []byte { + tmp := iam.IamDeviceIdentifier.Encode() + return append(append(append(append([]byte{}, encoding.EncodeTag(encoding.BACnetApplicationTag(BACnetObjectIdentifier), false, len(tmp))...), tmp...), encoding.EncodeApplicationUnsigned(iam.MaxAPDULengthAccepted)...), encoding.EncodeApplicationEnumerated(iam.SegmentationSupported, SegmentationSupported), encoding.EncodeApplicationUnsigned(iam.VendorID)...) +} + +type YouAreRequest struct { + VendorID uint32 + ModelName string + SerialNumber string + DeviceIdentifier ObjectIdentifier + DeviceMACAddress []byte +} + +func (youAre *YouAreRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, error) { + leng := 0 + + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == byte(UnsignedInt) { + leng1, decodedValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + youAre.VendorID = decodedValue + } else { + return -1, errors.New("Invalid tag number") + } + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == byte(CharacterString) { + decodedValue, err := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, lenValue) + if err != nil { + return -1, err + } + leng += decodedValue + youAre.ModelName = decodedValue + } else { + return -1, errors.New("Invalid tag number") + } + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == byte(CharacterString) { + decodedValue, err := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, lenValue) + if err != nil { + return -1, err + } + leng += decodedValue + youAre.SerialNumber = decodedValue + } else { + return -1, errors.New("Invalid tag number") + } + + if leng < apduLen { + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(BACnetObjectIdentifier) { + leng += leng1 + youAre.DeviceIdentifier = ObjectIdentifier{} + leng = youAre.DeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + } + } + + if leng < apduLen { + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(OctetString) { + leng += leng1 + leng1, decodedValue := encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) + leng += leng1 + youAre.DeviceMACAddress = decodedValue + } + } + + return leng, nil +} + +func (youAre *YouAreRequest) ASN1Encode() []byte { + buffer := append(append(append([]byte{}, encoding.EncodeApplicationUnsigned(youAre.VendorID)...), + encoding.EncodeApplicationCharacterString(youAre.ModelName)...), + encoding.EncodeApplicationCharacterString(youAre.SerialNumber)...) + + if youAre.DeviceIdentifier != (ObjectIdentifier{}) { + buffer = append(buffer, youAre.DeviceIdentifier.EncodeApp()...) + } + + if len(youAre.DeviceMACAddress) > 0 { + buffer = append(buffer, encoding.EncodeApplicationOctetString(youAre.DeviceMACAddress, 0, len(youAre.DeviceMACAddress))...) + } + + return buffer +} +*/ diff --git a/object.go b/object.go index f585e8e..ffc4b59 100644 --- a/object.go +++ b/object.go @@ -10,19 +10,83 @@ type ObjectInstance uint32 type ObjectType uint16 +const ( + AnalogInput ObjectType = iota + AnalogOutput + AnalogValue + BinaryInput + BinaryOutput + BinaryValue + Calendar + ObjectTypeCommand + ObjectTypeDevice + EventEnrollment + File + Group + Loop + MultiStateInput + MultiStateOutput + ObjectTypeNotificationClass + Program + Schedule + Averaging + MultiStateValue + TrendLog + LifeSafetyPoint + LifeSafetyZone + Accumulator + PulseConverter + EventLog + GlobalGroup + TrendLogMultiple + LoadControl + StructuredView + AccessDoor + Timer + AccessCredential + AccessPoint + AccessRights + AccessUser + AccessZone + CredentialDataInput + NetworkSecurity + BitStringValue + CharacterStringValue + DatePatternValue + DateValue + DateTimePatternValue + DateTimeValue + IntegerValue + LargeAnalogValue + OctetStringValue + PositiveIntegerValue + TimePatternValue + TimeValue + NotificationForwarder + AlertEnrollment + Channel + LightingOutput + BinaryLightingOutput + NetworkPort + ObjectTypeElevatorGroup + Escalator + Lift + Staging +) + type ObjectIdentifier struct { Type ObjectType Instance ObjectInstance } -func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdu_len int) int { +func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdulen int) int { len, val := encoding.DecodeUnsigned(buf, offset, 4) oi.Instance = ObjectInstance(val) & ObjectInstance(encoding.MaxInstance) oi.Type = ObjectType(val >> encoding.InstanceBits & encoding.MaxObject) return len } -func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdu_len int, tagNumber byte) int { +func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdulen int, tagNumber byte) int { len := 0 if encoding.DecodeIsCOntextTag(buf, offset+len, tagNumber) { len1, _, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+len) From 12b76cc786d81fdff5442a72be4b18800bad5b38 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Tue, 5 Sep 2023 16:40:40 +0300 Subject: [PATCH 10/24] add apdu add bvlc update npdu add transport Signed-off-by: SammyOina --- apdu.go | 165 +++++++++++++++++++++++++++++++++++++++++ base.go | 11 --- bvlc.go | 110 +++++++++++++++++++++++++++ example/whois.go | 46 ++++++++++-- npdu.go | 13 +++- transport/transport.go | 7 ++ 6 files changed, 332 insertions(+), 20 deletions(-) create mode 100644 apdu.go create mode 100644 bvlc.go create mode 100644 transport/transport.go diff --git a/apdu.go b/apdu.go new file mode 100644 index 0000000..83b1628 --- /dev/null +++ b/apdu.go @@ -0,0 +1,165 @@ +package bacnet + +type BACnetConfirmedServiceChoice int + +type BACnetUnconfirmedServiceChoice int + +const ( + // Alarm and Event Services + AcknowledgeAlarm BACnetConfirmedServiceChoice = 0 + ConfirmedCovNotification BACnetConfirmedServiceChoice = 1 + ConfirmedCovNotificationMultiple BACnetConfirmedServiceChoice = 31 + ConfirmedEventNotification BACnetConfirmedServiceChoice = 2 + GetAlarmSummary BACnetConfirmedServiceChoice = 3 + GetEnrollmentSummary BACnetConfirmedServiceChoice = 4 + GetEventInformation BACnetConfirmedServiceChoice = 29 + LifeSafetyOperation BACnetConfirmedServiceChoice = 27 + SubscribeCov BACnetConfirmedServiceChoice = 5 + SubscribeCovProperty BACnetConfirmedServiceChoice = 28 + SubscribeCovPropertyMultiple BACnetConfirmedServiceChoice = 30 + // File Access Services + AtomicReadFile BACnetConfirmedServiceChoice = 6 + AtomicWriteFile BACnetConfirmedServiceChoice = 7 + // Object Access Services + AddListElement BACnetConfirmedServiceChoice = 8 + RemoveListElement BACnetConfirmedServiceChoice = 9 + CreateObject BACnetConfirmedServiceChoice = 10 + DeleteObject BACnetConfirmedServiceChoice = 11 + ReadProperty BACnetConfirmedServiceChoice = 12 + // SERVICE_CONFIRMED_READ_CONDITIONAL = 13 removed + ReadPropertyMultiple BACnetConfirmedServiceChoice = 14 + ReadRange BACnetConfirmedServiceChoice = 26 + WriteProperty BACnetConfirmedServiceChoice = 15 + WritePropertyMultiple BACnetConfirmedServiceChoice = 16 + // Remote Device Management Services + DeviceCommunicationControl BACnetConfirmedServiceChoice = 17 + ConfirmedPrivateTransfer BACnetConfirmedServiceChoice = 18 + ConfirmedTextMessage BACnetConfirmedServiceChoice = 19 + ReinitializeDevice BACnetConfirmedServiceChoice = 20 + // Virtual Terminal Services + VTOpen BACnetConfirmedServiceChoice = 21 + VTClose BACnetConfirmedServiceChoice = 22 + VTData BACnetConfirmedServiceChoice = 23 + // Security Services + // SERVICE_CONFIRMED_AUTHENTICATE = 24 removed + // SERVICE_CONFIRMED_REQUEST_KEY = 25 removed +) + +const ( + ServiceChoiceIAm BACnetUnconfirmedServiceChoice = iota + ServiceChoiceIHave + UnconfirmedCovNotification + UnconfirmedEVENTNotification + UnconfirmedPrivateTransfer + UnconfirmedTextMessage + TimeSynchronization + ServiceChoiceWhoHas + ServiceChoiceWhoIs + UTCTimeSynchronization + WriteGroup + UnconfirmedCovNotificationMultiple + ServiceChoiceWhoAmI + ServiceChoiceYouAre +) + +type APDU struct { + PduType BacnetPduTypes + SegmentedMessage bool + MoreFollows bool + SegmentedResponseAccepted bool + MaxSegmentsAccepted BacnetMaxSegments + MaxApduLengthAccepted MaxAPDU + SequenceNumber byte + InvokeID byte + RequenceNumber byte + ProposedWindowSize byte + ServiceChoice byte +} + +func (a APDU) Encode() []byte { + buffer := make([]byte, 0) + + tmp := byte(a.PduType) + if a.SegmentedMessage { + tmp |= 0x10 + } + if a.MoreFollows { + tmp |= 0x20 + } + if a.SegmentedResponseAccepted { + tmp |= 0x40 + } + buffer = append(buffer, tmp) + + if a.PduType == PDUTypeConfirmedServiceRequest { + buffer = append(buffer, byte(a.MaxSegmentsAccepted)|byte(a.MaxApduLengthAccepted)) + buffer = append(buffer, a.InvokeID) + if a.SegmentedMessage { + buffer = append(buffer, a.SequenceNumber, a.ProposedWindowSize) + } + } else if a.PduType == PDUTypeUnconfirmedServiceRequest { + // No additional fields for unconfirmed service request + } else if a.PduType == PDUTypeSimpleAck { + buffer = append(buffer, a.InvokeID) + } else if a.PduType == PDUTypeComplexAck { + buffer = append(buffer, a.InvokeID) + if a.SegmentedMessage { + buffer = append(buffer, a.SequenceNumber, a.ProposedWindowSize) + } + } else { + // Handle other PDU types + } + + buffer = append(buffer, a.ServiceChoice) + return buffer +} + +func (a *APDU) Decode(buffer []byte, offset int) int { + length := 0 + a.PduType = BacnetPduTypes(buffer[offset]) + tmp := byte(buffer[offset]) + length++ + + if a.PduType == PDUTypeConfirmedServiceRequest { + a.SegmentedMessage = tmp&0x10 != 0 + a.MoreFollows = tmp&0x20 != 0 + a.SegmentedResponseAccepted = tmp&0x40 != 0 + a.MaxSegmentsAccepted = BacnetMaxSegments(buffer[offset+length] & 0xF0) + a.MaxApduLengthAccepted = MaxAPDU(buffer[offset+length] & 0x0F) + length++ + a.InvokeID = buffer[offset+length] + length++ + if a.SegmentedMessage { + a.SequenceNumber = buffer[offset+length] + length++ + a.ProposedWindowSize = buffer[offset+length] + length++ + } + a.ServiceChoice = buffer[offset+length] + length++ + } else if a.PduType == PDUTypeUnconfirmedServiceRequest { + a.ServiceChoice = buffer[offset+length] + length++ + } else if a.PduType == PDUTypeSimpleAck { + a.InvokeID = buffer[offset+length] + length++ + a.ServiceChoice = buffer[offset+length] + length++ + } else if a.PduType == PDUTypeComplexAck { + a.SegmentedMessage = tmp&0x10 != 0 + a.InvokeID = buffer[offset+length] + length++ + a.ServiceChoice = buffer[offset+length] + length++ + if a.SegmentedMessage { + a.SequenceNumber = buffer[offset+length] + length++ + a.ProposedWindowSize = buffer[offset+length] + length++ + } + } else { + return -1 + } + + return length +} diff --git a/base.go b/base.go index f44a793..697354f 100644 --- a/base.go +++ b/base.go @@ -47,17 +47,6 @@ const ( MaxSEG65 BacnetMaxSegments = 0x70 ) -type BacnetMaxAdpu int - -const ( - MaxAPDU50 BacnetMaxAdpu = iota - MaxAPDU128 - MaxAPDU206 - MaxAPDU480 - MaxAPDU1024 - MaxAPDU1476 -) - type BacnetPduTypes int const ( diff --git a/bvlc.go b/bvlc.go new file mode 100644 index 0000000..332243b --- /dev/null +++ b/bvlc.go @@ -0,0 +1,110 @@ +package bacnet + +import ( + "encoding/binary" + "errors" + + "github.com/absmach/bacnet/transport" +) + +var ( + errUnsupportedTransport = errors.New("unsupported transport") + errInvalidMessageLength = errors.New("invalid message length") + errUnsupportedFunction = errors.New("unsupported BVLC function") +) + +type BVLCFunctions int + +const ( + BVLCResult BVLCFunctions = iota + BVLCWriteBroadcastDistributionTable + BVLCReadBroadcastDistTable + BVLCReadBroadcastDistTableAck + BVLCForwardedNPDU + BVLCRegisterForeignDevice + BVLCReadForeignDeviceTable + BVLCReadForeignDeviceTableAck + BVLCDeleteForeignDeviceTableENTRY + BVLCDistributeBroadcastToNetwok + BVLCOriginalUnicastNPDU + BVLCOriginalBroadcastNPDU +) + +type MaxAPDU int + +const ( + MaxAPDU50 MaxAPDU = iota + MaxAPDU128 + MaxAPDU206 + MaxAPDU480 + MaxAPDU1024 + MaxAPDU1476 +) + +type BVLC struct { + BVLLTypeBACnetIP byte + BVLCHeaderLength byte + BVLCMaxAPDU MaxAPDU +} + +func NewBVLC(transprt transport.Transport) *BVLC { + bvlc := &BVLC{ + BVLLTypeBACnetIP: 0x81, + BVLCHeaderLength: 4, + } + + if transprt == transport.IP { + bvlc.BVLCMaxAPDU = MaxAPDU1476 + } + + return bvlc +} + +func (bvlc *BVLC) Decode(buffer []byte, offset int) (int, byte, uint16, error) { + msgType := buffer[0] + function := BVLCFunctions(buffer[1]) + msgLength := binary.BigEndian.Uint16(buffer[2:4]) + + if msgType != bvlc.BVLLTypeBACnetIP || msgLength != uint16(len(buffer)) { + return 0, 0, 0, errUnsupportedTransport + } + + switch function { + case BVLCResult: + return 4, byte(function), msgLength, nil + case BVLCOriginalUnicastNPDU: + return 4, byte(function), msgLength, nil + case BVLCOriginalBroadcastNPDU: + return 4, byte(function), msgLength, nil + case BVLCForwardedNPDU: + // Handle this case + case BVLCDistributeBroadcastToNetwok: + // Handle this case + case BVLCRegisterForeignDevice: + // Handle this case + case BVLCReadForeignDeviceTable: + // Handle this case + case BVLCDeleteForeignDeviceTableENTRY: + // Handle this case + case BVLCReadBroadcastDistTable: + // Handle this case + case BVLCWriteBroadcastDistributionTable: + // Handle this case + default: + return -1, 0, 0, errUnsupportedFunction + } + + return 0, 0, 0, errors.New("todo") +} + +func (bvlc BVLC) First4BytesHeaderEncode(function BVLCFunctions, msgLength uint16) []byte { + b := make([]byte, 4) + b[0] = bvlc.BVLLTypeBACnetIP + b[1] = byte(function) + binary.BigEndian.PutUint16(b[2:4], msgLength) + return b +} + +func (bvlc BVLC) Encode(function BVLCFunctions, msgLength uint16) []byte { + return bvlc.First4BytesHeaderEncode(function, msgLength) +} diff --git a/example/whois.go b/example/whois.go index 2b18b6e..f386a03 100644 --- a/example/whois.go +++ b/example/whois.go @@ -2,25 +2,59 @@ package main import ( "fmt" + "log" "net" "time" "github.com/absmach/bacnet" + "github.com/absmach/bacnet/transport" ) func main() { - var highlim, lowLim uint32 = 4194303, 0 - whi := bacnet.WhoIs{HighLimit: &highlim, LowLimit: &lowLim} - whoIsRequest := whi.Encode() + + var highLimit, lowLimit uint32 = 4000000, 0 + req := bacnet.WhoIs{ + HighLimit: &highLimit, + LowLimit: &lowLimit, + } + whoisBytes := req.Encode() + + netType := bacnet.IPV4 + source := bacnet.NewBACnetAddress(20, []byte{}, "127.0.0.255:47809", &netType) + + npdu := bacnet.NewNPDU(source, nil, nil, nil) + npdu.Control.SetNetworkPriority(bacnet.NormalMessage) + npduBytes, err := npdu.Encode() + if err != nil { + log.Fatalf("failed to encode npdu with error %v", err) + } + + apdu := bacnet.APDU{ + PduType: bacnet.PDUTypeUnconfirmedServiceRequest, + ServiceChoice: byte(bacnet.ServiceChoiceWhoIs), + } + + apduBytes := apdu.Encode() + + mes := append(npduBytes, apduBytes...) + mes = append(mes, whoisBytes...) + + fmt.Println(mes) + + blvc := bacnet.NewBVLC(transport.IP) + blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes))) + message := append(blvcBytes, mes...) + + fmt.Println(message) // Define the BACnet broadcast address (255.255.255.255:47808) - remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.255:47809") + remoteAddr, err := net.ResolveUDPAddr("udp", "255.255.255.255:47809") if err != nil { fmt.Println("Error resolving remote address:", err) return } - // Create a UDP connection + // Create a UDP connectionBACnetAddress conn, err := net.DialUDP("udp", nil, remoteAddr) if err != nil { fmt.Println("Error creating UDP connection:", err) @@ -29,7 +63,7 @@ func main() { defer conn.Close() // Send the WhoIsRequest packet - _, err = conn.Write(whoIsRequest) + _, err = conn.Write(message) if err != nil { fmt.Println("Error sending WhoIsRequest:", err) return diff --git a/npdu.go b/npdu.go index 65b7bea..7dc9f92 100644 --- a/npdu.go +++ b/npdu.go @@ -115,14 +115,21 @@ func (nci *NPDUControlInformation) Decode(buffer []byte, offset int) int { return 0 } -func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount int, vendorID int) *NPDU { +func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount *uint8, vendorID *uint16) *NPDU { npdu := &NPDU{ Version: 1, Control: *NewNPDUControlInformation(), Destination: destination, Source: source, - HopCount: uint8(hopCount), - VendorID: uint16(vendorID), + } + switch hopCount { + case nil: + npdu.HopCount = 255 + default: + npdu.HopCount = *hopCount + } + if vendorID != nil { + npdu.VendorID = *vendorID } if destination != nil && destination.NetworkNumber > 0 { diff --git a/transport/transport.go b/transport/transport.go new file mode 100644 index 0000000..57ba5ac --- /dev/null +++ b/transport/transport.go @@ -0,0 +1,7 @@ +package transport + +type Transport int + +const ( + IP = iota +) From 732dc10d1723476494411d1dbceb651c0accd9d7 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Tue, 5 Sep 2023 17:39:41 +0300 Subject: [PATCH 11/24] reorganize module Signed-off-by: SammyOina --- example/whois.go | 30 +++++++++--------- apdu.go => pkg/bacnet/apdu.go | 0 base.go => pkg/bacnet/base.go | 0 bvlc.go => pkg/bacnet/bvlc.go | 2 +- client.go => pkg/bacnet/client.go | 0 general.go => pkg/bacnet/general.go | 2 +- iam.go => pkg/bacnet/iam.go | 0 network.go => pkg/bacnet/network.go | 2 +- npdu.go => pkg/bacnet/npdu.go | 0 object.go => pkg/bacnet/object.go | 2 +- property.go => pkg/bacnet/property.go | 0 whois.go => pkg/bacnet/whois.go | 2 +- {encoding => pkg/encoding}/date_time.go | 0 {encoding => pkg/encoding}/decoding.go | 0 {encoding => pkg/encoding}/encoding.go | 0 {encoding => pkg/encoding}/tags.go | 0 {transport => pkg/transport}/transport.go | 0 pkg/transport/udp/broadcast.go | 38 +++++++++++++++++++++++ 18 files changed, 58 insertions(+), 20 deletions(-) rename apdu.go => pkg/bacnet/apdu.go (100%) rename base.go => pkg/bacnet/base.go (100%) rename bvlc.go => pkg/bacnet/bvlc.go (98%) rename client.go => pkg/bacnet/client.go (100%) rename general.go => pkg/bacnet/general.go (92%) rename iam.go => pkg/bacnet/iam.go (100%) rename network.go => pkg/bacnet/network.go (98%) rename npdu.go => pkg/bacnet/npdu.go (100%) rename object.go => pkg/bacnet/object.go (98%) rename property.go => pkg/bacnet/property.go (100%) rename whois.go => pkg/bacnet/whois.go (96%) rename {encoding => pkg/encoding}/date_time.go (100%) rename {encoding => pkg/encoding}/decoding.go (100%) rename {encoding => pkg/encoding}/encoding.go (100%) rename {encoding => pkg/encoding}/tags.go (100%) rename {transport => pkg/transport}/transport.go (100%) create mode 100644 pkg/transport/udp/broadcast.go diff --git a/example/whois.go b/example/whois.go index f386a03..77e918a 100644 --- a/example/whois.go +++ b/example/whois.go @@ -6,8 +6,9 @@ import ( "net" "time" - "github.com/absmach/bacnet" - "github.com/absmach/bacnet/transport" + "github.com/absmach/bacnet/pkg/bacnet" + "github.com/absmach/bacnet/pkg/transport" + "github.com/absmach/bacnet/pkg/transport/udp" ) func main() { @@ -19,10 +20,14 @@ func main() { } whoisBytes := req.Encode() + broads, err := udp.GetBroadcastAddress("127.0.0.6", 47809) + if err != nil { + log.Fatalf("failed to encode npdu with error %v", err) + } netType := bacnet.IPV4 - source := bacnet.NewBACnetAddress(20, []byte{}, "127.0.0.255:47809", &netType) + broads = *bacnet.NewBACnetAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) - npdu := bacnet.NewNPDU(source, nil, nil, nil) + npdu := bacnet.NewNPDU(&broads, nil, nil, nil) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) npduBytes, err := npdu.Encode() if err != nil { @@ -39,16 +44,12 @@ func main() { mes := append(npduBytes, apduBytes...) mes = append(mes, whoisBytes...) - fmt.Println(mes) - blvc := bacnet.NewBVLC(transport.IP) - blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes))) + blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) message := append(blvcBytes, mes...) - fmt.Println(message) - // Define the BACnet broadcast address (255.255.255.255:47808) - remoteAddr, err := net.ResolveUDPAddr("udp", "255.255.255.255:47809") + remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.255:47809") if err != nil { fmt.Println("Error resolving remote address:", err) return @@ -65,8 +66,7 @@ func main() { // Send the WhoIsRequest packet _, err = conn.Write(message) if err != nil { - fmt.Println("Error sending WhoIsRequest:", err) - return + log.Fatal("Error sending WhoIsRequest:", err) } // Wait for responses @@ -78,15 +78,15 @@ func main() { if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // Timeout reached, no more responses - fmt.Println("No more responses received.") + log.Println("No more responses received.") break } - fmt.Println("Error reading response:", err) + log.Println("Error reading response:", err) break } // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] - fmt.Printf("Received response: %X\n", response) + log.Printf("Received response: %X\n", response) } } diff --git a/apdu.go b/pkg/bacnet/apdu.go similarity index 100% rename from apdu.go rename to pkg/bacnet/apdu.go diff --git a/base.go b/pkg/bacnet/base.go similarity index 100% rename from base.go rename to pkg/bacnet/base.go diff --git a/bvlc.go b/pkg/bacnet/bvlc.go similarity index 98% rename from bvlc.go rename to pkg/bacnet/bvlc.go index 332243b..4859b21 100644 --- a/bvlc.go +++ b/pkg/bacnet/bvlc.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "errors" - "github.com/absmach/bacnet/transport" + "github.com/absmach/bacnet/pkg/transport" ) var ( diff --git a/client.go b/pkg/bacnet/client.go similarity index 100% rename from client.go rename to pkg/bacnet/client.go diff --git a/general.go b/pkg/bacnet/general.go similarity index 92% rename from general.go rename to pkg/bacnet/general.go index 3a5d08d..ba24376 100644 --- a/general.go +++ b/pkg/bacnet/general.go @@ -3,7 +3,7 @@ package bacnet import ( "time" - "github.com/absmach/bacnet/encoding" + "github.com/absmach/bacnet/pkg/encoding" ) type DateTime struct { diff --git a/iam.go b/pkg/bacnet/iam.go similarity index 100% rename from iam.go rename to pkg/bacnet/iam.go diff --git a/network.go b/pkg/bacnet/network.go similarity index 98% rename from network.go rename to pkg/bacnet/network.go index 2455cab..0a885d1 100644 --- a/network.go +++ b/pkg/bacnet/network.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/absmach/bacnet/encoding" + "github.com/absmach/bacnet/pkg/encoding" ) type BACnetNetworkType int diff --git a/npdu.go b/pkg/bacnet/npdu.go similarity index 100% rename from npdu.go rename to pkg/bacnet/npdu.go diff --git a/object.go b/pkg/bacnet/object.go similarity index 98% rename from object.go rename to pkg/bacnet/object.go index ffc4b59..487aab1 100644 --- a/object.go +++ b/pkg/bacnet/object.go @@ -3,7 +3,7 @@ package bacnet import ( "encoding/binary" - "github.com/absmach/bacnet/encoding" + "github.com/absmach/bacnet/pkg/encoding" ) type ObjectInstance uint32 diff --git a/property.go b/pkg/bacnet/property.go similarity index 100% rename from property.go rename to pkg/bacnet/property.go diff --git a/whois.go b/pkg/bacnet/whois.go similarity index 96% rename from whois.go rename to pkg/bacnet/whois.go index 1ea2d51..e3a0826 100644 --- a/whois.go +++ b/pkg/bacnet/whois.go @@ -1,6 +1,6 @@ package bacnet -import "github.com/absmach/bacnet/encoding" +import "github.com/absmach/bacnet/pkg/encoding" type WhoIs struct { HighLimit, LowLimit *uint32 diff --git a/encoding/date_time.go b/pkg/encoding/date_time.go similarity index 100% rename from encoding/date_time.go rename to pkg/encoding/date_time.go diff --git a/encoding/decoding.go b/pkg/encoding/decoding.go similarity index 100% rename from encoding/decoding.go rename to pkg/encoding/decoding.go diff --git a/encoding/encoding.go b/pkg/encoding/encoding.go similarity index 100% rename from encoding/encoding.go rename to pkg/encoding/encoding.go diff --git a/encoding/tags.go b/pkg/encoding/tags.go similarity index 100% rename from encoding/tags.go rename to pkg/encoding/tags.go diff --git a/transport/transport.go b/pkg/transport/transport.go similarity index 100% rename from transport/transport.go rename to pkg/transport/transport.go diff --git a/pkg/transport/udp/broadcast.go b/pkg/transport/udp/broadcast.go new file mode 100644 index 0000000..3de1911 --- /dev/null +++ b/pkg/transport/udp/broadcast.go @@ -0,0 +1,38 @@ +package udp + +import ( + "net" + "strconv" + + "github.com/absmach/bacnet/pkg/bacnet" +) + +func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, error) { + broadcast := "255.255.255.255" + + interfaces, err := net.Interfaces() + if err != nil { + return bacnet.BACnetAddress{}, err + } + + for _, iface := range interfaces { + addrs, err := iface.Addrs() + if err != nil { + return bacnet.BACnetAddress{}, err + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil { + ipAddress := ipnet.IP.String() + if ipAddress == localEndpoint { + if iface.Flags&net.FlagBroadcast != 0 { + broadcast = ipnet.IP.Mask(ipnet.IP.DefaultMask()).String() + } + } + } + } + } + netType := bacnet.IPV4 + return *bacnet.NewBACnetAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil + +} From 292c9496475b76d3f321549924f5950263b47be5 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 8 Sep 2023 16:28:43 +0300 Subject: [PATCH 12/24] add read property request Signed-off-by: SammyOina --- example/whois.go | 3 +- pkg/bacnet/base.go | 477 -------- pkg/bacnet/client.go | 10 +- pkg/bacnet/network.go | 23 +- pkg/bacnet/object.go | 72 +- pkg/bacnet/property.go | 66 +- pkg/encoding/property.go | 1853 ++++++++++++++++++++++++++++++++ pkg/encoding/tags.go | 10 +- pkg/transport/udp/broadcast.go | 3 +- 9 files changed, 1940 insertions(+), 577 deletions(-) create mode 100644 pkg/encoding/property.go diff --git a/example/whois.go b/example/whois.go index 77e918a..11a6b07 100644 --- a/example/whois.go +++ b/example/whois.go @@ -7,6 +7,7 @@ import ( "time" "github.com/absmach/bacnet/pkg/bacnet" + "github.com/absmach/bacnet/pkg/encoding" "github.com/absmach/bacnet/pkg/transport" "github.com/absmach/bacnet/pkg/transport/udp" ) @@ -24,7 +25,7 @@ func main() { if err != nil { log.Fatalf("failed to encode npdu with error %v", err) } - netType := bacnet.IPV4 + netType := encoding.IPV4 broads = *bacnet.NewBACnetAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) npdu := bacnet.NewNPDU(&broads, nil, nil, nil) diff --git a/pkg/bacnet/base.go b/pkg/bacnet/base.go index 697354f..7a550e4 100644 --- a/pkg/bacnet/base.go +++ b/pkg/bacnet/base.go @@ -275,480 +275,3 @@ const ( DuplicateEntry InvalidValueInThisState ) - -// BACnetPropertyIdentifier represents BACnet property identifiers. -type PropertyIdentifier int - -const ( - AckedTransitions PropertyIdentifier = 0 - AckRequired PropertyIdentifier = 1 - Action PropertyIdentifier = 2 - ActionText PropertyIdentifier = 3 - ActiveText PropertyIdentifier = 4 - ActiveVtSessions PropertyIdentifier = 5 - AlarmValue PropertyIdentifier = 6 - AlarmValues PropertyIdentifier = 7 - All PropertyIdentifier = 8 - AllWritesSuccessful PropertyIdentifier = 9 - ApduSegmentTimeout PropertyIdentifier = 10 - ApduTimeout PropertyIdentifier = 11 - ApplicationSoftwareVersion PropertyIdentifier = 12 - Archive PropertyIdentifier = 13 - Bias PropertyIdentifier = 14 - ChangeOfStateCount PropertyIdentifier = 15 - ChangeOfStateTime PropertyIdentifier = 16 - NotificationClass PropertyIdentifier = 17 - Blank1 PropertyIdentifier = 18 - ControlledVariableReference PropertyIdentifier = 19 - ControlledVariableUnits PropertyIdentifier = 20 - ControlledVariableValue PropertyIdentifier = 21 - CovIncrement PropertyIdentifier = 22 - DateList PropertyIdentifier = 23 - DaylightSavingsStatus PropertyIdentifier = 24 - Deadband PropertyIdentifier = 25 - DerivativeConstant PropertyIdentifier = 26 - DerivativeConstantUnits PropertyIdentifier = 27 - Description PropertyIdentifier = 28 - DescriptionOfHalt PropertyIdentifier = 29 - DeviceAddressBinding PropertyIdentifier = 30 - DeviceType PropertyIdentifier = 31 - EffectivePeriod PropertyIdentifier = 32 - ElapsedActiveTime PropertyIdentifier = 33 - ErrorLimit PropertyIdentifier = 34 - EventEnable PropertyIdentifier = 35 - EventState PropertyIdentifier = 36 - EventType PropertyIdentifier = 37 - ExceptionSchedule PropertyIdentifier = 38 - FaultValues PropertyIdentifier = 39 - FeedbackValue PropertyIdentifier = 40 - FileAccessMethod PropertyIdentifier = 41 - FileSize PropertyIdentifier = 42 - FileType PropertyIdentifier = 43 - FirmwareRevision PropertyIdentifier = 44 - HighLimit PropertyIdentifier = 45 - InactiveText PropertyIdentifier = 46 - InProcess PropertyIdentifier = 47 - InstanceOf PropertyIdentifier = 48 - IntegralConstant PropertyIdentifier = 49 - IntegralConstantUnits PropertyIdentifier = 50 - IssueConfirmedNotifications PropertyIdentifier = 51 - LimitEnable PropertyIdentifier = 52 - ListOfGroupMembers PropertyIdentifier = 53 - ListOfObjectPropertyReferences PropertyIdentifier = 54 - ListOfSessionKeys PropertyIdentifier = 55 - LocalDate PropertyIdentifier = 56 - LocalTime PropertyIdentifier = 57 - Location PropertyIdentifier = 58 - LowLimit PropertyIdentifier = 59 - ManipulatedVariableReference PropertyIdentifier = 60 - MaximumOutput PropertyIdentifier = 61 - MaxApduLengthAccepted PropertyIdentifier = 62 - MaxInfoFrames PropertyIdentifier = 63 - MaxMaster PropertyIdentifier = 64 - MaxPresValue PropertyIdentifier = 65 - MinimumOffTime PropertyIdentifier = 66 - MinimumOnTime PropertyIdentifier = 67 - MinimumOutput PropertyIdentifier = 68 - MinPresValue PropertyIdentifier = 69 - ModelName PropertyIdentifier = 70 - ModificationDate PropertyIdentifier = 71 - NotifyType PropertyIdentifier = 72 - NumberOfApduRetries PropertyIdentifier = 73 - NumberOfStates PropertyIdentifier = 74 - ObjectIdentifierPI PropertyIdentifier = 75 - ObjectList PropertyIdentifier = 76 - ObjectName PropertyIdentifier = 77 - ObjectPropertyReference PropertyIdentifier = 78 - ObjectTypePI PropertyIdentifier = 79 - Optional PropertyIdentifier = 80 - OutOfService PropertyIdentifier = 81 - OutputUnits PropertyIdentifier = 82 - EventParameters PropertyIdentifier = 83 - Polarity PropertyIdentifier = 84 - PresentValue PropertyIdentifier = 85 - Priority PropertyIdentifier = 86 - PriorityArray PropertyIdentifier = 87 - PriorityForWriting PropertyIdentifier = 88 - ProcessIdentifier PropertyIdentifier = 89 - ProgramChange PropertyIdentifier = 90 - ProgramLocation PropertyIdentifier = 91 - ProgramState PropertyIdentifier = 92 - ProportionalConstant PropertyIdentifier = 93 - ProportionalConstantUnits PropertyIdentifier = 94 - ProtocolConformanceClass PropertyIdentifier = 95 - ProtocolObjectTypesSupported PropertyIdentifier = 96 - ProtocolServicesSupported PropertyIdentifier = 97 - ProtocolVersion PropertyIdentifier = 98 - ReadOnly PropertyIdentifier = 99 - ReasonForHalt PropertyIdentifier = 100 - Recipient PropertyIdentifier = 101 - RecipientList PropertyIdentifier = 102 - Reliability PropertyIdentifier = 103 - RelinquishDefault PropertyIdentifier = 104 - Required PropertyIdentifier = 105 - Resolution PropertyIdentifier = 106 - SegmentationSupported PropertyIdentifier = 107 - Setpoint PropertyIdentifier = 108 - SetpointReference PropertyIdentifier = 109 - StateText PropertyIdentifier = 110 - StatusFlags PropertyIdentifier = 111 - SystemStatus PropertyIdentifier = 112 - TimeDelay PropertyIdentifier = 113 - TimeOfActiveTimeReset PropertyIdentifier = 114 - TimeOfStateCountReset PropertyIdentifier = 115 - TimeSynchronizationRecipients PropertyIdentifier = 116 - Units PropertyIdentifier = 117 - UpdateInterval PropertyIdentifier = 118 - UtcOffset PropertyIdentifier = 119 - VendorIdentifier PropertyIdentifier = 120 - VendorName PropertyIdentifier = 121 - VtClassesSupported PropertyIdentifier = 122 - WeeklySchedule PropertyIdentifier = 123 - AttemptedSamples PropertyIdentifier = 124 - AverageValue PropertyIdentifier = 125 - BufferSize PropertyIdentifier = 126 - ClientCovIncrement PropertyIdentifier = 127 - CovResubscriptionInterval PropertyIdentifier = 128 - CurrentNotifyTime PropertyIdentifier = 129 - EventTimeStamps PropertyIdentifier = 130 - LogBuffer PropertyIdentifier = 131 - LogDeviceObjectProperty PropertyIdentifier = 132 - Enable PropertyIdentifier = 133 - LogInterval PropertyIdentifier = 134 - MaximumValue PropertyIdentifier = 135 - MinimumValue PropertyIdentifier = 136 - NotificationThreshold PropertyIdentifier = 137 - PreviousNotifyTime PropertyIdentifier = 138 - ProtocolRevision PropertyIdentifier = 139 - RecordsSinceNotification PropertyIdentifier = 140 - RecordCount PropertyIdentifier = 141 - StartTime PropertyIdentifier = 142 - StopTime PropertyIdentifier = 143 - StopWhenFull PropertyIdentifier = 144 - TotalRecordCount PropertyIdentifier = 145 - ValidSamples PropertyIdentifier = 146 - WindowInterval PropertyIdentifier = 147 - WindowSamples PropertyIdentifier = 148 - MaximumValueTimestamp PropertyIdentifier = 149 - MinimumValueTimestamp PropertyIdentifier = 150 - VarianceValue PropertyIdentifier = 151 - ActiveCovSubscriptions PropertyIdentifier = 152 - BackupFailureTimeout PropertyIdentifier = 153 - ConfigurationFiles PropertyIdentifier = 154 - DatabaseRevision PropertyIdentifier = 155 - DirectReading PropertyIdentifier = 156 - LastRestoreTime PropertyIdentifier = 157 - MaintenanceRequired PropertyIdentifier = 158 - MemberOf PropertyIdentifier = 159 - Mode PropertyIdentifier = 160 - OperationExpected PropertyIdentifier = 161 - Setting PropertyIdentifier = 162 - Silenced PropertyIdentifier = 163 - TrackingValue PropertyIdentifier = 164 - ZoneMembers PropertyIdentifier = 165 - LifeSafetyAlarmValues PropertyIdentifier = 166 - MaxSegmentsAccepted PropertyIdentifier = 167 - ProfileName PropertyIdentifier = 168 - AutoSlaveDiscovery PropertyIdentifier = 169 - ManualSlaveAddressBinding PropertyIdentifier = 170 - SlaveAddressBinding PropertyIdentifier = 171 - SlaveProxyEnable PropertyIdentifier = 172 - LastNotifyRecord PropertyIdentifier = 173 - ScheduleDefault PropertyIdentifier = 174 - AcceptedModes PropertyIdentifier = 175 - AdjustValue PropertyIdentifier = 176 - Count PropertyIdentifier = 177 - CountBeforeChange PropertyIdentifier = 178 - CountChangeTime PropertyIdentifier = 179 - CovPeriod PropertyIdentifier = 180 - InputReference PropertyIdentifier = 181 - LimitMonitoringInterval PropertyIdentifier = 182 - LoggingObject PropertyIdentifier = 183 - LoggingRecord PropertyIdentifier = 184 - Prescale PropertyIdentifier = 185 - PulseRate PropertyIdentifier = 186 - Scale PropertyIdentifier = 187 - ScaleFactor PropertyIdentifier = 188 - UpdateTime PropertyIdentifier = 189 - ValueBeforeChange PropertyIdentifier = 190 - ValueSet PropertyIdentifier = 191 - ValueChangeTime PropertyIdentifier = 192 - AlignIntervals PropertyIdentifier = 193 - IntervalOffset PropertyIdentifier = 195 - LastRestartReason PropertyIdentifier = 196 - LoggingType PropertyIdentifier = 197 - RestartNotificationRecipients PropertyIdentifier = 202 - TimeOfDeviceRestart PropertyIdentifier = 203 - TimeSynchronizationInterval PropertyIdentifier = 204 - Trigger PropertyIdentifier = 205 - UtcTimeSynchronizationRecipients PropertyIdentifier = 206 - NodeSubtype PropertyIdentifier = 207 - NodeType PropertyIdentifier = 208 - StructuredObjectList PropertyIdentifier = 209 - SubordinateAnnotations PropertyIdentifier = 210 - SubordinateList PropertyIdentifier = 211 - ActualShedLevel PropertyIdentifier = 212 - DutyWindow PropertyIdentifier = 213 - ExpectedShedLevel PropertyIdentifier = 214 - FullDutyBaseline PropertyIdentifier = 215 - RequestedShedLevel PropertyIdentifier = 218 - ShedDuration PropertyIdentifier = 219 - ShedLevelDescriptions PropertyIdentifier = 220 - ShedLevels PropertyIdentifier = 221 - StateDescription PropertyIdentifier = 222 - DoorAlarmState PropertyIdentifier = 226 - DoorExtendedPulseTime PropertyIdentifier = 227 - DoorMembers PropertyIdentifier = 228 - DoorOpenTooLongTime PropertyIdentifier = 229 - DoorPulseTime PropertyIdentifier = 230 - DoorStatus PropertyIdentifier = 231 - DoorUnlockDelayTime PropertyIdentifier = 232 - LockStatus PropertyIdentifier = 233 - MaskedAlarmValues PropertyIdentifier = 234 - SecuredStatus PropertyIdentifier = 235 - AbsenteeLimit PropertyIdentifier = 244 - AccessAlarmEvents PropertyIdentifier = 245 - AccessDoors PropertyIdentifier = 246 - AccessEvent PropertyIdentifier = 247 - AccessEventAuthenticationFactor PropertyIdentifier = 248 - AccessEventCredential PropertyIdentifier = 249 - AccessEventTime PropertyIdentifier = 250 - AccessTransactionEvents PropertyIdentifier = 251 - Accompaniment PropertyIdentifier = 252 - AccompanimentTime PropertyIdentifier = 253 - ActivationTime PropertyIdentifier = 254 - ActiveAuthenticationPolicy PropertyIdentifier = 255 - AssignedAccessRights PropertyIdentifier = 256 - AuthenticationFactors PropertyIdentifier = 257 - AuthenticationPolicyList PropertyIdentifier = 258 - AuthenticationPolicyNames PropertyIdentifier = 259 - AuthenticationStatus PropertyIdentifier = 260 - AuthorizationMode PropertyIdentifier = 261 - BelongsTo PropertyIdentifier = 262 - CredentialDisable PropertyIdentifier = 263 - CredentialStatus PropertyIdentifier = 264 - Credentials PropertyIdentifier = 265 - CredentialsInZone PropertyIdentifier = 266 - DaysRemaining PropertyIdentifier = 267 - EntryPoints PropertyIdentifier = 268 - ExitPoints PropertyIdentifier = 269 - ExpiryTime PropertyIdentifier = 270 - ExtendedTimeEnable PropertyIdentifier = 271 - FailedAttemptEvents PropertyIdentifier = 272 - FailedAttempts PropertyIdentifier = 273 - FailedAttemptsTime PropertyIdentifier = 274 - LastAccessEvent PropertyIdentifier = 275 - LastAccessPoint PropertyIdentifier = 276 - LastCredentialAdded PropertyIdentifier = 277 - LastCredentialAddedTime PropertyIdentifier = 278 - LastCredentialRemoved PropertyIdentifier = 279 - LastCredentialRemovedTime PropertyIdentifier = 280 - LastUseTime PropertyIdentifier = 281 - Lockout PropertyIdentifier = 282 - LockoutRelinquishTime PropertyIdentifier = 283 - MasterExemption PropertyIdentifier = 284 - MaxFailedAttempts PropertyIdentifier = 285 - Members PropertyIdentifier = 286 - MusterPoint PropertyIdentifier = 287 - NegativeAccessRules PropertyIdentifier = 288 - NumberOfAuthenticationPolicies PropertyIdentifier = 289 - OccupancyCount PropertyIdentifier = 290 - OccupancyCountAdjust PropertyIdentifier = 291 - OccupancyCountEnable PropertyIdentifier = 292 - OccupancyExemption PropertyIdentifier = 293 - OccupancyLowerLimit PropertyIdentifier = 294 - OccupancyLowerLimitEnforced PropertyIdentifier = 295 - OccupancyState PropertyIdentifier = 296 - OccupancyUpperLimit PropertyIdentifier = 297 - OccupancyUpperLimitEnforced PropertyIdentifier = 298 - PassbackExemption PropertyIdentifier = 299 - PassbackMode PropertyIdentifier = 300 - PassbackTimeout PropertyIdentifier = 301 - PositiveAccessRules PropertyIdentifier = 302 - ReasonForDisable PropertyIdentifier = 303 - SupportedFormats PropertyIdentifier = 304 - SupportedFormatClasses PropertyIdentifier = 305 - ThreatAuthority PropertyIdentifier = 306 - ThreatLevel PropertyIdentifier = 307 - TraceFlag PropertyIdentifier = 308 - TransactionNotificationClass PropertyIdentifier = 309 - UserExternalIdentifier PropertyIdentifier = 310 - UserInformationReference PropertyIdentifier = 311 - UserName PropertyIdentifier = 317 - UserType PropertyIdentifier = 318 - UsesRemaining PropertyIdentifier = 319 - ZoneFrom PropertyIdentifier = 320 - ZoneTo PropertyIdentifier = 321 - AccessEventTag PropertyIdentifier = 322 - GlobalIdentifier PropertyIdentifier = 323 - VerificationTime PropertyIdentifier = 326 - BaseDeviceSecurityPolicy PropertyIdentifier = 327 - DistributionKeyRevision PropertyIdentifier = 328 - DoNotHide PropertyIdentifier = 329 - KeySets PropertyIdentifier = 330 - LastKeyServer PropertyIdentifier = 331 - NetworkAccessSecurityPolicies PropertyIdentifier = 332 - PacketReorderTime PropertyIdentifier = 333 - SecurityPduTimeout PropertyIdentifier = 334 - SecurityTimeWindow PropertyIdentifier = 335 - SupportedSecurityAlgorithm PropertyIdentifier = 336 - UpdateKeySetTimeout PropertyIdentifier = 337 - BackupAndRestoreState PropertyIdentifier = 338 - BackupPreparationTime PropertyIdentifier = 339 - RestoreCompletionTime PropertyIdentifier = 340 - RestorePreparationTime PropertyIdentifier = 341 - BitMask PropertyIdentifier = 342 - BitText PropertyIdentifier = 343 - IsUtc PropertyIdentifier = 344 - GroupMembers PropertyIdentifier = 345 - GroupMemberNames PropertyIdentifier = 346 - MemberStatusFlags PropertyIdentifier = 347 - RequestedUpdateInterval PropertyIdentifier = 348 - CovuPeriod PropertyIdentifier = 349 - CovuRecipients PropertyIdentifier = 350 - EventMessageTexts PropertyIdentifier = 351 - EventMessageTextsConfig PropertyIdentifier = 352 - EventDetectionEnable PropertyIdentifier = 353 - EventAlgorithmInhibit PropertyIdentifier = 354 - EventAlgorithmInhibitRef PropertyIdentifier = 355 - TimeDelayNormal PropertyIdentifier = 356 - ReliabilityEvaluationInhibit PropertyIdentifier = 357 - FaultParameters PropertyIdentifier = 358 - FaultType PropertyIdentifier = 359 - LocalForwardingOnly PropertyIdentifier = 360 - ProcessIdentifierFilter PropertyIdentifier = 361 - SubscribedRecipients PropertyIdentifier = 362 - PortFilter PropertyIdentifier = 363 - AuthorizationExemptions PropertyIdentifier = 364 - AllowGroupDelayInhibit PropertyIdentifier = 365 - ChannelNumber PropertyIdentifier = 366 - ControlGroups PropertyIdentifier = 367 - ExecutionDelay PropertyIdentifier = 368 - LastPriority PropertyIdentifier = 369 - WriteStatus PropertyIdentifier = 370 - PropertyList PropertyIdentifier = 371 - SerialNumber PropertyIdentifier = 372 - BlinkWarnEnable PropertyIdentifier = 373 - DefaultFadeTime PropertyIdentifier = 374 - DefaultRampRate PropertyIdentifier = 375 - DefaultStepIncrement PropertyIdentifier = 376 - EgressTime PropertyIdentifier = 377 - InProgress PropertyIdentifier = 378 - InstantaneousPower PropertyIdentifier = 379 - LightingCommand PropertyIdentifier = 380 - LightingCommandDefaultPriority PropertyIdentifier = 381 - MaxActualValue PropertyIdentifier = 382 - MinActualValue PropertyIdentifier = 383 - Power PropertyIdentifier = 384 - Transition PropertyIdentifier = 385 - EgressActive PropertyIdentifier = 386 - InterfaceValue PropertyIdentifier = 387 - FaultHighLimit PropertyIdentifier = 388 - FaultLowLimit PropertyIdentifier = 389 - LowDiffLimit PropertyIdentifier = 390 - StrikeCount PropertyIdentifier = 391 - TimeOfStrikeCountReset PropertyIdentifier = 392 - DefaultTimeout PropertyIdentifier = 393 - InitialTimeout PropertyIdentifier = 394 - LastStateChange PropertyIdentifier = 395 - StateChangeValues PropertyIdentifier = 396 - TimerRunning PropertyIdentifier = 397 - TimerState PropertyIdentifier = 398 - ApduLength PropertyIdentifier = 399 - IpAddress PropertyIdentifier = 400 - IpDefaultGateway PropertyIdentifier = 401 - IpDhcpEnable PropertyIdentifier = 402 - IpDhcpLeaseTime PropertyIdentifier = 403 - IpDhcpLeaseTimeRemaining PropertyIdentifier = 404 - IpDhcpServer PropertyIdentifier = 405 - IpDnsServer PropertyIdentifier = 406 - BacnetIpGlobalAddress PropertyIdentifier = 407 - BacnetIpMode PropertyIdentifier = 408 - BacnetIpMulticastAddress PropertyIdentifier = 409 - BacnetIpNatTraversal PropertyIdentifier = 410 - IpSubnetMask PropertyIdentifier = 411 - BacnetIpUdpPort PropertyIdentifier = 412 - BbmdAcceptFdRegistrations PropertyIdentifier = 413 - BbmdBroadcastDistributionTable PropertyIdentifier = 414 - BbmdForeignDeviceTable PropertyIdentifier = 415 - ChangesPending PropertyIdentifier = 416 - Command PropertyIdentifier = 417 - FdBbmdAddress PropertyIdentifier = 418 - FdSubscriptionLifetime PropertyIdentifier = 419 - LinkSpeed PropertyIdentifier = 420 - LinkSpeeds PropertyIdentifier = 421 - LinkSpeedAutonegotiate PropertyIdentifier = 422 - MacAddress PropertyIdentifier = 423 - NetworkInterfaceName PropertyIdentifier = 424 - NetworkNumber PropertyIdentifier = 425 - NetworkNumberQuality PropertyIdentifier = 426 - NetworkType PropertyIdentifier = 427 - RoutingTable PropertyIdentifier = 428 - VirtualMacAddressTable PropertyIdentifier = 429 - CommandTimeArray PropertyIdentifier = 430 - CurrentCommandPriority PropertyIdentifier = 431 - LastCommandTime PropertyIdentifier = 432 - ValueSource PropertyIdentifier = 433 - ValueSourceArray PropertyIdentifier = 434 - BacnetIpv6Mode PropertyIdentifier = 435 - Ipv6Address PropertyIdentifier = 436 - Ipv6PrefixLength PropertyIdentifier = 437 - BacnetIpv6UdpPort PropertyIdentifier = 438 - Ipv6DefaultGateway PropertyIdentifier = 439 - BacnetIpv6MulticastAddress PropertyIdentifier = 440 - Ipv6DnsServer PropertyIdentifier = 441 - Ipv6AutoAddressingEnable PropertyIdentifier = 442 - Ipv6DhcpLeaseTime PropertyIdentifier = 443 - Ipv6DhcpLeaseTimeRemaining PropertyIdentifier = 444 - Ipv6DhcpServer PropertyIdentifier = 445 - Ipv6ZoneIndex PropertyIdentifier = 446 - AssignedLandingCalls PropertyIdentifier = 447 - CarAssignedDirection PropertyIdentifier = 448 - CarDoorCommand PropertyIdentifier = 449 - CarDoorStatus PropertyIdentifier = 450 - CarDoorText PropertyIdentifier = 451 - CarDoorZone PropertyIdentifier = 452 - CarDriveStatus PropertyIdentifier = 453 - CarLoad PropertyIdentifier = 454 - CarLoadUnits PropertyIdentifier = 455 - CarMode PropertyIdentifier = 456 - CarMovingDirection PropertyIdentifier = 457 - CarPosition PropertyIdentifier = 458 - ElevatorGroup PropertyIdentifier = 459 - EnergyMeter PropertyIdentifier = 460 - EnergyMeterRef PropertyIdentifier = 461 - EscalatorMode PropertyIdentifier = 462 - FloorText PropertyIdentifier = 464 - GroupId PropertyIdentifier = 465 - GroupMode PropertyIdentifier = 467 - HigherDeck PropertyIdentifier = 468 - InstallationId PropertyIdentifier = 469 - LandingCalls PropertyIdentifier = 470 - LandingCallControl PropertyIdentifier = 471 - LandingDoorStatus PropertyIdentifier = 472 - LowerDeck PropertyIdentifier = 473 - MachineRoomId PropertyIdentifier = 474 - MakingCarCall PropertyIdentifier = 475 - NextStoppingFloor PropertyIdentifier = 476 - OperationDirection PropertyIdentifier = 477 - PassengerAlarm PropertyIdentifier = 478 - PowerMode PropertyIdentifier = 479 - RegisteredCarCall PropertyIdentifier = 480 - ActiveCovMultipleSubscriptions PropertyIdentifier = 481 - ProtocolLevel PropertyIdentifier = 482 - ReferencePort PropertyIdentifier = 483 - DeployedProfileLocation PropertyIdentifier = 484 - ProfileLocation PropertyIdentifier = 485 - Tags PropertyIdentifier = 486 - SubordinateNodeTypes PropertyIdentifier = 487 - SubordinateRelationships PropertyIdentifier = 489 - SubordinateTags PropertyIdentifier = 488 - DefaultSubordinateRelationship PropertyIdentifier = 490 - Represents PropertyIdentifier = 491 - DefaultPresentValue PropertyIdentifier = 492 - PresentStage PropertyIdentifier = 493 - Stages PropertyIdentifier = 494 - StageNames PropertyIdentifier = 495 - TargetReferences PropertyIdentifier = 496 - FaultSignals PropertyIdentifier = 463 -) diff --git a/pkg/bacnet/client.go b/pkg/bacnet/client.go index 98f6c67..3d6f055 100644 --- a/pkg/bacnet/client.go +++ b/pkg/bacnet/client.go @@ -1,22 +1,24 @@ package bacnet +import "github.com/absmach/bacnet/pkg/encoding" + type client struct { // Fields for client configuration } type Client interface { - ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (interface{}, error) - WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value interface{}) error + ReadProperty(objectID ObjectIdentifier, propertyID encoding.PropertyIdentifier) (interface{}, error) + WriteProperty(objectID ObjectIdentifier, propertyID encoding.PropertyIdentifier, value interface{}) error } func NewClient(address string, port int) (Client, error) { return &client{}, nil } -func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier) (interface{}, error) { +func (c *client) ReadProperty(objectID ObjectIdentifier, propertyID encoding.PropertyIdentifier) (interface{}, error) { return nil, nil } -func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID PropertyIdentifier, value interface{}) error { +func (c *client) WriteProperty(objectID ObjectIdentifier, propertyID encoding.PropertyIdentifier, value interface{}) error { return nil } diff --git a/pkg/bacnet/network.go b/pkg/bacnet/network.go index 0a885d1..15650e5 100644 --- a/pkg/bacnet/network.go +++ b/pkg/bacnet/network.go @@ -8,21 +8,6 @@ import ( "github.com/absmach/bacnet/pkg/encoding" ) -type BACnetNetworkType int - -const ( - Ethernet BACnetNetworkType = iota - ARCnet - MSTP - PTP - LonTalk - IPV4 - Zigbee - Virtual - IPV6 - Serial -) - type ApplicationTags int const ( @@ -53,7 +38,7 @@ type BACnetAddress struct { MacAddress []byte } -func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *BACnetNetworkType) *BACnetAddress { +func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *encoding.BACnetNetworkType) *BACnetAddress { addr := &BACnetAddress{ NetworkNumber: networkNumber, MacAddress: macAddress, @@ -63,7 +48,7 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface case string: if address != "" { switch *netType { - case IPV4: + case encoding.IPV4: tmp1 := strings.Split(addr1, ":") parts := strings.Split(tmp1[0], ".") var ipAddr [4]byte @@ -75,7 +60,7 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface var port uint16 fmt.Sscanf(tmp1[1], "%d", &port) addr.MacAddress = append(ipAddr[:], byte(port>>8), byte(port)) - case Ethernet: + case encoding.Ethernet: parts := strings.Split(addr1, "-") for _, part := range parts { val := byte(0) @@ -85,7 +70,7 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface } } case ObjectIdentifier: - if *netType == IPV4 { + if *netType == encoding.IPV4 { addr.MacAddress = make([]byte, 6) binary.LittleEndian.PutUint64(addr.MacAddress, uint64(addr1.Instance)) } diff --git a/pkg/bacnet/object.go b/pkg/bacnet/object.go index 487aab1..a68a104 100644 --- a/pkg/bacnet/object.go +++ b/pkg/bacnet/object.go @@ -8,87 +8,21 @@ import ( type ObjectInstance uint32 -type ObjectType uint16 - -const ( - AnalogInput ObjectType = iota - AnalogOutput - AnalogValue - BinaryInput - BinaryOutput - BinaryValue - Calendar - ObjectTypeCommand - ObjectTypeDevice - EventEnrollment - File - Group - Loop - MultiStateInput - MultiStateOutput - ObjectTypeNotificationClass - Program - Schedule - Averaging - MultiStateValue - TrendLog - LifeSafetyPoint - LifeSafetyZone - Accumulator - PulseConverter - EventLog - GlobalGroup - TrendLogMultiple - LoadControl - StructuredView - AccessDoor - Timer - AccessCredential - AccessPoint - AccessRights - AccessUser - AccessZone - CredentialDataInput - NetworkSecurity - BitStringValue - CharacterStringValue - DatePatternValue - DateValue - DateTimePatternValue - DateTimeValue - IntegerValue - LargeAnalogValue - OctetStringValue - PositiveIntegerValue - TimePatternValue - TimeValue - NotificationForwarder - AlertEnrollment - Channel - LightingOutput - BinaryLightingOutput - NetworkPort - ObjectTypeElevatorGroup - Escalator - Lift - Staging -) - type ObjectIdentifier struct { - Type ObjectType + Type encoding.ObjectType Instance ObjectInstance } func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdulen int) int { len, val := encoding.DecodeUnsigned(buf, offset, 4) oi.Instance = ObjectInstance(val) & ObjectInstance(encoding.MaxInstance) - oi.Type = ObjectType(val >> encoding.InstanceBits & encoding.MaxObject) + oi.Type = encoding.ObjectType(val >> encoding.InstanceBits & encoding.MaxObject) return len } func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdulen int, tagNumber byte) int { len := 0 - if encoding.DecodeIsCOntextTag(buf, offset+len, tagNumber) { + if encoding.IsContextTag(buf, offset+len, tagNumber) { len1, _, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+len) len += len1 len += oi.Decode(buf, offset+len1, int(lenVal)) diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 08d5908..f7b2124 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -1,8 +1,72 @@ package bacnet +import ( + "github.com/absmach/bacnet/pkg/encoding" +) + type PropertyValue struct { - Identifier PropertyIdentifier + Identifier encoding.PropertyIdentifier Arrayindex *uint32 Value uint32 Priority uint32 } + +type ReadPropertyRequest struct { + ObjectIdentifier *ObjectIdentifier + PropertyIdentifier interface{} + PropertyArrayIndex uint32 +} + +func (r ReadPropertyRequest) Encode() []byte { + var ret []byte + + if r.ObjectIdentifier != nil { + ret = append(ret, r.ObjectIdentifier.EncodeContext(0)...) + } + + propID := r.PropertyIdentifier.(int) + + ret = append(ret, encoding.EncodeContextEnumerated(1, uint32(propID))...) + + if r.PropertyArrayIndex != 0 { + ret = append(ret, encoding.EncodeContextUnsigned(2, r.PropertyArrayIndex)...) + } + + return ret +} + +func (r *ReadPropertyRequest) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // objectIdentifier + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + r.ObjectIdentifier = &ObjectIdentifier{} + leng += r.ObjectIdentifier.Decode(buffer, offset+leng, int(lenValue)) + } else { + return -1 + } + + // propertyIdentifier + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, r.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng += leng1 + } else { + return -1 + } + + // propertyArrayIndex (optional) + if leng < apduLen && encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, r.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + + leng += leng1 + } + + return leng +} diff --git a/pkg/encoding/property.go b/pkg/encoding/property.go new file mode 100644 index 0000000..4428f67 --- /dev/null +++ b/pkg/encoding/property.go @@ -0,0 +1,1853 @@ +package encoding + +type BACnetNetworkType int + +const ( + Ethernet BACnetNetworkType = iota + ARCnet + MSTP + PTP + LonTalk + IPV4 + Zigbee + Virtual + IPV6 + Serial +) + +type ObjectType uint16 + +const ( + AnalogInput ObjectType = iota + AnalogOutput + AnalogValue + BinaryInput + BinaryOutput + BinaryValue + Calendar + ObjectTypeCommand + ObjectTypeDevice + EventEnrollment + File + Group + Loop + MultiStateInput + MultiStateOutput + ObjectTypeNotificationClass + Program + Schedule + Averaging + MultiStateValue + TrendLog + LifeSafetyPoint + LifeSafetyZone + Accumulator + PulseConverter + EventLog + GlobalGroup + TrendLogMultiple + LoadControl + StructuredView + AccessDoor + Timer + AccessCredential + AccessPoint + AccessRights + AccessUser + AccessZone + CredentialDataInput + NetworkSecurity + BitStringValue + CharacterStringValue + DatePatternValue + DateValue + DateTimePatternValue + DateTimeValue + IntegerValue + LargeAnalogValue + OctetStringValue + PositiveIntegerValue + TimePatternValue + TimeValue + NotificationForwarder + AlertEnrollment + Channel + LightingOutput + BinaryLightingOutput + NetworkPort + ObjectTypeElevatorGroup + Escalator + Lift + Staging +) + +// BACnetPropertyIdentifier represents BACnet property identifiers. +type PropertyIdentifier int + +const ( + AckedTransitions PropertyIdentifier = 0 + AckRequired PropertyIdentifier = 1 + Action PropertyIdentifier = 2 + ActionText PropertyIdentifier = 3 + ActiveText PropertyIdentifier = 4 + ActiveVtSessions PropertyIdentifier = 5 + AlarmValue PropertyIdentifier = 6 + AlarmValues PropertyIdentifier = 7 + All PropertyIdentifier = 8 + AllWritesSuccessful PropertyIdentifier = 9 + ApduSegmentTimeout PropertyIdentifier = 10 + ApduTimeout PropertyIdentifier = 11 + ApplicationSoftwareVersion PropertyIdentifier = 12 + Archive PropertyIdentifier = 13 + Bias PropertyIdentifier = 14 + ChangeOfStateCount PropertyIdentifier = 15 + ChangeOfStateTime PropertyIdentifier = 16 + NotificationClass PropertyIdentifier = 17 + Blank1 PropertyIdentifier = 18 + ControlledVariableReference PropertyIdentifier = 19 + ControlledVariableUnits PropertyIdentifier = 20 + ControlledVariableValue PropertyIdentifier = 21 + CovIncrement PropertyIdentifier = 22 + DateList PropertyIdentifier = 23 + DaylightSavingsStatus PropertyIdentifier = 24 + Deadband PropertyIdentifier = 25 + DerivativeConstant PropertyIdentifier = 26 + DerivativeConstantUnits PropertyIdentifier = 27 + Description PropertyIdentifier = 28 + DescriptionOfHalt PropertyIdentifier = 29 + DeviceAddressBinding PropertyIdentifier = 30 + DeviceType PropertyIdentifier = 31 + EffectivePeriod PropertyIdentifier = 32 + ElapsedActiveTime PropertyIdentifier = 33 + ErrorLimit PropertyIdentifier = 34 + EventEnable PropertyIdentifier = 35 + EventState PropertyIdentifier = 36 + EventType PropertyIdentifier = 37 + ExceptionSchedule PropertyIdentifier = 38 + FaultValues PropertyIdentifier = 39 + FeedbackValue PropertyIdentifier = 40 + FileAccessMethod PropertyIdentifier = 41 + FileSize PropertyIdentifier = 42 + FileType PropertyIdentifier = 43 + FirmwareRevision PropertyIdentifier = 44 + HighLimit PropertyIdentifier = 45 + InactiveText PropertyIdentifier = 46 + InProcess PropertyIdentifier = 47 + InstanceOf PropertyIdentifier = 48 + IntegralConstant PropertyIdentifier = 49 + IntegralConstantUnits PropertyIdentifier = 50 + IssueConfirmedNotifications PropertyIdentifier = 51 + LimitEnable PropertyIdentifier = 52 + ListOfGroupMembers PropertyIdentifier = 53 + ListOfObjectPropertyReferences PropertyIdentifier = 54 + ListOfSessionKeys PropertyIdentifier = 55 + LocalDate PropertyIdentifier = 56 + LocalTime PropertyIdentifier = 57 + Location PropertyIdentifier = 58 + LowLimit PropertyIdentifier = 59 + ManipulatedVariableReference PropertyIdentifier = 60 + MaximumOutput PropertyIdentifier = 61 + MaxApduLengthAccepted PropertyIdentifier = 62 + MaxInfoFrames PropertyIdentifier = 63 + MaxMaster PropertyIdentifier = 64 + MaxPresValue PropertyIdentifier = 65 + MinimumOffTime PropertyIdentifier = 66 + MinimumOnTime PropertyIdentifier = 67 + MinimumOutput PropertyIdentifier = 68 + MinPresValue PropertyIdentifier = 69 + ModelName PropertyIdentifier = 70 + ModificationDate PropertyIdentifier = 71 + NotifyType PropertyIdentifier = 72 + NumberOfApduRetries PropertyIdentifier = 73 + NumberOfStates PropertyIdentifier = 74 + ObjectIdentifierPI PropertyIdentifier = 75 + ObjectList PropertyIdentifier = 76 + ObjectName PropertyIdentifier = 77 + ObjectPropertyReference PropertyIdentifier = 78 + ObjectTypePI PropertyIdentifier = 79 + Optional PropertyIdentifier = 80 + OutOfService PropertyIdentifier = 81 + OutputUnits PropertyIdentifier = 82 + EventParameters PropertyIdentifier = 83 + Polarity PropertyIdentifier = 84 + PresentValue PropertyIdentifier = 85 + Priority PropertyIdentifier = 86 + PriorityArray PropertyIdentifier = 87 + PriorityForWriting PropertyIdentifier = 88 + ProcessIdentifier PropertyIdentifier = 89 + ProgramChange PropertyIdentifier = 90 + ProgramLocation PropertyIdentifier = 91 + ProgramState PropertyIdentifier = 92 + ProportionalConstant PropertyIdentifier = 93 + ProportionalConstantUnits PropertyIdentifier = 94 + ProtocolConformanceClass PropertyIdentifier = 95 + ProtocolObjectTypesSupported PropertyIdentifier = 96 + ProtocolServicesSupported PropertyIdentifier = 97 + ProtocolVersion PropertyIdentifier = 98 + ReadOnly PropertyIdentifier = 99 + ReasonForHalt PropertyIdentifier = 100 + Recipient PropertyIdentifier = 101 + RecipientList PropertyIdentifier = 102 + Reliability PropertyIdentifier = 103 + RelinquishDefault PropertyIdentifier = 104 + Required PropertyIdentifier = 105 + Resolution PropertyIdentifier = 106 + SegmentationSupported PropertyIdentifier = 107 + Setpoint PropertyIdentifier = 108 + SetpointReference PropertyIdentifier = 109 + StateText PropertyIdentifier = 110 + StatusFlags PropertyIdentifier = 111 + SystemStatus PropertyIdentifier = 112 + TimeDelay PropertyIdentifier = 113 + TimeOfActiveTimeReset PropertyIdentifier = 114 + TimeOfStateCountReset PropertyIdentifier = 115 + TimeSynchronizationRecipients PropertyIdentifier = 116 + Units PropertyIdentifier = 117 + UpdateInterval PropertyIdentifier = 118 + UtcOffset PropertyIdentifier = 119 + VendorIdentifier PropertyIdentifier = 120 + VendorName PropertyIdentifier = 121 + VtClassesSupported PropertyIdentifier = 122 + WeeklySchedule PropertyIdentifier = 123 + AttemptedSamples PropertyIdentifier = 124 + AverageValue PropertyIdentifier = 125 + BufferSize PropertyIdentifier = 126 + ClientCovIncrement PropertyIdentifier = 127 + CovResubscriptionInterval PropertyIdentifier = 128 + CurrentNotifyTime PropertyIdentifier = 129 + EventTimeStamps PropertyIdentifier = 130 + LogBuffer PropertyIdentifier = 131 + LogDeviceObjectProperty PropertyIdentifier = 132 + Enable PropertyIdentifier = 133 + LogInterval PropertyIdentifier = 134 + MaximumValue PropertyIdentifier = 135 + MinimumValue PropertyIdentifier = 136 + NotificationThreshold PropertyIdentifier = 137 + PreviousNotifyTime PropertyIdentifier = 138 + ProtocolRevision PropertyIdentifier = 139 + RecordsSinceNotification PropertyIdentifier = 140 + RecordCount PropertyIdentifier = 141 + StartTime PropertyIdentifier = 142 + StopTime PropertyIdentifier = 143 + StopWhenFull PropertyIdentifier = 144 + TotalRecordCount PropertyIdentifier = 145 + ValidSamples PropertyIdentifier = 146 + WindowInterval PropertyIdentifier = 147 + WindowSamples PropertyIdentifier = 148 + MaximumValueTimestamp PropertyIdentifier = 149 + MinimumValueTimestamp PropertyIdentifier = 150 + VarianceValue PropertyIdentifier = 151 + ActiveCovSubscriptions PropertyIdentifier = 152 + BackupFailureTimeout PropertyIdentifier = 153 + ConfigurationFiles PropertyIdentifier = 154 + DatabaseRevision PropertyIdentifier = 155 + DirectReading PropertyIdentifier = 156 + LastRestoreTime PropertyIdentifier = 157 + MaintenanceRequired PropertyIdentifier = 158 + MemberOf PropertyIdentifier = 159 + Mode PropertyIdentifier = 160 + OperationExpected PropertyIdentifier = 161 + Setting PropertyIdentifier = 162 + Silenced PropertyIdentifier = 163 + TrackingValue PropertyIdentifier = 164 + ZoneMembers PropertyIdentifier = 165 + LifeSafetyAlarmValues PropertyIdentifier = 166 + MaxSegmentsAccepted PropertyIdentifier = 167 + ProfileName PropertyIdentifier = 168 + AutoSlaveDiscovery PropertyIdentifier = 169 + ManualSlaveAddressBinding PropertyIdentifier = 170 + SlaveAddressBinding PropertyIdentifier = 171 + SlaveProxyEnable PropertyIdentifier = 172 + LastNotifyRecord PropertyIdentifier = 173 + ScheduleDefault PropertyIdentifier = 174 + AcceptedModes PropertyIdentifier = 175 + AdjustValue PropertyIdentifier = 176 + Count PropertyIdentifier = 177 + CountBeforeChange PropertyIdentifier = 178 + CountChangeTime PropertyIdentifier = 179 + CovPeriod PropertyIdentifier = 180 + InputReference PropertyIdentifier = 181 + LimitMonitoringInterval PropertyIdentifier = 182 + LoggingObject PropertyIdentifier = 183 + LoggingRecord PropertyIdentifier = 184 + Prescale PropertyIdentifier = 185 + PulseRate PropertyIdentifier = 186 + Scale PropertyIdentifier = 187 + ScaleFactor PropertyIdentifier = 188 + UpdateTime PropertyIdentifier = 189 + ValueBeforeChange PropertyIdentifier = 190 + ValueSet PropertyIdentifier = 191 + ValueChangeTime PropertyIdentifier = 192 + AlignIntervals PropertyIdentifier = 193 + IntervalOffset PropertyIdentifier = 195 + LastRestartReason PropertyIdentifier = 196 + LoggingType PropertyIdentifier = 197 + RestartNotificationRecipients PropertyIdentifier = 202 + TimeOfDeviceRestart PropertyIdentifier = 203 + TimeSynchronizationInterval PropertyIdentifier = 204 + Trigger PropertyIdentifier = 205 + UtcTimeSynchronizationRecipients PropertyIdentifier = 206 + NodeSubtype PropertyIdentifier = 207 + NodeType PropertyIdentifier = 208 + StructuredObjectList PropertyIdentifier = 209 + SubordinateAnnotations PropertyIdentifier = 210 + SubordinateList PropertyIdentifier = 211 + ActualShedLevel PropertyIdentifier = 212 + DutyWindow PropertyIdentifier = 213 + ExpectedShedLevel PropertyIdentifier = 214 + FullDutyBaseline PropertyIdentifier = 215 + RequestedShedLevel PropertyIdentifier = 218 + ShedDuration PropertyIdentifier = 219 + ShedLevelDescriptions PropertyIdentifier = 220 + ShedLevels PropertyIdentifier = 221 + StateDescription PropertyIdentifier = 222 + DoorAlarmState PropertyIdentifier = 226 + DoorExtendedPulseTime PropertyIdentifier = 227 + DoorMembers PropertyIdentifier = 228 + DoorOpenTooLongTime PropertyIdentifier = 229 + DoorPulseTime PropertyIdentifier = 230 + DoorStatus PropertyIdentifier = 231 + DoorUnlockDelayTime PropertyIdentifier = 232 + LockStatus PropertyIdentifier = 233 + MaskedAlarmValues PropertyIdentifier = 234 + SecuredStatus PropertyIdentifier = 235 + AbsenteeLimit PropertyIdentifier = 244 + AccessAlarmEvents PropertyIdentifier = 245 + AccessDoors PropertyIdentifier = 246 + AccessEvent PropertyIdentifier = 247 + AccessEventAuthenticationFactor PropertyIdentifier = 248 + AccessEventCredential PropertyIdentifier = 249 + AccessEventTime PropertyIdentifier = 250 + AccessTransactionEvents PropertyIdentifier = 251 + Accompaniment PropertyIdentifier = 252 + AccompanimentTime PropertyIdentifier = 253 + ActivationTime PropertyIdentifier = 254 + ActiveAuthenticationPolicy PropertyIdentifier = 255 + AssignedAccessRights PropertyIdentifier = 256 + AuthenticationFactors PropertyIdentifier = 257 + AuthenticationPolicyList PropertyIdentifier = 258 + AuthenticationPolicyNames PropertyIdentifier = 259 + AuthenticationStatus PropertyIdentifier = 260 + AuthorizationMode PropertyIdentifier = 261 + BelongsTo PropertyIdentifier = 262 + CredentialDisable PropertyIdentifier = 263 + CredentialStatus PropertyIdentifier = 264 + Credentials PropertyIdentifier = 265 + CredentialsInZone PropertyIdentifier = 266 + DaysRemaining PropertyIdentifier = 267 + EntryPoints PropertyIdentifier = 268 + ExitPoints PropertyIdentifier = 269 + ExpiryTime PropertyIdentifier = 270 + ExtendedTimeEnable PropertyIdentifier = 271 + FailedAttemptEvents PropertyIdentifier = 272 + FailedAttempts PropertyIdentifier = 273 + FailedAttemptsTime PropertyIdentifier = 274 + LastAccessEvent PropertyIdentifier = 275 + LastAccessPoint PropertyIdentifier = 276 + LastCredentialAdded PropertyIdentifier = 277 + LastCredentialAddedTime PropertyIdentifier = 278 + LastCredentialRemoved PropertyIdentifier = 279 + LastCredentialRemovedTime PropertyIdentifier = 280 + LastUseTime PropertyIdentifier = 281 + Lockout PropertyIdentifier = 282 + LockoutRelinquishTime PropertyIdentifier = 283 + MasterExemption PropertyIdentifier = 284 + MaxFailedAttempts PropertyIdentifier = 285 + Members PropertyIdentifier = 286 + MusterPoint PropertyIdentifier = 287 + NegativeAccessRules PropertyIdentifier = 288 + NumberOfAuthenticationPolicies PropertyIdentifier = 289 + OccupancyCount PropertyIdentifier = 290 + OccupancyCountAdjust PropertyIdentifier = 291 + OccupancyCountEnable PropertyIdentifier = 292 + OccupancyExemption PropertyIdentifier = 293 + OccupancyLowerLimit PropertyIdentifier = 294 + OccupancyLowerLimitEnforced PropertyIdentifier = 295 + OccupancyState PropertyIdentifier = 296 + OccupancyUpperLimit PropertyIdentifier = 297 + OccupancyUpperLimitEnforced PropertyIdentifier = 298 + PassbackExemption PropertyIdentifier = 299 + PassbackMode PropertyIdentifier = 300 + PassbackTimeout PropertyIdentifier = 301 + PositiveAccessRules PropertyIdentifier = 302 + ReasonForDisable PropertyIdentifier = 303 + SupportedFormats PropertyIdentifier = 304 + SupportedFormatClasses PropertyIdentifier = 305 + ThreatAuthority PropertyIdentifier = 306 + ThreatLevel PropertyIdentifier = 307 + TraceFlag PropertyIdentifier = 308 + TransactionNotificationClass PropertyIdentifier = 309 + UserExternalIdentifier PropertyIdentifier = 310 + UserInformationReference PropertyIdentifier = 311 + UserName PropertyIdentifier = 317 + UserType PropertyIdentifier = 318 + UsesRemaining PropertyIdentifier = 319 + ZoneFrom PropertyIdentifier = 320 + ZoneTo PropertyIdentifier = 321 + AccessEventTag PropertyIdentifier = 322 + GlobalIdentifier PropertyIdentifier = 323 + VerificationTime PropertyIdentifier = 326 + BaseDeviceSecurityPolicy PropertyIdentifier = 327 + DistributionKeyRevision PropertyIdentifier = 328 + DoNotHide PropertyIdentifier = 329 + KeySets PropertyIdentifier = 330 + LastKeyServer PropertyIdentifier = 331 + NetworkAccessSecurityPolicies PropertyIdentifier = 332 + PacketReorderTime PropertyIdentifier = 333 + SecurityPduTimeout PropertyIdentifier = 334 + SecurityTimeWindow PropertyIdentifier = 335 + SupportedSecurityAlgorithm PropertyIdentifier = 336 + UpdateKeySetTimeout PropertyIdentifier = 337 + BackupAndRestoreState PropertyIdentifier = 338 + BackupPreparationTime PropertyIdentifier = 339 + RestoreCompletionTime PropertyIdentifier = 340 + RestorePreparationTime PropertyIdentifier = 341 + BitMask PropertyIdentifier = 342 + BitText PropertyIdentifier = 343 + IsUtc PropertyIdentifier = 344 + GroupMembers PropertyIdentifier = 345 + GroupMemberNames PropertyIdentifier = 346 + MemberStatusFlags PropertyIdentifier = 347 + RequestedUpdateInterval PropertyIdentifier = 348 + CovuPeriod PropertyIdentifier = 349 + CovuRecipients PropertyIdentifier = 350 + EventMessageTexts PropertyIdentifier = 351 + EventMessageTextsConfig PropertyIdentifier = 352 + EventDetectionEnable PropertyIdentifier = 353 + EventAlgorithmInhibit PropertyIdentifier = 354 + EventAlgorithmInhibitRef PropertyIdentifier = 355 + TimeDelayNormal PropertyIdentifier = 356 + ReliabilityEvaluationInhibit PropertyIdentifier = 357 + FaultParameters PropertyIdentifier = 358 + FaultType PropertyIdentifier = 359 + LocalForwardingOnly PropertyIdentifier = 360 + ProcessIdentifierFilter PropertyIdentifier = 361 + SubscribedRecipients PropertyIdentifier = 362 + PortFilter PropertyIdentifier = 363 + AuthorizationExemptions PropertyIdentifier = 364 + AllowGroupDelayInhibit PropertyIdentifier = 365 + ChannelNumber PropertyIdentifier = 366 + ControlGroups PropertyIdentifier = 367 + ExecutionDelay PropertyIdentifier = 368 + LastPriority PropertyIdentifier = 369 + WriteStatus PropertyIdentifier = 370 + PropertyList PropertyIdentifier = 371 + SerialNumber PropertyIdentifier = 372 + BlinkWarnEnable PropertyIdentifier = 373 + DefaultFadeTime PropertyIdentifier = 374 + DefaultRampRate PropertyIdentifier = 375 + DefaultStepIncrement PropertyIdentifier = 376 + EgressTime PropertyIdentifier = 377 + InProgress PropertyIdentifier = 378 + InstantaneousPower PropertyIdentifier = 379 + LightingCommand PropertyIdentifier = 380 + LightingCommandDefaultPriority PropertyIdentifier = 381 + MaxActualValue PropertyIdentifier = 382 + MinActualValue PropertyIdentifier = 383 + Power PropertyIdentifier = 384 + Transition PropertyIdentifier = 385 + EgressActive PropertyIdentifier = 386 + InterfaceValue PropertyIdentifier = 387 + FaultHighLimit PropertyIdentifier = 388 + FaultLowLimit PropertyIdentifier = 389 + LowDiffLimit PropertyIdentifier = 390 + StrikeCount PropertyIdentifier = 391 + TimeOfStrikeCountReset PropertyIdentifier = 392 + DefaultTimeout PropertyIdentifier = 393 + InitialTimeout PropertyIdentifier = 394 + LastStateChange PropertyIdentifier = 395 + StateChangeValues PropertyIdentifier = 396 + TimerRunning PropertyIdentifier = 397 + TimerState PropertyIdentifier = 398 + ApduLength PropertyIdentifier = 399 + IpAddress PropertyIdentifier = 400 + IpDefaultGateway PropertyIdentifier = 401 + IpDhcpEnable PropertyIdentifier = 402 + IpDhcpLeaseTime PropertyIdentifier = 403 + IpDhcpLeaseTimeRemaining PropertyIdentifier = 404 + IpDhcpServer PropertyIdentifier = 405 + IpDnsServer PropertyIdentifier = 406 + BacnetIpGlobalAddress PropertyIdentifier = 407 + BacnetIpMode PropertyIdentifier = 408 + BacnetIpMulticastAddress PropertyIdentifier = 409 + BacnetIpNatTraversal PropertyIdentifier = 410 + IpSubnetMask PropertyIdentifier = 411 + BacnetIpUdpPort PropertyIdentifier = 412 + BbmdAcceptFdRegistrations PropertyIdentifier = 413 + BbmdBroadcastDistributionTable PropertyIdentifier = 414 + BbmdForeignDeviceTable PropertyIdentifier = 415 + ChangesPending PropertyIdentifier = 416 + Command PropertyIdentifier = 417 + FdBbmdAddress PropertyIdentifier = 418 + FdSubscriptionLifetime PropertyIdentifier = 419 + LinkSpeed PropertyIdentifier = 420 + LinkSpeeds PropertyIdentifier = 421 + LinkSpeedAutonegotiate PropertyIdentifier = 422 + MacAddress PropertyIdentifier = 423 + NetworkInterfaceName PropertyIdentifier = 424 + NetworkNumber PropertyIdentifier = 425 + NetworkNumberQuality PropertyIdentifier = 426 + NetworkType PropertyIdentifier = 427 + RoutingTable PropertyIdentifier = 428 + VirtualMacAddressTable PropertyIdentifier = 429 + CommandTimeArray PropertyIdentifier = 430 + CurrentCommandPriority PropertyIdentifier = 431 + LastCommandTime PropertyIdentifier = 432 + ValueSource PropertyIdentifier = 433 + ValueSourceArray PropertyIdentifier = 434 + BacnetIpv6Mode PropertyIdentifier = 435 + Ipv6Address PropertyIdentifier = 436 + Ipv6PrefixLength PropertyIdentifier = 437 + BacnetIpv6UdpPort PropertyIdentifier = 438 + Ipv6DefaultGateway PropertyIdentifier = 439 + BacnetIpv6MulticastAddress PropertyIdentifier = 440 + Ipv6DnsServer PropertyIdentifier = 441 + Ipv6AutoAddressingEnable PropertyIdentifier = 442 + Ipv6DhcpLeaseTime PropertyIdentifier = 443 + Ipv6DhcpLeaseTimeRemaining PropertyIdentifier = 444 + Ipv6DhcpServer PropertyIdentifier = 445 + Ipv6ZoneIndex PropertyIdentifier = 446 + AssignedLandingCalls PropertyIdentifier = 447 + CarAssignedDirection PropertyIdentifier = 448 + CarDoorCommand PropertyIdentifier = 449 + CarDoorStatus PropertyIdentifier = 450 + CarDoorText PropertyIdentifier = 451 + CarDoorZone PropertyIdentifier = 452 + CarDriveStatus PropertyIdentifier = 453 + CarLoad PropertyIdentifier = 454 + CarLoadUnits PropertyIdentifier = 455 + CarMode PropertyIdentifier = 456 + CarMovingDirection PropertyIdentifier = 457 + CarPosition PropertyIdentifier = 458 + ElevatorGroup PropertyIdentifier = 459 + EnergyMeter PropertyIdentifier = 460 + EnergyMeterRef PropertyIdentifier = 461 + EscalatorMode PropertyIdentifier = 462 + FloorText PropertyIdentifier = 464 + GroupId PropertyIdentifier = 465 + GroupMode PropertyIdentifier = 467 + HigherDeck PropertyIdentifier = 468 + InstallationId PropertyIdentifier = 469 + LandingCalls PropertyIdentifier = 470 + LandingCallControl PropertyIdentifier = 471 + LandingDoorStatus PropertyIdentifier = 472 + LowerDeck PropertyIdentifier = 473 + MachineRoomId PropertyIdentifier = 474 + MakingCarCall PropertyIdentifier = 475 + NextStoppingFloor PropertyIdentifier = 476 + OperationDirection PropertyIdentifier = 477 + PassengerAlarm PropertyIdentifier = 478 + PowerMode PropertyIdentifier = 479 + RegisteredCarCall PropertyIdentifier = 480 + ActiveCovMultipleSubscriptions PropertyIdentifier = 481 + ProtocolLevel PropertyIdentifier = 482 + ReferencePort PropertyIdentifier = 483 + DeployedProfileLocation PropertyIdentifier = 484 + ProfileLocation PropertyIdentifier = 485 + Tags PropertyIdentifier = 486 + SubordinateNodeTypes PropertyIdentifier = 487 + SubordinateRelationships PropertyIdentifier = 489 + SubordinateTags PropertyIdentifier = 488 + DefaultSubordinateRelationship PropertyIdentifier = 490 + Represents PropertyIdentifier = 491 + DefaultPresentValue PropertyIdentifier = 492 + PresentStage PropertyIdentifier = 493 + Stages PropertyIdentifier = 494 + StageNames PropertyIdentifier = 495 + TargetReferences PropertyIdentifier = 496 + FaultSignals PropertyIdentifier = 463 +) + +type BACnetSegmentation int + +const ( + SEGMENTED_BOTH BACnetSegmentation = iota + SEGMENTED_TRANSMIT + SEGMENTED_RECEIVE + NO_SEGMENTATION +) + +type BACnetEventType int + +const ( + ChangeOfBitstring BACnetEventType = 0 + ChangeOfState BACnetEventType = 1 + ChangeOfValue BACnetEventType = 2 + CommandFailure BACnetEventType = 3 + FloatingLimit BACnetEventType = 4 + OutOfRange BACnetEventType = 5 + Complex BACnetEventType = 6 + ChangeOfLifeSafety BACnetEventType = 8 + Extended BACnetEventType = 9 + BufferReady BACnetEventType = 10 + UnsignedRange BACnetEventType = 11 + BACnetEventTypeAccessEvent BACnetEventType = 13 + DoubleOutOfRange BACnetEventType = 14 + SignedOutOfRange BACnetEventType = 15 + UnsignedOutOfRange BACnetEventType = 16 + ChangeOfCharacterstring BACnetEventType = 17 + ChangeOfStatusFlag BACnetEventType = 18 + ChangeOfReliability BACnetEventType = 19 + None BACnetEventType = 20 + ChangeOfDiscreteValue BACnetEventType = 21 + ChangeOfTimer BACnetEventType = 22 +) + +type BACnetFaultType int + +const ( + BacnetFaultTypeNone BACnetFaultType = iota + FaultCHARACTERSTRING + FaultEXTENDED + FaultLIFE_SAFETY + FaultSTATE + FaultStatusFlags + FaultOutOfRange + FaultListed +) + +type BACnetNotifyType int + +const ( + ALARM BACnetNotifyType = iota + EVENT + ACK_NOTIFICATION +) + +type BACnetEventState int + +const ( + Normal BACnetEventState = iota + Fault + OffNormal + BACnetEventStateHighLimit + BACnetEventStateLowLimit + LifeSafetyAlarm +) + +type BACnetAccessCredentialDisableReason int + +const ( + Disabled BACnetAccessCredentialDisableReason = iota + DisabledNeedsProvisioning + DisabledUnassigned + DisabledNotYetActive + DisabledExpired + DisabledLockout + DisabledMaxDays + DisabledMaxUses + DisabledInactivity + DisabledManual +) + +type BACnetAccessCredentialDisable int + +const ( + BACnetAccessCredentialDisableNone BACnetAccessCredentialDisable = iota + Disable + DisableManual + DisableLockout +) + +type BACnetAccessPassbackMode int + +const ( + PassbackOff BACnetAccessPassbackMode = iota + HardPassback + SoftPassback +) + +type BACnetAccessUserType int + +const ( + Asset BACnetAccessUserType = iota + BACnetAccessUserTypeGroup + Person +) + +type BACnetAccessZoneOccupancyState int + +const ( + BACnetAccessZoneOccupancyStateNormal BACnetAccessZoneOccupancyState = iota + BelowLowerLimit + AtLowerLimit + AtUpperLimit + AboveUpperLimit + BACnetAccessZoneOccupancyStateDisabled + NotSupported +) + +type BACnetAction int + +const ( + Direct BACnetAction = iota + Reverse +) + +type BACnetNetworkNumberQuality int + +const ( + Unknown BACnetNetworkNumberQuality = iota + Learned + LearnedConfigured + Configured +) + +type BACnetBinaryPV int + +const ( + Inactive BACnetBinaryPV = iota + Active +) + +type BACnetDoorValue int + +const ( + Lock BACnetDoorValue = iota + Unlock + PulseUnlock + ExtendedPulseUnlock +) + +type BACnetAuthenticationStatus int + +const ( + NotReady BACnetAuthenticationStatus = iota + Ready + BACnetAuthenticationStatusDisabled + WaitingForAuthenticationFactor + WaitingForAccompaniment + WaitingForVerification + BACnetAuthenticationStatusInProgress +) + +type BACnetAuthorizationExemption int + +const ( + Passback BACnetAuthorizationExemption = iota + OccupancyCheck + BACnetAuthorizationExemptionAccessRights + BACnetAuthorizationExemptionLockout + Deny + Verification + AuthorizationDelay +) + +type BACnetAuthorizationMode int + +const ( + Authorize BACnetAuthorizationMode = iota + GrantActive + DenyAll + VerificationRequired + AuthorizationDelayed + BACnetAuthorizationModeNone +) + +type BACnetBackupState int + +const ( + Idle BACnetBackupState = iota + PreparingForBackup + PreparingForRestor + PerformingABACKUP + PerformingARestor +) + +type BACnetBinaryLightingPV int + +const ( + Off BACnetBinaryLightingPV = iota + On + Warn + WarnOff + WarnRelinquish + Stop +) + +type BACnetDeviceStatus int + +const ( + Operational BACnetDeviceStatus = iota + OperationalReadOnly + DownloadRequired + DownloadInProgress + NonOperational + BackupInProgress +) + +type BACnetDoorAlarmState int + +const ( + BACnetDoorAlarmStateNormal BACnetDoorAlarmState = iota + Alarm + DoorOpenTooLong + ForcedOpen + Tamper + DoorFault + LockDown + FreeAccess + EgressOpen +) + +type BACnetDoorSecuredStatus int + +const ( + Secured BACnetDoorSecuredStatus = iota + UNSecured + BACnetDoorSecuredStatusUnknown +) + +type BACnetDoorStatus int + +const ( + CLOSED BACnetDoorStatus = iota + OPENED + UNKNOWN + DOOR_FAULT + UNUSED + NONE + CLOSING + OPENING + SAFETY_LOCKED + LIMITED_OPENED +) + +type BACnetEngineeringUnits int + +const ( + metersPerSecondPerSecond BACnetEngineeringUnits = 166 + SquareMeters BACnetEngineeringUnits = 0 + SquareCentimeters BACnetEngineeringUnits = 116 + SquareFeet BACnetEngineeringUnits = 1 + SquareInches BACnetEngineeringUnits = 115 + Currency1 BACnetEngineeringUnits = 105 + Currency2 BACnetEngineeringUnits = 106 + Currency3 BACnetEngineeringUnits = 107 + Currency4 BACnetEngineeringUnits = 108 + Currency5 BACnetEngineeringUnits = 109 + Currency6 BACnetEngineeringUnits = 110 + Currency7 BACnetEngineeringUnits = 111 + Currency8 BACnetEngineeringUnits = 112 + Currency9 BACnetEngineeringUnits = 113 + Currency10 BACnetEngineeringUnits = 114 + Milliamperes BACnetEngineeringUnits = 2 + Amperes BACnetEngineeringUnits = 3 + AmperesPerMeter BACnetEngineeringUnits = 167 + AmperesPerSquareMeter BACnetEngineeringUnits = 168 + AmpereSquareMeters BACnetEngineeringUnits = 169 + Decibels BACnetEngineeringUnits = 199 + DecibelsMillivolt BACnetEngineeringUnits = 200 + DecibelsVolt BACnetEngineeringUnits = 201 + Farads BACnetEngineeringUnits = 170 + Henrys BACnetEngineeringUnits = 171 + Ohms BACnetEngineeringUnits = 4 + OhmMeters BACnetEngineeringUnits = 172 + Milliohms BACnetEngineeringUnits = 145 + Kilohms BACnetEngineeringUnits = 122 + Megohms BACnetEngineeringUnits = 123 + Microsiemens BACnetEngineeringUnits = 190 + Millisiemens BACnetEngineeringUnits = 202 + Siemens BACnetEngineeringUnits = 173 + SiemensPerMeter BACnetEngineeringUnits = 174 + Teslas BACnetEngineeringUnits = 175 + Volts BACnetEngineeringUnits = 5 + Millivolts BACnetEngineeringUnits = 124 + Kilovolts BACnetEngineeringUnits = 6 + Megavolts BACnetEngineeringUnits = 7 + VoltAmperes BACnetEngineeringUnits = 8 + KilovoltAmperes BACnetEngineeringUnits = 9 + MegavoltAmperes BACnetEngineeringUnits = 10 + VoltAmperesReactive BACnetEngineeringUnits = 11 + KilovoltAmperesReactive BACnetEngineeringUnits = 12 + MegavoltAmperesReactive BACnetEngineeringUnits = 13 + VoltsPerDegreeKelvin BACnetEngineeringUnits = 176 + VoltsPerMeter BACnetEngineeringUnits = 177 + DegreesPhase BACnetEngineeringUnits = 14 + PowerFactor BACnetEngineeringUnits = 15 + Webers BACnetEngineeringUnits = 178 + Joules BACnetEngineeringUnits = 16 + Kilojoules BACnetEngineeringUnits = 17 + KilojoulesPerKilogram BACnetEngineeringUnits = 125 + Megajoules BACnetEngineeringUnits = 126 + WattHours BACnetEngineeringUnits = 18 + KilowattHours BACnetEngineeringUnits = 19 + MegawattHours BACnetEngineeringUnits = 146 + WattHoursReactive BACnetEngineeringUnits = 203 + KilowattHoursReactive BACnetEngineeringUnits = 204 + MegawattHoursReactive BACnetEngineeringUnits = 205 + Btus BACnetEngineeringUnits = 20 + KiloBtus BACnetEngineeringUnits = 147 + MegaBtus BACnetEngineeringUnits = 148 + Therms BACnetEngineeringUnits = 21 + TonHours BACnetEngineeringUnits = 22 + JoulesPerKilogramDryAir BACnetEngineeringUnits = 23 + KilojoulesPerKilogramDryAir BACnetEngineeringUnits = 149 + MegajoulesPerKilogramDryAir BACnetEngineeringUnits = 150 + BtusPerPoundDryAir BACnetEngineeringUnits = 24 + BtusPerPound BACnetEngineeringUnits = 117 + JoulesPerDegreeKelvin BACnetEngineeringUnits = 127 + KilojoulesPerDegreeKelvin BACnetEngineeringUnits = 151 + MegajoulesPerDegreeKelvin BACnetEngineeringUnits = 152 + JoulesPerKilogramDegreeKelvin BACnetEngineeringUnits = 128 + Newton BACnetEngineeringUnits = 153 + CyclesPerHour BACnetEngineeringUnits = 25 + CyclesPerMinute BACnetEngineeringUnits = 26 + Hertz BACnetEngineeringUnits = 27 + Kilohertz BACnetEngineeringUnits = 129 + Megahertz BACnetEngineeringUnits = 130 + PerHour BACnetEngineeringUnits = 131 + GramsOfWaterPerKilogramDryAir BACnetEngineeringUnits = 28 + PercentRelativeHumidity BACnetEngineeringUnits = 29 + Micrometers BACnetEngineeringUnits = 194 + Millimeters BACnetEngineeringUnits = 30 + Centimeters BACnetEngineeringUnits = 118 + Kilometers BACnetEngineeringUnits = 193 + Meters BACnetEngineeringUnits = 31 + Inches BACnetEngineeringUnits = 32 + Feet BACnetEngineeringUnits = 33 + Candelas BACnetEngineeringUnits = 179 + CandelasPerSquareMeter BACnetEngineeringUnits = 180 + WattsPerSquareFoot BACnetEngineeringUnits = 34 + WattsPerSquareMeter BACnetEngineeringUnits = 35 + Lumens BACnetEngineeringUnits = 36 + Luxes BACnetEngineeringUnits = 37 + FootCandles BACnetEngineeringUnits = 38 + Milligrams BACnetEngineeringUnits = 196 + Grams BACnetEngineeringUnits = 195 + Kilograms BACnetEngineeringUnits = 39 + PoundsMass BACnetEngineeringUnits = 40 + Tons BACnetEngineeringUnits = 41 + GramsPerSecond BACnetEngineeringUnits = 154 + GramsPerMinute BACnetEngineeringUnits = 155 + KilogramsPerSecond BACnetEngineeringUnits = 42 + KilogramsPerMinute BACnetEngineeringUnits = 43 + KilogramsPerHour BACnetEngineeringUnits = 44 + PoundsMassPerSecond BACnetEngineeringUnits = 119 + PoundsMassPerMinute BACnetEngineeringUnits = 45 + PoundsMassPerHour BACnetEngineeringUnits = 46 + TonsPerHour BACnetEngineeringUnits = 156 + Milliwatts BACnetEngineeringUnits = 132 + Watts BACnetEngineeringUnits = 47 + Kilowatts BACnetEngineeringUnits = 48 + Megawatts BACnetEngineeringUnits = 49 + BtusPerHour BACnetEngineeringUnits = 50 + KiloBtusPerHour BACnetEngineeringUnits = 157 + Horsepower BACnetEngineeringUnits = 51 + TonsRefrigeration BACnetEngineeringUnits = 52 + Pascals BACnetEngineeringUnits = 53 + Hectopascals BACnetEngineeringUnits = 133 + Kilopascals BACnetEngineeringUnits = 54 + Millibars BACnetEngineeringUnits = 134 + Bars BACnetEngineeringUnits = 55 + PoundsForcePerSquareInch BACnetEngineeringUnits = 56 + MillimetersOfWater BACnetEngineeringUnits = 206 + CentimetersOfWater BACnetEngineeringUnits = 57 + InchesOfWater BACnetEngineeringUnits = 58 + MillimetersOfMercury BACnetEngineeringUnits = 59 + CentimetersOfMercury BACnetEngineeringUnits = 60 + InchesOfMercury BACnetEngineeringUnits = 61 + DegreesCelsius BACnetEngineeringUnits = 62 + DegreesKelvin BACnetEngineeringUnits = 63 + DegreesKelvinPerHour BACnetEngineeringUnits = 181 + DegreesKelvinPerMinute BACnetEngineeringUnits = 182 + DegreesFahrenheit BACnetEngineeringUnits = 64 + DegreeDaysCelsius BACnetEngineeringUnits = 65 + DegreeDaysFahrenheit BACnetEngineeringUnits = 66 + DeltaDegreesFahrenheit BACnetEngineeringUnits = 120 + DeltaDegreesKelvin BACnetEngineeringUnits = 121 + Years BACnetEngineeringUnits = 67 + Months BACnetEngineeringUnits = 68 + Weeks BACnetEngineeringUnits = 69 + Days BACnetEngineeringUnits = 70 + Hours BACnetEngineeringUnits = 71 + Minutes BACnetEngineeringUnits = 72 + Seconds BACnetEngineeringUnits = 73 + HundredthsSeconds BACnetEngineeringUnits = 158 + Milliseconds BACnetEngineeringUnits = 159 + NewtonMeters BACnetEngineeringUnits = 160 + MillimetersPerSecond BACnetEngineeringUnits = 161 + MillimetersPerMinute BACnetEngineeringUnits = 162 + MetersPerSecond BACnetEngineeringUnits = 74 + MetersPerMinute BACnetEngineeringUnits = 163 + MetersPerHour BACnetEngineeringUnits = 164 + KilometersPerHour BACnetEngineeringUnits = 75 + FeetPerSecond BACnetEngineeringUnits = 76 + FeetPerMinute BACnetEngineeringUnits = 77 + MilesPerHour BACnetEngineeringUnits = 78 + CubicFeet BACnetEngineeringUnits = 79 + CubicMeters BACnetEngineeringUnits = 80 + ImperialGallons BACnetEngineeringUnits = 81 + Milliliters BACnetEngineeringUnits = 197 + Liters BACnetEngineeringUnits = 82 + UsGallons BACnetEngineeringUnits = 83 + CubicFeetPerSecond BACnetEngineeringUnits = 142 + CubicFeetPerMinute BACnetEngineeringUnits = 84 + MillionCubicFeetPerMinute BACnetEngineeringUnits = 254 + CubicFeetPerHour BACnetEngineeringUnits = 191 + StandardCubicFeetPerDay BACnetEngineeringUnits = 47808 + MillionStandardCubicFeetPerDay BACnetEngineeringUnits = 47809 + ThousandCubicFeetPerDay BACnetEngineeringUnits = 47810 + ThousandStandardCubicFeetPerDay BACnetEngineeringUnits = 47811 + PoundsMassPerDay BACnetEngineeringUnits = 47812 + CubicMetersPerSecond BACnetEngineeringUnits = 85 + CubicMetersPerMinute BACnetEngineeringUnits = 165 + CubicMetersPerHour BACnetEngineeringUnits = 135 + ImperialGallonsPerMinute BACnetEngineeringUnits = 86 + MillilitersPerSecond BACnetEngineeringUnits = 198 + LitersPerSecond BACnetEngineeringUnits = 87 + LitersPerMinute BACnetEngineeringUnits = 88 + LitersPerHour BACnetEngineeringUnits = 136 + UsGallonsPerMinute BACnetEngineeringUnits = 89 + UsGallonsPerHour BACnetEngineeringUnits = 192 + DegreesAngular BACnetEngineeringUnits = 90 + DegreesCelsiusPerHour BACnetEngineeringUnits = 91 + DegreesCelsiusPerMinute BACnetEngineeringUnits = 92 + DegreesFahrenheitPerHour BACnetEngineeringUnits = 93 + DegreesFahrenheitPerMinute BACnetEngineeringUnits = 94 + JouleSeconds BACnetEngineeringUnits = 183 + KilogramsPerCubicMeter BACnetEngineeringUnits = 186 + KwHoursPerSquareMeter BACnetEngineeringUnits = 137 + KwHoursPerSquareFoot BACnetEngineeringUnits = 138 + MegajoulesPerSquareMeter BACnetEngineeringUnits = 139 + MegajoulesPerSquareFoot BACnetEngineeringUnits = 140 + NoUnits BACnetEngineeringUnits = 95 + NewtonSeconds BACnetEngineeringUnits = 187 + NewtonsPerMeter BACnetEngineeringUnits = 188 + PartsPerMillion BACnetEngineeringUnits = 96 + PartsPerBillion BACnetEngineeringUnits = 97 + Percent BACnetEngineeringUnits = 98 + PercentObscurationPerFoot BACnetEngineeringUnits = 143 + PercentObscurationPerMeter BACnetEngineeringUnits = 144 + PercentPerSecond BACnetEngineeringUnits = 99 + PerMinute BACnetEngineeringUnits = 100 + PerSecond BACnetEngineeringUnits = 101 + PsiPerDegreeFahrenheit BACnetEngineeringUnits = 102 + Radians BACnetEngineeringUnits = 103 + RadiansPerSecond BACnetEngineeringUnits = 184 + RevolutionsPerMinute BACnetEngineeringUnits = 104 + SquareMetersPerNewton BACnetEngineeringUnits = 185 + WattsPerMeterPerDegreeKelvin BACnetEngineeringUnits = 189 + WattsPerSquareMeterDegreeKelvin BACnetEngineeringUnits = 141 + PerMille BACnetEngineeringUnits = 207 + GramsPerGram BACnetEngineeringUnits = 208 + KilogramsPerKilogram BACnetEngineeringUnits = 209 + GramsPerKilogram BACnetEngineeringUnits = 210 + MilligramsPerGram BACnetEngineeringUnits = 211 + MilligramsPerKilogram BACnetEngineeringUnits = 212 + GramsPerMilliliter BACnetEngineeringUnits = 213 + GramsPerLiter BACnetEngineeringUnits = 214 + MilligramsPerLiter BACnetEngineeringUnits = 215 + MicrogramsPerLiter BACnetEngineeringUnits = 216 + GramsPerCubicMeter BACnetEngineeringUnits = 217 + MilligramsPerCubicMeter BACnetEngineeringUnits = 218 + MicrogramsPerCubicMeter BACnetEngineeringUnits = 219 + NanogramsPerCubicMeter BACnetEngineeringUnits = 220 + GramsPerCubicCentimeter BACnetEngineeringUnits = 221 + Becquerels BACnetEngineeringUnits = 222 + Kilobecquerels BACnetEngineeringUnits = 223 + Megabecquerels BACnetEngineeringUnits = 224 + Gray BACnetEngineeringUnits = 225 + Milligray BACnetEngineeringUnits = 226 + Microgray BACnetEngineeringUnits = 227 + Sieverts BACnetEngineeringUnits = 228 + Millisieverts BACnetEngineeringUnits = 229 + Microsieverts BACnetEngineeringUnits = 230 + MicrosievertsPerHour BACnetEngineeringUnits = 231 + Millirems BACnetEngineeringUnits = 47814 + MilliremsPerHour BACnetEngineeringUnits = 47815 + DecibelsA BACnetEngineeringUnits = 232 + NephelometricTurbidityUnit BACnetEngineeringUnits = 233 + Ph BACnetEngineeringUnits = 234 + GramsPerSquareMeter BACnetEngineeringUnits = 235 + MinutesPerDegreeKelvin BACnetEngineeringUnits = 236 + MeterSquaredPerMeter BACnetEngineeringUnits = 237 + AmpereSeconds BACnetEngineeringUnits = 238 + VoltAmpereHours BACnetEngineeringUnits = 239 + KilovoltAmpereHours BACnetEngineeringUnits = 240 + MegavoltAmpereHours BACnetEngineeringUnits = 241 + VoltAmpereHoursReactive BACnetEngineeringUnits = 242 + KilovoltAmpereHoursReactive BACnetEngineeringUnits = 243 + MegavoltAmpereHoursReactive BACnetEngineeringUnits = 244 + VoltSquareHours BACnetEngineeringUnits = 245 + AmpereSquareHours BACnetEngineeringUnits = 246 + JoulePerHours BACnetEngineeringUnits = 247 + CubicFeetPerDay BACnetEngineeringUnits = 248 + CubicMetersPerDay BACnetEngineeringUnits = 249 + WattHoursPerCubicMeter BACnetEngineeringUnits = 250 + JoulesPerCubicMeter BACnetEngineeringUnits = 251 + MolePercent BACnetEngineeringUnits = 252 + PascalSeconds BACnetEngineeringUnits = 253 + MillionStandardCubicFeetPerMinute BACnetEngineeringUnits = 254 +) + +type BACnetEscalatorMode int + +const ( + BacnetescalatorModeUnknown BACnetEscalatorMode = iota + BacnetescalatorModeStop + BACnetEscalatorModeUp + BACnetEscalatorModeDown + BACnetEscalatorModeInspection + BacnetescalatorModeOutOfService +) + +type BACnetEscalatorOperationDirection int + +const ( + BacnetEscalatorOperationDirectionUnknown BACnetEscalatorOperationDirection = iota + BACnetEscalatorOperationDirectionStopped + UpRatedSpeed + UpReducedSpeed + DownRatedSpeed + DownReducedSpeed +) + +type BACnetFileAccessMethod int + +const ( + RecordAccess BACnetFileAccessMethod = iota + StreamAccess +) + +type BACnetIPMode int + +const ( + BacnetIPModeNormal BACnetIPMode = iota + Foreign + Bbmd +) + +type BACnetLifeSafetyMode int + +const ( + BacnetLifeSafetyModeOff BACnetLifeSafetyMode = iota + Lon + Test + Manned + Unmanned + Armed + Disarmed + Prearmed + Slow + Fast + Disconnected + Enabled + BacnetLifeSafetyModeDisabled + AutomaticReleaseDisabled + Default +) + +type BACnetLifeSafetyOperation int + +const ( + BacnetLifeSafetyOperationNone BACnetLifeSafetyOperation = iota + Silence + SilenceAudible + SilenceVisual + Reset + ResetAlarm + ResetFault + Unsilence + UnsilenceAudible + UnsilenceVisual +) + +type BACnetLifeSafetyState int + +const ( + Quiet BACnetLifeSafetyState = iota + PreAlarm + BacnetlifesafetystateAlarm + BacnetlifesafetystateFault + FaultPreAlarm + FaultAlarm + BacnetlifesafetystateNotReady + BacnetlifesafetystateActive + BacnetlifesafetystateTamper + TestAlarm + TestActive + TestFault + TestFaultAlarm + Holdup + Duress + TamperAlarm + Abnormal + BacnetlifesafetystateEmergencyPower + Delayed + Blocked + LocalAlarm + GeneralAlarm + Supervisory + TestSupervisory +) + +type BACnetLiftCarDirection int + +const ( + BacnetliftcardirectionUnknown BACnetLiftCarDirection = iota + BacnetliftcardirectionNone + Stopped + Up + Down + UpAndDown +) + +type BACnetLiftCarDoorCommand int + +const ( + BACnetLiftCarDoorCommandNone BACnetLiftCarDoorCommand = iota + Open + Close +) + +type BACnetLiftCarDriveStatus int + +const ( + BACnetLiftCarDriveStatusUnknown BACnetLiftCarDriveStatus = iota + Stationary + Braking + Accelerate + Decelerate + RatedSpeed + SingleFloorJump + TwoFloorJump + ThreeFloorJump + MultiFloorJump +) + +type BACnetLiftCarMode int + +const ( + BACnetLiftCarModeUnknown BACnetLiftCarMode = iota + BACnetLiftCarModeNormal + Vip + Homing + Parking + AttendantControl + FirefighterControl + BACnetLiftCarModeEmergencyPower + Inspection + CabinetRecall + EarthquakeOperation + FireOperation + BACnetLiftCarModeOutOfService + OccupantEvacuation +) + +type BACnetLiftFault int + +const ( + ControllerFault BACnetLiftFault = iota + DriveAndMotorFault + GovernorAndSafetyGearFault + LiftShaftDeviceFault + PowerSupplyFault + SafetyInterlockFault + DoorClosingFault + DoorOpeningFault + CarStoppedOutsideLandingZone + CallButtonStuck + StartFailure + ControllerSupplyFault + SelfTestFailure + RuntimeLimitExceeded + PositionLost + DriveTemperatureExceeded + LoadMeasurementFault +) + +type BACnetLiftGroupMode int + +const ( + BACnetLiftGroupModeUnknown BACnetLiftGroupMode = iota + BACnetLiftGroupModeNormal + DownPeak + TwoWay + FourWay + EmergencyPower + UpPeak +) + +type BACnetLoggingType int + +const ( + Polled BACnetLoggingType = iota + Cov + Triggered +) + +type BACnetMaintenance int + +const ( + BACnetMaintenanceNone BACnetMaintenance = iota + PeriodicTest + NeedServiceOperational + NeedServiceInoperative +) + +type BACnetNetworkPortCommand int + +const ( + BACnetNetworkPortCommandIdle BACnetNetworkPortCommand = iota + DiscardChanges + RenewFdRegistration + RestartSlaveDiscovery + RenewDhcp + RestartAutonegotiation + Disconnect + RestartPort +) + +type BACnetNodeType int + +const ( + BACnetNodeTypeUnknown BACnetNodeType = iota + System + Network + BACnetNodeTypeDevice + Organizational + Area + Equipment + Point + Collection + BACnetNodeTypeProperty + Functional + BACnetNodeTypeOther + Subsystem + Building + Floor + Section + Module + Tree + Member + Protocol + Room + Zone +) + +type BACnetRelationship int + +const ( + BACnetRelationshipUnknown BACnetRelationship = iota + BACnetRelationshipDefault + Contains + ContainedBy + Uses + UsedBy + Commands + CommandedBy + Adjusts + AdjustedBy + Ingress + Egress + SuppliesAir + ReceivesAir + SuppliesHotAir + ReceivesHotAir + SuppliesCoolAir + ReceivesCoolAir + SuppliesPower + ReceivesPower + SuppliesGas + ReceivesGas + SuppliesWater + ReceivesWater + SuppliesHotWater + ReceivesHotWater + SuppliesCoolWater + ReceivesCoolWater + SuppliesSteam + ReceivesSteam +) + +type BACnetReliability int + +const ( + NoFaultDetected BACnetReliability = iota + NoSensor + OverRange + UnderRange + OpenLoop + ShortedLoop + NoOutput + UnreliableOther + ProcessError + MultiStateFault + ConfigurationError + CommunicationFailure BACnetReliability = iota + 1 + MemberFault + MonitoredObjectFault + Tripped + LampFailure + ActivationFailure + RenewDhcpFailure + RenewFdRegistrationFailure + RestartAutoNegotiationFailure + RestartFailure + ProprietaryCommandFailure + FaultsListed + ReferencedObjectFault +) + +type BACnetRestartReason int + +const ( + BACnetRestartReasonUnknown BACnetRestartReason = iota + ColdStart + WarmStart + DetectedPowerLost + DetectedPowerOff + HardwareWatchdog + SoftwareWatchdog + Suspended +) + +type BACnetSecurityLevel int + +const ( + Incapable BACnetSecurityLevel = iota + Plain + Signed + Encrypted + SignedEndToEnd + EncryptedEndToEnd +) + +type BACnetPolarity int + +const ( + BACnetPolarityNormal BACnetPolarity = iota + BACnetPolarityReverse +) + +type BACnetProtocolLevel int + +const ( + Physical BACnetProtocolLevel = iota + BACnetProtocolLevelProtocol + BACnetApplication + NonBACnetApplication +) + +type BACnetSilencedState int + +const ( + Unsilenced BACnetSilencedState = iota + AudibleSilenced + VisibleSilenced + AllSilenced +) + +type BACnetTimerState int + +const ( + BACnetTimerStateIdle BACnetTimerState = iota + Running + Expired +) + +type BACnetTimerTransition int + +const ( + BACnetTimerTransitionNone BACnetTimerTransition = iota + IdleToRunning + RunningToIdle + RunningToRunning + RunningToExpired + ForcedToExpired + ExpiredToIdle + ExpiredToRunning +) + +type BACnetVTClass int + +const ( + DefaultTerminal BACnetVTClass = iota + ANSI_X3_64 + DEC_VT52 + DEC_VT100 + DEC_VT220 + HP_700_94 + IBM_3130 +) + +type BACnetAccessEvent int + +const ( + BACnetAccessEventNone BACnetAccessEvent = iota + Granted + Muster + PassbackDetected + BACnetAccessEventDuress + Trace + LockoutMaxAttempts + LockoutOther + LockoutRelinquished + LockedByHigherPriority + BACnetAccessEventOutOfService + OutOfServiceRelinquished + AccompanimentBy + AuthenticationFactorRead + BACnetAccessEventAuthorizationDelayed + BACnetAccessEventVerificationRequired + NoEntryAfterGrant + DeniedDenyAll BACnetAccessEvent = iota + 111 + DeniedUnknownCredential + DeniedAuthenticationUnavailable + DeniedAuthenticationFactorTimeout + DeniedIncorrectAuthenticationFactor + DeniedZoneNoAccessRights + DeniedPointNoAccessRights + DeniedNoAccessRights + DeniedOutOfTimeRange + DeniedThreatLevel + DeniedPassback + DeniedUnexpectedLocationUsage + DeniedMaxAttempts + DeniedLowerOccupancyLimit + DeniedUpperOccupancyLimit + DeniedAuthenticationFactorLost + DeniedAuthenticationFactorStolen + DeniedAuthenticationFactorDamaged + DeniedAuthenticationFactorDestroyed + DeniedAuthenticationFactorDisabled + DeniedAuthenticationFactorError + DeniedCredentialUnassigned + DeniedCredentialNotProvisioned + DeniedCredentialNotYetActive + DeniedCredentialExpired + DeniedCredentialManualDisable + DeniedCredentialLockout + DeniedCredentialMaxDays + DeniedCredentialMaxUses + DeniedCredentialInactivity + DeniedCredentialDisabled + DeniedNoAccompaniment + DeniedIncorrectAccompaniment + DeniedLockout + DeniedVerificationFailed + DeniedVerificationTimeout + DeniedOther +) + +type BACnetLightingInProgress int + +const ( + BACnetLightingInProgressIdle BACnetLightingInProgress = iota + FadeActive + RampActive + NotControlled + BACnetLightingInProgressOther +) + +type BACnetLightingOperation int + +const ( + BACnetLightingOperationNone BACnetLightingOperation = iota + FadeTo + RampTo + StepUp + StepDown + StepOn + StepOff + BACnetLightingOperationWarn + BACnetLightingOperationWarnOff + BACnetLightingOperationWarnRelinquish + BACnetLightingOperationStop +) + +type BACnetLightingTransition int + +const ( + BACnetLightingTransitionNone BACnetLightingTransition = iota + Fade + Ramp +) + +type BACnetLockStatus int + +const ( + Locked BACnetLockStatus = iota + Unlocked + LockFault + Unused + BACnetLockStatusUnknown +) + +type BACnetEscalatorFault int + +const ( + BACnetescalatorfaultControllerFault BACnetEscalatorFault = iota + BACnetescalatorfaultDriveAndMotorFault + MechanicalComponentFault + OverspeedFault + BACnetescalatorfaultPowerSupplyFault + SafetyDeviceFault + BACnetescalatorfaultControllerSupplyFault + BACnetescalatorfaultDriveTemperatureExceeded + CombPlateFault +) + +type BACnetProgramError int + +const ( + BACnetProgramErrorNormal = iota + LoadFailed + Internal + BACnetProgramErrorProgram + BACnetProgramErrorOther +) + +type BACnetProgramRequest int + +const ( + BACnetProgramRequestReady = iota + Load + Run + Halt + Restart + Unload +) + +type BACnetProgramState int + +const ( + BACnetProgramStateIdle BACnetProgramState = iota + Loading + BACnetProgramStateRunning + Waiting + Halted + Unloading +) + +type BACnetShedState int + +const ( + BACnetShedStateInactive BACnetShedState = iota + RequestPending + Compliant + NonCompliant +) + +type BACnetWriteStatus int + +const ( + BACnetWriteStatusIdle BACnetWriteStatus = iota + BACnetWriteStatusInProgress + Successful + Failed +) + +type VendorSpecificValue int + +func DecodeEnumerated(buffer []byte, offset int, lenValue uint32, objType *ObjectType, propID *PropertyIdentifier) (length int, val interface{}) { + leng, value := DecodeUnsigned(buffer, offset, int(lenValue)) + if propID != nil { + switch *propID { + case SegmentationSupported: + val = BACnetSegmentation(value) + case PropertyList: + val = PropertyIdentifier(value) + case EventType: + val = BACnetEventType(value) + case NotifyType: + val = BACnetNotifyType(value) + case FaultType: + val = BACnetFaultType(value) + case EventState: + val = BACnetEventState(value) + case ObjectTypePI: + val = ObjectType(value) + case ReasonForDisable: + val = BACnetAccessCredentialDisableReason(value) + case CredentialDisable: + val = BACnetAccessCredentialDisable(value) + case PassbackMode: + val = BACnetAccessPassbackMode(value) + case UserType: + val = BACnetAccessUserType(value) + case NetworkNumberQuality: + val = BACnetNetworkNumberQuality(value) + case OccupancyState: + val = BACnetAccessZoneOccupancyState(value) + case Action: + if *objType == Loop { + val = BACnetAction(value) + } + case PresentValue, AlarmValue, FeedbackValue, RelinquishDefault: + switch *objType { + case BinaryInput, BinaryOutput, BinaryValue: + val = BACnetBinaryPV(value) + case AccessDoor: + val = BACnetDoorValue(value) + case LifeSafetyPoint, LifeSafetyZone: + val = BACnetLifeSafetyState(value) + case LightingOutput: + val = BACnetBinaryLightingPV(value) + case LoadControl: + val = BACnetShedState(value) + } + case AuthenticationStatus: + val = BACnetAuthenticationStatus(value) + case AuthorizationExemptions: + val = BACnetAuthorizationExemption(value) + case AuthorizationMode: + val = BACnetAuthorizationMode(value) + case BackupAndRestoreState: + val = BACnetBackupState(value) + case SystemStatus: + val = BACnetDeviceStatus(value) + case SecuredStatus: + val = BACnetDoorSecuredStatus(value) + case DoorStatus, CarDoorStatus: + val = BACnetDoorStatus(value) + case Units, CarLoadUnits: + val = BACnetEngineeringUnits(value) + case EscalatorMode: + val = BACnetEscalatorMode(value) + case OperationDirection: + val = BACnetEscalatorOperationDirection(value) + case FileAccessMethod: + val = BACnetFileAccessMethod(value) + case OperationExpected: + val = BACnetLifeSafetyOperation(value) + case CarDoorCommand: + val = BACnetLiftCarDoorCommand(value) + case CarDriveStatus: + val = BACnetLiftCarDriveStatus(value) + case CarMode: + val = BACnetLiftCarMode(value) + case GroupMode: + val = BACnetLiftGroupMode(value) + case LoggingType: + val = BACnetLoggingType(value) + case Reliability: + val = BACnetReliability(value) + case LastRestartReason: + val = BACnetRestartReason(value) + case NetworkType: + val = BACnetNetworkType(value) + case BaseDeviceSecurityPolicy: + val = BACnetSecurityLevel(value) + case CarMovingDirection, CarAssignedDirection: + val = BACnetLiftCarDirection(value) + case BacnetIpMode, BacnetIpv6Mode: + val = BACnetIPMode(value) + case MaintenanceRequired: + val = BACnetMaintenance(value) + case Polarity: + val = BACnetPolarity(value) + case ProtocolLevel: + val = BACnetProtocolLevel(value) + case Silenced: + val = BACnetSilencedState(value) + case AccessEvent, AccessAlarmEvents, AccessTransactionEvents, FailedAttemptEvents: + if *objType == AccessPoint { + val = BACnetAccessEvent(value) + } + case LastAccessEvent: + if *objType == AccessCredential { + val = BACnetAccessEvent(value) + } + case CredentialStatus: + if *objType == AccessCredential { + val = BACnetBinaryPV(value) + } + case LockStatus: + if *objType == AccessDoor { + val = BACnetLockStatus(value) + } + case DoorAlarmState, MaskedAlarmValues, AlarmValues, FaultValues: + switch *objType { + case AccessDoor: + val = BACnetDoorAlarmState(value) + case LifeSafetyPoint, LifeSafetyZone: + val = BACnetLifeSafetyState(value) + case Timer: + val = BACnetTimerState(value) + } + case Mode, AcceptedModes: + if *objType == LifeSafetyPoint || *objType == LifeSafetyZone { + val = BACnetLifeSafetyMode(value) + } + case TrackingValue, LifeSafetyAlarmValues: + if *objType == LifeSafetyPoint || *objType == LifeSafetyZone { + val = BACnetLifeSafetyState(value) + } + case FaultSignals: + switch *objType { + case Escalator: + val = BACnetEscalatorFault(value) + case Lift: + val = BACnetLiftFault(value) + } + case InProgress: + if *objType == LightingOutput { + val = BACnetLightingInProgress(value) + } + case Transition: + if *objType == LightingOutput { + val = BACnetLightingTransition(value) + } + case Command: + if *objType == NetworkPort { + val = BACnetNetworkPortCommand(value) + } + case NodeType, SubordinateNodeTypes: + if *objType == StructuredView { + val = BACnetNodeType(value) + } + case SubordinateRelationships, DefaultSubordinateRelationship: + if *objType == StructuredView { + val = BACnetRelationship(value) + } + case ReasonForHalt: + if *objType == Program { + val = BACnetProgramError(value) + } + case ProgramChange: + if *objType == Program { + val = BACnetProgramRequest(value) + } + case ProgramState: + if *objType == Program { + val = BACnetProgramState(value) + } + case TimerState: + if *objType == Timer { + val = BACnetTimerState(value) + } + case LastStateChange: + if *objType == Timer { + val = BACnetTimerTransition(value) + } + case VtClassesSupported: + val = BACnetVTClass(value) + case WriteStatus: + if *objType == Channel { + val = BACnetWriteStatus(value) + } + default: + val = VendorSpecificValue(value) + } + + return leng, val + } + return leng, value +} + +func EncodeContextEnumerated(tagNumber BACnetApplicationTag, value uint32) []byte { + length := 0 + if value < 0x100 { + length = 1 + } else if value < 0x10000 { + length = 2 + } else if value < 0x1000000 { + length = 3 + } else { + length = 4 + } + + return append(EncodeTag(tagNumber, true, length), EncodeUnsigned(value)...) +} diff --git a/pkg/encoding/tags.go b/pkg/encoding/tags.go index b5888de..0507038 100644 --- a/pkg/encoding/tags.go +++ b/pkg/encoding/tags.go @@ -37,7 +37,7 @@ func isClosingTag(b byte) bool { return (b & 0x07) == 7 } -func isContextSpecific(b byte) bool { +func IsContextSpecific(b byte) bool { return (b & 0x8) == 0x8 } @@ -50,15 +50,15 @@ func decodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { return len, buf[offset] >> 4 } -func DecodeIsCOntextTag(buf []byte, offset int, tagNum byte) bool { +func IsContextTag(buf []byte, offset int, tagNum byte) bool { _, myTagNum := decodeTagNumber(buf, offset) - return isContextSpecific(buf[offset]) && myTagNum == tagNum + return IsContextSpecific(buf[offset]) && myTagNum == tagNum } -func DecodeIsCOntextTagWithLength(buf []byte, offset int, tagNum byte) (int, bool) { +func IsContextTagWithLength(buf []byte, offset int, tagNum byte) (int, bool) { tagLen, myTagNum := decodeTagNumber(buf, offset) - return tagLen, isContextSpecific(buf[offset]) && myTagNum == tagNum + return tagLen, IsContextSpecific(buf[offset]) && myTagNum == tagNum } func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val uint32) { diff --git a/pkg/transport/udp/broadcast.go b/pkg/transport/udp/broadcast.go index 3de1911..f4edff2 100644 --- a/pkg/transport/udp/broadcast.go +++ b/pkg/transport/udp/broadcast.go @@ -5,6 +5,7 @@ import ( "strconv" "github.com/absmach/bacnet/pkg/bacnet" + "github.com/absmach/bacnet/pkg/encoding" ) func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, error) { @@ -32,7 +33,7 @@ func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, } } } - netType := bacnet.IPV4 + netType := encoding.IPV4 return *bacnet.NewBACnetAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil } From f231ed7fc677350ff2ecbbafafb9ace9c6c84efe Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 11 Sep 2023 00:33:01 +0300 Subject: [PATCH 13/24] add read property Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 105 +++++++++++++++++++++++++++ example/{ => whoIs}/whois.go | 11 ++- pkg/bacnet/iam.go | 9 +-- pkg/bacnet/network.go | 2 +- pkg/bacnet/property.go | 2 +- pkg/encoding/property.go | 8 +- 6 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 example/readProperty/readProperty.go rename example/{ => whoIs}/whois.go (89%) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go new file mode 100644 index 0000000..73c31d9 --- /dev/null +++ b/example/readProperty/readProperty.go @@ -0,0 +1,105 @@ +package main + +import ( + "fmt" + "log" + "net" + "time" + + "github.com/absmach/bacnet/pkg/bacnet" + "github.com/absmach/bacnet/pkg/encoding" + "github.com/absmach/bacnet/pkg/transport" +) + +func main() { + netType := encoding.IPV4 + /*deviceID := bacnet.ObjectIdentifier{ + Type: encoding.AnalogInput, + Instance: 101, + }*/ + destination := bacnet.NewBACnetAddress(0, nil, "127.0.0.6:47809", &netType) + npdu := bacnet.NewNPDU(destination, nil, nil, nil) + npdu.Control.SetDataExpectingReply(true) + npdu.Control.SetNetworkPriority(bacnet.NormalMessage) + + npduBytes, err := npdu.Encode() + if err != nil { + log.Fatal(err) + } + + apdu := bacnet.APDU{ + PduType: bacnet.PDUTypeConfirmedServiceRequest, + ServiceChoice: byte(bacnet.ReadProperty), + SegmentedResponseAccepted: false, + MaxSegmentsAccepted: bacnet.BacnetMaxSegments(encoding.NoSegmentation), + //MaxApduLengthAccepted: bacnet.MaxAPDU1476, + InvokeID: 0, + } + + req := bacnet.ReadPropertyRequest{ + PropertyIdentifier: encoding.PresentValue, + ObjectIdentifier: &bacnet.ObjectIdentifier{Type: encoding.AnalogInput, Instance: 10}, + } + + mes := append(npduBytes, apdu.Encode()...) + mes = append(mes, req.Encode()...) + + blvc := bacnet.NewBVLC(transport.IP) + blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) + message := append(blvcBytes, mes...) + + fmt.Println(message) + + message = []byte{129, 10, 0, 17, 1, 4, 0, 5, 1, 12, 12, 0, 0, 0, 10, 25, 85} + fmt.Println(message) + + // Define the BACnet broadcast address (255.255.255.255:47808) + remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") + if err != nil { + fmt.Println("Error resolving remote address:", err) + return + } + + localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") + if err != nil { + fmt.Println("Error: ", err) + return + } + + // Create a UDP connectionBACnetAddress + conn, err := net.DialUDP("udp", localAddr, remoteAddr) + if err != nil { + fmt.Println("Error creating UDP connection:", err) + return + } + defer conn.Close() + + // Send the WhoIsRequest packet + _, err = conn.Write(message) + if err != nil { + log.Fatal("Error sending WhoIsRequest:", err) + } + + // Wait for responses + buffer := make([]byte, 1500) + conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // Set a timeout for responses + + for { + //conn.ReadFromUDPAddrPort() + n, _, err := conn.ReadFromUDP(buffer) + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + // Timeout reached, no more responses + log.Println("No more responses received.") + break + } + log.Println("Error reading response:", err) + break + } + + // Process the response (you'll need to parse BACnet responses here) + response := buffer[:n] + log.Printf("Received response: %X\n", response) + + } +} diff --git a/example/whois.go b/example/whoIs/whois.go similarity index 89% rename from example/whois.go rename to example/whoIs/whois.go index 11a6b07..4310f6f 100644 --- a/example/whois.go +++ b/example/whoIs/whois.go @@ -50,14 +50,20 @@ func main() { message := append(blvcBytes, mes...) // Define the BACnet broadcast address (255.255.255.255:47808) - remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.255:47809") + remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") if err != nil { fmt.Println("Error resolving remote address:", err) return } + localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") + if err != nil { + fmt.Println("Error: ", err) + return + } + // Create a UDP connectionBACnetAddress - conn, err := net.DialUDP("udp", nil, remoteAddr) + conn, err := net.DialUDP("udp", localAddr, remoteAddr) if err != nil { fmt.Println("Error creating UDP connection:", err) return @@ -89,5 +95,6 @@ func main() { // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] log.Printf("Received response: %X\n", response) + fmt.Println(response) } } diff --git a/pkg/bacnet/iam.go b/pkg/bacnet/iam.go index bfad5be..4b0707d 100644 --- a/pkg/bacnet/iam.go +++ b/pkg/bacnet/iam.go @@ -1,10 +1,9 @@ package bacnet -/* import ( "errors" - "github.com/absmach/bacnet/encoding" + "github.com/absmach/bacnet/pkg/encoding" ) type IAmRequest struct { @@ -27,8 +26,7 @@ func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, leng = iam.IamDeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) - if iam.IamDeviceIdentifier.Type != ObjectTypeDevice { - // Handle error or log message + if iam.IamDeviceIdentifier.Type != encoding.ObjectTypeDevice { return -1, errors.New("Got Iam from no device") } @@ -49,7 +47,7 @@ func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, if tagNumber != byte(Enumerated) { return -1, errors.New("Invalid tag number") } - segmentationSupported, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, SegmentationSupported) + segmentationSupported, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, encoding.SegmentationSupported) if err != nil { return -1, err } @@ -167,4 +165,3 @@ func (youAre *YouAreRequest) ASN1Encode() []byte { return buffer } -*/ diff --git a/pkg/bacnet/network.go b/pkg/bacnet/network.go index 15650e5..aeb5c3c 100644 --- a/pkg/bacnet/network.go +++ b/pkg/bacnet/network.go @@ -71,7 +71,7 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface } case ObjectIdentifier: if *netType == encoding.IPV4 { - addr.MacAddress = make([]byte, 6) + addr.MacAddress = make([]byte, 8) binary.LittleEndian.PutUint64(addr.MacAddress, uint64(addr1.Instance)) } } diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index f7b2124..0a10a46 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -24,7 +24,7 @@ func (r ReadPropertyRequest) Encode() []byte { ret = append(ret, r.ObjectIdentifier.EncodeContext(0)...) } - propID := r.PropertyIdentifier.(int) + propID := r.PropertyIdentifier.(encoding.PropertyIdentifier) ret = append(ret, encoding.EncodeContextEnumerated(1, uint32(propID))...) diff --git a/pkg/encoding/property.go b/pkg/encoding/property.go index 4428f67..2ed48a0 100644 --- a/pkg/encoding/property.go +++ b/pkg/encoding/property.go @@ -561,10 +561,10 @@ const ( type BACnetSegmentation int const ( - SEGMENTED_BOTH BACnetSegmentation = iota - SEGMENTED_TRANSMIT - SEGMENTED_RECEIVE - NO_SEGMENTATION + SegmentedBoth BACnetSegmentation = iota + SegmentedTransmit + SegmentedReceive + NoSegmentation ) type BACnetEventType int From 76792fab135d36b63fea181164bbe99f58097c87 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Mon, 11 Sep 2023 10:09:26 +0300 Subject: [PATCH 14/24] add iam and you are Signed-off-by: SammyOina --- go.sum | 0 pkg/bacnet/base.go | 17 +-------- pkg/bacnet/iam.go | 37 +++++++------------ pkg/encoding/decoding.go | 80 ++++++++++++++++++++++++++++++++++++++++ pkg/encoding/encoding.go | 30 +++++++++++++++ 5 files changed, 126 insertions(+), 38 deletions(-) create mode 100644 go.sum diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/pkg/bacnet/base.go b/pkg/bacnet/base.go index 7a550e4..19e857f 100644 --- a/pkg/bacnet/base.go +++ b/pkg/bacnet/base.go @@ -55,8 +55,8 @@ const ( NegativeAck // TODO SegmentResponseAccepted - MORE_FOLLOWS - SEGMENTED_MESSAGE BacnetPduTypes = 8 + MoreFollows + SegmentedMessage BacnetPduTypes = 8 PDUTypeUnconfirmedServiceRequest BacnetPduTypes = 0x10 PDUTypeSimpleAck BacnetPduTypes = 0x20 PDUTypeComplexAck BacnetPduTypes = 0x30 @@ -67,19 +67,6 @@ const ( PDUTypeMask BacnetPduTypes = 0xF0 ) -type BacnetCharacterStringEncodings int - -const ( - CharacterANSIX34 BacnetCharacterStringEncodings = 0 - CharacterUTF8 BacnetCharacterStringEncodings = 0 - CharacterMSDBCS BacnetCharacterStringEncodings = 1 - CharacterJISC6226 BacnetCharacterStringEncodings = 2 - CharacterJISX0208 BacnetCharacterStringEncodings = 2 - CharacterUCS4 BacnetCharacterStringEncodings = 3 - CharacterUCS2 BacnetCharacterStringEncodings = 4 - CharacterISO8859 BacnetCharacterStringEncodings = 5 -) - type BacnetNpduControl int const ( diff --git a/pkg/bacnet/iam.go b/pkg/bacnet/iam.go index 4b0707d..e53723c 100644 --- a/pkg/bacnet/iam.go +++ b/pkg/bacnet/iam.go @@ -9,11 +9,11 @@ import ( type IAmRequest struct { IamDeviceIdentifier ObjectIdentifier MaxAPDULengthAccepted uint32 - SegmentationSupported int + SegmentationSupported interface{} VendorID uint32 } -func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 iam.IamDeviceIdentifier = ObjectIdentifier{} // OBJECT ID - object id @@ -47,10 +47,8 @@ func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, if tagNumber != byte(Enumerated) { return -1, errors.New("Invalid tag number") } - segmentationSupported, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, encoding.SegmentationSupported) - if err != nil { - return -1, err - } + propID := encoding.SegmentationSupported + leng1, segmentationSupported := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) leng += leng1 iam.SegmentationSupported = segmentationSupported @@ -63,9 +61,6 @@ func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, } leng1, decodedValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) - if err != nil { - return -1, err - } leng += leng1 if decodedValue > 0xFFFF { @@ -76,9 +71,10 @@ func (iam *IAmRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, return leng, nil } -func (iam *IAmRequest) ASN1Encode() []byte { +func (iam IAmRequest) Encode() []byte { tmp := iam.IamDeviceIdentifier.Encode() - return append(append(append(append([]byte{}, encoding.EncodeTag(encoding.BACnetApplicationTag(BACnetObjectIdentifier), false, len(tmp))...), tmp...), encoding.EncodeApplicationUnsigned(iam.MaxAPDULengthAccepted)...), encoding.EncodeApplicationEnumerated(iam.SegmentationSupported, SegmentationSupported), encoding.EncodeApplicationUnsigned(iam.VendorID)...) + propID := iam.SegmentationSupported.(encoding.PropertyIdentifier) + return append(append(append(append(encoding.EncodeTag(encoding.BACnetApplicationTag(BACnetObjectIdentifier), false, len(tmp)), tmp...), encoding.EncodeApplicationUnsigned(iam.MaxAPDULengthAccepted)...), encoding.EncodeApplicationEnumerated(uint32(propID))...), encoding.EncodeApplicationUnsigned(iam.VendorID)...) } type YouAreRequest struct { @@ -89,7 +85,7 @@ type YouAreRequest struct { DeviceMACAddress []byte } -func (youAre *YouAreRequest) ASN1Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (youAre *YouAreRequest) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) @@ -105,11 +101,9 @@ func (youAre *YouAreRequest) ASN1Decode(buffer []byte, offset int, apduLen int) leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) leng += leng1 if tagNumber == byte(CharacterString) { - decodedValue, err := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, lenValue) - if err != nil { - return -1, err - } - leng += decodedValue + leng1, decodedValue := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) + + leng += leng1 youAre.ModelName = decodedValue } else { return -1, errors.New("Invalid tag number") @@ -118,11 +112,8 @@ func (youAre *YouAreRequest) ASN1Decode(buffer []byte, offset int, apduLen int) leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) leng += leng1 if tagNumber == byte(CharacterString) { - decodedValue, err := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, lenValue) - if err != nil { - return -1, err - } - leng += decodedValue + leng1, decodedValue := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) + leng += leng1 youAre.SerialNumber = decodedValue } else { return -1, errors.New("Invalid tag number") @@ -150,7 +141,7 @@ func (youAre *YouAreRequest) ASN1Decode(buffer []byte, offset int, apduLen int) return leng, nil } -func (youAre *YouAreRequest) ASN1Encode() []byte { +func (youAre YouAreRequest) Encode() []byte { buffer := append(append(append([]byte{}, encoding.EncodeApplicationUnsigned(youAre.VendorID)...), encoding.EncodeApplicationCharacterString(youAre.ModelName)...), encoding.EncodeApplicationCharacterString(youAre.SerialNumber)...) diff --git a/pkg/encoding/decoding.go b/pkg/encoding/decoding.go index bcdeb14..52065e5 100644 --- a/pkg/encoding/decoding.go +++ b/pkg/encoding/decoding.go @@ -1,5 +1,18 @@ package encoding +type BacnetCharacterStringEncodings int + +const ( + CharacterANSIX34 BacnetCharacterStringEncodings = 0 + CharacterUTF8 BacnetCharacterStringEncodings = 0 + CharacterMSDBCS BacnetCharacterStringEncodings = 1 + CharacterJISC6226 BacnetCharacterStringEncodings = 2 + CharacterJISX0208 BacnetCharacterStringEncodings = 2 + CharacterUCS4 BacnetCharacterStringEncodings = 3 + CharacterUCS2 BacnetCharacterStringEncodings = 4 + CharacterISO8859 BacnetCharacterStringEncodings = 5 +) + func DecodeUnsigned(buffer []byte, offset, len int) (int, uint32) { value := uint32(0) for i := 0; i < len; i++ { @@ -13,3 +26,70 @@ func DecodeOctetString(buf []byte, offset, lenVal int) (int, []byte) { copy(tmp, buf[offset:offset+lenVal]) return len(tmp), tmp } + +// multiCharsetCharacterstringDecode decodes a multi-character set character string. +func multiCharsetCharacterStringDecode(buffer []byte, offset, maxLength int, encoding BacnetCharacterStringEncodings, length int) (bool, string) { + var charString, enc string + + switch encoding { + case CharacterUCS2: + enc = "utf-16" + case CharacterUCS4: + enc = "utf-32" + case CharacterISO8859: + enc = "latin-1" + case CharacterJISX0208: + enc = "shift_jisx0213" + case CharacterMSDBCS: + enc = "dbcs" + default: + enc = "utf-8" + } + + c := make([]byte, 0) + for i := 0; i < length; i++ { + c = append(c, buffer[offset+i]) + } + + if enc == "utf-8" { + charString = string(c) + } else { + charString = string(c) + charString = string([]rune(charString)) // Convert to Unicode + } + + return true, charString +} + +func DecodeCharacterString(buffer []byte, offset, maxLength, lenValue int) (int, string) { + leng := 0 + status := false + var charString string + + status, charString = multiCharsetCharacterStringDecode(buffer, offset+1, maxLength, BacnetCharacterStringEncodings(buffer[offset]), lenValue-1) + if status { + leng = lenValue + } + + return leng, charString +} + +func decodeContextCharacterString(buffer []byte, offset, maxLength int, tagNumber byte) (int, string) { + leng := 0 + status := false + charString := "" + + if IsContextTag(buffer, offset+leng, tagNumber) { + leng1, _, lenValue := DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + + status, charString = multiCharsetCharacterStringDecode(buffer, offset+1+leng, maxLength, BacnetCharacterStringEncodings(buffer[offset+leng]), int(lenValue)-1) + if status { + leng += int(lenValue) + } else { + leng = -1 + } + } + + return leng, charString +} diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index e7a64b2..5b85e75 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -76,3 +76,33 @@ func EncodeContextUnsigned(tagNum BACnetApplicationTag, val uint32) []byte { } return append(EncodeTag(tagNum, true, len), EncodeUnsigned(val)...) } + +// EncodeApplicationUnsigned encodes an unsigned integer value as a BACnet application tag. +func EncodeApplicationUnsigned(value uint32) []byte { + tmp := EncodeUnsigned(value) + tag := EncodeTag(UnsignedInt, false, len(tmp)) + return append(tag, tmp...) +} + +func EncodeApplicationEnumerated(value uint32) []byte { + tmp := EncodeUnsigned(value) + return append(EncodeTag(Enumerated, false, len(tmp)), tmp...) +} + +func EncodeApplicationOctetString(octetString []byte, octetOffset, octetCount int) []byte { + tag := EncodeTag(OctetString, false, octetCount) + octetStringSegment := octetString[octetOffset : octetOffset+octetCount] + return append(tag, octetStringSegment...) +} + +func EncodeApplicationCharacterString(value string) []byte { + tmp := encodeBACnetCharacterString(value) + tag := EncodeTag(CharacterString, false, len(tmp)) + return append(tag, tmp...) +} + +func encodeBACnetCharacterString(value string) []byte { + encoding := []byte{byte(CharacterUTF8)} + encodedValue := []byte(value) + return append(encoding, encodedValue...) +} From 6b2822edede83fe55751d213d6401fd53eb79736 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Tue, 12 Sep 2023 18:17:24 +0300 Subject: [PATCH 15/24] add bacnet Value Signed-off-by: SammyOina --- example/whoIs/whois.go | 23 + pkg/bacnet/bvlc.go | 11 +- pkg/bacnet/iam.go | 7 +- pkg/bacnet/property.go | 1168 +++++++++++++++++++++++++++++++++++++- pkg/encoding/decoding.go | 51 ++ pkg/encoding/encoding.go | 33 ++ pkg/encoding/tags.go | 22 +- 7 files changed, 1293 insertions(+), 22 deletions(-) diff --git a/example/whoIs/whois.go b/example/whoIs/whois.go index 4310f6f..cd52b4d 100644 --- a/example/whoIs/whois.go +++ b/example/whoIs/whois.go @@ -95,6 +95,29 @@ func main() { // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] log.Printf("Received response: %X\n", response) + blvc := bacnet.BVLC{BVLLTypeBACnetIP: 0x81} + headerLength, function, msgLength, err := blvc.Decode(response, 0) + if err != nil { + log.Fatal(err) + } fmt.Println(response) + fmt.Printf("headerLength %v BVLCfunction %v msgLen %v\n", headerLength, function, msgLength) + fmt.Println("blvc", blvc) + fmt.Println(response[headerLength:]) + npdu := bacnet.NPDU{Version: 1} + npduLen := npdu.Decode(response, headerLength) + fmt.Println("npdu", npdu) + fmt.Println(response[headerLength+npduLen:]) + apdu := bacnet.APDU{} + apduLen := apdu.Decode(response, headerLength+npduLen) + fmt.Println("apdu", apdu) + fmt.Println(response[headerLength+npduLen+apduLen:]) + iam := bacnet.IAmRequest{} + iamLen, err := iam.Decode(response, headerLength+npduLen+apduLen) + if err != nil { + log.Fatal(err) + } + fmt.Println("iam", iam) + fmt.Println(response[headerLength+npduLen+apduLen+iamLen:]) } } diff --git a/pkg/bacnet/bvlc.go b/pkg/bacnet/bvlc.go index 4859b21..5591d9f 100644 --- a/pkg/bacnet/bvlc.go +++ b/pkg/bacnet/bvlc.go @@ -3,6 +3,7 @@ package bacnet import ( "encoding/binary" "errors" + "fmt" "github.com/absmach/bacnet/pkg/transport" ) @@ -13,6 +14,7 @@ var ( errUnsupportedFunction = errors.New("unsupported BVLC function") ) +//go:generate stringer -type=BVLCFunctions type BVLCFunctions int const ( @@ -60,22 +62,23 @@ func NewBVLC(transprt transport.Transport) *BVLC { return bvlc } -func (bvlc *BVLC) Decode(buffer []byte, offset int) (int, byte, uint16, error) { +func (bvlc *BVLC) Decode(buffer []byte, offset int) (int, BVLCFunctions, uint16, error) { msgType := buffer[0] function := BVLCFunctions(buffer[1]) msgLength := binary.BigEndian.Uint16(buffer[2:4]) if msgType != bvlc.BVLLTypeBACnetIP || msgLength != uint16(len(buffer)) { + fmt.Println(msgType, bvlc.BVLLTypeBACnetIP, msgLength, uint16(len(buffer))) return 0, 0, 0, errUnsupportedTransport } switch function { case BVLCResult: - return 4, byte(function), msgLength, nil + return 4, function, msgLength, nil case BVLCOriginalUnicastNPDU: - return 4, byte(function), msgLength, nil + return 4, function, msgLength, nil case BVLCOriginalBroadcastNPDU: - return 4, byte(function), msgLength, nil + return 4, function, msgLength, nil case BVLCForwardedNPDU: // Handle this case case BVLCDistributeBroadcastToNetwok: diff --git a/pkg/bacnet/iam.go b/pkg/bacnet/iam.go index e53723c..551c63b 100644 --- a/pkg/bacnet/iam.go +++ b/pkg/bacnet/iam.go @@ -2,6 +2,7 @@ package bacnet import ( "errors" + "fmt" "github.com/absmach/bacnet/pkg/encoding" ) @@ -13,7 +14,7 @@ type IAmRequest struct { VendorID uint32 } -func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (iam *IAmRequest) Decode(buffer []byte, offset int) (int, error) { leng := 0 iam.IamDeviceIdentifier = ObjectIdentifier{} // OBJECT ID - object id @@ -21,6 +22,7 @@ func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, erro leng += leng1 if tagNumber != byte(BACnetObjectIdentifier) { + fmt.Println("tag num object id", tagNumber) return -1, errors.New("Invalid tag number") } @@ -34,6 +36,7 @@ func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, erro leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) leng += leng1 if tagNumber != byte(UnsignedInt) { + fmt.Println("tag num max apdu", tagNumber) return -1, errors.New("Invalid tag number") } @@ -45,6 +48,7 @@ func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, erro leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) leng += leng1 if tagNumber != byte(Enumerated) { + fmt.Println("tag num segmentation", tagNumber) return -1, errors.New("Invalid tag number") } propID := encoding.SegmentationSupported @@ -57,6 +61,7 @@ func (iam *IAmRequest) Decode(buffer []byte, offset int, apduLen int) (int, erro leng += leng1 if tagNumber != byte(UnsignedInt) { + fmt.Println("tag num vendor ID", tagNumber) return -1, errors.New("Invalid tag number") } diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 0a10a46..f91fe9e 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -1,16 +1,15 @@ package bacnet import ( + "errors" + "fmt" + "log" + "time" + + "github.com/absmach/bacnet/internal" "github.com/absmach/bacnet/pkg/encoding" ) -type PropertyValue struct { - Identifier encoding.PropertyIdentifier - Arrayindex *uint32 - Value uint32 - Priority uint32 -} - type ReadPropertyRequest struct { ObjectIdentifier *ObjectIdentifier PropertyIdentifier interface{} @@ -70,3 +69,1158 @@ func (r *ReadPropertyRequest) Decode(buffer []byte, offset, apduLen int) int { return leng } + +type ReadPropertyACK struct { + ObjectIdentifier ObjectIdentifier + PropertyIdentifier interface{} + PropertyArrayIndex uint32 + PropertyValue []BACnetValue +} + +func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + // 0 object_identifier + if encoding.IsContextTag(buffer, offset+leng, 0) { + r.ObjectIdentifier = ObjectIdentifier{} + leng1 := r.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng += leng1 + } else { + return -1, errors.New("ASN.1 decoding error for object_identifier") + } + + // 2 propertyidentifier + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + PropertyID := encoding.PropertyList + leng1, propID := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &PropertyID) + r.PropertyIdentifier = propID + leng += leng1 + } else { + return -1, errors.New("ASN.1 decoding error for property_identifier") + } + + // 2 property_array_index + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, r.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + + // tag 3 property-value + if encoding.IsOpeningTagNumber(buffer, offset+leng, 3) { + leng++ + r.PropertyValue = make([]BACnetValue, 0) + for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) && leng < apduLen { + bValue := BACnetValue{} + propId := r.PropertyIdentifier.(encoding.PropertyIdentifier) + leng1 := bValue.Decode(buffer, offset+leng, apduLen-leng, r.ObjectIdentifier.Type, propId) + leng += leng1 + r.PropertyValue = append(r.PropertyValue, bValue) + } + if encoding.IsClosingTagNumber(buffer, offset+leng, 3) { + leng++ + } else { + return -1, errors.New("ASN.1 decoding error for property_value") + } + } else { + return -1, errors.New("ASN.1 decoding error for property_value") + } + + return leng, nil +} + +type BACnetValue struct { + Tag *ApplicationTags + Value interface{} +} + +func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encoding.ObjectType, propID encoding.PropertyIdentifier) int { + length := 0 + var err error + + if !encoding.IsContextSpecific(buffer[offset]) { + tagLen, tagNumber, lenValueType := encoding.DecodeTagNumberAndValue(buffer, offset) + if tagLen > 0 { + ttag := ApplicationTags(tagNumber) + bv.Tag = &ttag + length += tagLen + + decodeLen := 0 + + switch *bv.Tag { + case Null: + bv.Value = nil + decodeLen = 0 + case Boolean: + if lenValueType > 0 { + bv.Value = true + } else { + bv.Value = false + } + case UnsignedInt: + if propID == encoding.RoutingTable { + bv.Tag = nil + bv.Value = &RouterEntry{} + length-- + decodeLen, err = bv.Value.(*RouterEntry).Decode(buffer, offset+length, apduLen) + if err != nil { + return -1 + } + } else if propID == encoding.ActiveVtSessions { + bv.Tag = nil + bv.Value = &BACnetVTSession{} + length-- + decodeLen = bv.Value.(*BACnetVTSession).Decode(buffer, offset+length, apduLen) + } else if propID == encoding.ThreatLevel || propID == encoding.ThreatAuthority { + bv.Tag = nil + bv.Value = &BACnetAccessThreatLevel{} + length-- + decodeLen = bv.Value.(*BACnetAccessThreatLevel).Decode(buffer, offset+length, apduLen) + } else { + var uintVal uint32 + decodeLen, uintVal = encoding.DecodeUnsigned(buffer, offset+length, int(lenValueType)) + bv.Value = uintVal + } + case SignedInt: + var intValue int + decodeLen, intValue = encoding.DecodeSigned(buffer, offset+length, int(lenValueType)) + bv.Value = intValue + case Real: + var floatValue float32 + decodeLen, floatValue = encoding.DecodeRealSafe(buffer, offset+length, int(lenValueType)) + bv.Value = floatValue + case Double: + var doubleValue float64 + decodeLen, doubleValue = encoding.DecodeDoubleSafe(buffer, offset+length, int(lenValueType)) + bv.Value = doubleValue + case OctetString: + var octetValue []byte + decodeLen, octetValue = encoding.DecodeOctetString(buffer, offset+length, int(lenValueType)) + bv.Value = octetValue + case CharacterString: + var stringValue string + decodeLen, stringValue = encoding.DecodeCharacterString(buffer, offset+length, apduLen, int(lenValueType)) + bv.Value = stringValue + case BitString: + switch propID { + case encoding.RecipientList: + bv.Tag = nil + bv.Value = &BACnetDestination{} + length-- + decodeLen = bv.Value.(*BACnetDestination).Decode(buffer, offset+length, apduLen) + case encoding.StatusFlags: + bv.Tag = nil + bitValue := &BACnetStatusFlags{} + decodeLen = bitValue.Decode(buffer, offset, lenValueType) + bv.Value = bitValue + case encoding.EventEnable, encoding.AckedTransitions: + bv.Tag = nil + bitValue := &BACnetEventTransitionBits{} + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) + bv.Value = bitValue + case encoding.LimitEnable: + bv.Tag = nil + bitValue := &BACnetLimitEnable{} + decodeLen = bitValue.Decode(buffer, offset, lenValueType) + bv.Value = bitValue + case encoding.ProtocolObjectTypesSupported: + bv.Tag = nil + bitValue := &BACnetObjectTypesSupported{} + decodeLen = bitValue.Decode(buffer, offset, lenValueType) + bv.Value = bitValue + case encoding.ProtocolServicesSupported: + bv.Tag = nil + bitValue := &BACnetServicesSupported{} + decodeLen = bitValue.Decode(buffer, offset, lenValueType) + bv.Value = bitValue + default: + bitValue := &BACnetBitString{} + decodeLen = bitValue.Decode(buffer, offset, lenValueType) + bv.Value = bitValue + } + case Enumerated: + decodeLen, uintValue := encoding.DecodeEnumerated(buffer, offset+length, lenValueType, objType, propID) + bv.Value = uintValue + case Date: + switch propID { + case encoding.EffectivePeriod: + bv.Tag = nil + bv.Value = NewBACnetDateRange() + length-- + decodeLen = bv.Value.(*BACnetDateRange).Decode(buffer, offset+length, apduLen) + case encoding.MinimumValueTimestamp, + encoding.MaximumValueTimestamp, + encoding.ChangeOfStateTime, + encoding.TimeOfStateCountReset, + encoding.TimeOfActiveTimeReset, + encoding.ModificationDate, + encoding.UpdateTime, + encoding.CountChangeTime, + encoding.StartTime, + encoding.StopTime, + encoding.LastCredentialAddedTime, + encoding.LastCredentialRemovedTime, + encoding.ActivationTime, + encoding.ExpiryTime, + encoding.LastUseTime, + encoding.TimeOfStrikeCountReset, + encoding.ValueChangeTime: + bv.Tag = nil + bv.Value = &DateTime{} + length-- + decodeLen = bv.Value.(*DateTime).Decode(buffer, offset+length) + default: + decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+length, lenValueType) + bv.Value = dateValue + } + if (objType == encoding.DateTimeValue || objType == encoding.TimePatternValue) && (propID == encoding.PresentValue || propID == encoding.RelinquishDefault) { + decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+length, lenValueType) + bv.Value = dateValue + } + case Time: + decodeLen, timeValue := encoding.DecodeBACnetTimeSafe(buffer, offset+length, lenValueType) + bv.Value = timeValue + case BACnetObjectIdentifier: + if propID == encoding.LastKeyServer || + propID == encoding.ManualSlaveAddressBinding || + propID == encoding.SlaveAddressBinding || + propID == encoding.DeviceAddressBinding { + bv.Tag = nil + bv.Value = NewBACnetAddressBinding() + length-- + decodeLen = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) + } else { + decodeLen, objectType, instance := encoding.DecodeObjectIDSafe(buffer, offset+length, lenValueType) + bv.Value = ObjectIdentifier{Type: objectType, Instance: instance} + } + default: + log.Println("Unhandled tag:", bv.Tag) + length = apduLen + } + + if decodeLen < 0 { + return -1 + } + length += decodeLen + } + } else { + switch propID { + case encoding.BacnetIpGlobalAddress, encoding.FdBbmdAddress: + bv.Value = NewBACnetHostNPort() + length += bv.Value.(*BACnetHostNPort).Decode(buffer, offset+length, apduLen-length) + case encoding.UtcTimeSynchronizationRecipients, + encoding.RestartNotificationRecipients, + encoding.TimeSynchronizationRecipients, + encoding.CovuRecipients: + bv.Value = NewBACnetRecipient() + length += bv.Value.(*BACnetRecipient).Decode(buffer, offset+length, apduLen-length) + case encoding.KeySets: + bv.Value = NewBACnetSecurityKeySet() + length += bv.Value.(*BACnetSecurityKeySet).Decode(buffer, offset+length, apduLen-length) + case encoding.EventTimeStamps, + encoding.LastCommandTime, + encoding.CommandTimeArray, + encoding.LastRestoreTime, + encoding.TimeOfDeviceRestart, + encoding.AccessEventTime, + encoding.UpdateTime: + bv.Value = NewBACnetTimeStamp() + length += bv.Value.(*BACnetTimeStamp).Decode(buffer, offset+length, apduLen-length) + case encoding.ListOfGroupMembers: + bv.Value = NewReadAccessSpecification() + length += bv.Value.(*ReadAccessSpecification).Decode(buffer, offset+length, apduLen-length) + case encoding.ListOfObjectPropertyReferences: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case encoding.MemberOf, + encoding.ZoneMembers, + encoding.DoorMembers, + encoding.SubordinateList, + encoding.Represents, + encoding.AccessEventCredential, + encoding.AccessDoors, + encoding.ZoneTo, + encoding.ZoneFrom, + encoding.CredentialsInZone, + encoding.LastCredentialAdded, + encoding.LastCredentialRemoved, + encoding.EntryPoints, + encoding.ExitPoints, + encoding.Members, + encoding.Credentials, + encoding.Accompaniment, + encoding.BelongsTo, + encoding.LastAccessPoint, + encoding.EnergyMeterRef: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case encoding.EventAlgorithmInhibitRef, + encoding.InputReference, + encoding.ManipulatedVariableReference, + encoding.ControlledVariableReference: + bv.Value = NewBACnetObjectPropertyReference() + length += bv.Value.(*BACnetObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case encoding.LoggingRecord: + bv.Value = NewBACnetAccumulatorRecord() + length += bv.Value.(*BACnetAccumulatorRecord).Decode(buffer, offset+length, apduLen-length) + case encoding.Action: + bv.Value = NewBACnetActionList() + length += bv.Value.(*BACnetActionList).Decode(buffer, offset+length, apduLen-length) + case encoding.Scale: + bv.Value = NewBACnetScale() + length += bv.Value.(*BACnetScale).Decode(buffer, offset+length, apduLen-length) + case encoding.LightingCommand: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case encoding.Prescale: + bv.Value = NewBACnetPrescale() + length += bv.Value.(*BACnetPrescale).Decode(buffer, offset+length, apduLen-length) + case encoding.RequestedShedLevel, + encoding.ExpectedShedLevel, + encoding.ActualShedLevel: + bv.Value = NewBACnetShedLevel() + length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) + case encoding.LogBuffer: + if objType == encoding.TrendLog { + bv.Value = NewBACnetLogRecord() + length += bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length) + } else { + log.Println("Unhandled context-specific tag:", bv.Tag) + length = apduLen + } + case encoding.DateList: + bv.Value = NewBACnetCalendarEntry() + length += bv.Value.(*BACnetCalendarEntry).Decode(buffer, offset+length, apduLen-length) + case encoding.LogBuffer: + if objType == encoding.EventLog { + bv.Value = NewBACnetEventLogRecord() + length += bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) + } else { + log.Println("Unhandled context-specific tag:", bv.Tag) + length = apduLen + } + case encoding.PresentValue: + if objType == encoding.Group { + bv.Value = NewReadAccessResult() + length += bv.Value.(*ReadAccessResult).Decode(buffer, offset+length, apduLen-length) + } else { + log.Println("Unhandled context-specific tag:", bv.Tag) + length = apduLen + } + case encoding.NegativeAccessRules, + encoding.PositiveAccessRules: + bv.Value = NewBACnetAccessRule() + length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) + case encoding.Tags: + bv.Value = NewBACnetNameValue() + length += bv.Value.(*BACnetNameValue).Decode(buffer, offset+length, apduLen-length) + case encoding.SubordinateTags: + bv.Value = NewBACnetNameValueCollection() + length += bv.Value.(*BACnetNameValueCollection).Decode(buffer, offset+length, apduLen-length) + case encoding.NetworkAccessSecurityPolicies: + bv.Value = NewBACnetNetworkSecurityPolicy() + length += bv.Value.(*BACnetNetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case encoding.PortFilter: + bv.Value = NewBACnetPortPermission() + length += bv.Value.(*BACnetPortPermission).Decode(buffer, offset+length, apduLen-length) + case encoding.PriorityArray: + bv.Value = NewBACnetPriorityArray() + length += bv.Value.(*BACnetPriorityArray).Decode(buffer, offset+length, apduLen-length) + case encoding.ProcessIdentifierFilter: + bv.Value = NewBACnetProcessIdSelection() + length += bv.Value.(*BACnetProcessIdSelection).Decode(buffer, offset+length, apduLen-length) + case encoding.GlobalGroup && propID == encoding.PresentValue: + bv.Value = NewBACnetPropertyAccessResult() + length += bv.Value.(*BACnetPropertyAccessResult).Decode(buffer, offset+length, apduLen-length) + case encoding.SetpointReference: + bv.Value = NewBACnetSetpointReference() + length += bv.Value.(*BACnetSetpointReference).Decode(buffer, offset+length, apduLen-length) + case encoding.ExceptionSchedule: + bv.Value = NewBACnetSpecialEvent() + length += bv.Value.(*BACnetSpecialEvent).Decode(buffer, offset+length, apduLen-length) + case encoding.StateChangeValues: + bv.Value = NewBACnetTimerStateChangeValue() + length += bv.Value.(*BACnetTimerStateChangeValue).Decode(buffer, offset+length, apduLen-length) + case encoding.ValueSource, encoding.ValueSourceArray: + bv.Value = NewBACnetValueSource() + length += bv.Value.(*BACnetValueSource).Decode(buffer, offset+length, apduLen-length) + case encoding.VirtualMacAddressTable: + bv.Value = NewBACnetVMACEntry() + length += bv.Value.(*BACnetVMACEntry).Decode(buffer, offset+length, apduLen-length) + case encoding.AssignedAccessRights: + bv.Value = NewBACnetAssignedAccessRights() + length += bv.Value.(*BACnetAssignedAccessRights).Decode(buffer, offset+length, apduLen-length) + case encoding.AssignedLandingCalls: + bv.Value = NewBACnetAssignedLandingCalls() + length += bv.Value.(*BACnetAssignedLandingCalls).Decode(buffer, offset+length, apduLen-length) + case encoding.AccessEventAuthenticationFactor, + (objType == encoding.CredentialDataInput && propID == encoding.PresentValue): + bv.Value = NewBACnetAuthenticationFactor() + length += bv.Value.(*BACnetAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) + case encoding.SupportedFormats: + bv.Value = NewBACnetAuthenticationFactorFormat() + length += bv.Value.(*BACnetAuthenticationFactorFormat).Decode(buffer, offset+length, apduLen-length) + case encoding.AuthenticationPolicyList: + bv.Value = NewBACnetAuthenticationPolicy() + length += bv.Value.(*BACnetAuthenticationPolicy).Decode(buffer, offset+length, apduLen-length) + case encoding.Channel && propID == encoding.PresentValue: + bv.Value = NewBACnetChannelValue() + length += bv.Value.(*BACnetChannelValue).Decode(buffer, offset+length, apduLen-length) + case encoding.ActiveCovSubscriptions: + bv.Value = NewBACnetCOVSubscription() + length += bv.Value.(*BACnetCOVSubscription).Decode(buffer, offset+length, apduLen-length) + case encoding.AuthenticationFactors: + bv.Value = NewBACnetCredentialAuthenticationFactor() + length += bv.Value.(*BACnetCredentialAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) + case encoding.WeeklySchedule: + bv.Value = NewBACnetDailySchedule() + length += bv.Value.(*BACnetDailySchedule).Decode(buffer, offset+length, apduLen-length) + case encoding.SubscribedRecipients: + bv.Value = NewBACnetEventNotificationSubscription() + length += bv.Value.(*BACnetEventNotificationSubscription).Decode(buffer, offset+length, apduLen-length) + case encoding.EventParameters: + bv.Value = NewBACnetEventParameter() + length += bv.Value.(*BACnetEventParameter).Decode(buffer, offset+length, apduLen-length) + case encoding.FaultParameters: + bv.Value = NewBACnetFaultParameter() + length += bv.Value.(*BACnetFaultParameter).Decode(buffer, offset+length, apduLen-length) + case encoding.LoggingObject: + bv.Value = NewBACnetLoggingObject() + length += bv.Value.(*BACnetLoggingObject).Decode(buffer, offset+length, apduLen-length) + case encoding.LoggingRecord: + bv.Value = NewBACnetLoggingRecord() + length += bv.Value.(*BACnetLoggingRecord).Decode(buffer, offset+length, apduLen-length) + case encoding.ReinitiateDevice: + bv.Value = NewBACnetReinitializeDevice() + length += bv.Value.(*BACnetReinitializeDevice).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierBACNETIPUDPDATAGRAMCONFIGURATION: + bv.Value = NewBACnetBACnetIPUDPDatagramConfiguration() + length += bv.Value.(*BACnetBACnetIPUDPDatagramConfiguration).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierREINITIALIZEPARAMETERS: + bv.Value = NewBACnetReinitializeParameters() + length += bv.Value.(*BACnetReinitializeParameters).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierDISCONNECTEDONEXCEPTION: + bv.Value = NewBACnetDisconnect() + length += bv.Value.(*BACnetDisconnect).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierNOMINALENCYCLE: + bv.Value = NewBACnetNominalBACnetInterval() + length += bv.Value.(*BACnetNominalBACnetInterval).Decode(buffer, offset+length, apduLen-length) + case encoding.NotifyType: + bv.Value = NewBACnetNotifyType() + length += bv.Value.(*BACnetNotifyType).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierSUMMATION: + bv.Value = NewBACnetEventSummation() + length += bv.Value.(*BACnetEventSummation).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSUSERPASSWORD: + bv.Value = NewBACnetAccessUserPassword() + length += bv.Value.(*BACnetAccessUserPassword).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPULSECONFIGURATION: + bv.Value = NewBACnetPulseConverter() + length += bv.Value.(*BACnetPulseConverter).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPORTPARAMETERS: + bv.Value = NewBACnetPortParameters() + length += bv.Value.(*BACnetPortParameters).Decode(buffer, offset+length, apduLen-length) + case encoding.TimeDelay, + BACnetPropertyIdentifierLIGHTCONTROLDELAY, + BACnetPropertyIdentifierINITIALTIMEDELAY: + bv.Value = NewBACnetTimeValue() + length += bv.Value.(*BACnetTimeValue).Decode(buffer, offset+length, apduLen-length) + case encoding.LightingCommand, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierRADIOFAILUREEVENTS, + BACnetPropertyIdentifierRADIOFAILUREEVENTS2, + BACnetPropertyIdentifierMACADDRESSCHANGEEVENTS: + bv.Value = NewBACnetCOVSubscription() + length += bv.Value.(*BACnetCOVSubscription).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierSHEDLEVELDESCENDANTS: + bv.Value = NewBACnetShedLevelDescendants() + length += bv.Value.(*BACnetShedLevelDescendants).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPERSISTENTDATA: + bv.Value = NewBACnetScheduleObjectPeriod() + length += bv.Value.(*BACnetScheduleObjectPeriod).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierRADIOSTATUS, + BACnetPropertyIdentifierRADIOSTATUS2: + bv.Value = NewBACnetRadioStatus() + length += bv.Value.(*BACnetRadioStatus).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierUSERINFORMATION, + BACnetPropertyIdentifierMACADDRESS: + bv.Value = NewBACnetMACAddress() + length += bv.Value.(*BACnetMACAddress).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierCOVMULTIPLESUBSCRIPTIONSFILTER, + BACnetPropertyIdentifierMONITORMULTIPLEBINARYINPUTS, + BACnetPropertyIdentifierMONITORMULTIPLEBINARYOUTPUTS, + BACnetPropertyIdentifierMULTIPLEMONITORING, + BACnetPropertyIdentifierSTOPWHENFULL, + BACnetPropertyIdentifierLIMITENABLE, + BACnetPropertyIdentifierDATAGROUPS, + BACnetPropertyIdentifierDEVICEADDRESSBINDING: + bv.Value = NewBACnetMultistateValue() + length += bv.Value.(*BACnetMultistateValue).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierLIGHTINGDEVICESTATUSALOGGING, + BACnetPropertyIdentifierLIGHTINGDEVICESTATUSLOGGING, + BACnetPropertyIdentifierDEVICEADDRESSBINDING, + BACnetPropertyIdentifierLIGHTINGDEVICEOPERATIONALMODE, + BACnetPropertyIdentifierLIGHTINGDEVICEOPERATIONALSTATUS, + BACnetPropertyIdentifierLIGHTINGGROUP, + BACnetPropertyIdentifierLIGHTINGGRP, + BACnetPropertyIdentifierLIGHTINGLOGGING: + bv.Value = NewBACnetLightingGroup() + length += bv.Value.(*BACnetLightingGroup).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierEVENTTIMESTAMPS: + bv.Value = NewBACnetTimeStampedValue() + length += bv.Value.(*BACnetTimeStampedValue).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGGROUP: + bv.Value = NewBACnetLightingGroup() + length += bv.Value.(*BACnetLightingGroup).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierNEGATIVEACCESSRULES, + BACnetPropertyIdentifierPOSITIVEACCESSRULES: + bv.Value = NewBACnetAccessRule() + length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierNETWORKADDRESS, + BACnetPropertyIdentifierMASTERKEY, + encoding.AccessUser, + encoding.AccessZone, + BACnetPropertyIdentifierAREADELIVERING, + BACnetPropertyIdentifierAREARELAY, + BACnetPropertyIdentifierCONTROLLING, + BACnetPropertyIdentifierDELIVERING, + BACnetPropertyIdentifierENROLLING, + BACnetPropertyIdentifierLOWLIMIT, + BACnetPropertyIdentifierMAXIMUMOUTPUT, + BACnetPropertyIdentifierMAXIMUMVALUE, + BACnetPropertyIdentifierMINIMUMOUTPUT, + BACnetPropertyIdentifierMINIMUMVALUE, + BACnetPropertyIdentifierEVENTTIME, + BACnetPropertyIdentifierTIMEDELAY, + BACnetPropertyIdentifierDURATION, + BACnetPropertyIdentifierEXCEPTIONALLIMITS, + BACnetPropertyIdentifierINACTIVESTATE, + BACnetPropertyIdentifierINSTANTANEOUS, + BACnetPropertyIdentifierINVALIDATED, + BACnetPropertyIdentifierLIMITENABLE, + BACnetPropertyIdentifierRELIABILITY, + BACnetPropertyIdentifierSCALE, + BACnetPropertyIdentifierSTEPINCREMENT, + BACnetPropertyIdentifierTIMER, + BACnetPropertyIdentifierLIMIT, + BACnetPropertyIdentifierMAXIMUM, + BACnetPropertyIdentifierMINIMUM, + BACnetPropertyIdentifierPULSESCALING, + BACnetPropertyIdentifierSHUTDOWN, + BACnetPropertyIdentifierBUFFERPROPERTY, + BACnetPropertyIdentifierSTREAMINGTHRESHOLDS: + bv.Value = NewBACnetOctetString() + length += bv.Value.(*BACnetOctetString).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierCOVMULTIPLESUBSCRIPTIONSFILTER, + encoding.MultiStateValue: + bv.Value = NewBACnetMultistateValue() + length += bv.Value.(*BACnetMultistateValue).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierAUTHENTICATIONFACTORSUPPLIED, + BACnetPropertyIdentifierAUTHENTICATIONFACTORFORMAT, + BACnetPropertyIdentifierAUTHENTICATIONPOLICYNAME, + BACnetPropertyIdentifierAUTHENTICATIONPOLICYNAMES, + BACnetPropertyIdentifierPOLICYNAMES: + bv.Value = NewBACnetAuthorization() + length += bv.Value.(*BACnetAuthorization).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierDEVICEIDENTIFICATION: + bv.Value = NewBACnetCharacterString() + length += bv.Value.(*BACnetCharacterString).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierEVENTTIMESTAMPS: + bv.Value = NewBACnetTimeStampedValue() + length += bv.Value.(*BACnetTimeStampedValue).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierDEVICEIDENTIFICATION: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierSHEDLEVELS: + bv.Value = NewBACnetShedLevel() + length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetPortFilter() + length += bv.Value.(*BACnetPortFilter).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPOLICY: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSRULES, + BACnetPropertyIdentifierINVALIDACTIONS, + BACnetPropertyIdentifierLOGGINGOBJECT, + BACnetPropertyIdentifierSAVERESTORESTATE: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACTIVESEQUENCE, + BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPORTFILTER, + BACnetPropertyIdentifierAUTHENTICATIONPOLICIES, + BACnetPropertyIdentifierAUTHENTICATIONPOLICYLIST: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPOLICYPASSWORD, + BACnetPropertyIdentifierPOLICYTYPE, + BACnetPropertyIdentifierTIMEDELAY, + BACnetPropertyIdentifierVERIFYPASSWORD, + BACnetPropertyIdentifierPORTPARAMETERS, + BACnetPropertyIdentifierDEVICEADDRESSBINDING: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierRELINQUISHDEFAULT, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSRULES, + BACnetPropertyIdentifierINVALIDACTIONS, + BACnetPropertyIdentifierLOGGINGOBJECT, + BACnetPropertyIdentifierSAVERESTORESTATE: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSSEQUENCE, + BACnetPropertyIdentifierACTIVESEQUENCE, + BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, + BACnetPropertyIdentifierFEEDINGPIPEINDEX, + BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE, + BACnetPropertyIdentifierSTATUSFLAGS: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICY, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPOLICYNAMES, + BACnetPropertyIdentifierACCESSRULES, + BACnetPropertyIdentifierLIMITDISABLE, + BACnetPropertyIdentifierMANUALSLIDERSETTINGS: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSRULES, + BACnetPropertyIdentifierINVALIDACTIONS, + BACnetPropertyIdentifierLOGGINGOBJECT, + BACnetPropertyIdentifierSAVERESTORESTATE: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPOLICYPASSWORD, + BACnetPropertyIdentifierPOLICYTYPE, + BACnetPropertyIdentifierTIMEDELAY, + BACnetPropertyIdentifierVERIFYPASSWORD: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, + BACnetPropertyIdentifierEXCEPTIONSCHEDULE, + BACnetPropertyIdentifierEVENTTIMESTAMPS: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierALARMVALUES: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierALARMVALUES, + BACnetPropertyIdentifierEVENTTYPE, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierSAFETYPOINTS: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCONTROLMODE: + bv.Value = NewBACnetLightingControlMode() + length += bv.Value.(*BACnetLightingControlMode).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierBACNETIPADDRESS, + BACnetPropertyIdentifierDEFAULTGATEWAY, + BACnetPropertyIdentifierIPADDRESS, + BACnetPropertyIdentifierSUBNETMASK: + bv.Value = NewBACnetIPAddress() + length += bv.Value.(*BACnetIPAddress).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetPortFilter() + length += bv.Value.(*BACnetPortFilter).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSRULES: + bv.Value = NewBACnetDeviceObjectReference() + length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierRELIABILITY, + BACnetPropertyIdentifierUNITS: + bv.Value = NewBACnetReliability() + length += bv.Value.(*BACnetReliability).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPARAMETERSETUSAGE: + bv.Value = NewBACnetParameterSetUsage() + length += bv.Value.(*BACnetParameterSetUsage).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, + BACnetPropertyIdentifierEXCEPTIONSCHEDULE, + BACnetPropertyIdentifierEXCEPTIONSCHEDULEDEFAULT, + BACnetPropertyIdentifierLIGHTINGCOMMAND: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGINGDEFAULT, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierEVENTCODE, + BACnetPropertyIdentifierLONMARKRESOURCE, + BACnetPropertyIdentifierPOLICIES: + bv.Value = NewBACnetUnsignedInteger() + length += bv.Value.(*BACnetUnsignedInteger).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCOMMAND: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, + BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: + bv.Value = NewBACnetLightingCommand() + length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierSAFETYPOINTS: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPOLICYPASSWORD, + BACnetPropertyIdentifierPOLICYTYPE, + BACnetPropertyIdentifierTIMEDELAY, + BACnetPropertyIdentifierVERIFYPASSWORD: + bv.Value = NewBACnetDeviceObjectPropertyReference() + length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICY, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierDEVICEIDENTIFICATION: + bv.Value = NewBACnetCharacterString() + length += bv.Value.(*BACnetCharacterString).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICY, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case encoding.AccessEvent, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + case BACnetPropertyIdentifierACCESSEVENTS, + BACnetPropertyIdentifierPOLICIES, + BACnetPropertyIdentifierPORTFILTER: + bv.Value = NewBACnetDeviceSecurityPolicy() + length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + default: + bv.Value = nil + } + } + return length, nil +} + +func (bv *BACnetValue) Encode() []byte { + if bv.Tag == nil { + // Handle NULL case + } else { + switch *bv.Tag { + case Boolean: + return encoding.EncodeApplicationBoolean(bv.Value.(bool)) + case UnsignedInt: + return encoding.EncodeApplicationUnsigned(bv.Value.(uint32)) + case SignedInt: + return encoding.EncodeApplicationSigned(bv.Value.(int32)) + case Real: + return encoding.EncodeApplicationReal(bv.Value.(float32)) + case Double: + return encoding.EncodeApplicationDouble(bv.Value.(float64)) + case OctetString: + return encoding.EncodeApplicationOctetString(bv.Value.([]byte), 0, len(bv.Value.([]byte))) + case CharacterString: + return encoding.EncodeApplicationCharacterString(bv.Value.(string)) + case BitString: + return encoding.EncodeApplicationBitString(b) + // Handle BIT_STRING case + // Add your code here... + case Enumerated: + // Handle ENUMERATED case + // Add your code here... + case Date: + // Handle DATE case + // Add your code here... + case Time: + // Handle TIME case + // Add your code here... + case BACnetObjectIdentifier: + // Handle BACNETOBJECTIDENTIFIER case + // Add your code here... + default: + log.Printf("Unsupported BACnetApplicationTag: %v", bv.Tag) + // Handle other BACnetApplicationTags as needed... + } + } + + return nil +} + +// BACnetRouterEntryStatus is an enumeration for the status of BACnetRouterEntry. +type BACnetRouterEntryStatus int + +const ( + Available BACnetRouterEntryStatus = iota + BACnetRouterEntryStatusBusy + Disconnected +) + +// BACnetRouterEntry represents a BACnet router entry. +type RouterEntry struct { + NetworkNumber uint32 + MACAddress []byte + Status BACnetRouterEntryStatus + PerformanceIndex uint32 +} + +// Decode decodes a RouterEntry from an encoded byte buffer. +func (entry *RouterEntry) Decode(buffer []byte, offset, apduLen int) (int, error) { + var length int + + // network_number + length1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset) + if tagNumber != byte(encoding.UnsignedInt) { + return -1, errors.New("Error decoding network_number") + } + length += length1 + length1, entry.NetworkNumber = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length += length1 + + // mac_address + length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if tagNumber != byte(encoding.OctetString) { + return -1, errors.New("Error decoding mac_address") + } + length += length1 + length1, entry.MACAddress = encoding.DecodeOctetString(buffer, offset+length, int(lenValue)) + length += length1 + + // status + length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if tagNumber != byte(encoding.Enumerated) { + return -1, errors.New("Error decoding status") + } + length += length1 + length1, Val := encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length += length1 + entry.Status = BACnetRouterEntryStatus(Val) + + // performance_index (optional) + if offset < apduLen { + length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if tagNumber != byte(encoding.UnsignedInt) { + length += length1 + length1, entry.PerformanceIndex = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length += length1 + } + } + + return length, nil +} + +type BACnetVTSession struct { + LocalVTSessionID int + RemoteVTSessionID int + RemoteVTAddress BACnetAddress +} + +// decode method for BACnetVTSession +func (b *BACnetVTSession) Decode(buffer []byte, offset, apduLen int) int { + // Implement decode logic here + return -1 +} + +// BACnetAccessThreatLevel struct definition +type BACnetAccessThreatLevel struct { + Value int +} + +// decode method for BACnetAccessThreatLevel +func (b *BACnetAccessThreatLevel) Decode(buffer []byte, offset, apduLen int) int { + // Implement decode logic here + return -1 +} + +type BACnetDestination struct { + ValidDays *BACnetDaysOfWeek + FromTime time.Time + ToTime time.Time + Recipient *BACnetRecipient + ProcessIdentifier uint32 + IssueConfirmedNotifications bool + Transitions *BACnetEventTransitionBits +} + +func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.BitString) { + return -1 + } + leng += leng1 + b.ValidDays = &BACnetDaysOfWeek{} + + leng1 = b.ValidDays.Decode(buffer, offset+leng, int(lenValue)) + + if leng1 < 0 { + return -1 + } + leng += leng1 + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.Time) { + return -1 + } + leng += leng1 + leng1, b.FromTime = encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) + + leng += leng1 + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.Time) { + return -1 + } + leng += leng1 + leng1, b.ToTime = encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) + + leng += leng1 + + b.Recipient = &BACnetRecipient{} + leng1 = b.Recipient.Decode(buffer, offset+leng, apduLen-leng) + + if leng1 < 0 { + return -1 + } + leng += leng1 + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.UnsignedInt) { + return -1 + } + leng += leng1 + leng1, b.ProcessIdentifier = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + + leng += leng1 + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.Boolean) { + return -1 + } + leng += leng1 + if lenValue > 0 { + b.IssueConfirmedNotifications = true + } else { + b.IssueConfirmedNotifications = false + } + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != byte(encoding.BitString) { + return -1 + } + leng += leng1 + + b.Transitions = &BACnetEventTransitionBits{} + leng1 = b.Transitions.Decode(buffer, offset+leng, int(lenValue)) + if leng1 < 0 { + return -1 + } + leng += leng1 + + return leng +} + +type BACnetDaysOfWeek struct { + unusedBits byte + bitString BACnetBitString + monday bool + tuesday bool + wednesday bool + thursday bool + friday bool + saturday bool + sunday bool +} + +func NewBACnetDaysOfWeek() *BACnetDaysOfWeek { + return &BACnetDaysOfWeek{ + unusedBits: 1, + bitString: *NewBACnetBitString(1, *internal.NewBitArray(8)), + } +} + +func (d *BACnetDaysOfWeek) String() string { + return fmt.Sprintf("%08b", d.bitString.Value) +} + +func (d *BACnetDaysOfWeek) Decode(buffer []byte, offset int, apduLen int) int { + d.bitString = BACnetBitString{} + return d.bitString.Decode(buffer, offset, apduLen) +} + +func (d *BACnetDaysOfWeek) SetDay(day int, value bool) error { + if day < 0 || day > 6 { + return fmt.Errorf("Day index out of range") + } + d.bitString.Value.Set(day, value) + return nil +} + +func (d *BACnetDaysOfWeek) GetDay(day int) (bool, error) { + if day < 0 || day > 6 { + return false, fmt.Errorf("Day index out of range") + } + return d.bitString.Value.Get(day) == true, nil +} + +type BACnetBitString struct { + UnusedBits byte + Value internal.BitArray +} + +func NewBACnetBitString(unusedBits byte, value internal.BitArray) *BACnetBitString { + return &BACnetBitString{ + UnusedBits: unusedBits, + Value: value, + } +} + +func (b *BACnetBitString) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + if apduLen > 0 { + b.UnusedBits = buffer[offset] + leng += 1 + b.Value = *internal.NewBitArray((apduLen - 1) * 8) + bit := 0 + for i := 1; i < apduLen; i++ { + for i2 := 0; i2 < 8; i2++ { + b.Value.Set(bit, buffer[offset+i]&(1<<(7-i2)) != 0) + bit++ + } + } + } + return apduLen +} + +type BACnetRecipient struct { + Value interface{} +} + +func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + + if tagNumber == 0 { + // device_identifier + leng += leng1 + br.Value = &ObjectIdentifier{} + leng += br.Value.(*ObjectIdentifier).Decode(buffer, offset+leng, int(lenValue)) + } else if tagNumber == 1 { + // address + br.Value = &BACnetAddress{} + leng += br.Value.(*BACnetAddress).Decode(buffer, offset+leng, int(lenValue)) + } else { + return -1 + } + + return leng +} + +// BACnetEventTransitionBits represents a BACnet event transition bits structure. +type BACnetEventTransitionBits struct { + UnusedBits uint8 + BitString *BACnetBitString +} + +// NewBACnetEventTransitionBits creates a new BACnet event transition bits instance. +func NewBACnetEventTransitionBits() *BACnetEventTransitionBits { + return &BACnetEventTransitionBits{ + UnusedBits: 5, + BitString: NewBACnetBitString(5, *internal.NewBitArray(5)), + } +} + +// Decode decodes the bit string from a buffer. +func (e *BACnetEventTransitionBits) Decode(buffer []byte, offset, apduLen int) int { + bitString := NewBACnetBitString(0, internal.BitArray{}) + decodedLen := bitString.Decode(buffer, offset, apduLen) + + e.BitString = bitString + return decodedLen +} + +// ToOffNormal returns the value of ToOffNormal property. +func (e *BACnetEventTransitionBits) ToOffNormal() bool { + return e.BitString.Value.Get(0) == true +} + +// SetToOffNormal sets the value of ToOffNormal property. +func (e *BACnetEventTransitionBits) SetToOffNormal(a bool) { + e.BitString.Value.Set(0, a) +} + +// ToFault returns the value of ToFault property. +func (e *BACnetEventTransitionBits) ToFault() bool { + return e.BitString.Value.Get(1) == true +} + +// SetToFault sets the value of ToFault property. +func (e *BACnetEventTransitionBits) SetToFault(a bool) { + e.BitString.Value.Set(1, a) +} + +// ToNormal returns the value of ToNormal property. +func (e *BACnetEventTransitionBits) ToNormal() bool { + return e.BitString.Value.Get(2) == true +} + +// SetToNormal sets the value of ToNormal property. +func (e *BACnetEventTransitionBits) SetToNormal(a bool) { + e.BitString.Value.Set(2, a) +} diff --git a/pkg/encoding/decoding.go b/pkg/encoding/decoding.go index 52065e5..84b8717 100644 --- a/pkg/encoding/decoding.go +++ b/pkg/encoding/decoding.go @@ -1,5 +1,11 @@ package encoding +import ( + "encoding/binary" + "math" + "time" +) + type BacnetCharacterStringEncodings int const ( @@ -93,3 +99,48 @@ func decodeContextCharacterString(buffer []byte, offset, maxLength int, tagNumbe return leng, charString } + +func DecodeSigned(buffer []byte, offset int, lenValue int) (int, int) { + value := 0 + for i := 0; i < lenValue; i++ { + value += int(buffer[offset+i]) << uint(8*(lenValue-i-1)) + } + // Check if it is negative + if value > int(math.Pow(256, float64(lenValue))/2)-1 { + value = -(int(math.Pow(256, float64(lenValue))) - value) + } + return lenValue, value +} + +func decodeReal(buffer []byte, offset int) (int, float32) { + value := binary.BigEndian.Uint32(buffer[offset : offset+4]) + return 4, math.Float32frombits(value) +} + +func DecodeRealSafe(buffer []byte, offset int, lenValue int) (int, float32) { + if lenValue != 4 { + value := float32(0.0) + return lenValue, value + } + return decodeReal(buffer, offset) +} + +func decodeDouble(buffer []byte, offset int) (int, float64) { + value := binary.BigEndian.Uint64(buffer[offset : offset+8]) + return 8, math.Float64frombits(value) +} + +func DecodeDoubleSafe(buffer []byte, offset int, lenValue int) (int, float64) { + if lenValue != 8 { + value := float64(0.0) + return lenValue, value + } + return decodeDouble(buffer, offset) +} + +func DecodeBACnetTimeSafe(buf []byte, offset, lenVal int) (int, time.Time) { + if lenVal != 4 { + return lenVal, time.Time{} + } + return decodeBACnetTime(buf, offset) +} diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index 5b85e75..b537c83 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -3,6 +3,7 @@ package encoding import ( "bytes" "encoding/binary" + "math" ) const ( @@ -106,3 +107,35 @@ func encodeBACnetCharacterString(value string) []byte { encodedValue := []byte(value) return append(encoding, encodedValue...) } + +func EncodeApplicationBoolean(val bool) []byte { + if val { + return EncodeTag(Boolean, false, 1) + } + return EncodeTag(Boolean, false, 0) +} + +func EncodeApplicationSigned(val int32) []byte { + tmp := EncodeSigned(val) + return append(EncodeTag(SignedInt, false, len(tmp)), tmp...) +} + +func EncodeApplicationReal(val float32) []byte { + return append(EncodeTag(Real, false, 4), encodeBACnetReal(val)...) +} + +func EncodeApplicationDouble(val float64) []byte { + return append(EncodeTag(Double, false, 8), encodeBACnetDouble(val)...) +} + +func encodeBACnetReal(value float32) []byte { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, math.Float32bits(value)) + return buf +} + +func encodeBACnetDouble(value float64) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, math.Float64bits(value)) + return buf +} diff --git a/pkg/encoding/tags.go b/pkg/encoding/tags.go index 0507038..8bd9239 100644 --- a/pkg/encoding/tags.go +++ b/pkg/encoding/tags.go @@ -41,15 +41,6 @@ func IsContextSpecific(b byte) bool { return (b & 0x8) == 0x8 } -func decodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { - len = 1 - - if isExtendedTagNumber(buf[offset]) { - return len + 1, buf[offset+len] - } - return len, buf[offset] >> 4 -} - func IsContextTag(buf []byte, offset int, tagNum byte) bool { _, myTagNum := decodeTagNumber(buf, offset) return IsContextSpecific(buf[offset]) && myTagNum == tagNum @@ -90,8 +81,9 @@ func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val } -func DecodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { +func decodeTagNumber(buf []byte, offset int) (len int, tagNum byte) { len = 1 + if isExtendedTagNumber(buf[offset]) { return len + 1, buf[offset+len] } @@ -132,3 +124,13 @@ func EncodeTag(tagNum BACnetApplicationTag, ctxSpecific bool, lenVal int) []byte return append(tag, EncodeUnsigned(uint32(lenVal))...) } } + +func IsOpeningTagNumber(buf []byte, offset int, tagNum byte) bool { + _, myTagNum := decodeTagNumber(buf, offset) + return isOpeningTag(buf[offset]) && myTagNum == tagNum +} + +func IsClosingTagNumber(buf []byte, offset int, tagNum byte) bool { + _, myTagNum := decodeTagNumber(buf, offset) + return isClosingTag(buf[offset]) && myTagNum == tagNum +} From 0c7837d5faeb4f2803b28e1a3910f67f9e35b714 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Wed, 13 Sep 2023 19:06:03 +0300 Subject: [PATCH 16/24] Fix error handling in BACnetValue.Decode() The BACnetValue.Decode() method now returns an error to handle decoding errors properly. - The method signature has been updated to return (int, error) - If there is an error during decoding, the method now returns (-1, err) This change ensures that decoding errors are properly handled and allows for better error reporting and debugging. Signed-off-by: SammyOina --- pkg/bacnet/property.go | 284 +++++++++++++++++++++++++++++++++++--- pkg/encoding/date_time.go | 2 +- 2 files changed, 266 insertions(+), 20 deletions(-) diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index f91fe9e..f4d950d 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -137,7 +137,7 @@ type BACnetValue struct { Value interface{} } -func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encoding.ObjectType, propID encoding.PropertyIdentifier) int { +func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encoding.ObjectType, propID encoding.PropertyIdentifier) (int, error) { length := 0 var err error @@ -167,7 +167,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi length-- decodeLen, err = bv.Value.(*RouterEntry).Decode(buffer, offset+length, apduLen) if err != nil { - return -1 + return -1, err } } else if propID == encoding.ActiveVtSessions { bv.Tag = nil @@ -214,7 +214,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi case encoding.StatusFlags: bv.Tag = nil bitValue := &BACnetStatusFlags{} - decodeLen = bitValue.Decode(buffer, offset, lenValueType) + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.EventEnable, encoding.AckedTransitions: bv.Tag = nil @@ -224,33 +224,35 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi case encoding.LimitEnable: bv.Tag = nil bitValue := &BACnetLimitEnable{} - decodeLen = bitValue.Decode(buffer, offset, lenValueType) + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.ProtocolObjectTypesSupported: bv.Tag = nil bitValue := &BACnetObjectTypesSupported{} - decodeLen = bitValue.Decode(buffer, offset, lenValueType) + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.ProtocolServicesSupported: bv.Tag = nil bitValue := &BACnetServicesSupported{} - decodeLen = bitValue.Decode(buffer, offset, lenValueType) + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue default: bitValue := &BACnetBitString{} - decodeLen = bitValue.Decode(buffer, offset, lenValueType) + decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue } case Enumerated: - decodeLen, uintValue := encoding.DecodeEnumerated(buffer, offset+length, lenValueType, objType, propID) - bv.Value = uintValue + decodeLen, bv.Value = encoding.DecodeEnumerated(buffer, offset+length, lenValueType, &objType, &propID) case Date: switch propID { case encoding.EffectivePeriod: bv.Tag = nil - bv.Value = NewBACnetDateRange() + bv.Value = &BACnetDateRange{} length-- - decodeLen = bv.Value.(*BACnetDateRange).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*BACnetDateRange).Decode(buffer, offset+length, apduLen) + if err != nil { + return -1, err + } case encoding.MinimumValueTimestamp, encoding.MaximumValueTimestamp, encoding.ChangeOfStateTime, @@ -273,23 +275,20 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi length-- decodeLen = bv.Value.(*DateTime).Decode(buffer, offset+length) default: - decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+length, lenValueType) - bv.Value = dateValue + decodeLen, bv.Value = encoding.DecodeDateSafe(buffer, offset+length, int(lenValueType)) } if (objType == encoding.DateTimeValue || objType == encoding.TimePatternValue) && (propID == encoding.PresentValue || propID == encoding.RelinquishDefault) { - decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+length, lenValueType) - bv.Value = dateValue + decodeLen, bv.Value = encoding.DecodeDateSafe(buffer, offset+length, int(lenValueType)) } case Time: - decodeLen, timeValue := encoding.DecodeBACnetTimeSafe(buffer, offset+length, lenValueType) - bv.Value = timeValue + decodeLen, bv.Value = encoding.DecodeBACnetTimeSafe(buffer, offset+length, int(lenValueType)) case BACnetObjectIdentifier: if propID == encoding.LastKeyServer || propID == encoding.ManualSlaveAddressBinding || propID == encoding.SlaveAddressBinding || propID == encoding.DeviceAddressBinding { bv.Tag = nil - bv.Value = NewBACnetAddressBinding() + bv.Value = &BACnetAddressBinding{} length-- decodeLen = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) } else { @@ -302,7 +301,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi } if decodeLen < 0 { - return -1 + return -1, fmt.Errorf("no tags decoded") } length += decodeLen } @@ -1224,3 +1223,250 @@ func (e *BACnetEventTransitionBits) ToNormal() bool { func (e *BACnetEventTransitionBits) SetToNormal(a bool) { e.BitString.Value.Set(2, a) } + +// BACnetStatusFlags represents a BACnet status flags. +type BACnetStatusFlags struct { + unusedbits int + bitstring BACnetBitString + inalarm bool + fault bool + overridden bool + outofservice bool +} + +// NewBACnetStatusFlags creates a new BACnetStatusFlags instance. +func NewBACnetStatusFlags() *BACnetStatusFlags { + return &BACnetStatusFlags{ + unusedbits: 4, + bitstring: *NewBACnetBitString(4, *internal.NewBitArrayFromByte(0x00)), + inalarm: false, + fault: false, + overridden: false, + outofservice: false, + } +} + +// ASN1decode decodes BACnetStatusFlags from a buffer. +func (s *BACnetStatusFlags) Decode(buffer []byte, offset, apduLen int) int { + s.bitstring = *NewBACnetBitString(byte(s.unusedbits), *internal.NewBitArrayFromByte(0x00)) + return s.bitstring.Decode(buffer, offset, apduLen) +} + +// InAlarm returns the inalarm property. +func (s *BACnetStatusFlags) InAlarm() bool { + return s.bitstring.Value.Get(0) +} + +// SetInAlarm sets the inalarm property. +func (s *BACnetStatusFlags) SetInAlarm(a bool) { + s.bitstring.Value.Set(0, a) +} + +// Fault returns the fault property. +func (s *BACnetStatusFlags) Fault() bool { + return s.bitstring.Value.Get(1) +} + +// SetFault sets the fault property. +func (s *BACnetStatusFlags) SetFault(a bool) { + s.bitstring.Value.Set(1, a) +} + +// Overridden returns the overridden property. +func (s *BACnetStatusFlags) Overridden() bool { + return s.bitstring.Value.Get(2) +} + +// SetOverridden sets the overridden property. +func (s *BACnetStatusFlags) SetOverridden(a bool) { + s.bitstring.Value.Set(2, a) +} + +// OutOfService returns the outofservice property. +func (s *BACnetStatusFlags) OutOfService() bool { + return s.bitstring.Value.Get(3) +} + +// SetOutOfService sets the outofservice property. +func (s *BACnetStatusFlags) SetOutOfService(a bool) { + s.bitstring.Value.Set(3, a) +} + +type BACnetLimitEnable struct { + unusedBits uint8 + bitString BACnetBitString + lowLimitEnable bool + highLimitEnable bool +} + +func NewBACnetLimitEnable() *BACnetLimitEnable { + return &BACnetLimitEnable{ + unusedBits: 6, + bitString: *NewBACnetBitString(6, *internal.NewBitArrayFromByte(0x00)), + lowLimitEnable: false, + highLimitEnable: false, + } +} + +func (b *BACnetLimitEnable) Decode(buffer []byte, offset, apduLen int) int { + b.bitString = *NewBACnetBitString(0, *internal.NewBitArrayFromByte(0x00)) + return b.bitString.Decode(buffer, offset, apduLen) +} + +func (b *BACnetLimitEnable) LowLimitEnable() bool { + return b.bitString.Value.Get(0) +} + +func (b *BACnetLimitEnable) SetLowLimitEnable(a bool) { + b.bitString.Value.Set(0, a) +} + +func (b *BACnetLimitEnable) HighLimitEnable() bool { + return b.bitString.Value.Get(1) +} + +func (b *BACnetLimitEnable) SetHighLimitEnable(a bool) { + b.bitString.Value.Set(1, a) +} + +type BACnetObjectTypesSupported struct { + unusedbits uint8 + bitstring BACnetBitString +} + +type ObjectTypesSupportedProperty int + +const ( + AnalogInput ObjectTypesSupportedProperty = iota + AanalofOutput + AnalogValue + BinaryInput + BinaryOutput + // TODO Add other properties here +) + +func NewBACnetObjectTypesSupported() *BACnetObjectTypesSupported { + return &BACnetObjectTypesSupported{ + unusedbits: 3, + bitstring: *NewBACnetBitString(3, *internal.NewBitArray(64)), + } +} + +func (b *BACnetObjectTypesSupported) Set(property ObjectTypesSupportedProperty, value bool) { + b.bitstring.Value.Set(int(property), value) +} + +func (b *BACnetObjectTypesSupported) Get(property ObjectTypesSupportedProperty) bool { + return b.bitstring.Value.Get(int(property)) +} + +func (b *BACnetObjectTypesSupported) Decode(buf []byte, offset, apduLen int) int { + return b.bitstring.Decode(buf, offset, apduLen) +} + +type BACnetServicesSupported struct { + unusedbits uint8 + bitstring BACnetBitString +} + +type ServicesSupportedProperty int + +// TODO check index sequence +const ( + acknowledgeAlarm ServicesSupportedProperty = iota + confirmedCOVNotification + confirmedCOVNotificationMultiple + confirmedEventNotification + getAlarmSummary + getEnrollmentSummary + getEventInformation + lifeSafetyOperation + subscribeCOV + subscribeCOVProperty + subscribeCOVPropertyMultiple + atomicReadFile + atomicWriteFile + addListElement + removeListElement + createObject + deleteObject + readProperty + readPropertyMultiple + readRange + writeGroup + writeProperty + writePropertyMultiple + deviceCommunicationControl + confirmedPrivateTransfer + confirmedTextMessage + reinitializeDevice + vtOpen + vtClose + vtData + whoAmI + youAre + iAm + iHave + unconfirmedCOVNotification + unconfirmedCOVNotificationMultiple + unconfirmedEventNotification + unconfirmedPrivateTransfer + unconfirmedTextMessage + timeSynchronization + utcTimeSynchronization + whoHas + whoIs +) + +func NewBACnetServicesSupported() *BACnetServicesSupported { + return &BACnetServicesSupported{ + unusedbits: 7, + bitstring: *NewBACnetBitString(7, *internal.NewBitArrayFromByte(0x00000000000000)), + } +} + +func (b *BACnetServicesSupported) Set(property ServicesSupportedProperty, value bool) { + b.bitstring.Value.Set(int(property), value) +} + +func (b *BACnetServicesSupported) Get(property ServicesSupportedProperty) bool { + return b.bitstring.Value.Get(int(property)) +} + +func (b *BACnetServicesSupported) Decode(buf []byte, offset, apduLen int) int { + return b.bitstring.Decode(buf, offset, apduLen) +} + +// BACnetDateRange is a struct representing a date range in BACnet. +type BACnetDateRange struct { + StartDate time.Time + EndDate time.Time +} + +// Decode decodes a BACnetDateRange from the given buffer, offset, and length. +func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, error) { + var leng int + + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(Date) { + leng += leng1 + leng1, startDate := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) + dr.StartDate = startDate + leng += leng1 + } else { + return -1, fmt.Errorf("Unexpected tag number: %v", tagNumber) + } + + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber == byte(Date) { + leng += leng1 + leng1, endDate := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) + + dr.EndDate = endDate + leng += leng1 + } else { + return -1, fmt.Errorf("Unexpected tag number: %v", tagNumber) + } + + return leng, nil +} diff --git a/pkg/encoding/date_time.go b/pkg/encoding/date_time.go index a1a7250..a47f305 100644 --- a/pkg/encoding/date_time.go +++ b/pkg/encoding/date_time.go @@ -31,7 +31,7 @@ func decodeDate(buf []byte, offset int) (int, time.Time) { return 4, time.Date(int(year)+1900, time.Month(month), int(day), 0, 0, 0, 0, nil) } -func decodeDateSafe(buf []byte, offset, lenVal int) (int, time.Time) { +func DecodeDateSafe(buf []byte, offset, lenVal int) (int, time.Time) { if lenVal != 4 { return lenVal, time.Time{} } From 42fcc509ce0d05eb4c55d45957fc689813fb35fb Mon Sep 17 00:00:00 2001 From: SammyOina Date: Thu, 14 Sep 2023 00:17:01 +0300 Subject: [PATCH 17/24] Fix decoding error for object_identifier and property_identifier in ReadPropertyACK.Decode() method The decoding error for object_identifier and property_identifier in the ReadPropertyACK.Decode() method has been fixed. This change ensures that the error message accurately reflects the cause of the decoding failure. This commit addresses the following changes: - Updated error message for object_identifier decoding error - Updated error message for property_identifier decoding error Signed-off-by: SammyOina --- pkg/bacnet/property.go | 305 ++++++++++++++++++++++++++++++++++++--- pkg/encoding/decoding.go | 20 +++ 2 files changed, 308 insertions(+), 17 deletions(-) diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index f4d950d..52c3483 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -86,7 +86,7 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error leng1 := r.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) leng += leng1 } else { - return -1, errors.New("ASN.1 decoding error for object_identifier") + return -1, errors.New("decoding error for object_identifier") } // 2 propertyidentifier @@ -98,7 +98,7 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error r.PropertyIdentifier = propID leng += leng1 } else { - return -1, errors.New("ASN.1 decoding error for property_identifier") + return -1, errors.New("decoding error for property_identifier") } // 2 property_array_index @@ -116,17 +116,20 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) && leng < apduLen { bValue := BACnetValue{} propId := r.PropertyIdentifier.(encoding.PropertyIdentifier) - leng1 := bValue.Decode(buffer, offset+leng, apduLen-leng, r.ObjectIdentifier.Type, propId) + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng, r.ObjectIdentifier.Type, propId) + if err != nil { + return -1, err + } leng += leng1 r.PropertyValue = append(r.PropertyValue, bValue) } if encoding.IsClosingTagNumber(buffer, offset+leng, 3) { leng++ } else { - return -1, errors.New("ASN.1 decoding error for property_value") + return -1, errors.New("decoding error for property_value") } } else { - return -1, errors.New("ASN.1 decoding error for property_value") + return -1, errors.New("decoding error for property_value") } return leng, nil @@ -292,8 +295,10 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi length-- decodeLen = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) } else { - decodeLen, objectType, instance := encoding.DecodeObjectIDSafe(buffer, offset+length, lenValueType) - bv.Value = ObjectIdentifier{Type: objectType, Instance: instance} + var objectType encoding.ObjectType + var instance uint32 + decodeLen, objectType, instance = encoding.DecodeObjectIDSafe(buffer, offset+length, lenValueType) + bv.Value = ObjectIdentifier{Type: objectType, Instance: ObjectInstance(instance)} } default: log.Println("Unhandled tag:", bv.Tag) @@ -308,17 +313,25 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi } else { switch propID { case encoding.BacnetIpGlobalAddress, encoding.FdBbmdAddress: - bv.Value = NewBACnetHostNPort() - length += bv.Value.(*BACnetHostNPort).Decode(buffer, offset+length, apduLen-length) + bv.Value = &BACnetHostNPort{} + length1, err := bv.Value.(*BACnetHostNPort).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.UtcTimeSynchronizationRecipients, encoding.RestartNotificationRecipients, encoding.TimeSynchronizationRecipients, encoding.CovuRecipients: - bv.Value = NewBACnetRecipient() + bv.Value = &BACnetRecipient{} length += bv.Value.(*BACnetRecipient).Decode(buffer, offset+length, apduLen-length) case encoding.KeySets: - bv.Value = NewBACnetSecurityKeySet() - length += bv.Value.(*BACnetSecurityKeySet).Decode(buffer, offset+length, apduLen-length) + bv.Value = &BACnetSecurityKeySet{} + length1, err := bv.Value.(*BACnetSecurityKeySet).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.EventTimeStamps, encoding.LastCommandTime, encoding.CommandTimeArray, @@ -326,13 +339,17 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi encoding.TimeOfDeviceRestart, encoding.AccessEventTime, encoding.UpdateTime: - bv.Value = NewBACnetTimeStamp() - length += bv.Value.(*BACnetTimeStamp).Decode(buffer, offset+length, apduLen-length) + bv.Value = &BACnetTimeStamp{} + length1, err := bv.Value.(*BACnetTimeStamp).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.ListOfGroupMembers: - bv.Value = NewReadAccessSpecification() + bv.Value = &ReadAccessSpecification{} length += bv.Value.(*ReadAccessSpecification).Decode(buffer, offset+length, apduLen-length) case encoding.ListOfObjectPropertyReferences: - bv.Value = NewBACnetDeviceObjectPropertyReference() + bv.Value = &BACnetDeviceObjectPropertyReference{} length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) case encoding.MemberOf, encoding.ZoneMembers, @@ -1246,7 +1263,7 @@ func NewBACnetStatusFlags() *BACnetStatusFlags { } } -// ASN1decode decodes BACnetStatusFlags from a buffer. +// decode decodes BACnetStatusFlags from a buffer. func (s *BACnetStatusFlags) Decode(buffer []byte, offset, apduLen int) int { s.bitstring = *NewBACnetBitString(byte(s.unusedbits), *internal.NewBitArrayFromByte(0x00)) return s.bitstring.Decode(buffer, offset, apduLen) @@ -1470,3 +1487,257 @@ func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, erro return leng, nil } + +type BACnetAddressBinding struct { + DeviceIdentifier ObjectIdentifier + DeviceAddress BACnetAddress +} + +func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen int) int { + length := 0 + length1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+length) + + // device_identifier + if tagNumber == byte(BACnetObjectIdentifier) { + length += length1 + binding.DeviceIdentifier = ObjectIdentifier{} + length += binding.DeviceIdentifier.Decode(buffer, offset+length, int(lenValue)) + } else { + return -1 + } + + length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + + if tagNumber == byte(UnsignedInt) { + binding.DeviceAddress = BACnetAddress{} + length += binding.DeviceAddress.Decode(buffer, offset+length, int(lenValue)) + } else { + return -1 + } + + return length +} + +type BACnetHostNPort struct { + Host *BACnetHostAddress + Port uint32 +} + +func (b *BACnetHostNPort) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + if !encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { + return -1, errors.New("Invalid opening tag") + } + leng++ + b.Host = &BACnetHostAddress{} + hostLen, err := b.Host.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + leng += hostLen + leng++ + + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 1 { + leng1, b.Port = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Invalid tag number") + } + } else { + return -1, errors.New("Invalid context tag") + } + + return leng, nil +} + +type BACnetHostAddress struct { + Value interface{} +} + +func (b *BACnetHostAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + + switch tagNumber { + case byte(Null): + leng += leng1 + b.Value = nil + case byte(OctetString): + leng += leng1 + leng1, octetString := encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) + b.Value = octetString + leng += leng1 + case byte(CharacterString): + leng += leng1 + leng1, characterString := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) + b.Value = characterString + leng += leng1 + default: + return -1, errors.New("Invalid tag number") + } + + return leng, nil +} + +type BACnetSecurityKeySet struct { + KeyRevision uint32 + ActivationTime *DateTime + ExpirationTime *DateTime + KeyIDs []*BACnetKeyIdentifier +} + +func (b *BACnetSecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + // key_revision + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 0 { + leng1, b.KeyRevision = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Invalid tag number") + } + } else { + return -1, errors.New("Invalid context tag") + } + + // activation_time + if encoding.IsOpeningTagNumber(buffer, offset+leng, 1) { + leng++ + b.ActivationTime = &DateTime{} + leng1 := b.ActivationTime.Decode(buffer, offset+leng) + leng += leng1 + } else { + return -1, errors.New("Invalid opening tag for activation_time") + } + + // expiration_time + if encoding.IsOpeningTagNumber(buffer, offset+leng, 2) { + leng++ + b.ExpirationTime = &DateTime{} + leng1 := b.ExpirationTime.Decode(buffer, offset+leng) + leng += leng1 + } else { + return -1, errors.New("Invalid opening tag for expiration_time") + } + + b.KeyIDs = make([]*BACnetKeyIdentifier, 0) + if encoding.IsOpeningTagNumber(buffer, offset+leng, 3) && leng < apduLen { + leng++ + for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) { + bValue := &BACnetKeyIdentifier{} + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + b.KeyIDs = append(b.KeyIDs, bValue) + leng += leng1 + } + leng++ + } else { + return -1, errors.New("Invalid opening tag for key_ids or unexpected end of data") + } + + return leng, nil +} + +type BACnetKeyIdentifier struct { + Algorithm uint32 + KeyID uint32 +} + +func (b *BACnetKeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + // algorithm + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 0 { + leng1, b.Algorithm = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Invalid tag number for algorithm") + } + } else { + return -1, errors.New("Invalid context tag for algorithm") + } + + // key_id + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 1 { + leng1, b.KeyID = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Invalid tag number for key_id") + } + } else { + return -1, errors.New("Invalid context tag for key_id") + } + + return leng, nil +} + +type BACnetTimeStamp struct { + Value interface{} +} + +func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + if encoding.IsContextTag(buffer, offset+leng, 2) { + // BACnetDateTime + leng1, tagNumber, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 2 { + b.Value = &DateTime{} + leng1 := b.Value.(*DateTime).Decode(buffer, offset+leng) + leng += leng1 + } else { + return -1, errors.New("Invalid tag number for BACnetDateTime") + } + } else if encoding.IsContextTag(buffer, offset+leng, 1) { + // sequence number + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 1 { + leng1, seqNum := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + b.Value = seqNum + leng += leng1 + } else { + return -1, errors.New("Invalid tag number for sequence number") + } + } else if encoding.IsContextTag(buffer, offset+leng, 0) { + // time + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 0 { + leng1, bacnetTime := encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) + b.Value = bacnetTime + leng += leng1 + } else { + return -1, errors.New("Invalid tag number for time") + } + } else { + return -1, errors.New("Invalid context tag") + } + + return leng, nil +} + +func (b *BACnetTimeStamp) Encode() []byte { + // Implement the encoding logic as needed for your specific application. + return nil +} + +func (b *BACnetTimeStamp) EncodeContext(tagNumber encoding.BACnetApplicationTag) []byte { + tmp := b.Encode() + return append(encoding.EncodeTag(tagNumber, true, len(tmp)), tmp...) +} diff --git a/pkg/encoding/decoding.go b/pkg/encoding/decoding.go index 84b8717..0cf82de 100644 --- a/pkg/encoding/decoding.go +++ b/pkg/encoding/decoding.go @@ -144,3 +144,23 @@ func DecodeBACnetTimeSafe(buf []byte, offset, lenVal int) (int, time.Time) { } return decodeBACnetTime(buf, offset) } + +func decodeObjectID(buffer []byte, offset int) (int, ObjectType, uint32) { + var value uint32 + var leng int + + leng, value = DecodeUnsigned(buffer, offset, 4) + + objectInstance := value & MaxInstance + + objectType := ObjectType((int(value) >> InstanceBits) & MaxObject) + + return leng, objectType, objectInstance +} + +func DecodeObjectIDSafe(buffer []byte, offset int, lenValue uint32) (int, ObjectType, uint32) { + if lenValue != 4 { + return 0, 0, 0 + } + return decodeObjectID(buffer, offset) +} From b8a8db0e0f62792056569fab8e830844d06999e5 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 15 Sep 2023 00:59:58 +0300 Subject: [PATCH 18/24] Fix decoding error in BACnetValue.Decode() The BACnetValue.Decode() method was updated to handle decoding errors in the ReadAccessSpecification and BACnetDeviceObjectPropertyReference types. This ensures that the decoding process is accurate and reliable. Signed-off-by: SammyOina --- pkg/bacnet/property.go | 434 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 423 insertions(+), 11 deletions(-) diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 52c3483..907a249 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -347,10 +347,16 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi length += length1 case encoding.ListOfGroupMembers: bv.Value = &ReadAccessSpecification{} - length += bv.Value.(*ReadAccessSpecification).Decode(buffer, offset+length, apduLen-length) + length, err = bv.Value.(*ReadAccessSpecification).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } case encoding.ListOfObjectPropertyReferences: bv.Value = &BACnetDeviceObjectPropertyReference{} - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + length, err = bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } case encoding.MemberOf, encoding.ZoneMembers, encoding.DoorMembers, @@ -371,33 +377,36 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi encoding.BelongsTo, encoding.LastAccessPoint, encoding.EnergyMeterRef: - bv.Value = NewBACnetDeviceObjectReference() + bv.Value = &BACnetDeviceObjectReference{} length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) case encoding.EventAlgorithmInhibitRef, encoding.InputReference, encoding.ManipulatedVariableReference, encoding.ControlledVariableReference: - bv.Value = NewBACnetObjectPropertyReference() + bv.Value = &BACnetObjectPropertyReference{} length += bv.Value.(*BACnetObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) case encoding.LoggingRecord: - bv.Value = NewBACnetAccumulatorRecord() - length += bv.Value.(*BACnetAccumulatorRecord).Decode(buffer, offset+length, apduLen-length) + bv.Value = &BACnetAccumulatorRecord{} + length, err = bv.Value.(*BACnetAccumulatorRecord).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } case encoding.Action: - bv.Value = NewBACnetActionList() + bv.Value = &BACnetActionList{} length += bv.Value.(*BACnetActionList).Decode(buffer, offset+length, apduLen-length) case encoding.Scale: - bv.Value = NewBACnetScale() + bv.Value = &BACnetScale{} length += bv.Value.(*BACnetScale).Decode(buffer, offset+length, apduLen-length) case encoding.LightingCommand: - bv.Value = NewBACnetLightingCommand() + bv.Value = &BACnetLightingCommand{} length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) case encoding.Prescale: - bv.Value = NewBACnetPrescale() + bv.Value = &BACnetPrescale{} length += bv.Value.(*BACnetPrescale).Decode(buffer, offset+length, apduLen-length) case encoding.RequestedShedLevel, encoding.ExpectedShedLevel, encoding.ActualShedLevel: - bv.Value = NewBACnetShedLevel() + bv.Value = &BACnetShedLevel{} length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) case encoding.LogBuffer: if objType == encoding.TrendLog { @@ -1741,3 +1750,406 @@ func (b *BACnetTimeStamp) EncodeContext(tagNumber encoding.BACnetApplicationTag) tmp := b.Encode() return append(encoding.EncodeTag(tagNumber, true, len(tmp)), tmp...) } + +// ReadAccessSpecification represents a BACnet Read Access Specification. +type ReadAccessSpecification struct { + ObjectIdentifier ObjectIdentifier + ListOfPropertyReferences []BACnetPropertyReference +} + +// Decode decodes the ReadAccessSpecification from the buffer. +func (ras *ReadAccessSpecification) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + // ObjectIdentifier + ras.ObjectIdentifier = ObjectIdentifier{} + leng += ras.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + + // ListOfPropertyReferences + if buffer[offset+leng] == 0x30 { // Check for opening tag (0x30) + leng++ + + ras.ListOfPropertyReferences = make([]BACnetPropertyReference, 0) + + for apduLen-leng > 1 && buffer[offset+leng] != 0x00 { // Check for closing tag (0x00) + bValue := BACnetPropertyReference{} + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + leng += leng1 + + ras.ListOfPropertyReferences = append(ras.ListOfPropertyReferences, bValue) + } + } else { + return -1, errors.New("Invalid opening tag for ListOfPropertyReferences") + } + + leng++ + + return leng, nil +} + +// BACnetPropertyReference represents a BACnet property reference. +type BACnetPropertyReference struct { + PropertyIdentifier interface{} + PropertyArrayIndex uint32 +} + +// Decode decodes the BACnetPropertyReference from the buffer. +func (ref *BACnetPropertyReference) Decode(buffer []byte, offset, apduLen int) (int, error) { + leng := 0 + + // propertyIdentifier + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, ref.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng += leng1 + } else { + return -1, errors.New("Missing context tag for PropertyIdentifier") + } + + if leng < apduLen { + if encoding.IsContextTag(buffer, offset+leng, 1) && !encoding.IsClosingTagNumber(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, ref.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + return leng, nil +} + +type BACnetDeviceObjectPropertyReference struct { + ObjectIdentifier ObjectIdentifier + PropertyIdentifier interface{} + PropertyArrayIndex uint32 + DeviceIdentifier ObjectIdentifier +} + +func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { + leng := 0 + + // tag 0 objectidentifier + bdopr.ObjectIdentifier = ObjectIdentifier{} + leng1 := bdopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if leng1 < 0 { + return -1, errors.New("failed to decode object identifier") + } + leng += leng1 + + // tag 1 propertyidentifier + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, bdopr.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng += leng1 + } else { + return -1, errors.New("Missing tag property Identifier") + } + + if leng < apduLen { + // tag 2 property-array-index optional + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bdopr.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // tag 3 device-identifier optional + bdopr.DeviceIdentifier = ObjectIdentifier{} + leng1 := bdopr.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 3) + if leng1 < 0 { + return -1, errors.New("failed to decode device identifier") + } + leng += leng1 + } + + return leng, nil +} + +type BACnetDeviceObjectReference struct { + DeviceIdentifier ObjectIdentifier + ObjectIdentifier ObjectIdentifier +} + +func (bdor *BACnetDeviceObjectReference) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // tag 0 device-identifier optional + bdor.DeviceIdentifier = ObjectIdentifier{} + leng1 := bdor.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if leng1 > 0 { + leng += leng1 + } + + // tag 1 objectidentifier + bdor.ObjectIdentifier = ObjectIdentifier{} + leng1 = bdor.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + if leng1 < 0 { + return -1 + } + leng += leng1 + + return leng +} + +type BACnetObjectPropertyReference struct { + ObjectIdentifier ObjectIdentifier + PropertyIdentifier interface{} + PropertyArrayIndex uint32 +} + +func (bopr *BACnetObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // tag 0 objectidentifier + bopr.ObjectIdentifier = ObjectIdentifier{} + leng1 := bopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if leng1 < 0 { + return -1 + } + leng += leng1 + + // tag 1 propertyidentifier + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, bopr.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng += leng1 + } else { + return -1 + } + + if leng < apduLen { + // tag 2 property-array-index optional + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bopr.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + return leng +} + +type BACnetAccumulatorRecord struct { + Timestamp BACnetTimeStamp + PresentValue uint32 + AccumulatedValue uint32 + AccumulatorStatus BACnetAccumulatorStatus +} + +type BACnetAccumulatorStatus int + +const ( + AccumulatorStatusNormal BACnetAccumulatorStatus = iota + AccumulatorStatusStarting + AccumulatorStatusRecovered + AccumulatorStatusAbnormal + AccumulatorStatusFailed +) + +func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen int) (int, error) { + leng := 0 + + // 0 timestamp + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + bar.Timestamp = BACnetTimeStamp{} + leng1, err := bar.Timestamp.Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, errors.New("failed to decode timestamp") + } + } else { + return -1, errors.New("Missing tag 0") + } + + // 1 present-value + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bar.PresentValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Missing tag 1") + } + + // 2 accumulated-value + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bar.AccumulatedValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1, errors.New("Missing tag 2") + } + + // 3 accumulator-status + if encoding.IsContextTag(buffer, offset+leng, 3) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, statusValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + bar.AccumulatorStatus = BACnetAccumulatorStatus(statusValue) + leng += leng1 + } else { + return -1, errors.New("Missing tag 3") + } + + return leng, nil +} + +type BACnetActionList struct { + Action []BACnetActionCommand +} + +func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // SEQUENCE OF BACnetActionCommand + if encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { + leng += 1 + bal.Action = make([]BACnetActionCommand, 0) + for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { + bac := BACnetActionCommand{} + leng1 := bac.Decode(buffer, offset+leng, apduLen-leng) + if leng1 < 0 { + return -1 + } + leng += leng1 + bal.Action = append(bal.Action, bac) + } + leng += 1 + } + + return leng +} + +type BACnetActionCommand struct { + DeviceIdentifier ObjectIdentifier + ObjectIdentifier ObjectIdentifier + PropertyIdentifier interface{} + PropertyArrayIndex int + PropertyValue []BACnetValue + Priority int + PostDelay int + QuitOnFailure bool + WriteSuccessful bool +} + +func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // 0 device_identifier optional + if encoding.IsContextTag(buffer, offset+leng, 0) { + bac.DeviceIdentifier = ObjectIdentifier{} + leng += bac.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + } + + // 1 object_identifier + if encoding.IsContextTag(buffer, offset+leng, 1) { + bac.ObjectIdentifier = ObjectIdentifier{} + leng += bac.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + } else { + return -1 + } + + // 2 property_identifier + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, bac.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if leng1 < 0 { + return -1 + } + leng += leng1 + } else { + return -1 + } + + // 3 property_array_index + if encoding.IsContextTag(buffer, offset+leng, 3) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + bac.PropertyArrayIndex, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + + // tag 4 property-value + if encoding.IsOpeningTagNumber(buffer, offset+leng, 4) { + leng += 1 + bac.PropertyValue = []BACnetValue{} + for !encoding.IsClosingTagNumber(buffer, offset+leng, 4) && leng < apduLen { + bv := BACnetValue{} + propID := bac.PropertyIdentifier.(encoding.PropertyIdentifier) + leng1, _ := bv.Decode(buffer, offset+leng, apduLen-leng, bac.ObjectIdentifier.Type, propID) + if leng1 < 0 { + return -1 + } + leng += leng1 + bac.PropertyValue = append(bac.PropertyValue, bv) + } + if encoding.IsClosingTagNumber(buffer, offset+leng, 4) { + leng += 1 + } else { + return -1 + } + } else { + return -1 + } + + if leng < apduLen { + // tag 5 priority optional + if encoding.IsContextTag(buffer, offset+leng, 5) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + bac.Priority, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // tag 6 post-delay optional + if encoding.IsContextTag(buffer, offset+leng, 6) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + bac.PostDelay, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // tag 7 quit-on-failure optional + if encoding.IsContextTag(buffer, offset+leng, 7) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + uVal, _ := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bac.QuitOnFailure = uVal > 0 + } + } + + if leng < apduLen { + // tag 8 write-successful optional + if encoding.IsContextTag(buffer, offset+leng, 8) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + uVal, _ := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bac.WriteSuccessful = uVal > 0 + } + } + + return leng +} From 079d92bce616094d26a55b3a6bb19821a57e2973 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 15 Sep 2023 17:04:18 +0300 Subject: [PATCH 19/24] finish implementing bacnet value Signed-off-by: SammyOina --- pkg/bacnet/property.go | 1503 ++++++++++++++++++++++++++------------ pkg/encoding/encoding.go | 5 + 2 files changed, 1059 insertions(+), 449 deletions(-) diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 907a249..98c3ce6 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -116,7 +116,7 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) && leng < apduLen { bValue := BACnetValue{} propId := r.PropertyIdentifier.(encoding.PropertyIdentifier) - leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng, r.ObjectIdentifier.Type, propId) + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng, &r.ObjectIdentifier.Type, &propId) if err != nil { return -1, err } @@ -140,7 +140,7 @@ type BACnetValue struct { Value interface{} } -func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encoding.ObjectType, propID encoding.PropertyIdentifier) (int, error) { +func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { length := 0 var err error @@ -164,7 +164,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi bv.Value = false } case UnsignedInt: - if propID == encoding.RoutingTable { + if *propID == encoding.RoutingTable { bv.Tag = nil bv.Value = &RouterEntry{} length-- @@ -172,12 +172,12 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi if err != nil { return -1, err } - } else if propID == encoding.ActiveVtSessions { + } else if *propID == encoding.ActiveVtSessions { bv.Tag = nil bv.Value = &BACnetVTSession{} length-- decodeLen = bv.Value.(*BACnetVTSession).Decode(buffer, offset+length, apduLen) - } else if propID == encoding.ThreatLevel || propID == encoding.ThreatAuthority { + } else if *propID == encoding.ThreatLevel || *propID == encoding.ThreatAuthority { bv.Tag = nil bv.Value = &BACnetAccessThreatLevel{} length-- @@ -208,7 +208,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi decodeLen, stringValue = encoding.DecodeCharacterString(buffer, offset+length, apduLen, int(lenValueType)) bv.Value = stringValue case BitString: - switch propID { + switch *propID { case encoding.RecipientList: bv.Tag = nil bv.Value = &BACnetDestination{} @@ -245,9 +245,9 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi bv.Value = bitValue } case Enumerated: - decodeLen, bv.Value = encoding.DecodeEnumerated(buffer, offset+length, lenValueType, &objType, &propID) + decodeLen, bv.Value = encoding.DecodeEnumerated(buffer, offset+length, lenValueType, objType, propID) case Date: - switch propID { + switch *propID { case encoding.EffectivePeriod: bv.Tag = nil bv.Value = &BACnetDateRange{} @@ -280,16 +280,16 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi default: decodeLen, bv.Value = encoding.DecodeDateSafe(buffer, offset+length, int(lenValueType)) } - if (objType == encoding.DateTimeValue || objType == encoding.TimePatternValue) && (propID == encoding.PresentValue || propID == encoding.RelinquishDefault) { + if (*objType == encoding.DateTimeValue || *objType == encoding.TimePatternValue) && (*propID == encoding.PresentValue || *propID == encoding.RelinquishDefault) { decodeLen, bv.Value = encoding.DecodeDateSafe(buffer, offset+length, int(lenValueType)) } case Time: decodeLen, bv.Value = encoding.DecodeBACnetTimeSafe(buffer, offset+length, int(lenValueType)) case BACnetObjectIdentifier: - if propID == encoding.LastKeyServer || - propID == encoding.ManualSlaveAddressBinding || - propID == encoding.SlaveAddressBinding || - propID == encoding.DeviceAddressBinding { + if *propID == encoding.LastKeyServer || + *propID == encoding.ManualSlaveAddressBinding || + *propID == encoding.SlaveAddressBinding || + *propID == encoding.DeviceAddressBinding { bv.Tag = nil bv.Value = &BACnetAddressBinding{} length-- @@ -311,7 +311,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi length += decodeLen } } else { - switch propID { + switch *propID { case encoding.BacnetIpGlobalAddress, encoding.FdBbmdAddress: bv.Value = &BACnetHostNPort{} length1, err := bv.Value.(*BACnetHostNPort).Decode(buffer, offset+length, apduLen-length) @@ -409,473 +409,102 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi bv.Value = &BACnetShedLevel{} length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) case encoding.LogBuffer: - if objType == encoding.TrendLog { - bv.Value = NewBACnetLogRecord() - length += bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length) - } else { - log.Println("Unhandled context-specific tag:", bv.Tag) - length = apduLen + switch *objType { + case encoding.TrendLog: + bv.Value = &BACnetLogRecord{} + length += bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length, nil, nil) + case encoding.EventLog: + bv.Value = &BACnetEventLogRecord{} + length += bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) } case encoding.DateList: - bv.Value = NewBACnetCalendarEntry() + bv.Value = &BACnetCalendarEntry{} length += bv.Value.(*BACnetCalendarEntry).Decode(buffer, offset+length, apduLen-length) - case encoding.LogBuffer: - if objType == encoding.EventLog { - bv.Value = NewBACnetEventLogRecord() - length += bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) - } else { - log.Println("Unhandled context-specific tag:", bv.Tag) - length = apduLen - } case encoding.PresentValue: - if objType == encoding.Group { - bv.Value = NewReadAccessResult() + switch *objType { + case encoding.Group: + bv.Value = &ReadAccessResult{} length += bv.Value.(*ReadAccessResult).Decode(buffer, offset+length, apduLen-length) - } else { - log.Println("Unhandled context-specific tag:", bv.Tag) - length = apduLen + case encoding.Channel: + bv.Value = &BACnetChannelValue{} + length += bv.Value.(*BACnetChannelValue).Decode(buffer, offset+length, apduLen-length) + case encoding.GlobalGroup: + bv.Value = &BACnetPropertyAccessResult{} + length += bv.Value.(*BACnetPropertyAccessResult).Decode(buffer, offset+length, apduLen-length) + case encoding.CredentialDataInput: + bv.Value = &BACnetAuthenticationFactor{} + length += bv.Value.(*BACnetAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) } case encoding.NegativeAccessRules, encoding.PositiveAccessRules: - bv.Value = NewBACnetAccessRule() + bv.Value = &BACnetAccessRule{} length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) case encoding.Tags: - bv.Value = NewBACnetNameValue() + bv.Value = &BACnetNameValue{} length += bv.Value.(*BACnetNameValue).Decode(buffer, offset+length, apduLen-length) case encoding.SubordinateTags: - bv.Value = NewBACnetNameValueCollection() + bv.Value = &BACnetNameValueCollection{} length += bv.Value.(*BACnetNameValueCollection).Decode(buffer, offset+length, apduLen-length) case encoding.NetworkAccessSecurityPolicies: - bv.Value = NewBACnetNetworkSecurityPolicy() + bv.Value = &BACnetNetworkSecurityPolicy{} length += bv.Value.(*BACnetNetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) case encoding.PortFilter: - bv.Value = NewBACnetPortPermission() + bv.Value = &BACnetPortPermission{} length += bv.Value.(*BACnetPortPermission).Decode(buffer, offset+length, apduLen-length) case encoding.PriorityArray: - bv.Value = NewBACnetPriorityArray() + bv.Value = &BACnetPriorityArray{} length += bv.Value.(*BACnetPriorityArray).Decode(buffer, offset+length, apduLen-length) case encoding.ProcessIdentifierFilter: - bv.Value = NewBACnetProcessIdSelection() + bv.Value = &BACnetProcessIdSelection{} length += bv.Value.(*BACnetProcessIdSelection).Decode(buffer, offset+length, apduLen-length) - case encoding.GlobalGroup && propID == encoding.PresentValue: - bv.Value = NewBACnetPropertyAccessResult() - length += bv.Value.(*BACnetPropertyAccessResult).Decode(buffer, offset+length, apduLen-length) case encoding.SetpointReference: - bv.Value = NewBACnetSetpointReference() + bv.Value = &BACnetSetpointReference{} length += bv.Value.(*BACnetSetpointReference).Decode(buffer, offset+length, apduLen-length) case encoding.ExceptionSchedule: - bv.Value = NewBACnetSpecialEvent() + bv.Value = &BACnetSpecialEvent{} length += bv.Value.(*BACnetSpecialEvent).Decode(buffer, offset+length, apduLen-length) case encoding.StateChangeValues: - bv.Value = NewBACnetTimerStateChangeValue() + bv.Value = &BACnetTimerStateChangeValue{} length += bv.Value.(*BACnetTimerStateChangeValue).Decode(buffer, offset+length, apduLen-length) case encoding.ValueSource, encoding.ValueSourceArray: - bv.Value = NewBACnetValueSource() + bv.Value = &BACnetValueSource{} length += bv.Value.(*BACnetValueSource).Decode(buffer, offset+length, apduLen-length) case encoding.VirtualMacAddressTable: - bv.Value = NewBACnetVMACEntry() + bv.Value = &BACnetVMACEntry{} length += bv.Value.(*BACnetVMACEntry).Decode(buffer, offset+length, apduLen-length) case encoding.AssignedAccessRights: - bv.Value = NewBACnetAssignedAccessRights() + bv.Value = &BACnetAssignedAccessRights{} length += bv.Value.(*BACnetAssignedAccessRights).Decode(buffer, offset+length, apduLen-length) case encoding.AssignedLandingCalls: - bv.Value = NewBACnetAssignedLandingCalls() + bv.Value = &BACnetAssignedLandingCalls{} length += bv.Value.(*BACnetAssignedLandingCalls).Decode(buffer, offset+length, apduLen-length) - case encoding.AccessEventAuthenticationFactor, - (objType == encoding.CredentialDataInput && propID == encoding.PresentValue): - bv.Value = NewBACnetAuthenticationFactor() + case encoding.AccessEventAuthenticationFactor: + bv.Value = &BACnetAuthenticationFactor{} length += bv.Value.(*BACnetAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) case encoding.SupportedFormats: - bv.Value = NewBACnetAuthenticationFactorFormat() + bv.Value = &BACnetAuthenticationFactorFormat{} length += bv.Value.(*BACnetAuthenticationFactorFormat).Decode(buffer, offset+length, apduLen-length) case encoding.AuthenticationPolicyList: - bv.Value = NewBACnetAuthenticationPolicy() + bv.Value = &BACnetAuthenticationPolicy{} length += bv.Value.(*BACnetAuthenticationPolicy).Decode(buffer, offset+length, apduLen-length) - case encoding.Channel && propID == encoding.PresentValue: - bv.Value = NewBACnetChannelValue() - length += bv.Value.(*BACnetChannelValue).Decode(buffer, offset+length, apduLen-length) case encoding.ActiveCovSubscriptions: - bv.Value = NewBACnetCOVSubscription() + bv.Value = &BACnetCOVSubscription{} length += bv.Value.(*BACnetCOVSubscription).Decode(buffer, offset+length, apduLen-length) case encoding.AuthenticationFactors: - bv.Value = NewBACnetCredentialAuthenticationFactor() + bv.Value = &BACnetCredentialAuthenticationFactor{} length += bv.Value.(*BACnetCredentialAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) case encoding.WeeklySchedule: - bv.Value = NewBACnetDailySchedule() + bv.Value = &BACnetDailySchedule{} length += bv.Value.(*BACnetDailySchedule).Decode(buffer, offset+length, apduLen-length) case encoding.SubscribedRecipients: - bv.Value = NewBACnetEventNotificationSubscription() + bv.Value = &BACnetEventNotificationSubscription{} length += bv.Value.(*BACnetEventNotificationSubscription).Decode(buffer, offset+length, apduLen-length) case encoding.EventParameters: - bv.Value = NewBACnetEventParameter() + bv.Value = &BACnetEventParameter{} length += bv.Value.(*BACnetEventParameter).Decode(buffer, offset+length, apduLen-length) case encoding.FaultParameters: - bv.Value = NewBACnetFaultParameter() + bv.Value = &BACnetFaultParameter{} length += bv.Value.(*BACnetFaultParameter).Decode(buffer, offset+length, apduLen-length) - case encoding.LoggingObject: - bv.Value = NewBACnetLoggingObject() - length += bv.Value.(*BACnetLoggingObject).Decode(buffer, offset+length, apduLen-length) - case encoding.LoggingRecord: - bv.Value = NewBACnetLoggingRecord() - length += bv.Value.(*BACnetLoggingRecord).Decode(buffer, offset+length, apduLen-length) - case encoding.ReinitiateDevice: - bv.Value = NewBACnetReinitializeDevice() - length += bv.Value.(*BACnetReinitializeDevice).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierBACNETIPUDPDATAGRAMCONFIGURATION: - bv.Value = NewBACnetBACnetIPUDPDatagramConfiguration() - length += bv.Value.(*BACnetBACnetIPUDPDatagramConfiguration).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierREINITIALIZEPARAMETERS: - bv.Value = NewBACnetReinitializeParameters() - length += bv.Value.(*BACnetReinitializeParameters).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierDISCONNECTEDONEXCEPTION: - bv.Value = NewBACnetDisconnect() - length += bv.Value.(*BACnetDisconnect).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierNOMINALENCYCLE: - bv.Value = NewBACnetNominalBACnetInterval() - length += bv.Value.(*BACnetNominalBACnetInterval).Decode(buffer, offset+length, apduLen-length) - case encoding.NotifyType: - bv.Value = NewBACnetNotifyType() - length += bv.Value.(*BACnetNotifyType).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierSUMMATION: - bv.Value = NewBACnetEventSummation() - length += bv.Value.(*BACnetEventSummation).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSUSERPASSWORD: - bv.Value = NewBACnetAccessUserPassword() - length += bv.Value.(*BACnetAccessUserPassword).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPULSECONFIGURATION: - bv.Value = NewBACnetPulseConverter() - length += bv.Value.(*BACnetPulseConverter).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPORTPARAMETERS: - bv.Value = NewBACnetPortParameters() - length += bv.Value.(*BACnetPortParameters).Decode(buffer, offset+length, apduLen-length) - case encoding.TimeDelay, - BACnetPropertyIdentifierLIGHTCONTROLDELAY, - BACnetPropertyIdentifierINITIALTIMEDELAY: - bv.Value = NewBACnetTimeValue() - length += bv.Value.(*BACnetTimeValue).Decode(buffer, offset+length, apduLen-length) - case encoding.LightingCommand, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierRADIOFAILUREEVENTS, - BACnetPropertyIdentifierRADIOFAILUREEVENTS2, - BACnetPropertyIdentifierMACADDRESSCHANGEEVENTS: - bv.Value = NewBACnetCOVSubscription() - length += bv.Value.(*BACnetCOVSubscription).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierSHEDLEVELDESCENDANTS: - bv.Value = NewBACnetShedLevelDescendants() - length += bv.Value.(*BACnetShedLevelDescendants).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPERSISTENTDATA: - bv.Value = NewBACnetScheduleObjectPeriod() - length += bv.Value.(*BACnetScheduleObjectPeriod).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierRADIOSTATUS, - BACnetPropertyIdentifierRADIOSTATUS2: - bv.Value = NewBACnetRadioStatus() - length += bv.Value.(*BACnetRadioStatus).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierUSERINFORMATION, - BACnetPropertyIdentifierMACADDRESS: - bv.Value = NewBACnetMACAddress() - length += bv.Value.(*BACnetMACAddress).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierCOVMULTIPLESUBSCRIPTIONSFILTER, - BACnetPropertyIdentifierMONITORMULTIPLEBINARYINPUTS, - BACnetPropertyIdentifierMONITORMULTIPLEBINARYOUTPUTS, - BACnetPropertyIdentifierMULTIPLEMONITORING, - BACnetPropertyIdentifierSTOPWHENFULL, - BACnetPropertyIdentifierLIMITENABLE, - BACnetPropertyIdentifierDATAGROUPS, - BACnetPropertyIdentifierDEVICEADDRESSBINDING: - bv.Value = NewBACnetMultistateValue() - length += bv.Value.(*BACnetMultistateValue).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierLIGHTINGDEVICESTATUSALOGGING, - BACnetPropertyIdentifierLIGHTINGDEVICESTATUSLOGGING, - BACnetPropertyIdentifierDEVICEADDRESSBINDING, - BACnetPropertyIdentifierLIGHTINGDEVICEOPERATIONALMODE, - BACnetPropertyIdentifierLIGHTINGDEVICEOPERATIONALSTATUS, - BACnetPropertyIdentifierLIGHTINGGROUP, - BACnetPropertyIdentifierLIGHTINGGRP, - BACnetPropertyIdentifierLIGHTINGLOGGING: - bv.Value = NewBACnetLightingGroup() - length += bv.Value.(*BACnetLightingGroup).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierEVENTTIMESTAMPS: - bv.Value = NewBACnetTimeStampedValue() - length += bv.Value.(*BACnetTimeStampedValue).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGGROUP: - bv.Value = NewBACnetLightingGroup() - length += bv.Value.(*BACnetLightingGroup).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierNEGATIVEACCESSRULES, - BACnetPropertyIdentifierPOSITIVEACCESSRULES: - bv.Value = NewBACnetAccessRule() - length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierNETWORKADDRESS, - BACnetPropertyIdentifierMASTERKEY, - encoding.AccessUser, - encoding.AccessZone, - BACnetPropertyIdentifierAREADELIVERING, - BACnetPropertyIdentifierAREARELAY, - BACnetPropertyIdentifierCONTROLLING, - BACnetPropertyIdentifierDELIVERING, - BACnetPropertyIdentifierENROLLING, - BACnetPropertyIdentifierLOWLIMIT, - BACnetPropertyIdentifierMAXIMUMOUTPUT, - BACnetPropertyIdentifierMAXIMUMVALUE, - BACnetPropertyIdentifierMINIMUMOUTPUT, - BACnetPropertyIdentifierMINIMUMVALUE, - BACnetPropertyIdentifierEVENTTIME, - BACnetPropertyIdentifierTIMEDELAY, - BACnetPropertyIdentifierDURATION, - BACnetPropertyIdentifierEXCEPTIONALLIMITS, - BACnetPropertyIdentifierINACTIVESTATE, - BACnetPropertyIdentifierINSTANTANEOUS, - BACnetPropertyIdentifierINVALIDATED, - BACnetPropertyIdentifierLIMITENABLE, - BACnetPropertyIdentifierRELIABILITY, - BACnetPropertyIdentifierSCALE, - BACnetPropertyIdentifierSTEPINCREMENT, - BACnetPropertyIdentifierTIMER, - BACnetPropertyIdentifierLIMIT, - BACnetPropertyIdentifierMAXIMUM, - BACnetPropertyIdentifierMINIMUM, - BACnetPropertyIdentifierPULSESCALING, - BACnetPropertyIdentifierSHUTDOWN, - BACnetPropertyIdentifierBUFFERPROPERTY, - BACnetPropertyIdentifierSTREAMINGTHRESHOLDS: - bv.Value = NewBACnetOctetString() - length += bv.Value.(*BACnetOctetString).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierCOVMULTIPLESUBSCRIPTIONSFILTER, - encoding.MultiStateValue: - bv.Value = NewBACnetMultistateValue() - length += bv.Value.(*BACnetMultistateValue).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierAUTHENTICATIONFACTORSUPPLIED, - BACnetPropertyIdentifierAUTHENTICATIONFACTORFORMAT, - BACnetPropertyIdentifierAUTHENTICATIONPOLICYNAME, - BACnetPropertyIdentifierAUTHENTICATIONPOLICYNAMES, - BACnetPropertyIdentifierPOLICYNAMES: - bv.Value = NewBACnetAuthorization() - length += bv.Value.(*BACnetAuthorization).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierDEVICEIDENTIFICATION: - bv.Value = NewBACnetCharacterString() - length += bv.Value.(*BACnetCharacterString).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierEVENTTIMESTAMPS: - bv.Value = NewBACnetTimeStampedValue() - length += bv.Value.(*BACnetTimeStampedValue).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierDEVICEIDENTIFICATION: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierSHEDLEVELS: - bv.Value = NewBACnetShedLevel() - length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetPortFilter() - length += bv.Value.(*BACnetPortFilter).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPOLICY: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSRULES, - BACnetPropertyIdentifierINVALIDACTIONS, - BACnetPropertyIdentifierLOGGINGOBJECT, - BACnetPropertyIdentifierSAVERESTORESTATE: - bv.Value = NewBACnetDeviceObjectReference() - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACTIVESEQUENCE, - BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPORTFILTER, - BACnetPropertyIdentifierAUTHENTICATIONPOLICIES, - BACnetPropertyIdentifierAUTHENTICATIONPOLICYLIST: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPOLICYPASSWORD, - BACnetPropertyIdentifierPOLICYTYPE, - BACnetPropertyIdentifierTIMEDELAY, - BACnetPropertyIdentifierVERIFYPASSWORD, - BACnetPropertyIdentifierPORTPARAMETERS, - BACnetPropertyIdentifierDEVICEADDRESSBINDING: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierRELINQUISHDEFAULT, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSRULES, - BACnetPropertyIdentifierINVALIDACTIONS, - BACnetPropertyIdentifierLOGGINGOBJECT, - BACnetPropertyIdentifierSAVERESTORESTATE: - bv.Value = NewBACnetDeviceObjectReference() - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSSEQUENCE, - BACnetPropertyIdentifierACTIVESEQUENCE, - BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, - BACnetPropertyIdentifierFEEDINGPIPEINDEX, - BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE, - BACnetPropertyIdentifierSTATUSFLAGS: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICY, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPOLICYNAMES, - BACnetPropertyIdentifierACCESSRULES, - BACnetPropertyIdentifierLIMITDISABLE, - BACnetPropertyIdentifierMANUALSLIDERSETTINGS: - bv.Value = NewBACnetDeviceObjectReference() - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSRULES, - BACnetPropertyIdentifierINVALIDACTIONS, - BACnetPropertyIdentifierLOGGINGOBJECT, - BACnetPropertyIdentifierSAVERESTORESTATE: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPOLICYPASSWORD, - BACnetPropertyIdentifierPOLICYTYPE, - BACnetPropertyIdentifierTIMEDELAY, - BACnetPropertyIdentifierVERIFYPASSWORD: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, - BACnetPropertyIdentifierEXCEPTIONSCHEDULE, - BACnetPropertyIdentifierEVENTTIMESTAMPS: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierALARMVALUES: - bv.Value = NewBACnetDeviceObjectReference() - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierALARMVALUES, - BACnetPropertyIdentifierEVENTTYPE, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierSAFETYPOINTS: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCONTROLMODE: - bv.Value = NewBACnetLightingControlMode() - length += bv.Value.(*BACnetLightingControlMode).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierBACNETIPADDRESS, - BACnetPropertyIdentifierDEFAULTGATEWAY, - BACnetPropertyIdentifierIPADDRESS, - BACnetPropertyIdentifierSUBNETMASK: - bv.Value = NewBACnetIPAddress() - length += bv.Value.(*BACnetIPAddress).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetPortFilter() - length += bv.Value.(*BACnetPortFilter).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSRULES: - bv.Value = NewBACnetDeviceObjectReference() - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierRELIABILITY, - BACnetPropertyIdentifierUNITS: - bv.Value = NewBACnetReliability() - length += bv.Value.(*BACnetReliability).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPARAMETERSETUSAGE: - bv.Value = NewBACnetParameterSetUsage() - length += bv.Value.(*BACnetParameterSetUsage).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierCONTROLSEQUENCEOFOPERATION, - BACnetPropertyIdentifierEXCEPTIONSCHEDULE, - BACnetPropertyIdentifierEXCEPTIONSCHEDULEDEFAULT, - BACnetPropertyIdentifierLIGHTINGCOMMAND: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGINGDEFAULT, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierEVENTCODE, - BACnetPropertyIdentifierLONMARKRESOURCE, - BACnetPropertyIdentifierPOLICIES: - bv.Value = NewBACnetUnsignedInteger() - length += bv.Value.(*BACnetUnsignedInteger).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCOMMAND: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierLIGHTINGCONTROLOVERLOADALOGGING, - BACnetPropertyIdentifierRELOCATELIGHTINGOUTPUTDEVICE: - bv.Value = NewBACnetLightingCommand() - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierSAFETYPOINTS: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPOLICYPASSWORD, - BACnetPropertyIdentifierPOLICYTYPE, - BACnetPropertyIdentifierTIMEDELAY, - BACnetPropertyIdentifierVERIFYPASSWORD: - bv.Value = NewBACnetDeviceObjectPropertyReference() - length += bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICY, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierDEVICEIDENTIFICATION: - bv.Value = NewBACnetCharacterString() - length += bv.Value.(*BACnetCharacterString).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICY, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case encoding.AccessEvent, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) - case BACnetPropertyIdentifierACCESSEVENTS, - BACnetPropertyIdentifierPOLICIES, - BACnetPropertyIdentifierPORTFILTER: - bv.Value = NewBACnetDeviceSecurityPolicy() - length += bv.Value.(*BACnetDeviceSecurityPolicy).Decode(buffer, offset+length, apduLen-length) default: bv.Value = nil } @@ -885,7 +514,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType encodi func (bv *BACnetValue) Encode() []byte { if bv.Tag == nil { - // Handle NULL case + return nil } else { switch *bv.Tag { case Boolean: @@ -903,28 +532,24 @@ func (bv *BACnetValue) Encode() []byte { case CharacterString: return encoding.EncodeApplicationCharacterString(bv.Value.(string)) case BitString: - return encoding.EncodeApplicationBitString(b) - // Handle BIT_STRING case - // Add your code here... + return encoding.EncodeApplicationBitString(bv.Value) case Enumerated: - // Handle ENUMERATED case - // Add your code here... + return encoding.EncodeApplicationEnumerated(bv.Value.(uint32)) case Date: - // Handle DATE case - // Add your code here... + return encoding.EncodeApplicationDate(bv.Value.(time.Time)) case Time: - // Handle TIME case - // Add your code here... + return encoding.EncodeApplicationTime(bv.Value.(time.Time)) case BACnetObjectIdentifier: - // Handle BACNETOBJECTIDENTIFIER case - // Add your code here... + return bv.Value.(*ObjectIdentifier).EncodeApp() default: + switch bv.Value.(type) { + case int: + return encoding.EncodeApplicationEnumerated(uint32(bv.Value.(int))) + } log.Printf("Unsupported BACnetApplicationTag: %v", bv.Tag) - // Handle other BACnetApplicationTags as needed... + return nil } } - - return nil } // BACnetRouterEntryStatus is an enumeration for the status of BACnetRouterEntry. @@ -1120,10 +745,6 @@ func NewBACnetDaysOfWeek() *BACnetDaysOfWeek { } } -func (d *BACnetDaysOfWeek) String() string { - return fmt.Sprintf("%08b", d.bitString.Value) -} - func (d *BACnetDaysOfWeek) Decode(buffer []byte, offset int, apduLen int) int { d.bitString = BACnetBitString{} return d.bitString.Decode(buffer, offset, apduLen) @@ -2093,7 +1714,7 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i for !encoding.IsClosingTagNumber(buffer, offset+leng, 4) && leng < apduLen { bv := BACnetValue{} propID := bac.PropertyIdentifier.(encoding.PropertyIdentifier) - leng1, _ := bv.Decode(buffer, offset+leng, apduLen-leng, bac.ObjectIdentifier.Type, propID) + leng1, _ := bv.Decode(buffer, offset+leng, apduLen-leng, &bac.ObjectIdentifier.Type, &propID) if leng1 < 0 { return -1 } @@ -2153,3 +1774,987 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i return leng } + +type BACnetScale struct { + Value interface{} +} + +func (bs *BACnetScale) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + if encoding.IsContextTag(buffer, offset+leng, 0) { + // float-scale + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bs.Value = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else if encoding.IsContextTag(buffer, offset+leng, 1) { + // integer-scale + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bs.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1 + } + + return leng +} + +type BACnetLightingCommand struct { + Operation BACnetLightingOperation + TargetLevel float32 + RampRate float32 + StepIncrement float32 + FadeTime uint32 + Priority uint32 +} + +type BACnetLightingOperation uint32 + +const ( + LightingOperationUnknown BACnetLightingOperation = iota + LightingOperationOff + LightingOperationOn + LightingOperationToggle + LightingOperationDecrement + LightingOperationIncrement +) + +func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // operation + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, uVal := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + blc.Operation = BACnetLightingOperation(uVal) + } else { + return -1 + } + + if leng < apduLen { + // target-level + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, blc.TargetLevel = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // ramp-rate + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, blc.RampRate = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // step-increment + if encoding.IsContextTag(buffer, offset+leng, 3) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, blc.StepIncrement = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // fade-time + if encoding.IsContextTag(buffer, offset+leng, 4) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, blc.FadeTime = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + if leng < apduLen { + // priority + if encoding.IsContextTag(buffer, offset+leng, 5) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, blc.Priority = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } + } + + return leng +} + +type BACnetPrescale struct { + Multiplier uint32 + ModuloDivide uint32 +} + +func (bp *BACnetPrescale) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + // multiplier + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bp.Multiplier = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1 + } + + // modulo_divide + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bp.ModuloDivide = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else { + return -1 + } + + return leng +} + +type BACnetShedLevelChoice int + +const ( + BACnetShedLevelChoicePercent BACnetShedLevelChoice = iota + BACnetShedLevelChoiceLevel + BACnetShedLevelChoiceAmount +) + +type BACnetShedLevel struct { + Choice BACnetShedLevelChoice + Value interface{} +} + +func (bsl *BACnetShedLevel) Decode(buffer []byte, offset int, apduLen int) int { + leng := 0 + + if encoding.IsContextTag(buffer, offset+leng, 0) { + // percent + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bsl.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bsl.Choice = BACnetShedLevelChoicePercent + } else if encoding.IsContextTag(buffer, offset+leng, 1) { + // level + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bsl.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bsl.Choice = BACnetShedLevelChoiceLevel + } else if encoding.IsContextTag(buffer, offset+leng, 2) { + // amount + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, bsl.Value = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + bsl.Choice = BACnetShedLevelChoiceAmount + } else { + return -1 + } + + return leng +} + +type BACnetLogRecordChoice int + +const ( + BACnetLogRecordChoiceLogStatus BACnetLogRecordChoice = iota + BACnetLogRecordChoiceBooleanValue + BACnetLogRecordChoiceRealValue + BACnetLogRecordChoiceEnumeratedValue + BACnetLogRecordChoiceUnsignedValue + BACnetLogRecordChoiceIntegerValue + BACnetLogRecordChoiceBitstringValue + BACnetLogRecordChoiceNullValue + BACnetLogRecordChoiceFailure + BACnetLogRecordChoiceTimeChange + BACnetLogRecordChoiceAnyValue +) + +type BACnetLogRecord struct { + Timestamp BACnetTimeStamp + LogDatum interface{} + StatusFlags BACnetStatusFlags +} + +func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) int { + leng := 0 + + // timestamp + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + blr.Timestamp = BACnetTimeStamp{} + leng1, err := blr.Timestamp.Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1 + } + leng += leng1 + } else { + return -1 + } + + if encoding.IsContextTag(buffer, offset+leng, 1) { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + + switch BACnetLogRecordChoice(tagNumber) { + case BACnetLogRecordChoiceLogStatus: + blr.LogDatum = &BACnetLogStatus{} + leng += blr.LogDatum.(*BACnetLogStatus).Decode(buffer, offset+leng, int(lenValue)) + case BACnetLogRecordChoiceBooleanValue: + blr.LogDatum = buffer[offset+leng] > 0 + leng++ + case BACnetLogRecordChoiceRealValue: + leng1, logValue := encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + blr.LogDatum = logValue + case BACnetLogRecordChoiceEnumeratedValue: + leng1, logValue := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng += leng1 + blr.LogDatum = logValue + case BACnetLogRecordChoiceUnsignedValue: + leng1, logValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + blr.LogDatum = logValue + case BACnetLogRecordChoiceIntegerValue: + leng1, logValue := encoding.DecodeSigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + blr.LogDatum = logValue + case BACnetLogRecordChoiceBitstringValue: + blr.LogDatum = &BACnetBitString{} + leng += blr.LogDatum.(*BACnetBitString).Decode(buffer, offset+leng, int(lenValue)) + case BACnetLogRecordChoiceNullValue: + blr.LogDatum = nil + leng++ + case BACnetLogRecordChoiceFailure: + blr.LogDatum = &BACnetError{} + leng += blr.LogDatum.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + if encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceFailure)) { + leng++ + } else { + return -1 + } + case BACnetLogRecordChoiceTimeChange: + leng1, logValue := encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + blr.LogDatum = logValue + case BACnetLogRecordChoiceAnyValue: + blr.LogDatum = []BACnetValue{} + for !encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceAnyValue)) && leng < apduLen { + bValue := BACnetValue{} + leng1, _ := bValue.Decode(buffer, offset+leng, apduLen-leng, objType, propID) + if leng1 < 0 { + return -1 + } + leng += leng1 + blr.LogDatum = append(blr.LogDatum.([]BACnetValue), bValue) + } + if encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceAnyValue)) { + leng++ + } else { + return -1 + } + default: + return -1 + } + } else { + return -1 + } + + if leng < apduLen { + // status-flags optional + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + blr.StatusFlags = BACnetStatusFlags{} + leng += blr.StatusFlags.Decode(buffer, offset+leng, int(lenValue)) + } + } + + return leng +} + +type BACnetLogStatus struct { + UnusedBits uint8 + BitString *BACnetBitString +} + +func NewBACnetLogStatus() BACnetLogStatus { + return BACnetLogStatus{ + UnusedBits: 5, + BitString: NewBACnetBitString(5, *internal.NewBitArrayFromByte(0x00)), + } +} + +func (bls *BACnetLogStatus) Decode(buffer []byte, offset, apduLen int) int { + bls.BitString = NewBACnetBitString(5, *internal.NewBitArrayFromByte(0x00)) + return bls.BitString.Decode(buffer, offset, apduLen) +} + +func (bls *BACnetLogStatus) SetLogDisabled(a bool) { + bls.BitString.Value.Set(0, a) +} + +func (bls *BACnetLogStatus) SetBufferPurged(a bool) { + bls.BitString.Value.Set(1, a) +} + +func (bls *BACnetLogStatus) SetLogInterrupted(a bool) { + bls.BitString.Value.Set(2, a) +} + +func (bls *BACnetLogStatus) LogDisabled() bool { + return bls.BitString.Value.Get(0) +} + +func (bls *BACnetLogStatus) BufferPurged() bool { + return bls.BitString.Value.Get(1) +} + +func (bls *BACnetLogStatus) LogInterrupted() bool { + return bls.BitString.Value.Get(2) +} + +type BACnetError struct { + ErrorClass ErrorClassEnum + ErrorCode ErrorCodeEnum +} + +func (be *BACnetError) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // Decode error_class + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == byte(Enumerated) { + leng1, eVal := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng += leng1 + be.ErrorClass = ErrorClassEnum(eVal.(uint32)) + } else { + return -1 + } + + // Decode error_code + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == byte(Enumerated) { + leng1, eVal := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng += leng1 + be.ErrorCode = ErrorCodeEnum(eVal.(uint32)) + } else { + return -1 + } + + return leng +} + +type BACnetCalendarEntry struct { + Value interface{} +} + +func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + if tagNumber == 0 { + leng1, ce.Value = encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) + leng += leng1 + } else if tagNumber == 1 { + ce.Value = &BACnetDateRange{} + leng1, err := ce.Value.(*BACnetDateRange).Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1 + } + leng += leng1 + } else if tagNumber == 2 { + ce.Value = &BACnetWeekNDay{} + leng += ce.Value.(*BACnetWeekNDay).Decode(buffer, offset+leng, int(lenValue)) + } else { + return -1 + } + + return leng +} + +type BACnetEventLogRecord struct { + Timestamp DateTime + LogDatum interface{} +} + +func (elr *BACnetEventLogRecord) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + if encoding.IsContextTag(buffer, offset+leng, 0) { + leng1, _, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + elr.Timestamp = DateTime{} + leng += elr.Timestamp.Decode(buffer, offset+leng) + } else { + return -1 + } + + return leng +} + +type BACnetWeekNDay struct { + Month int + WeekOfMonth int + DayOfWeek int +} + +func (wnd *BACnetWeekNDay) Decode(buffer []byte, offset, apduLen int) int { + if apduLen >= 3 { + wnd.Month = int(buffer[offset]) + wnd.WeekOfMonth = int(buffer[offset+1]) + wnd.DayOfWeek = int(buffer[offset+2]) + } else { + return -1 + } + return 3 +} + +type ReadAccessResultReadResult struct { + PropertyIdentifier encoding.PropertyIdentifier + PropertyArrayIndex uint32 + ReadResult interface{} // Either BACnetValue or BACnetError +} + +func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + // 2 propertyidentifier + if encoding.IsContextTag(buffer, offset+leng, 2) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + propID := encoding.PropertyList + leng1, propertyIdentifier := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng += leng1 + rarr.PropertyIdentifier = encoding.PropertyIdentifier(propertyIdentifier.(uint32)) + } else { + return -1 + } + + // 3 property_array_index + if encoding.IsContextTag(buffer, offset+leng, 3) { + leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + leng1, propertyArrayIndex := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + rarr.PropertyArrayIndex = propertyArrayIndex + } + + if leng < apduLen { + if encoding.IsOpeningTagNumber(buffer, offset+leng, 4) { + rarr.ReadResult = &BACnetValue{} + leng1, err := rarr.ReadResult.(*BACnetValue).Decode(buffer, offset+leng, apduLen-leng, nil, nil) + if err != nil { + return -1 + } + leng += leng1 + if encoding.IsClosingTagNumber(buffer, offset+leng, 4) { + leng += 1 + } else { + return -1 + } + } else if encoding.IsOpeningTagNumber(buffer, offset+leng, 5) { + rarr.ReadResult = &BACnetError{} + leng += rarr.ReadResult.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + if encoding.IsClosingTagNumber(buffer, offset+leng, 5) { + leng += 1 + } else { + return -1 + } + } + } + return leng +} + +type ReadAccessResult struct { + ObjectIdentifier ObjectIdentifier + ListOfResults []ReadAccessResultReadResult +} + +func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + // tag 0 objectidentifier + rar.ObjectIdentifier = ObjectIdentifier{} + if encoding.IsClosingTagNumber(buffer, offset+leng, 0) { + leng += rar.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + } else { + return -1 + } + + if encoding.IsOpeningTagNumber(buffer, offset+leng, 1) { + leng += 1 + rar.ListOfResults = make([]ReadAccessResultReadResult, 0) + + for (apduLen-leng) > 1 && !encoding.IsClosingTagNumber(buffer, offset+leng, 1) { + bValue := ReadAccessResultReadResult{} + leng += bValue.Decode(buffer, offset+leng, apduLen-leng) + + rar.ListOfResults = append(rar.ListOfResults, bValue) + } + + if encoding.IsClosingTagNumber(buffer, offset+leng, 1) { + leng += 1 + } else { + return -1 + } + } else { + return -1 + } + + return leng +} + +type BACnetAccessRule struct { + TimeRangeSpecifier BACnetTimeRangeSpecifierChoice + TimeRange BACnetDeviceObjectPropertyReference + LocationSpecifier BACnetLocationSpecifierChoice + Location BACnetDeviceObjectReference + Enable bool +} + +type BACnetTimeRangeSpecifierChoice int + +const ( + Specified BACnetTimeRangeSpecifierChoice = iota + Always +) + +type BACnetLocationSpecifierChoice int + +const ( + SpecifiedLocation BACnetLocationSpecifierChoice = iota + All +) + +func (bar *BACnetAccessRule) Decode(buffer []byte, offset, apduLen int) int { + return -1 +} + +type BACnetNameValue struct { + Name string + Value BACnetValue +} + +func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // Name + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != 0 { + return -1 + } + leng += leng1 + leng1, bnv.Name = encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) + leng += leng1 + + // Decode value + decodeLen := 0 + if leng < apduLen { + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng += leng1 + + switch ApplicationTags(tagNumber) { + case Null: + bnv.Value = BACnetValue{Value: nil} + decodeLen = 0 + // Fixme: fix null type nothing else to do, some Error occurs!!!! + case Boolean: + if lenValue > 0 { + bnv.Value = BACnetValue{Value: true} + } else { + bnv.Value = BACnetValue{Value: false} + } + case UnsignedInt: + decodeLen, bnv.Value.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + case SignedInt: + decodeLen, bnv.Value.Value = encoding.DecodeSigned(buffer, offset+leng, int(lenValue)) + case Real: + decodeLen, bnv.Value.Value = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) + case Double: + decodeLen, bnv.Value.Value = encoding.DecodeDoubleSafe(buffer, offset+leng, int(lenValue)) + case OctetString: + decodeLen, bnv.Value.Value = encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) + case CharacterString: + decodeLen, bnv.Value.Value = encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) + case BitString: + bitValue := BACnetBitString{} + decodeLen = bitValue.Decode(buffer, offset+leng, int(lenValue)) + bnv.Value.Value = bitValue + case Enumerated: + decodeLen, bnv.Value.Value = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + case Date: + decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) + + if leng < apduLen { + leng1, tagNumber, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng+decodeLen) + if tagNumber == byte(Time) { + leng += leng1 + leng-- + bnv.Value.Value = &DateTime{} + decodeLen = bnv.Value.Value.(*DateTime).Decode(buffer, offset+leng) + } + } else { + bnv.Value.Value = dateValue + } + case Time: + decodeLen, bnv.Value.Value = encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) + } + + if decodeLen < 0 { + return -1 + } + leng += decodeLen + } + + return leng +} + +type BACnetNameValueCollection struct { + Members []BACnetNameValue +} + +func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // Check if it's an opening tag number + if !encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { + return -1 + } + + leng += 1 + bnc.Members = make([]BACnetNameValue, 0) + + for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { + bValue := BACnetNameValue{} + leng1 := bValue.Decode(buffer, offset+leng, apduLen-leng) + if leng1 < 0 { + return -1 + } + leng += leng1 + bnc.Members = append(bnc.Members, bValue) + } + + leng += 1 + return leng +} + +type BACnetSecurityPolicy int + +type BACnetNetworkSecurityPolicy struct { + PortID int + SecurityLevel BACnetSecurityPolicy +} + +func (bns *BACnetNetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // port_id + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != 0 { + return -1 + } + leng += leng1 + leng1, portID := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bns.PortID = int(portID) + + leng = 0 + // security_level + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != 1 { + return -1 + } + leng += leng1 + leng1, uVal := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bns.SecurityLevel = BACnetSecurityPolicy(uVal) + + return leng +} + +type BACnetPortPermission struct { + PortID int + Enabled bool +} + +func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + + // port_id + leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != 0 { + return -1 + } + leng += leng1 + leng1, portID := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng += leng1 + bpp.PortID = int(portID) + + leng = 0 + // enabled + leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if tagNumber != 1 { + return -1 + } + leng += leng1 + if lenValue > 0 { + bpp.Enabled = true + } else { + bpp.Enabled = false + } + + return leng +} + +type BACnetPriorityValue struct { + Value interface{} +} + +func (bpv *BACnetPriorityValue) Decode(buffer []byte, offset, apduLen int) int { + // TODO Implement decoding logic for BACnetPriorityValue + return -1 +} + +type BACnetPriorityArray struct { + Value [16]BACnetPriorityValue +} + +func (bpa *BACnetPriorityArray) Decode(buffer []byte, offset, apduLen int) int { + leng := 0 + i := 0 + + for leng < apduLen && i < 16 { + bpa.Value[i] = BACnetPriorityValue{} + leng += bpa.Value[i].Decode(buffer, offset+leng, apduLen-leng) + i++ + } + + return leng +} + +type BACnetProcessIdSelection struct { + Value interface{} // You can specify the type you expect here +} + +func (bps *BACnetProcessIdSelection) Decode(buffer []byte, offset, apduLen int) int { + // TODO Implement decoding logic for BACnetProcessIdSelection + return -1 +} + +type BACnetPropertyAccessResult struct { + ObjectIdentifier ObjectIdentifier + PropertyIdentifier encoding.PropertyIdentifier + PropertyArrayIndex int + DeviceIdentifier ObjectIdentifier + AccessResult interface{} +} + +func (bpar *BACnetPropertyAccessResult) Decode(buffer []byte, offset, apduLen int) int { + // TODO Implement decoding logic for BACnetPropertyAccessResult here + return -1 +} + +type BACnetSetpointReference struct { + Value interface{} +} + +func (bsr *BACnetSetpointReference) Decode(buffer []byte, offset, apduLen int) int { + // TODO Implement decoding logic for BACnetSetpointReference here + return 0 +} + +type BACnetSpecialEvent struct { + Period interface{} + ListOfTimeValues []interface{} + EventPriority int +} + +func (bse *BACnetSpecialEvent) Decode(buffer []byte, offset, apduLen int) int { + // TODO Implement decoding logic for BACnetSpecialEvent here + return 0 +} + +type BACnetTimerStateChangeValue struct { + Value interface{} +} + +func (scv *BACnetTimerStateChangeValue) Decode([]byte, int, int) int { + // TODO implement decoder + return -1 +} + +type BACnetValueSource struct { + Value interface{} +} + +func (scv *BACnetValueSource) Decode([]byte, int, int) int { + // TODO implement decoder + return -1 +} + +type BACnetVMACEntry struct { + VirtualMacAddress interface{} + NativeMacAddress interface{} +} + +func (scv *BACnetVMACEntry) Decode([]byte, int, int) int { + // TODO implement decoder + return -1 +} + +type BACnetAssignedAccessRights struct { + AssignedAccessRights BACnetDeviceObjectReference + Enable bool +} + +func (scv *BACnetAssignedAccessRights) Decode([]byte, int, int) int { + // TODO implement decoder + return -1 +} + +type BACnetAssignedLandingCalls struct { + LandingCalls []landingCall +} + +type landingCall struct { + FloorNumber int + Direction BACnetLiftCarDirection +} + +func (balc *BACnetAssignedLandingCalls) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetAssignedLandingCalls + return 0 +} + +type BACnetLiftCarDirection int + +type BACnetAuthenticationFactor struct { + FormatType BACnetAuthenticationFactorType + FormatClass int + Value []byte +} + +func (baf *BACnetAuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetAuthenticationFactor + return 0 +} + +type BACnetAuthenticationFactorType int + +type BACnetAuthenticationFactorFormat struct { + FormatType BACnetAuthenticationFactorType + VendorID int + VendorFormat int +} + +func (baff *BACnetAuthenticationFactorFormat) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetAuthenticationFactorFormat + return 0 +} + +type BACnetAuthenticationPolicy struct { + Policies []policy + OrderEnforced bool + Timeout int +} + +type policy struct { + CredentialDataInput BACnetDeviceObjectReference + Index int +} + +func (bap *BACnetAuthenticationPolicy) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetAuthenticationPolicy + return 0 +} + +type BACnetBDTEntry struct { + // Define BACnetBDTEntry structure here +} + +type BACnetChannelValue struct { + Value interface{} +} + +func (bcv *BACnetChannelValue) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetChannelValue + return 0 +} + +type BACnetCOVSubscription struct { + Recipient BACnetRecipientProcess + MonitoredPropertyReference BACnetObjectPropertyReference + IssueConfirmedNotifications bool + TimeRemaining int + COVIncrement float64 +} + +func (bcs *BACnetCOVSubscription) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetCOVSubscription + return 0 +} + +type BACnetAccessAuthenticationFactorDisable int + +type BACnetCredentialAuthenticationFactor struct { + Disable BACnetAccessAuthenticationFactorDisable + AuthenticationFactor BACnetAuthenticationFactor +} + +func (bcaf *BACnetCredentialAuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetCredentialAuthenticationFactor + return 0 +} + +type BACnetDailySchedule struct { + DaySchedule []interface{} +} + +func (bds *BACnetDailySchedule) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetDailySchedule + return 0 +} + +type BACnetRecipientProcess struct { + // Define BACnetRecipientProcess structure here +} + +type BACnetEventNotificationSubscription struct { + Recipient BACnetRecipient + ProcessIdentifier int + IssueConfirmedNotifications bool + TimeRemaining int +} + +func (bens *BACnetEventNotificationSubscription) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetEventNotificationSubscription + return 0 +} + +type BACnetEventParameter struct { + Value interface{} +} + +func (bep *BACnetEventParameter) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetEventParameter + return 0 +} + +type BACnetFaultParameter struct { + Value interface{} +} + +func (bfp *BACnetFaultParameter) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for BACnetFaultParameter + return 0 +} diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index b537c83..d2f84ed 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -139,3 +139,8 @@ func encodeBACnetDouble(value float64) []byte { binary.BigEndian.PutUint64(buf, math.Float64bits(value)) return buf } + +func EncodeApplicationBitString(val interface{}) []byte { + // TODO + return nil +} From 3eb993e901de535e73d86465bd2c12c6cdc00fc1 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 15 Sep 2023 22:52:11 +0300 Subject: [PATCH 20/24] Fix issue with unnecessary print statements and add BACnet header decoding The commit fixes the issue where unnecessary print statements were present in the code. Additionally, it adds the decoding of the BACnet message in the response of the read property example. Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go index 73c31d9..fcbf4da 100644 --- a/example/readProperty/readProperty.go +++ b/example/readProperty/readProperty.go @@ -48,11 +48,6 @@ func main() { blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) message := append(blvcBytes, mes...) - fmt.Println(message) - - message = []byte{129, 10, 0, 17, 1, 4, 0, 5, 1, 12, 12, 0, 0, 0, 10, 25, 85} - fmt.Println(message) - // Define the BACnet broadcast address (255.255.255.255:47808) remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") if err != nil { @@ -99,7 +94,23 @@ func main() { // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] - log.Printf("Received response: %X\n", response) - + blvc := bacnet.BVLC{BVLLTypeBACnetIP: 0x81} + headerLength, function, msgLength, err := blvc.Decode(response, 0) + if err != nil { + log.Fatal(err) + } + fmt.Printf("headerLength %v BVLCfunction %v msgLen %v\n", headerLength, function, msgLength) + fmt.Println("blvc", blvc) + npdu := bacnet.NPDU{Version: 1} + npduLen := npdu.Decode(response, headerLength) + fmt.Println("npdu", npdu) + apdu := bacnet.APDU{} + apduLen := apdu.Decode(response, headerLength+npduLen) + fmt.Println("apdu", apdu) + readPropACK := bacnet.ReadPropertyACK{} + if _, err = readPropACK.Decode(response, headerLength+npduLen+apduLen-2, len(response)); err != nil { + log.Fatal(err) + } + fmt.Println("readprop", readPropACK) } } From d2c5be983822d6adeaa61b7eff753e49d1ae477e Mon Sep 17 00:00:00 2001 From: SammyOina Date: Wed, 20 Sep 2023 13:43:26 +0300 Subject: [PATCH 21/24] Fix bug in readProperty.go Remove commented out code and fix formatting in readProperty.go file. extract constants add coomments Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 25 +- example/whoIs/whois.go | 30 +- internal/bitarray.go | 23 +- pkg/bacnet/apdu.go | 46 +- pkg/bacnet/bvlc.go | 17 +- pkg/bacnet/general.go | 6 +- pkg/bacnet/iam.go | 82 +- pkg/bacnet/network.go | 36 +- pkg/bacnet/npdu.go | 59 +- pkg/bacnet/object.go | 26 +- pkg/bacnet/property.go | 1079 +++++++++++++++++++------- pkg/bacnet/whois.go | 53 +- pkg/encoding/decoding.go | 46 +- pkg/encoding/encoding.go | 21 +- pkg/encoding/property.go | 11 +- pkg/encoding/tags.go | 38 +- pkg/transport/udp/broadcast.go | 6 +- 17 files changed, 1155 insertions(+), 449 deletions(-) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go index fcbf4da..531215e 100644 --- a/example/readProperty/readProperty.go +++ b/example/readProperty/readProperty.go @@ -13,10 +13,6 @@ import ( func main() { netType := encoding.IPV4 - /*deviceID := bacnet.ObjectIdentifier{ - Type: encoding.AnalogInput, - Instance: 101, - }*/ destination := bacnet.NewBACnetAddress(0, nil, "127.0.0.6:47809", &netType) npdu := bacnet.NewNPDU(destination, nil, nil, nil) npdu.Control.SetDataExpectingReply(true) @@ -32,8 +28,12 @@ func main() { ServiceChoice: byte(bacnet.ReadProperty), SegmentedResponseAccepted: false, MaxSegmentsAccepted: bacnet.BacnetMaxSegments(encoding.NoSegmentation), - //MaxApduLengthAccepted: bacnet.MaxAPDU1476, - InvokeID: 0, + InvokeID: 0, + } + + apduBytes, err := apdu.Encode() + if err != nil { + log.Fatal(err) } req := bacnet.ReadPropertyRequest{ @@ -41,10 +41,13 @@ func main() { ObjectIdentifier: &bacnet.ObjectIdentifier{Type: encoding.AnalogInput, Instance: 10}, } - mes := append(npduBytes, apdu.Encode()...) + mes := append(npduBytes, apduBytes...) mes = append(mes, req.Encode()...) - blvc := bacnet.NewBVLC(transport.IP) + blvc, err := bacnet.NewBVLC(transport.IP) + if err != nil { + log.Fatal(err) + } blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) message := append(blvcBytes, mes...) @@ -80,7 +83,6 @@ func main() { conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // Set a timeout for responses for { - //conn.ReadFromUDPAddrPort() n, _, err := conn.ReadFromUDP(buffer) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { @@ -105,7 +107,10 @@ func main() { npduLen := npdu.Decode(response, headerLength) fmt.Println("npdu", npdu) apdu := bacnet.APDU{} - apduLen := apdu.Decode(response, headerLength+npduLen) + apduLen, err := apdu.Decode(response, headerLength+npduLen) + if err != nil { + log.Fatal(err) + } fmt.Println("apdu", apdu) readPropACK := bacnet.ReadPropertyACK{} if _, err = readPropACK.Decode(response, headerLength+npduLen+apduLen-2, len(response)); err != nil { diff --git a/example/whoIs/whois.go b/example/whoIs/whois.go index cd52b4d..c00d173 100644 --- a/example/whoIs/whois.go +++ b/example/whoIs/whois.go @@ -9,7 +9,6 @@ import ( "github.com/absmach/bacnet/pkg/bacnet" "github.com/absmach/bacnet/pkg/encoding" "github.com/absmach/bacnet/pkg/transport" - "github.com/absmach/bacnet/pkg/transport/udp" ) func main() { @@ -21,12 +20,8 @@ func main() { } whoisBytes := req.Encode() - broads, err := udp.GetBroadcastAddress("127.0.0.6", 47809) - if err != nil { - log.Fatalf("failed to encode npdu with error %v", err) - } netType := encoding.IPV4 - broads = *bacnet.NewBACnetAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) + broads := *bacnet.NewBACnetAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) npdu := bacnet.NewNPDU(&broads, nil, nil, nil) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) @@ -40,33 +35,37 @@ func main() { ServiceChoice: byte(bacnet.ServiceChoiceWhoIs), } - apduBytes := apdu.Encode() + apduBytes, err := apdu.Encode() + if err != nil { + log.Fatal(err) + } mes := append(npduBytes, apduBytes...) mes = append(mes, whoisBytes...) - blvc := bacnet.NewBVLC(transport.IP) + blvc, err := bacnet.NewBVLC(transport.IP) + if err != nil { + log.Fatal(err) + } blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) message := append(blvcBytes, mes...) // Define the BACnet broadcast address (255.255.255.255:47808) remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") if err != nil { - fmt.Println("Error resolving remote address:", err) - return + log.Fatal("Error resolving remote address:", err) } localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") if err != nil { - fmt.Println("Error: ", err) + log.Fatal("Error: ", err) return } // Create a UDP connectionBACnetAddress conn, err := net.DialUDP("udp", localAddr, remoteAddr) if err != nil { - fmt.Println("Error creating UDP connection:", err) - return + log.Fatal("Error creating UDP connection:", err) } defer conn.Close() @@ -109,7 +108,10 @@ func main() { fmt.Println("npdu", npdu) fmt.Println(response[headerLength+npduLen:]) apdu := bacnet.APDU{} - apduLen := apdu.Decode(response, headerLength+npduLen) + apduLen, err := apdu.Decode(response, headerLength+npduLen) + if err != nil { + log.Fatal(err) + } fmt.Println("apdu", apdu) fmt.Println(response[headerLength+npduLen+apduLen:]) iam := bacnet.IAmRequest{} diff --git a/internal/bitarray.go b/internal/bitarray.go index ff03c23..b844815 100644 --- a/internal/bitarray.go +++ b/internal/bitarray.go @@ -2,31 +2,42 @@ package internal import "errors" -var errBitArrayLen = errors.New("bit array length must be 8 to convert to byte") +var ( + errBitArrayLen = errors.New("bit array length must be 8 to convert to byte") + errOutOfBounds = errors.New("index is out of the range for the bitarray") +) +// BitArray defines an array of bits. type BitArray struct { bits []bool } +// Creates a new bit array for the provided length. func NewBitArray(length int) *BitArray { return &BitArray{ bits: make([]bool, length), } } -func (ba *BitArray) Set(index int, value bool) { +// Set sets the value of the bit array at the given index and value. +func (ba *BitArray) Set(index int, value bool) error { if index >= 0 && index < len(ba.bits) { ba.bits[index] = value + return nil } + return errOutOfBounds } -func (ba *BitArray) Get(index int) bool { +// Get returns the the value of the bit array at the given index. +func (ba *BitArray) Get(index int) (bool, error) { if index >= 0 && index < len(ba.bits) { - return ba.bits[index] + return ba.bits[index], nil } - return false + return false, errOutOfBounds } +// ToByte converts bitarray to byte value. +// TODO return byte array. func (ba *BitArray) ToByte() (byte, error) { // Ensure the length of the bit array is 8 to convert to a byte. if len(ba.bits) != 8 { @@ -43,6 +54,8 @@ func (ba *BitArray) ToByte() (byte, error) { return byteValue, nil } +// NewBitArrayFromByte creates a new bit array from the given byte. +// TODO check length of incoming byte. func NewBitArrayFromByte(byteValue byte) *BitArray { bitArray := NewBitArray(8) for j := 0; j < 8; j++ { diff --git a/pkg/bacnet/apdu.go b/pkg/bacnet/apdu.go index 83b1628..5e8b8a4 100644 --- a/pkg/bacnet/apdu.go +++ b/pkg/bacnet/apdu.go @@ -1,5 +1,9 @@ package bacnet +import "errors" + +var errUnknownPDU = errors.New("unkown PDU type") + type BACnetConfirmedServiceChoice int type BACnetUnconfirmedServiceChoice int @@ -62,6 +66,7 @@ const ( ServiceChoiceYouAre ) +// APDU Application Protocol Data Unit. type APDU struct { PduType BacnetPduTypes SegmentedMessage bool @@ -76,7 +81,8 @@ type APDU struct { ServiceChoice byte } -func (a APDU) Encode() []byte { +// Encode encodes APDU data to []byte. +func (a APDU) Encode() ([]byte, error) { buffer := make([]byte, 0) tmp := byte(a.PduType) @@ -89,38 +95,42 @@ func (a APDU) Encode() []byte { if a.SegmentedResponseAccepted { tmp |= 0x40 } - buffer = append(buffer, tmp) - if a.PduType == PDUTypeConfirmedServiceRequest { + switch a.PduType { + case PDUTypeConfirmedServiceRequest: + buffer = append(buffer, tmp) buffer = append(buffer, byte(a.MaxSegmentsAccepted)|byte(a.MaxApduLengthAccepted)) buffer = append(buffer, a.InvokeID) if a.SegmentedMessage { buffer = append(buffer, a.SequenceNumber, a.ProposedWindowSize) } - } else if a.PduType == PDUTypeUnconfirmedServiceRequest { - // No additional fields for unconfirmed service request - } else if a.PduType == PDUTypeSimpleAck { + case PDUTypeUnconfirmedServiceRequest: + buffer = append(buffer, tmp) + case PDUTypeSimpleAck: + buffer = append(buffer, tmp) buffer = append(buffer, a.InvokeID) - } else if a.PduType == PDUTypeComplexAck { + case PDUTypeComplexAck: buffer = append(buffer, a.InvokeID) if a.SegmentedMessage { buffer = append(buffer, a.SequenceNumber, a.ProposedWindowSize) } - } else { - // Handle other PDU types + default: + return []byte{}, errUnknownPDU } buffer = append(buffer, a.ServiceChoice) - return buffer + return buffer, nil } -func (a *APDU) Decode(buffer []byte, offset int) int { +// Decode decodes []byte to APDU data. +func (a *APDU) Decode(buffer []byte, offset int) (int, error) { length := 0 a.PduType = BacnetPduTypes(buffer[offset]) tmp := byte(buffer[offset]) length++ - if a.PduType == PDUTypeConfirmedServiceRequest { + switch a.PduType { + case PDUTypeConfirmedServiceRequest: a.SegmentedMessage = tmp&0x10 != 0 a.MoreFollows = tmp&0x20 != 0 a.SegmentedResponseAccepted = tmp&0x40 != 0 @@ -137,15 +147,15 @@ func (a *APDU) Decode(buffer []byte, offset int) int { } a.ServiceChoice = buffer[offset+length] length++ - } else if a.PduType == PDUTypeUnconfirmedServiceRequest { + case PDUTypeUnconfirmedServiceRequest: a.ServiceChoice = buffer[offset+length] length++ - } else if a.PduType == PDUTypeSimpleAck { + case PDUTypeSimpleAck: a.InvokeID = buffer[offset+length] length++ a.ServiceChoice = buffer[offset+length] length++ - } else if a.PduType == PDUTypeComplexAck { + case PDUTypeComplexAck: a.SegmentedMessage = tmp&0x10 != 0 a.InvokeID = buffer[offset+length] length++ @@ -157,9 +167,9 @@ func (a *APDU) Decode(buffer []byte, offset int) int { a.ProposedWindowSize = buffer[offset+length] length++ } - } else { - return -1 + default: + return -1, errUnknownPDU } - return length + return length, nil } diff --git a/pkg/bacnet/bvlc.go b/pkg/bacnet/bvlc.go index 5591d9f..80f57a6 100644 --- a/pkg/bacnet/bvlc.go +++ b/pkg/bacnet/bvlc.go @@ -43,13 +43,15 @@ const ( MaxAPDU1476 ) +// BACnet Virtual Link Control type BVLC struct { BVLLTypeBACnetIP byte BVLCHeaderLength byte BVLCMaxAPDU MaxAPDU } -func NewBVLC(transprt transport.Transport) *BVLC { +// NewBVLC creates a new BVLC with the given transport. +func NewBVLC(transprt transport.Transport) (*BVLC, error) { bvlc := &BVLC{ BVLLTypeBACnetIP: 0x81, BVLCHeaderLength: 4, @@ -57,11 +59,15 @@ func NewBVLC(transprt transport.Transport) *BVLC { if transprt == transport.IP { bvlc.BVLCMaxAPDU = MaxAPDU1476 + } else { + return nil, errUnsupportedTransport } - return bvlc + return bvlc, nil } +// Decode decodes incoming buffer. +// TODO support other functions. func (bvlc *BVLC) Decode(buffer []byte, offset int) (int, BVLCFunctions, uint16, error) { msgType := buffer[0] function := BVLCFunctions(buffer[1]) @@ -100,14 +106,11 @@ func (bvlc *BVLC) Decode(buffer []byte, offset int) (int, BVLCFunctions, uint16, return 0, 0, 0, errors.New("todo") } -func (bvlc BVLC) First4BytesHeaderEncode(function BVLCFunctions, msgLength uint16) []byte { +// Encode encodes the bvlc header to []byte. +func (bvlc BVLC) Encode(function BVLCFunctions, msgLength uint16) []byte { b := make([]byte, 4) b[0] = bvlc.BVLLTypeBACnetIP b[1] = byte(function) binary.BigEndian.PutUint16(b[2:4], msgLength) return b } - -func (bvlc BVLC) Encode(function BVLCFunctions, msgLength uint16) []byte { - return bvlc.First4BytesHeaderEncode(function, msgLength) -} diff --git a/pkg/bacnet/general.go b/pkg/bacnet/general.go index ba24376..40f4329 100644 --- a/pkg/bacnet/general.go +++ b/pkg/bacnet/general.go @@ -7,16 +7,16 @@ import ( ) type DateTime struct { - Date time.Time + DateTime time.Time } func (dt *DateTime) Decode(buf []byte, offset int) int { len, date := encoding.DecodeApplicationDate(buf, offset) len1, ttime := encoding.DecodeApplicationTime(buf, offset+len) - dt.Date = ttime.AddDate(date.Year(), int(date.Month()), date.Day()) + dt.DateTime = ttime.AddDate(date.Year(), int(date.Month()), date.Day()) return len + len1 } func (dt DateTime) Encode() []byte { - return append(encoding.EncodeApplicationDate(dt.Date), encoding.EncodeApplicationTime(dt.Date)...) + return append(encoding.EncodeApplicationDate(dt.DateTime), encoding.EncodeApplicationTime(dt.DateTime)...) } diff --git a/pkg/bacnet/iam.go b/pkg/bacnet/iam.go index 551c63b..cc53e25 100644 --- a/pkg/bacnet/iam.go +++ b/pkg/bacnet/iam.go @@ -2,7 +2,6 @@ package bacnet import ( "errors" - "fmt" "github.com/absmach/bacnet/pkg/encoding" ) @@ -18,54 +17,75 @@ func (iam *IAmRequest) Decode(buffer []byte, offset int) (int, error) { leng := 0 iam.IamDeviceIdentifier = ObjectIdentifier{} // OBJECT ID - object id - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber != byte(BACnetObjectIdentifier) { - fmt.Println("tag num object id", tagNumber) return -1, errors.New("Invalid tag number") } - leng = iam.IamDeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + leng1, err = iam.IamDeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + leng += leng1 if iam.IamDeviceIdentifier.Type != encoding.ObjectTypeDevice { return -1, errors.New("Got Iam from no device") } // MAX APDU - unsigned - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber != byte(UnsignedInt) { - fmt.Println("tag num max apdu", tagNumber) return -1, errors.New("Invalid tag number") } - leng1, decodedValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, decodedValue, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 iam.MaxAPDULengthAccepted = decodedValue // Segmentation - enumerated - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber != byte(Enumerated) { - fmt.Println("tag num segmentation", tagNumber) return -1, errors.New("Invalid tag number") } propID := encoding.SegmentationSupported - leng1, segmentationSupported := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, segmentationSupported, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 iam.SegmentationSupported = segmentationSupported // Vendor ID - unsigned16 - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber != byte(UnsignedInt) { - fmt.Println("tag num vendor ID", tagNumber) return -1, errors.New("Invalid tag number") } - leng1, decodedValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, decodedValue, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 if decodedValue > 0xFFFF { @@ -93,17 +113,26 @@ type YouAreRequest struct { func (youAre *YouAreRequest) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == byte(UnsignedInt) { - leng1, decodedValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, decodedValue, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 youAre.VendorID = decodedValue } else { return -1, errors.New("Invalid tag number") } - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == byte(CharacterString) { leng1, decodedValue := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) @@ -114,7 +143,10 @@ func (youAre *YouAreRequest) Decode(buffer []byte, offset int, apduLen int) (int return -1, errors.New("Invalid tag number") } - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == byte(CharacterString) { leng1, decodedValue := encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) @@ -125,16 +157,26 @@ func (youAre *YouAreRequest) Decode(buffer []byte, offset int, apduLen int) (int } if leng < apduLen { - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(BACnetObjectIdentifier) { leng += leng1 youAre.DeviceIdentifier = ObjectIdentifier{} - leng = youAre.DeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + leng1, err = youAre.DeviceIdentifier.Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + leng += leng1 } } if leng < apduLen { - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(OctetString) { leng += leng1 leng1, decodedValue := encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) diff --git a/pkg/bacnet/network.go b/pkg/bacnet/network.go index aeb5c3c..ff87f7b 100644 --- a/pkg/bacnet/network.go +++ b/pkg/bacnet/network.go @@ -2,12 +2,18 @@ package bacnet import ( "encoding/binary" + "errors" "fmt" "strings" "github.com/absmach/bacnet/pkg/encoding" ) +var ( + errMacAddressLen = errors.New("invalid mac address length") + errInvalidTagNumber = errors.New("invalid tag number") +) + type ApplicationTags int const ( @@ -79,31 +85,43 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface return addr } -func (ba *BACnetAddress) IPAndPort() (string, int) { +func (ba *BACnetAddress) IPAndPort() (string, int, error) { + if len(ba.MacAddress) < 6 { + return "", 0, errMacAddressLen + } ip := fmt.Sprintf("%d.%d.%d.%d", ba.MacAddress[0], ba.MacAddress[1], ba.MacAddress[2], ba.MacAddress[3]) port := int(ba.MacAddress[4])<<8 + int(ba.MacAddress[5]) - return ip, port + return ip, port, nil } -func (ba *BACnetAddress) Decode(buffer []byte, offset, apduLen int) int { +func (ba *BACnetAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(UnsignedInt) { leng += leng1 - leng1, ba.NetworkNumber = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, ba.NetworkNumber, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(OctetString) { leng += leng1 leng1, ba.MacAddress = encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } diff --git a/pkg/bacnet/npdu.go b/pkg/bacnet/npdu.go index 7dc9f92..5f9f0d6 100644 --- a/pkg/bacnet/npdu.go +++ b/pkg/bacnet/npdu.go @@ -3,11 +3,11 @@ package bacnet import ( "encoding/binary" "errors" - "log" "github.com/absmach/bacnet/internal" ) +// NPDU Network Protocol Data Unit netwrok layer data packet. type NPDU struct { Version uint8 // Always one. Control NPDUControlInformation @@ -24,26 +24,39 @@ type NPDU struct { VendorID uint16 } +// NPDUControlInformation a bit array to define network control information. type NPDUControlInformation struct { control internal.BitArray } +// NewNPDUControlInformation creates a new bit array for network control info. func NewNPDUControlInformation() *NPDUControlInformation { return &NPDUControlInformation{ control: *internal.NewBitArray(8), } } +// IsNetworkLayerMessage returns wether a message is a network layer message. func (nci *NPDUControlInformation) IsNetworkLayerMessage() bool { - return nci.control.Get(0) + val, err := nci.control.Get(0) + if err != nil { + return false + } + return val } +// SetNetworkLayerMessage sets the value for the netwrok layer message bit. func (nci *NPDUControlInformation) SetNetworkLayerMessage(a bool) { nci.control.Set(0, a) } +// IsDestinationSpecifier returns based on the npdu control bit bit if it is a message specifier. func (nci *NPDUControlInformation) IsDestinationSpecifier() bool { - return nci.control.Get(2) + val, err := nci.control.Get(2) + if err != nil { + return false + } + return val } func (nci *NPDUControlInformation) SetDestinationSpecifier(a bool) { @@ -51,7 +64,11 @@ func (nci *NPDUControlInformation) SetDestinationSpecifier(a bool) { } func (nci *NPDUControlInformation) IsSourceSpecifier() bool { - return nci.control.Get(4) + val, err := nci.control.Get(4) + if err != nil { + return false + } + return val } func (nci *NPDUControlInformation) SetSourceSpecifier(a bool) { @@ -59,26 +76,42 @@ func (nci *NPDUControlInformation) SetSourceSpecifier(a bool) { } func (nci *NPDUControlInformation) IsDataExpectingReply() bool { - return nci.control.Get(5) + val, err := nci.control.Get(5) + if err != nil { + return false + } + return val } func (nci *NPDUControlInformation) SetDataExpectingReply(a bool) { nci.control.Set(5, a) } +// NetworkPriority returns the network priority based on the network control information bits. func (nci *NPDUControlInformation) NetworkPriority() (NetworkPriority, error) { - if !nci.control.Get(6) && !nci.control.Get(7) { + control7, err := nci.control.Get(7) + if err != nil { + return 0, err + } + control6, err := nci.control.Get(6) + if err != nil { + return 0, err + } + switch { + case !control6 && !control7: return NormalMessage, nil - } else if !nci.control.Get(6) && nci.control.Get(7) { + case !control6 && control7: return UrgentMessage, nil - } else if nci.control.Get(6) && !nci.control.Get(7) { + case control6 && !control7: return CriticalEquipmentMessage, nil - } else if nci.control.Get(6) && nci.control.Get(7) { + case control6 && control7: return LifeSafetyMessage, nil + default: + return 0, errors.New("invalid network priority") } - return 0, errors.New("invalid network priority") } +// SetNetworkPriority sets the network control information based on network priority set. func (nci *NPDUControlInformation) SetNetworkPriority(a NetworkPriority) error { switch a { case NormalMessage: @@ -99,6 +132,7 @@ func (nci *NPDUControlInformation) SetNetworkPriority(a NetworkPriority) error { return nil } +// Encode encodes network control information. func (nci *NPDUControlInformation) Encode() ([]byte, error) { b, err := nci.control.ToByte() if err != nil { @@ -107,6 +141,7 @@ func (nci *NPDUControlInformation) Encode() ([]byte, error) { return []byte{b}, nil } +// Decode decodes network control information from a byte buffer. func (nci *NPDUControlInformation) Decode(buffer []byte, offset int) int { if offset < len(buffer) { nci.control = *internal.NewBitArrayFromByte(buffer[offset]) @@ -115,6 +150,7 @@ func (nci *NPDUControlInformation) Decode(buffer []byte, offset int) int { return 0 } +// NewNPDU creates a new NPDU. func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount *uint8, vendorID *uint16) *NPDU { npdu := &NPDU{ Version: 1, @@ -149,6 +185,7 @@ func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount *uint8, return npdu } +// Encode encodes the NPDU data to []byte. func (npdu *NPDU) Encode() ([]byte, error) { buffer := make([]byte, 0) buffer = append(buffer, npdu.Version) @@ -188,12 +225,12 @@ func (npdu *NPDU) Encode() ([]byte, error) { return buffer, nil } +// Decode decodes []byte to NPDU. func (npdu *NPDU) Decode(buffer []byte, offset int) int { length := 0 version := buffer[offset] // always 1!!!! length++ if version != npdu.Version { - log.Println("Received something else!") return -1 } diff --git a/pkg/bacnet/object.go b/pkg/bacnet/object.go index a68a104..5477449 100644 --- a/pkg/bacnet/object.go +++ b/pkg/bacnet/object.go @@ -13,22 +13,32 @@ type ObjectIdentifier struct { Instance ObjectInstance } -func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdulen int) int { - len, val := encoding.DecodeUnsigned(buf, offset, 4) +func (oi *ObjectIdentifier) Decode(buf []byte, offset, apdulen int) (int, error) { + len, val, err := encoding.DecodeUnsigned(buf, offset, 4) + if err != nil { + return -1, err + } oi.Instance = ObjectInstance(val) & ObjectInstance(encoding.MaxInstance) oi.Type = encoding.ObjectType(val >> encoding.InstanceBits & encoding.MaxObject) - return len + return len, nil } -func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdulen int, tagNumber byte) int { +func (oi *ObjectIdentifier) DecodeContext(buf []byte, offset, apdulen int, tagNumber byte) (int, error) { len := 0 if encoding.IsContextTag(buf, offset+len, tagNumber) { - len1, _, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+len) + len1, _, lenVal, err := encoding.DecodeTagNumberAndValue(buf, offset+len) + if err != nil { + return -1, err + } len += len1 - len += oi.Decode(buf, offset+len1, int(lenVal)) - return len + leng1, err := oi.Decode(buf, offset+len1, int(lenVal)) + if err != nil { + return -1, err + } + len += leng1 + return len, nil } - return -1 + return -1, errInvalidTagNumber } func (oi ObjectIdentifier) Encode() []byte { diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 98c3ce6..2965bf5 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -34,40 +34,59 @@ func (r ReadPropertyRequest) Encode() []byte { return ret } -func (r *ReadPropertyRequest) Decode(buffer []byte, offset, apduLen int) int { +func (r *ReadPropertyRequest) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // objectIdentifier if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 r.ObjectIdentifier = &ObjectIdentifier{} - leng += r.ObjectIdentifier.Decode(buffer, offset+leng, int(lenValue)) + leng1, err = r.ObjectIdentifier.Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } // propertyIdentifier if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, r.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, r.PropertyIdentifier, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } // propertyArrayIndex (optional) if leng < apduLen && encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, r.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, r.PropertyArrayIndex, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } - return leng + return leng, nil } type ReadPropertyACK struct { @@ -83,7 +102,10 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error // 0 object_identifier if encoding.IsContextTag(buffer, offset+leng, 0) { r.ObjectIdentifier = ObjectIdentifier{} - leng1 := r.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := r.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("decoding error for object_identifier") @@ -91,10 +113,16 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error // 2 propertyidentifier if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 PropertyID := encoding.PropertyList - leng1, propID := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &PropertyID) + leng1, propID, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &PropertyID) + if err != nil { + return -1, err + } r.PropertyIdentifier = propID leng += leng1 } else { @@ -103,9 +131,15 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error // 2 property_array_index if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, r.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, r.PropertyArrayIndex, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } @@ -145,7 +179,10 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod var err error if !encoding.IsContextSpecific(buffer[offset]) { - tagLen, tagNumber, lenValueType := encoding.DecodeTagNumberAndValue(buffer, offset) + tagLen, tagNumber, lenValueType, err := encoding.DecodeTagNumberAndValue(buffer, offset) + if err != nil { + return -1, err + } if tagLen > 0 { ttag := ApplicationTags(tagNumber) bv.Tag = &ttag @@ -184,7 +221,10 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod decodeLen = bv.Value.(*BACnetAccessThreatLevel).Decode(buffer, offset+length, apduLen) } else { var uintVal uint32 - decodeLen, uintVal = encoding.DecodeUnsigned(buffer, offset+length, int(lenValueType)) + decodeLen, uintVal, err = encoding.DecodeUnsigned(buffer, offset+length, int(lenValueType)) + if err != nil { + return -1, err + } bv.Value = uintVal } case SignedInt: @@ -213,7 +253,10 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod bv.Tag = nil bv.Value = &BACnetDestination{} length-- - decodeLen = bv.Value.(*BACnetDestination).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*BACnetDestination).Decode(buffer, offset+length, apduLen) + if err != nil { + return -1, err + } case encoding.StatusFlags: bv.Tag = nil bitValue := &BACnetStatusFlags{} @@ -245,7 +288,10 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod bv.Value = bitValue } case Enumerated: - decodeLen, bv.Value = encoding.DecodeEnumerated(buffer, offset+length, lenValueType, objType, propID) + decodeLen, bv.Value, err = encoding.DecodeEnumerated(buffer, offset+length, lenValueType, objType, propID) + if err != nil { + return -1, err + } case Date: switch *propID { case encoding.EffectivePeriod: @@ -293,11 +339,17 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod bv.Tag = nil bv.Value = &BACnetAddressBinding{} length-- - decodeLen = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) + if err != nil { + return -1, err + } } else { var objectType encoding.ObjectType var instance uint32 - decodeLen, objectType, instance = encoding.DecodeObjectIDSafe(buffer, offset+length, lenValueType) + decodeLen, objectType, instance, err = encoding.DecodeObjectIDSafe(buffer, offset+length, lenValueType) + if err != nil { + return -1, err + } bv.Value = ObjectIdentifier{Type: objectType, Instance: ObjectInstance(instance)} } default: @@ -324,7 +376,11 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.TimeSynchronizationRecipients, encoding.CovuRecipients: bv.Value = &BACnetRecipient{} - length += bv.Value.(*BACnetRecipient).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetRecipient).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.KeySets: bv.Value = &BACnetSecurityKeySet{} length1, err := bv.Value.(*BACnetSecurityKeySet).Decode(buffer, offset+length, apduLen-length) @@ -378,13 +434,21 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.LastAccessPoint, encoding.EnergyMeterRef: bv.Value = &BACnetDeviceObjectReference{} - length += bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.EventAlgorithmInhibitRef, encoding.InputReference, encoding.ManipulatedVariableReference, encoding.ControlledVariableReference: bv.Value = &BACnetObjectPropertyReference{} - length += bv.Value.(*BACnetObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.LoggingRecord: bv.Value = &BACnetAccumulatorRecord{} length, err = bv.Value.(*BACnetAccumulatorRecord).Decode(buffer, offset+length, apduLen-length) @@ -393,38 +457,74 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod } case encoding.Action: bv.Value = &BACnetActionList{} - length += bv.Value.(*BACnetActionList).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetActionList).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.Scale: bv.Value = &BACnetScale{} - length += bv.Value.(*BACnetScale).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetScale).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.LightingCommand: bv.Value = &BACnetLightingCommand{} - length += bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.Prescale: bv.Value = &BACnetPrescale{} - length += bv.Value.(*BACnetPrescale).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetPrescale).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.RequestedShedLevel, encoding.ExpectedShedLevel, encoding.ActualShedLevel: bv.Value = &BACnetShedLevel{} - length += bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.LogBuffer: switch *objType { case encoding.TrendLog: bv.Value = &BACnetLogRecord{} - length += bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length, nil, nil) + length1, err := bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length, nil, nil) + if err != nil { + return -1, err + } + length += length1 case encoding.EventLog: bv.Value = &BACnetEventLogRecord{} - length += bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 } case encoding.DateList: bv.Value = &BACnetCalendarEntry{} - length += bv.Value.(*BACnetCalendarEntry).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetCalendarEntry).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.PresentValue: switch *objType { case encoding.Group: bv.Value = &ReadAccessResult{} - length += bv.Value.(*ReadAccessResult).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*ReadAccessResult).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.Channel: bv.Value = &BACnetChannelValue{} length += bv.Value.(*BACnetChannelValue).Decode(buffer, offset+length, apduLen-length) @@ -441,16 +541,32 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) case encoding.Tags: bv.Value = &BACnetNameValue{} - length += bv.Value.(*BACnetNameValue).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetNameValue).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.SubordinateTags: bv.Value = &BACnetNameValueCollection{} - length += bv.Value.(*BACnetNameValueCollection).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetNameValueCollection).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.NetworkAccessSecurityPolicies: bv.Value = &BACnetNetworkSecurityPolicy{} - length += bv.Value.(*BACnetNetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetNetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.PortFilter: bv.Value = &BACnetPortPermission{} - length += bv.Value.(*BACnetPortPermission).Decode(buffer, offset+length, apduLen-length) + length1, err := bv.Value.(*BACnetPortPermission).Decode(buffer, offset+length, apduLen-length) + if err != nil { + return -1, err + } + length += length1 case encoding.PriorityArray: bv.Value = &BACnetPriorityArray{} length += bv.Value.(*BACnetPriorityArray).Decode(buffer, offset+length, apduLen-length) @@ -574,16 +690,25 @@ func (entry *RouterEntry) Decode(buffer []byte, offset, apduLen int) (int, error var length int // network_number - length1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset) + length1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.UnsignedInt) { return -1, errors.New("Error decoding network_number") } length += length1 - length1, entry.NetworkNumber = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length1, entry.NetworkNumber, err = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + if err != nil { + return -1, err + } length += length1 // mac_address - length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + length1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.OctetString) { return -1, errors.New("Error decoding mac_address") } @@ -592,21 +717,33 @@ func (entry *RouterEntry) Decode(buffer []byte, offset, apduLen int) (int, error length += length1 // status - length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + length1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.Enumerated) { return -1, errors.New("Error decoding status") } length += length1 - length1, Val := encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length1, Val, err := encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + if err != nil { + return -1, err + } length += length1 entry.Status = BACnetRouterEntryStatus(Val) // performance_index (optional) if offset < apduLen { - length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + length1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.UnsignedInt) { length += length1 - length1, entry.PerformanceIndex = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + length1, entry.PerformanceIndex, err = encoding.DecodeUnsigned(buffer, offset+length, int(lenValue)) + if err != nil { + return -1, err + } length += length1 } } @@ -647,12 +784,15 @@ type BACnetDestination struct { Transitions *BACnetEventTransitionBits } -func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) int { +func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.BitString) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 b.ValidDays = &BACnetDaysOfWeek{} @@ -660,22 +800,28 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) int { leng1 = b.ValidDays.Decode(buffer, offset+leng, int(lenValue)) if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.Time) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 leng1, b.FromTime = encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) leng += leng1 - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.Time) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 leng1, b.ToTime = encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) @@ -683,25 +829,37 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) int { leng += leng1 b.Recipient = &BACnetRecipient{} - leng1 = b.Recipient.Decode(buffer, offset+leng, apduLen-leng) + leng1, err = b.Recipient.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.UnsignedInt) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 - leng1, b.ProcessIdentifier = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, b.ProcessIdentifier, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.Boolean) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 if lenValue > 0 { @@ -710,20 +868,23 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) int { b.IssueConfirmedNotifications = false } - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != byte(encoding.BitString) { - return -1 + return -1, errInvalidTagNumber } leng += leng1 b.Transitions = &BACnetEventTransitionBits{} leng1 = b.Transitions.Decode(buffer, offset+leng, int(lenValue)) if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 - return leng + return leng, nil } type BACnetDaysOfWeek struct { @@ -762,7 +923,7 @@ func (d *BACnetDaysOfWeek) GetDay(day int) (bool, error) { if day < 0 || day > 6 { return false, fmt.Errorf("Day index out of range") } - return d.bitString.Value.Get(day) == true, nil + return d.bitString.Value.Get(day) } type BACnetBitString struct { @@ -798,24 +959,35 @@ type BACnetRecipient struct { Value interface{} } -func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) int { +func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == 0 { // device_identifier leng += leng1 br.Value = &ObjectIdentifier{} - leng += br.Value.(*ObjectIdentifier).Decode(buffer, offset+leng, int(lenValue)) + leng1, err = br.Value.(*ObjectIdentifier).Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + leng += leng1 } else if tagNumber == 1 { // address br.Value = &BACnetAddress{} - leng += br.Value.(*BACnetAddress).Decode(buffer, offset+leng, int(lenValue)) + leng1, err = br.Value.(*BACnetAddress).Decode(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } + leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } // BACnetEventTransitionBits represents a BACnet event transition bits structure. @@ -842,8 +1014,8 @@ func (e *BACnetEventTransitionBits) Decode(buffer []byte, offset, apduLen int) i } // ToOffNormal returns the value of ToOffNormal property. -func (e *BACnetEventTransitionBits) ToOffNormal() bool { - return e.BitString.Value.Get(0) == true +func (e *BACnetEventTransitionBits) ToOffNormal() (bool, error) { + return e.BitString.Value.Get(0) } // SetToOffNormal sets the value of ToOffNormal property. @@ -852,8 +1024,8 @@ func (e *BACnetEventTransitionBits) SetToOffNormal(a bool) { } // ToFault returns the value of ToFault property. -func (e *BACnetEventTransitionBits) ToFault() bool { - return e.BitString.Value.Get(1) == true +func (e *BACnetEventTransitionBits) ToFault() (bool, error) { + return e.BitString.Value.Get(1) } // SetToFault sets the value of ToFault property. @@ -862,8 +1034,8 @@ func (e *BACnetEventTransitionBits) SetToFault(a bool) { } // ToNormal returns the value of ToNormal property. -func (e *BACnetEventTransitionBits) ToNormal() bool { - return e.BitString.Value.Get(2) == true +func (e *BACnetEventTransitionBits) ToNormal() (bool, error) { + return e.BitString.Value.Get(2) } // SetToNormal sets the value of ToNormal property. @@ -900,7 +1072,7 @@ func (s *BACnetStatusFlags) Decode(buffer []byte, offset, apduLen int) int { } // InAlarm returns the inalarm property. -func (s *BACnetStatusFlags) InAlarm() bool { +func (s *BACnetStatusFlags) InAlarm() (bool, error) { return s.bitstring.Value.Get(0) } @@ -910,7 +1082,7 @@ func (s *BACnetStatusFlags) SetInAlarm(a bool) { } // Fault returns the fault property. -func (s *BACnetStatusFlags) Fault() bool { +func (s *BACnetStatusFlags) Fault() (bool, error) { return s.bitstring.Value.Get(1) } @@ -920,7 +1092,7 @@ func (s *BACnetStatusFlags) SetFault(a bool) { } // Overridden returns the overridden property. -func (s *BACnetStatusFlags) Overridden() bool { +func (s *BACnetStatusFlags) Overridden() (bool, error) { return s.bitstring.Value.Get(2) } @@ -930,7 +1102,7 @@ func (s *BACnetStatusFlags) SetOverridden(a bool) { } // OutOfService returns the outofservice property. -func (s *BACnetStatusFlags) OutOfService() bool { +func (s *BACnetStatusFlags) OutOfService() (bool, error) { return s.bitstring.Value.Get(3) } @@ -960,7 +1132,7 @@ func (b *BACnetLimitEnable) Decode(buffer []byte, offset, apduLen int) int { return b.bitString.Decode(buffer, offset, apduLen) } -func (b *BACnetLimitEnable) LowLimitEnable() bool { +func (b *BACnetLimitEnable) LowLimitEnable() (bool, error) { return b.bitString.Value.Get(0) } @@ -968,7 +1140,7 @@ func (b *BACnetLimitEnable) SetLowLimitEnable(a bool) { b.bitString.Value.Set(0, a) } -func (b *BACnetLimitEnable) HighLimitEnable() bool { +func (b *BACnetLimitEnable) HighLimitEnable() (bool, error) { return b.bitString.Value.Get(1) } @@ -1003,7 +1175,7 @@ func (b *BACnetObjectTypesSupported) Set(property ObjectTypesSupportedProperty, b.bitstring.Value.Set(int(property), value) } -func (b *BACnetObjectTypesSupported) Get(property ObjectTypesSupportedProperty) bool { +func (b *BACnetObjectTypesSupported) Get(property ObjectTypesSupportedProperty) (bool, error) { return b.bitstring.Value.Get(int(property)) } @@ -1076,7 +1248,7 @@ func (b *BACnetServicesSupported) Set(property ServicesSupportedProperty, value b.bitstring.Value.Set(int(property), value) } -func (b *BACnetServicesSupported) Get(property ServicesSupportedProperty) bool { +func (b *BACnetServicesSupported) Get(property ServicesSupportedProperty) (bool, error) { return b.bitstring.Value.Get(int(property)) } @@ -1094,7 +1266,10 @@ type BACnetDateRange struct { func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, error) { var leng int - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(Date) { leng += leng1 leng1, startDate := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) @@ -1104,7 +1279,10 @@ func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, erro return -1, fmt.Errorf("Unexpected tag number: %v", tagNumber) } - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber == byte(Date) { leng += leng1 leng1, endDate := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) @@ -1123,29 +1301,43 @@ type BACnetAddressBinding struct { DeviceAddress BACnetAddress } -func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen int) int { +func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen int) (int, error) { length := 0 - length1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+length) + length1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+length) + if err != nil { + return -1, err + } // device_identifier if tagNumber == byte(BACnetObjectIdentifier) { length += length1 binding.DeviceIdentifier = ObjectIdentifier{} - length += binding.DeviceIdentifier.Decode(buffer, offset+length, int(lenValue)) + leng1, err := binding.DeviceIdentifier.Decode(buffer, offset+length, int(lenValue)) + if err != nil { + return -1, err + } + length += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - length1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+length) + length1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+length) + if err != nil { + return -1, err + } if tagNumber == byte(UnsignedInt) { binding.DeviceAddress = BACnetAddress{} - length += binding.DeviceAddress.Decode(buffer, offset+length, int(lenValue)) + leng1, err := binding.DeviceAddress.Decode(buffer, offset+length, int(lenValue)) + if err != nil { + return -1, err + } + length += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - return length + return length, nil } type BACnetHostNPort struct { @@ -1169,10 +1361,16 @@ func (b *BACnetHostNPort) Decode(buffer []byte, offset, apduLen int) (int, error leng++ if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 1 { - leng1, b.Port = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, b.Port, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Invalid tag number") @@ -1190,7 +1388,10 @@ type BACnetHostAddress struct { func (b *BACnetHostAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } switch tagNumber { case byte(Null): @@ -1225,10 +1426,16 @@ func (b *BACnetSecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, // key_revision if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 0 { - leng1, b.KeyRevision = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, b.KeyRevision, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Invalid tag number") @@ -1287,10 +1494,16 @@ func (b *BACnetKeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, e // algorithm if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 0 { - leng1, b.Algorithm = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, b.Algorithm, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Invalid tag number for algorithm") @@ -1301,10 +1514,16 @@ func (b *BACnetKeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, e // key_id if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 1 { - leng1, b.KeyID = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, b.KeyID, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Invalid tag number for key_id") @@ -1324,7 +1543,10 @@ func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error leng := 0 if encoding.IsContextTag(buffer, offset+leng, 2) { // BACnetDateTime - leng1, tagNumber, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, _, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 2 { b.Value = &DateTime{} @@ -1335,10 +1557,16 @@ func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error } } else if encoding.IsContextTag(buffer, offset+leng, 1) { // sequence number - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 1 { - leng1, seqNum := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, seqNum, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } b.Value = seqNum leng += leng1 } else { @@ -1346,7 +1574,10 @@ func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error } } else if encoding.IsContextTag(buffer, offset+leng, 0) { // time - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 0 { leng1, bacnetTime := encoding.DecodeBACnetTimeSafe(buffer, offset+leng, int(lenValue)) @@ -1384,7 +1615,11 @@ func (ras *ReadAccessSpecification) Decode(buffer []byte, offset, apduLen int) ( // ObjectIdentifier ras.ObjectIdentifier = ObjectIdentifier{} - leng += ras.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := ras.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } + leng += leng1 // ListOfPropertyReferences if buffer[offset+leng] == 0x30 { // Check for opening tag (0x30) @@ -1423,10 +1658,16 @@ func (ref *BACnetPropertyReference) Decode(buffer []byte, offset, apduLen int) ( // propertyIdentifier if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, ref.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, ref.PropertyIdentifier, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Missing context tag for PropertyIdentifier") @@ -1434,9 +1675,15 @@ func (ref *BACnetPropertyReference) Decode(buffer []byte, offset, apduLen int) ( if leng < apduLen { if encoding.IsContextTag(buffer, offset+leng, 1) && !encoding.IsClosingTagNumber(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, ref.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, ref.PropertyArrayIndex, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } @@ -1456,7 +1703,10 @@ func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset i // tag 0 objectidentifier bdopr.ObjectIdentifier = ObjectIdentifier{} - leng1 := bdopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := bdopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } if leng1 < 0 { return -1, errors.New("failed to decode object identifier") } @@ -1464,10 +1714,16 @@ func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset i // tag 1 propertyidentifier if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, bdopr.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, bdopr.PropertyIdentifier, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Missing tag property Identifier") @@ -1476,9 +1732,15 @@ func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset i if leng < apduLen { // tag 2 property-array-index optional if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bdopr.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bdopr.PropertyArrayIndex, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } @@ -1486,7 +1748,10 @@ func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset i if leng < apduLen { // tag 3 device-identifier optional bdopr.DeviceIdentifier = ObjectIdentifier{} - leng1 := bdopr.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 3) + leng1, err := bdopr.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 3) + if err != nil { + return -1, err + } if leng1 < 0 { return -1, errors.New("failed to decode device identifier") } @@ -1501,25 +1766,31 @@ type BACnetDeviceObjectReference struct { ObjectIdentifier ObjectIdentifier } -func (bdor *BACnetDeviceObjectReference) Decode(buffer []byte, offset int, apduLen int) int { +func (bdor *BACnetDeviceObjectReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // tag 0 device-identifier optional bdor.DeviceIdentifier = ObjectIdentifier{} - leng1 := bdor.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := bdor.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } if leng1 > 0 { leng += leng1 } // tag 1 objectidentifier bdor.ObjectIdentifier = ObjectIdentifier{} - leng1 = bdor.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + leng1, err = bdor.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 - return leng + return leng, nil } type BACnetObjectPropertyReference struct { @@ -1528,39 +1799,54 @@ type BACnetObjectPropertyReference struct { PropertyArrayIndex uint32 } -func (bopr *BACnetObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) int { +func (bopr *BACnetObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // tag 0 objectidentifier bopr.ObjectIdentifier = ObjectIdentifier{} - leng1 := bopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := bopr.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 // tag 1 propertyidentifier if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, bopr.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, bopr.PropertyIdentifier, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } if leng < apduLen { // tag 2 property-array-index optional if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bopr.PropertyArrayIndex = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bopr.PropertyArrayIndex, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } - return leng + return leng, nil } type BACnetAccumulatorRecord struct { @@ -1585,12 +1871,15 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in // 0 timestamp if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 bar.Timestamp = BACnetTimeStamp{} - leng1, err := bar.Timestamp.Decode(buffer, offset+leng, int(lenValue)) + leng1, err = bar.Timestamp.Decode(buffer, offset+leng, int(lenValue)) if err != nil { - return -1, errors.New("failed to decode timestamp") + return -1, err } } else { return -1, errors.New("Missing tag 0") @@ -1598,9 +1887,15 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in // 1 present-value if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bar.PresentValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bar.PresentValue, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Missing tag 1") @@ -1608,9 +1903,15 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in // 2 accumulated-value if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bar.AccumulatedValue = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bar.AccumulatedValue, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { return -1, errors.New("Missing tag 2") @@ -1618,9 +1919,15 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in // 3 accumulator-status if encoding.IsContextTag(buffer, offset+leng, 3) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, statusValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, statusValue, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } bar.AccumulatorStatus = BACnetAccumulatorStatus(statusValue) leng += leng1 } else { @@ -1634,7 +1941,7 @@ type BACnetActionList struct { Action []BACnetActionCommand } -func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) int { +func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // SEQUENCE OF BACnetActionCommand @@ -1643,9 +1950,12 @@ func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) int bal.Action = make([]BACnetActionCommand, 0) for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { bac := BACnetActionCommand{} - leng1 := bac.Decode(buffer, offset+leng, apduLen-leng) + leng1, err := bac.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 bal.Action = append(bal.Action, bac) @@ -1653,7 +1963,7 @@ func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) int leng += 1 } - return leng + return leng, nil } type BACnetActionCommand struct { @@ -1668,42 +1978,62 @@ type BACnetActionCommand struct { WriteSuccessful bool } -func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) int { +func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // 0 device_identifier optional if encoding.IsContextTag(buffer, offset+leng, 0) { bac.DeviceIdentifier = ObjectIdentifier{} - leng += bac.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := bac.DeviceIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } + leng += leng1 } // 1 object_identifier if encoding.IsContextTag(buffer, offset+leng, 1) { bac.ObjectIdentifier = ObjectIdentifier{} - leng += bac.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + leng1, err := bac.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 1) + if err != nil { + return -1, err + } + leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } // 2 property_identifier if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, bac.PropertyIdentifier = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, bac.PropertyIdentifier, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } // 3 property_array_index if encoding.IsContextTag(buffer, offset+leng, 3) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - bac.PropertyArrayIndex, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + bac.PropertyArrayIndex, _, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } @@ -1716,7 +2046,7 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i propID := bac.PropertyIdentifier.(encoding.PropertyIdentifier) leng1, _ := bv.Decode(buffer, offset+leng, apduLen-leng, &bac.ObjectIdentifier.Type, &propID) if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 bac.PropertyValue = append(bac.PropertyValue, bv) @@ -1724,18 +2054,24 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i if encoding.IsClosingTagNumber(buffer, offset+leng, 4) { leng += 1 } else { - return -1 + return -1, errInvalidTagNumber } } else { - return -1 + return -1, errInvalidTagNumber } if leng < apduLen { // tag 5 priority optional if encoding.IsContextTag(buffer, offset+leng, 5) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - bac.Priority, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + bac.Priority, _, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } @@ -1743,9 +2079,15 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i if leng < apduLen { // tag 6 post-delay optional if encoding.IsContextTag(buffer, offset+leng, 6) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - bac.PostDelay, _ = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + bac.PostDelay, _, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } @@ -1753,9 +2095,15 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i if leng < apduLen { // tag 7 quit-on-failure optional if encoding.IsContextTag(buffer, offset+leng, 7) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - uVal, _ := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + uVal, _, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bac.QuitOnFailure = uVal > 0 } @@ -1764,41 +2112,53 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) i if leng < apduLen { // tag 8 write-successful optional if encoding.IsContextTag(buffer, offset+leng, 8) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - uVal, _ := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + uVal, _, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bac.WriteSuccessful = uVal > 0 } } - return leng + return leng, nil } type BACnetScale struct { Value interface{} } -func (bs *BACnetScale) Decode(buffer []byte, offset int, apduLen int) int { +func (bs *BACnetScale) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { // float-scale - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 leng1, bs.Value = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) leng += leng1 } else if encoding.IsContextTag(buffer, offset+leng, 1) { // integer-scale - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bs.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bs.Value, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetLightingCommand struct { @@ -1821,24 +2181,33 @@ const ( LightingOperationIncrement ) -func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) int { +func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // operation if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, uVal := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, uVal, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 blc.Operation = BACnetLightingOperation(uVal) } else { - return -1 + return -1, errInvalidTagNumber } if leng < apduLen { // target-level if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 leng1, blc.TargetLevel = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) leng += leng1 @@ -1848,7 +2217,10 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) if leng < apduLen { // ramp-rate if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 leng1, blc.RampRate = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) leng += leng1 @@ -1858,7 +2230,10 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) if leng < apduLen { // step-increment if encoding.IsContextTag(buffer, offset+leng, 3) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 leng1, blc.StepIncrement = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) leng += leng1 @@ -1868,9 +2243,15 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) if leng < apduLen { // fade-time if encoding.IsContextTag(buffer, offset+leng, 4) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, blc.FadeTime = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, blc.FadeTime, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } @@ -1878,14 +2259,20 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) if leng < apduLen { // priority if encoding.IsContextTag(buffer, offset+leng, 5) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, blc.Priority = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, blc.Priority, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } } - return leng + return leng, nil } type BACnetPrescale struct { @@ -1893,30 +2280,42 @@ type BACnetPrescale struct { ModuloDivide uint32 } -func (bp *BACnetPrescale) Decode(buffer []byte, offset int, apduLen int) int { +func (bp *BACnetPrescale) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // multiplier if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bp.Multiplier = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bp.Multiplier, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } // modulo_divide if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bp.ModuloDivide = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bp.ModuloDivide, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetShedLevelChoice int @@ -1932,35 +2331,50 @@ type BACnetShedLevel struct { Value interface{} } -func (bsl *BACnetShedLevel) Decode(buffer []byte, offset int, apduLen int) int { +func (bsl *BACnetShedLevel) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { // percent - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bsl.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bsl.Value, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bsl.Choice = BACnetShedLevelChoicePercent } else if encoding.IsContextTag(buffer, offset+leng, 1) { // level - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, bsl.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, bsl.Value, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bsl.Choice = BACnetShedLevelChoiceLevel } else if encoding.IsContextTag(buffer, offset+leng, 2) { // amount - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 leng1, bsl.Value = encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) leng += leng1 bsl.Choice = BACnetShedLevelChoiceAmount } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetLogRecordChoice int @@ -1985,25 +2399,31 @@ type BACnetLogRecord struct { StatusFlags BACnetStatusFlags } -func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) int { +func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { leng := 0 // timestamp if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 blr.Timestamp = BACnetTimeStamp{} - leng1, err := blr.Timestamp.Decode(buffer, offset+leng, int(lenValue)) + leng1, err = blr.Timestamp.Decode(buffer, offset+leng, int(lenValue)) if err != nil { - return -1 + return -1, err } leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } if encoding.IsContextTag(buffer, offset+leng, 1) { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 switch BACnetLogRecordChoice(tagNumber) { @@ -2018,11 +2438,17 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * leng += leng1 blr.LogDatum = logValue case BACnetLogRecordChoiceEnumeratedValue: - leng1, logValue := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng1, logValue, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + if err != nil { + return -1, err + } leng += leng1 blr.LogDatum = logValue case BACnetLogRecordChoiceUnsignedValue: - leng1, logValue := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, logValue, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 blr.LogDatum = logValue case BACnetLogRecordChoiceIntegerValue: @@ -2037,11 +2463,15 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * leng++ case BACnetLogRecordChoiceFailure: blr.LogDatum = &BACnetError{} - leng += blr.LogDatum.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + leng1, err = blr.LogDatum.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + leng += leng1 if encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceFailure)) { leng++ } else { - return -1 + return -1, errInvalidTagNumber } case BACnetLogRecordChoiceTimeChange: leng1, logValue := encoding.DecodeRealSafe(buffer, offset+leng, int(lenValue)) @@ -2053,7 +2483,7 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * bValue := BACnetValue{} leng1, _ := bValue.Decode(buffer, offset+leng, apduLen-leng, objType, propID) if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 blr.LogDatum = append(blr.LogDatum.([]BACnetValue), bValue) @@ -2061,26 +2491,29 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * if encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceAnyValue)) { leng++ } else { - return -1 + return -1, errInvalidTagNumber } default: - return -1 + return -1, errInvalidTagNumber } } else { - return -1 + return -1, errInvalidTagNumber } if leng < apduLen { // status-flags optional if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 blr.StatusFlags = BACnetStatusFlags{} leng += blr.StatusFlags.Decode(buffer, offset+leng, int(lenValue)) } } - return leng + return leng, nil } type BACnetLogStatus struct { @@ -2112,15 +2545,15 @@ func (bls *BACnetLogStatus) SetLogInterrupted(a bool) { bls.BitString.Value.Set(2, a) } -func (bls *BACnetLogStatus) LogDisabled() bool { +func (bls *BACnetLogStatus) LogDisabled() (bool, error) { return bls.BitString.Value.Get(0) } -func (bls *BACnetLogStatus) BufferPurged() bool { +func (bls *BACnetLogStatus) BufferPurged() (bool, error) { return bls.BitString.Value.Get(1) } -func (bls *BACnetLogStatus) LogInterrupted() bool { +func (bls *BACnetLogStatus) LogInterrupted() (bool, error) { return bls.BitString.Value.Get(2) } @@ -2129,41 +2562,56 @@ type BACnetError struct { ErrorCode ErrorCodeEnum } -func (be *BACnetError) Decode(buffer []byte, offset, apduLen int) int { +func (be *BACnetError) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Decode error_class - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == byte(Enumerated) { - leng1, eVal := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng1, eVal, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + if err != nil { + return -1, err + } leng += leng1 be.ErrorClass = ErrorClassEnum(eVal.(uint32)) } else { - return -1 + return -1, errInvalidTagNumber } // Decode error_code - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == byte(Enumerated) { - leng1, eVal := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + leng1, eVal, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + if err != nil { + return -1, err + } leng += leng1 be.ErrorCode = ErrorCodeEnum(eVal.(uint32)) } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetCalendarEntry struct { Value interface{} } -func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) int { +func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 if tagNumber == 0 { leng1, ce.Value = encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) @@ -2172,17 +2620,17 @@ func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) int { ce.Value = &BACnetDateRange{} leng1, err := ce.Value.(*BACnetDateRange).Decode(buffer, offset+leng, int(lenValue)) if err != nil { - return -1 + return -1, err } leng += leng1 } else if tagNumber == 2 { ce.Value = &BACnetWeekNDay{} leng += ce.Value.(*BACnetWeekNDay).Decode(buffer, offset+leng, int(lenValue)) } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetEventLogRecord struct { @@ -2190,18 +2638,21 @@ type BACnetEventLogRecord struct { LogDatum interface{} } -func (elr *BACnetEventLogRecord) Decode(buffer []byte, offset, apduLen int) int { +func (elr *BACnetEventLogRecord) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { - leng1, _, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, _, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 elr.Timestamp = DateTime{} leng += elr.Timestamp.Decode(buffer, offset+leng) } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetWeekNDay struct { @@ -2227,25 +2678,37 @@ type ReadAccessResultReadResult struct { ReadResult interface{} // Either BACnetValue or BACnetError } -func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen int) int { +func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // 2 propertyidentifier if encoding.IsContextTag(buffer, offset+leng, 2) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 propID := encoding.PropertyList - leng1, propertyIdentifier := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + leng1, propertyIdentifier, err := encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, &propID) + if err != nil { + return -1, err + } leng += leng1 rarr.PropertyIdentifier = encoding.PropertyIdentifier(propertyIdentifier.(uint32)) } else { - return -1 + return -1, errInvalidTagNumber } // 3 property_array_index if encoding.IsContextTag(buffer, offset+leng, 3) { - leng1, _, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 - leng1, propertyArrayIndex := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, propertyArrayIndex, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 rarr.PropertyArrayIndex = propertyArrayIndex } @@ -2255,25 +2718,29 @@ func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen in rarr.ReadResult = &BACnetValue{} leng1, err := rarr.ReadResult.(*BACnetValue).Decode(buffer, offset+leng, apduLen-leng, nil, nil) if err != nil { - return -1 + return -1, err } leng += leng1 if encoding.IsClosingTagNumber(buffer, offset+leng, 4) { leng += 1 } else { - return -1 + return -1, errInvalidTagNumber } } else if encoding.IsOpeningTagNumber(buffer, offset+leng, 5) { rarr.ReadResult = &BACnetError{} - leng += rarr.ReadResult.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + leng1, err := rarr.ReadResult.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + leng += leng1 if encoding.IsClosingTagNumber(buffer, offset+leng, 5) { leng += 1 } else { - return -1 + return -1, errInvalidTagNumber } } } - return leng + return leng, nil } type ReadAccessResult struct { @@ -2281,14 +2748,18 @@ type ReadAccessResult struct { ListOfResults []ReadAccessResultReadResult } -func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) int { +func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // tag 0 objectidentifier rar.ObjectIdentifier = ObjectIdentifier{} if encoding.IsClosingTagNumber(buffer, offset+leng, 0) { - leng += rar.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + leng1, err := rar.ObjectIdentifier.DecodeContext(buffer, offset+leng, apduLen-leng, 0) + if err != nil { + return -1, err + } + leng += leng1 } else { - return -1 + return -1, errInvalidTagNumber } if encoding.IsOpeningTagNumber(buffer, offset+leng, 1) { @@ -2297,7 +2768,11 @@ func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) int { for (apduLen-leng) > 1 && !encoding.IsClosingTagNumber(buffer, offset+leng, 1) { bValue := ReadAccessResultReadResult{} - leng += bValue.Decode(buffer, offset+leng, apduLen-leng) + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } + leng += leng1 rar.ListOfResults = append(rar.ListOfResults, bValue) } @@ -2305,13 +2780,13 @@ func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) int { if encoding.IsClosingTagNumber(buffer, offset+leng, 1) { leng += 1 } else { - return -1 + return -1, errInvalidTagNumber } } else { - return -1 + return -1, errInvalidTagNumber } - return leng + return leng, nil } type BACnetAccessRule struct { @@ -2345,13 +2820,16 @@ type BACnetNameValue struct { Value BACnetValue } -func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { +func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Name - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != 0 { - return -1 + return -1, errInvalidTagNumber } leng += leng1 leng1, bnv.Name = encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) @@ -2360,7 +2838,10 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { // Decode value decodeLen := 0 if leng < apduLen { - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } leng += leng1 switch ApplicationTags(tagNumber) { @@ -2375,7 +2856,10 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { bnv.Value = BACnetValue{Value: false} } case UnsignedInt: - decodeLen, bnv.Value.Value = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + decodeLen, bnv.Value.Value, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } case SignedInt: decodeLen, bnv.Value.Value = encoding.DecodeSigned(buffer, offset+leng, int(lenValue)) case Real: @@ -2391,12 +2875,18 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { decodeLen = bitValue.Decode(buffer, offset+leng, int(lenValue)) bnv.Value.Value = bitValue case Enumerated: - decodeLen, bnv.Value.Value = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + decodeLen, bnv.Value.Value, err = encoding.DecodeEnumerated(buffer, offset+leng, lenValue, nil, nil) + if err != nil { + return -1, err + } case Date: decodeLen, dateValue := encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) if leng < apduLen { - leng1, tagNumber, _ := encoding.DecodeTagNumberAndValue(buffer, offset+leng+decodeLen) + leng1, tagNumber, _, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng+decodeLen) + if err != nil { + return -1, err + } if tagNumber == byte(Time) { leng += leng1 leng-- @@ -2411,24 +2901,24 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) int { } if decodeLen < 0 { - return -1 + return -1, errInvalidMessageLength } leng += decodeLen } - return leng + return leng, nil } type BACnetNameValueCollection struct { Members []BACnetNameValue } -func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) int { +func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Check if it's an opening tag number if !encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { - return -1 + return -1, errInvalidTagNumber } leng += 1 @@ -2436,16 +2926,19 @@ func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { bValue := BACnetNameValue{} - leng1 := bValue.Decode(buffer, offset+leng, apduLen-leng) + leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) + if err != nil { + return -1, err + } if leng1 < 0 { - return -1 + return -1, errInvalidMessageLength } leng += leng1 bnc.Members = append(bnc.Members, bValue) } leng += 1 - return leng + return leng, nil } type BACnetSecurityPolicy int @@ -2455,31 +2948,40 @@ type BACnetNetworkSecurityPolicy struct { SecurityLevel BACnetSecurityPolicy } -func (bns *BACnetNetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen int) int { +func (bns *BACnetNetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // port_id - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != 0 { - return -1 + return -1, errInvalidTagNumber } leng += leng1 - leng1, portID := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, portID, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) leng += leng1 bns.PortID = int(portID) leng = 0 // security_level - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != 1 { - return -1 + return -1, errInvalidTagNumber } leng += leng1 - leng1, uVal := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, uVal, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bns.SecurityLevel = BACnetSecurityPolicy(uVal) - return leng + return leng, nil } type BACnetPortPermission struct { @@ -2487,24 +2989,33 @@ type BACnetPortPermission struct { Enabled bool } -func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) int { +func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // port_id - leng1, tagNumber, lenValue := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != 0 { - return -1 + return -1, errInvalidTagNumber } leng += leng1 - leng1, portID := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + leng1, portID, err := encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) + if err != nil { + return -1, err + } leng += leng1 bpp.PortID = int(portID) leng = 0 // enabled - leng1, tagNumber, lenValue = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + leng1, tagNumber, lenValue, err = encoding.DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, err + } if tagNumber != 1 { - return -1 + return -1, errInvalidTagNumber } leng += leng1 if lenValue > 0 { @@ -2513,7 +3024,7 @@ func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) int bpp.Enabled = false } - return leng + return leng, nil } type BACnetPriorityValue struct { diff --git a/pkg/bacnet/whois.go b/pkg/bacnet/whois.go index e3a0826..56ef9b2 100644 --- a/pkg/bacnet/whois.go +++ b/pkg/bacnet/whois.go @@ -1,21 +1,31 @@ package bacnet -import "github.com/absmach/bacnet/pkg/encoding" +import ( + "fmt" + + "github.com/absmach/bacnet/pkg/encoding" +) type WhoIs struct { HighLimit, LowLimit *uint32 } -func (w *WhoIs) Decode(buf []byte, offset, apduLen int) int { +func (w *WhoIs) Decode(buf []byte, offset, apduLen int) (int, error) { if apduLen <= 0 { - return 0 + return 0, fmt.Errorf("invalid apdu length") + } + length, tagNum, lenVal, err := encoding.DecodeTagNumberAndValue(buf, offset) + if err != nil { + return -1, err } - length, tagNum, lenVal := encoding.DecodeTagNumberAndValue(buf, offset) if tagNum != 0 { - return -1 + return -1, fmt.Errorf("invalid tag number") } if apduLen > length { - len1, decVal := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + len1, decVal, err := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + if err != nil { + return -1, err + } length += len1 if decVal <= encoding.MaxInstance { @@ -23,33 +33,42 @@ func (w *WhoIs) Decode(buf []byte, offset, apduLen int) int { } if apduLen > length { - len1, tagNum, lenVal := encoding.DecodeTagNumberAndValue(buf, offset+length) + len1, tagNum, lenVal, err := encoding.DecodeTagNumberAndValue(buf, offset+length) + if err != nil { + return -1, err + } length += len1 if tagNum != 1 { - return -1 + return -1, fmt.Errorf("invalid tag number") } if apduLen > length { - len1, _ := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + len1, decVal, err := encoding.DecodeUnsigned(buf, offset+length, int(lenVal)) + if err != nil { + return -1, err + } length += len1 if decVal <= encoding.MaxInstance { w.HighLimit = &decVal } } else { - return -1 + return -1, fmt.Errorf("apdu lenth greater than message lenth") } } else { - return -1 + return -1, fmt.Errorf("apdu lenth greater than message lenth") } } else { - return -1 + return -1, fmt.Errorf("apdu lenth greater than message lenth") } - return length + return length, nil } func (w WhoIs) Encode() []byte { - if w.LowLimit != nil && *w.LowLimit <= encoding.MaxInstance && - w.HighLimit != nil && *w.HighLimit <= encoding.MaxInstance { - return append(encoding.EncodeContextUnsigned(0, *w.LowLimit), encoding.EncodeContextUnsigned(1, *w.HighLimit)...) + var res []byte + if w.LowLimit != nil && *w.LowLimit <= encoding.MaxInstance { + res = append(res, encoding.EncodeContextUnsigned(0, *w.LowLimit)...) + } + if w.HighLimit != nil && *w.HighLimit <= encoding.MaxInstance { + res = append(res, encoding.EncodeContextUnsigned(1, *w.HighLimit)...) } - return []byte{} + return res } diff --git a/pkg/encoding/decoding.go b/pkg/encoding/decoding.go index 0cf82de..6035dc4 100644 --- a/pkg/encoding/decoding.go +++ b/pkg/encoding/decoding.go @@ -2,10 +2,14 @@ package encoding import ( "encoding/binary" + "errors" + "fmt" "math" "time" ) +var errOutOfBounds = errors.New("lenth is out of range of array") + type BacnetCharacterStringEncodings int const ( @@ -19,12 +23,15 @@ const ( CharacterISO8859 BacnetCharacterStringEncodings = 5 ) -func DecodeUnsigned(buffer []byte, offset, len int) (int, uint32) { +func DecodeUnsigned(buffer []byte, offset, length int) (int, uint32, error) { + if length > len(buffer) { + return -1, 0, errOutOfBounds + } value := uint32(0) - for i := 0; i < len; i++ { - value += uint32(buffer[offset+i]) << uint(8*(len-i-1)) + for i := 0; i < length; i++ { + value += uint32(buffer[offset+i]) << uint(8*(length-i-1)) } - return len, value + return length, value, nil } func DecodeOctetString(buf []byte, offset, lenVal int) (int, []byte) { @@ -80,13 +87,16 @@ func DecodeCharacterString(buffer []byte, offset, maxLength, lenValue int) (int, return leng, charString } -func decodeContextCharacterString(buffer []byte, offset, maxLength int, tagNumber byte) (int, string) { +func decodeContextCharacterString(buffer []byte, offset, maxLength int, tagNumber byte) (int, string, error) { leng := 0 status := false charString := "" if IsContextTag(buffer, offset+leng, tagNumber) { - leng1, _, lenValue := DecodeTagNumberAndValue(buffer, offset+leng) + leng1, _, lenValue, err := DecodeTagNumberAndValue(buffer, offset+leng) + if err != nil { + return -1, "", err + } leng += leng1 status, charString = multiCharsetCharacterStringDecode(buffer, offset+1+leng, maxLength, BacnetCharacterStringEncodings(buffer[offset+leng]), int(lenValue)-1) @@ -97,7 +107,7 @@ func decodeContextCharacterString(buffer []byte, offset, maxLength int, tagNumbe } } - return leng, charString + return leng, charString, nil } func DecodeSigned(buffer []byte, offset int, lenValue int) (int, int) { @@ -119,8 +129,7 @@ func decodeReal(buffer []byte, offset int) (int, float32) { func DecodeRealSafe(buffer []byte, offset int, lenValue int) (int, float32) { if lenValue != 4 { - value := float32(0.0) - return lenValue, value + return lenValue, float32(0.0) } return decodeReal(buffer, offset) } @@ -132,8 +141,7 @@ func decodeDouble(buffer []byte, offset int) (int, float64) { func DecodeDoubleSafe(buffer []byte, offset int, lenValue int) (int, float64) { if lenValue != 8 { - value := float64(0.0) - return lenValue, value + return lenValue, float64(0.0) } return decodeDouble(buffer, offset) } @@ -145,22 +153,22 @@ func DecodeBACnetTimeSafe(buf []byte, offset, lenVal int) (int, time.Time) { return decodeBACnetTime(buf, offset) } -func decodeObjectID(buffer []byte, offset int) (int, ObjectType, uint32) { - var value uint32 - var leng int - - leng, value = DecodeUnsigned(buffer, offset, 4) +func decodeObjectID(buffer []byte, offset int) (int, ObjectType, uint32, error) { + leng, value, err := DecodeUnsigned(buffer, offset, 4) + if err != nil { + return -1, 0, 0, err + } objectInstance := value & MaxInstance objectType := ObjectType((int(value) >> InstanceBits) & MaxObject) - return leng, objectType, objectInstance + return leng, objectType, objectInstance, nil } -func DecodeObjectIDSafe(buffer []byte, offset int, lenValue uint32) (int, ObjectType, uint32) { +func DecodeObjectIDSafe(buffer []byte, offset int, lenValue uint32) (int, ObjectType, uint32, error) { if lenValue != 4 { - return 0, 0, 0 + return 0, 0, 0, fmt.Errorf("lenValue not equal to 4") } return decodeObjectID(buffer, offset) } diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index d2f84ed..9b7b910 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -15,19 +15,22 @@ const ( NoPriority = 0 MinPriority = 1 MaxPriority = 16 + maxUint8 = 0x100 + maxUint16 = 0x10000 + maxUint24 = 0x1000000 ) func EncodeUnsigned(value uint32) []byte { switch { - case value < 0x100: + case value < maxUint8: buf := make([]byte, 1) buf[0] = uint8(value) return buf - case value < 0x10000: + case value < maxUint16: buf := make([]byte, 2) binary.BigEndian.PutUint16(buf, uint16(value)) return buf - case value < 0x1000000: + case value < maxUint24: buf := make([]byte, 3) buf[0] = byte((value & 0xff0000) >> 16) buf[1] = byte((value & 0x00ff00) >> 8) @@ -42,15 +45,15 @@ func EncodeUnsigned(value uint32) []byte { func EncodeSigned(value int32) []byte { switch { - case value < 0x100: + case value < maxUint8: buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, uint8(value)) return buf.Bytes() - case value < 0x10000: + case value < maxUint16: buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, uint16(value)) return buf.Bytes() - case value < 0x1000000: + case value < maxUint24: buf := make([]byte, 3) buf[0] = byte((value & 0xff0000) >> 16) buf[1] = byte((value & 0x00ff00) >> 8) @@ -66,11 +69,11 @@ func EncodeSigned(value int32) []byte { func EncodeContextUnsigned(tagNum BACnetApplicationTag, val uint32) []byte { len := 0 switch { - case val < 0x100: + case val < maxUint8: len = 1 - case val < 0x10000: + case val < maxUint16: len = 2 - case val < 0x1000000: + case val < maxUint24: len = 3 default: len = 4 diff --git a/pkg/encoding/property.go b/pkg/encoding/property.go index 2ed48a0..4457cae 100644 --- a/pkg/encoding/property.go +++ b/pkg/encoding/property.go @@ -1641,8 +1641,11 @@ const ( type VendorSpecificValue int -func DecodeEnumerated(buffer []byte, offset int, lenValue uint32, objType *ObjectType, propID *PropertyIdentifier) (length int, val interface{}) { - leng, value := DecodeUnsigned(buffer, offset, int(lenValue)) +func DecodeEnumerated(buffer []byte, offset int, lenValue uint32, objType *ObjectType, propID *PropertyIdentifier) (length int, val interface{}, err error) { + leng, value, err := DecodeUnsigned(buffer, offset, int(lenValue)) + if err != nil { + return length, val, err + } if propID != nil { switch *propID { case SegmentationSupported: @@ -1832,9 +1835,9 @@ func DecodeEnumerated(buffer []byte, offset int, lenValue uint32, objType *Objec val = VendorSpecificValue(value) } - return leng, val + return leng, val, nil } - return leng, value + return leng, value, nil } func EncodeContextEnumerated(tagNumber BACnetApplicationTag, value uint32) []byte { diff --git a/pkg/encoding/tags.go b/pkg/encoding/tags.go index 8bd9239..a6f5036 100644 --- a/pkg/encoding/tags.go +++ b/pkg/encoding/tags.go @@ -21,24 +21,38 @@ const ( Reserve3 ) +const ( + extendedTagMask = 0xF0 + extendedValueMask = 0x07 + extendedTagValue = 5 + openingTagValue = 6 + closingTagValue = 7 + contextSpecificBit = 0x08 +) + +// isExtendedTagNumber checks if a byte represents an extended tag. func isExtendedTagNumber(b byte) bool { - return (b & 0xF0) == 0xF0 + return (b & extendedTagMask) == extendedTagMask } +// isExtendedValue checks if a byte represents an extended value. func isExtendedValue(b byte) bool { - return (b & 0x07) == 5 + return (b & extendedValueMask) == extendedTagValue } +// isOpeningTag checks if a byte represents an opening tag. func isOpeningTag(b byte) bool { - return (b & 0x07) == 6 + return (b & extendedValueMask) == openingTagValue } +// isClosingTag checks if a byte represents a closing tag. func isClosingTag(b byte) bool { - return (b & 0x07) == 7 + return (b & extendedValueMask) == closingTagValue } +// IsContextSpecific checks if the context-specific bit is set in a byte. func IsContextSpecific(b byte) bool { - return (b & 0x8) == 0x8 + return (b & contextSpecificBit) == contextSpecificBit } func IsContextTag(buf []byte, offset int, tagNum byte) bool { @@ -52,7 +66,7 @@ func IsContextTagWithLength(buf []byte, offset int, tagNum byte) (int, bool) { return tagLen, IsContextSpecific(buf[offset]) && myTagNum == tagNum } -func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val uint32) { +func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val uint32, err error) { len, tagNum = decodeTagNumber(buf, offset) switch { @@ -60,12 +74,18 @@ func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val switch buf[offset+len] { case 255: len += 1 - len1, val1 := DecodeUnsigned(buf, offset+len, 4) + len1, val1, err := DecodeUnsigned(buf, offset+len, 4) + if err != nil { + return len, tagNum, val, err + } len += len1 val = val1 case 254: len += 1 - len1, val1 := DecodeUnsigned(buf, offset+len, 2) + len1, val1, err := DecodeUnsigned(buf, offset+len, 2) + if err != nil { + return len, tagNum, val, err + } len += len1 val = val1 default: @@ -77,7 +97,7 @@ func DecodeTagNumberAndValue(buf []byte, offset int) (len int, tagNum byte, val default: val = uint32(buf[offset] & 0x07) } - return len, tagNum, val + return len, tagNum, val, nil } diff --git a/pkg/transport/udp/broadcast.go b/pkg/transport/udp/broadcast.go index f4edff2..56db012 100644 --- a/pkg/transport/udp/broadcast.go +++ b/pkg/transport/udp/broadcast.go @@ -8,9 +8,11 @@ import ( "github.com/absmach/bacnet/pkg/encoding" ) -func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, error) { - broadcast := "255.255.255.255" +const globalBroadcast = "255.255.255.255" +// GetBroadcasrAddress returns the broadcast address given the local address and port. +func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, error) { + broadcast := globalBroadcast interfaces, err := net.Interfaces() if err != nil { return bacnet.BACnetAddress{}, err From e93285d21b77cd207302b7163189c238ab742568 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Wed, 20 Sep 2023 21:02:15 +0300 Subject: [PATCH 22/24] Fix import and function name in readProperty.go The import and function name in readProperty.go have been fixed to use the correct package and function names. - Changed import from "bacnet" to "example/bacnet" - Changed function name from "NewBACnetAddress" to "NewAddress" - Changed "bacnet.BacnetMaxSegments" to "bacnet.MaxSegments" Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 4 +- example/whoIs/whois.go | 2 +- pkg/bacnet/apdu.go | 8 +- pkg/bacnet/base.go | 54 +- pkg/bacnet/network.go | 12 +- pkg/bacnet/npdu.go | 10 +- pkg/bacnet/property.go | 792 +++++------ pkg/encoding/date_time.go | 1 + pkg/encoding/property.go | 1960 +++++++++++++------------- pkg/transport/udp/broadcast.go | 8 +- 10 files changed, 1426 insertions(+), 1425 deletions(-) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go index 531215e..e8ffacd 100644 --- a/example/readProperty/readProperty.go +++ b/example/readProperty/readProperty.go @@ -13,7 +13,7 @@ import ( func main() { netType := encoding.IPV4 - destination := bacnet.NewBACnetAddress(0, nil, "127.0.0.6:47809", &netType) + destination := bacnet.NewAddress(0, nil, "127.0.0.6:47809", &netType) npdu := bacnet.NewNPDU(destination, nil, nil, nil) npdu.Control.SetDataExpectingReply(true) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) @@ -27,7 +27,7 @@ func main() { PduType: bacnet.PDUTypeConfirmedServiceRequest, ServiceChoice: byte(bacnet.ReadProperty), SegmentedResponseAccepted: false, - MaxSegmentsAccepted: bacnet.BacnetMaxSegments(encoding.NoSegmentation), + MaxSegmentsAccepted: bacnet.MaxSegments(encoding.NoSegmentation), InvokeID: 0, } diff --git a/example/whoIs/whois.go b/example/whoIs/whois.go index c00d173..9cc4e48 100644 --- a/example/whoIs/whois.go +++ b/example/whoIs/whois.go @@ -21,7 +21,7 @@ func main() { whoisBytes := req.Encode() netType := encoding.IPV4 - broads := *bacnet.NewBACnetAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) + broads := *bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) npdu := bacnet.NewNPDU(&broads, nil, nil, nil) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) diff --git a/pkg/bacnet/apdu.go b/pkg/bacnet/apdu.go index 5e8b8a4..190bb95 100644 --- a/pkg/bacnet/apdu.go +++ b/pkg/bacnet/apdu.go @@ -68,11 +68,11 @@ const ( // APDU Application Protocol Data Unit. type APDU struct { - PduType BacnetPduTypes + PduType PduTypes SegmentedMessage bool MoreFollows bool SegmentedResponseAccepted bool - MaxSegmentsAccepted BacnetMaxSegments + MaxSegmentsAccepted MaxSegments MaxApduLengthAccepted MaxAPDU SequenceNumber byte InvokeID byte @@ -125,7 +125,7 @@ func (a APDU) Encode() ([]byte, error) { // Decode decodes []byte to APDU data. func (a *APDU) Decode(buffer []byte, offset int) (int, error) { length := 0 - a.PduType = BacnetPduTypes(buffer[offset]) + a.PduType = PduTypes(buffer[offset]) tmp := byte(buffer[offset]) length++ @@ -134,7 +134,7 @@ func (a *APDU) Decode(buffer []byte, offset int) (int, error) { a.SegmentedMessage = tmp&0x10 != 0 a.MoreFollows = tmp&0x20 != 0 a.SegmentedResponseAccepted = tmp&0x40 != 0 - a.MaxSegmentsAccepted = BacnetMaxSegments(buffer[offset+length] & 0xF0) + a.MaxSegmentsAccepted = MaxSegments(buffer[offset+length] & 0xF0) a.MaxApduLengthAccepted = MaxAPDU(buffer[offset+length] & 0x0F) length++ a.InvokeID = buffer[offset+length] diff --git a/pkg/bacnet/base.go b/pkg/bacnet/base.go index 19e857f..ac812da 100644 --- a/pkg/bacnet/base.go +++ b/pkg/bacnet/base.go @@ -34,56 +34,56 @@ const ( NetworkNumberIs ) -type BacnetMaxSegments int +type MaxSegments int const ( - MaxSEG0 BacnetMaxSegments = 0 - MaxSEG2 BacnetMaxSegments = 0x10 - MaxSEG4 BacnetMaxSegments = 0x20 - MaxSEG8 BacnetMaxSegments = 0x30 - MaxSEG16 BacnetMaxSegments = 0x40 - MaxSEG32 BacnetMaxSegments = 0x50 - MaxSEG64 BacnetMaxSegments = 0x60 - MaxSEG65 BacnetMaxSegments = 0x70 + MaxSEG0 MaxSegments = 0 + MaxSEG2 MaxSegments = 0x10 + MaxSEG4 MaxSegments = 0x20 + MaxSEG8 MaxSegments = 0x30 + MaxSEG16 MaxSegments = 0x40 + MaxSEG32 MaxSegments = 0x50 + MaxSEG64 MaxSegments = 0x60 + MaxSEG65 MaxSegments = 0x70 ) -type BacnetPduTypes int +type PduTypes int const ( - PDUTypeConfirmedServiceRequest BacnetPduTypes = iota + PDUTypeConfirmedServiceRequest PduTypes = iota Server NegativeAck // TODO SegmentResponseAccepted MoreFollows - SegmentedMessage BacnetPduTypes = 8 - PDUTypeUnconfirmedServiceRequest BacnetPduTypes = 0x10 - PDUTypeSimpleAck BacnetPduTypes = 0x20 - PDUTypeComplexAck BacnetPduTypes = 0x30 - PDUTypeSegmentAck BacnetPduTypes = 0x40 - PDUTypeError BacnetPduTypes = 0x50 - PDUTypeReject BacnetPduTypes = 0x60 - PDUTypeAbort BacnetPduTypes = 0x70 - PDUTypeMask BacnetPduTypes = 0xF0 + SegmentedMessage PduTypes = 8 + PDUTypeUnconfirmedServiceRequest PduTypes = 0x10 + PDUTypeSimpleAck PduTypes = 0x20 + PDUTypeComplexAck PduTypes = 0x30 + PDUTypeSegmentAck PduTypes = 0x40 + PDUTypeError PduTypes = 0x50 + PDUTypeReject PduTypes = 0x60 + PDUTypeAbort PduTypes = 0x70 + PDUTypeMask PduTypes = 0xF0 ) -type BacnetNpduControl int +type NpduControl int const ( - PriorityNormalMessage BacnetNpduControl = iota + PriorityNormalMessage NpduControl = iota PriorityUrgentMessage PriorityCriticalMessage PriorityLifeSafetyMessage ExpectingReply - SourceSpecified BacnetNpduControl = 8 - DestinationSpecified BacnetNpduControl = 32 - NetworkLayerMessage BacnetNpduControl = 128 + SourceSpecified NpduControl = 8 + DestinationSpecified NpduControl = 32 + NetworkLayerMessage NpduControl = 128 ) -type BacnetNetworkMessageType int +type NetworkMessageType int const ( - NetworkMessageWhoIsRouterToNetwork BacnetNetworkMessageType = iota + NetworkMessageWhoIsRouterToNetwork NetworkMessageType = iota NetworkMessageIAmRouterToNetwork NetworkMessageICouldBeRouterToNetwork NetworkMessageRejectMessageToNetwork diff --git a/pkg/bacnet/network.go b/pkg/bacnet/network.go index ff87f7b..9db460e 100644 --- a/pkg/bacnet/network.go +++ b/pkg/bacnet/network.go @@ -25,7 +25,7 @@ const ( Double OctetString CharacterString - BitString + ApplicationTagsBitString Enumerated Date Time @@ -35,7 +35,7 @@ const ( Reserve3 ) -type BACnetAddress struct { +type Address struct { // BACnet Network Number. // NetworkNumber = 0, for local. NetworkNumber uint32 @@ -44,8 +44,8 @@ type BACnetAddress struct { MacAddress []byte } -func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *encoding.BACnetNetworkType) *BACnetAddress { - addr := &BACnetAddress{ +func NewAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *encoding.NetworkType) *Address { + addr := &Address{ NetworkNumber: networkNumber, MacAddress: macAddress, } @@ -85,7 +85,7 @@ func NewBACnetAddress(networkNumber uint32, macAddress []byte, address interface return addr } -func (ba *BACnetAddress) IPAndPort() (string, int, error) { +func (ba *Address) IPAndPort() (string, int, error) { if len(ba.MacAddress) < 6 { return "", 0, errMacAddressLen } @@ -94,7 +94,7 @@ func (ba *BACnetAddress) IPAndPort() (string, int, error) { return ip, port, nil } -func (ba *BACnetAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (ba *Address) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) if err != nil { diff --git a/pkg/bacnet/npdu.go b/pkg/bacnet/npdu.go index 5f9f0d6..be94b91 100644 --- a/pkg/bacnet/npdu.go +++ b/pkg/bacnet/npdu.go @@ -14,11 +14,11 @@ type NPDU struct { DNET uint16 DLEN uint8 DADR []byte - Destination *BACnetAddress + Destination *Address SNET uint16 SLEN uint8 SADR []byte - Source *BACnetAddress + Source *Address MessageType byte HopCount byte VendorID uint16 @@ -151,7 +151,7 @@ func (nci *NPDUControlInformation) Decode(buffer []byte, offset int) int { } // NewNPDU creates a new NPDU. -func NewNPDU(destination *BACnetAddress, source *BACnetAddress, hopCount *uint8, vendorID *uint16) *NPDU { +func NewNPDU(destination *Address, source *Address, hopCount *uint8, vendorID *uint16) *NPDU { npdu := &NPDU{ Version: 1, Control: *NewNPDUControlInformation(), @@ -244,7 +244,7 @@ func (npdu *NPDU) Decode(buffer []byte, offset int) int { length++ npdu.DADR = buffer[offset+length : offset+length+int(npdu.DLEN)] length += int(npdu.DLEN) - npdu.Destination = NewBACnetAddress(uint32(npdu.DNET), npdu.DADR, "", nil) + npdu.Destination = NewAddress(uint32(npdu.DNET), npdu.DADR, "", nil) } if npdu.Control.IsSourceSpecifier() { @@ -254,7 +254,7 @@ func (npdu *NPDU) Decode(buffer []byte, offset int) int { length++ npdu.SADR = buffer[offset+length : offset+length+int(npdu.SLEN)] length += int(npdu.SLEN) - npdu.Source = NewBACnetAddress(uint32(npdu.SNET), npdu.SADR, "", nil) + npdu.Source = NewAddress(uint32(npdu.SNET), npdu.SADR, "", nil) } if npdu.Control.IsDestinationSpecifier() { diff --git a/pkg/bacnet/property.go b/pkg/bacnet/property.go index 2965bf5..c232c6b 100644 --- a/pkg/bacnet/property.go +++ b/pkg/bacnet/property.go @@ -93,7 +93,7 @@ type ReadPropertyACK struct { ObjectIdentifier ObjectIdentifier PropertyIdentifier interface{} PropertyArrayIndex uint32 - PropertyValue []BACnetValue + PropertyValue []Value } func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error) { @@ -146,9 +146,9 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error // tag 3 property-value if encoding.IsOpeningTagNumber(buffer, offset+leng, 3) { leng++ - r.PropertyValue = make([]BACnetValue, 0) + r.PropertyValue = make([]Value, 0) for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) && leng < apduLen { - bValue := BACnetValue{} + bValue := Value{} propId := r.PropertyIdentifier.(encoding.PropertyIdentifier) leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng, &r.ObjectIdentifier.Type, &propId) if err != nil { @@ -169,12 +169,12 @@ func (r *ReadPropertyACK) Decode(buffer []byte, offset, apduLen int) (int, error return leng, nil } -type BACnetValue struct { +type Value struct { Tag *ApplicationTags Value interface{} } -func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { +func (bv *Value) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { length := 0 var err error @@ -211,14 +211,14 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod } } else if *propID == encoding.ActiveVtSessions { bv.Tag = nil - bv.Value = &BACnetVTSession{} + bv.Value = &VTSession{} length-- - decodeLen = bv.Value.(*BACnetVTSession).Decode(buffer, offset+length, apduLen) + decodeLen = bv.Value.(*VTSession).Decode(buffer, offset+length, apduLen) } else if *propID == encoding.ThreatLevel || *propID == encoding.ThreatAuthority { bv.Tag = nil - bv.Value = &BACnetAccessThreatLevel{} + bv.Value = &AccessThreatLevel{} length-- - decodeLen = bv.Value.(*BACnetAccessThreatLevel).Decode(buffer, offset+length, apduLen) + decodeLen = bv.Value.(*AccessThreatLevel).Decode(buffer, offset+length, apduLen) } else { var uintVal uint32 decodeLen, uintVal, err = encoding.DecodeUnsigned(buffer, offset+length, int(lenValueType)) @@ -247,43 +247,43 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod var stringValue string decodeLen, stringValue = encoding.DecodeCharacterString(buffer, offset+length, apduLen, int(lenValueType)) bv.Value = stringValue - case BitString: + case ApplicationTagsBitString: switch *propID { case encoding.RecipientList: bv.Tag = nil - bv.Value = &BACnetDestination{} + bv.Value = &Destination{} length-- - decodeLen, err = bv.Value.(*BACnetDestination).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*Destination).Decode(buffer, offset+length, apduLen) if err != nil { return -1, err } case encoding.StatusFlags: bv.Tag = nil - bitValue := &BACnetStatusFlags{} + bitValue := &StatusFlags{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.EventEnable, encoding.AckedTransitions: bv.Tag = nil - bitValue := &BACnetEventTransitionBits{} + bitValue := &EventTransitionBits{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.LimitEnable: bv.Tag = nil - bitValue := &BACnetLimitEnable{} + bitValue := &LimitEnable{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.ProtocolObjectTypesSupported: bv.Tag = nil - bitValue := &BACnetObjectTypesSupported{} + bitValue := &ObjectTypesSupported{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue case encoding.ProtocolServicesSupported: bv.Tag = nil - bitValue := &BACnetServicesSupported{} + bitValue := &ServicesSupported{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue default: - bitValue := &BACnetBitString{} + bitValue := &BitString{} decodeLen = bitValue.Decode(buffer, offset, int(lenValueType)) bv.Value = bitValue } @@ -296,9 +296,9 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod switch *propID { case encoding.EffectivePeriod: bv.Tag = nil - bv.Value = &BACnetDateRange{} + bv.Value = &DateRange{} length-- - decodeLen, err = bv.Value.(*BACnetDateRange).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*DateRange).Decode(buffer, offset+length, apduLen) if err != nil { return -1, err } @@ -337,9 +337,9 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod *propID == encoding.SlaveAddressBinding || *propID == encoding.DeviceAddressBinding { bv.Tag = nil - bv.Value = &BACnetAddressBinding{} + bv.Value = &AddressBinding{} length-- - decodeLen, err = bv.Value.(*BACnetAddressBinding).Decode(buffer, offset+length, apduLen) + decodeLen, err = bv.Value.(*AddressBinding).Decode(buffer, offset+length, apduLen) if err != nil { return -1, err } @@ -365,8 +365,8 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod } else { switch *propID { case encoding.BacnetIpGlobalAddress, encoding.FdBbmdAddress: - bv.Value = &BACnetHostNPort{} - length1, err := bv.Value.(*BACnetHostNPort).Decode(buffer, offset+length, apduLen-length) + bv.Value = &HostNPort{} + length1, err := bv.Value.(*HostNPort).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -375,15 +375,15 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.RestartNotificationRecipients, encoding.TimeSynchronizationRecipients, encoding.CovuRecipients: - bv.Value = &BACnetRecipient{} - length1, err := bv.Value.(*BACnetRecipient).Decode(buffer, offset+length, apduLen-length) + bv.Value = &Recipient{} + length1, err := bv.Value.(*Recipient).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.KeySets: - bv.Value = &BACnetSecurityKeySet{} - length1, err := bv.Value.(*BACnetSecurityKeySet).Decode(buffer, offset+length, apduLen-length) + bv.Value = &SecurityKeySet{} + length1, err := bv.Value.(*SecurityKeySet).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -395,8 +395,8 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.TimeOfDeviceRestart, encoding.AccessEventTime, encoding.UpdateTime: - bv.Value = &BACnetTimeStamp{} - length1, err := bv.Value.(*BACnetTimeStamp).Decode(buffer, offset+length, apduLen-length) + bv.Value = &TimeStamp{} + length1, err := bv.Value.(*TimeStamp).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -408,8 +408,8 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod return -1, err } case encoding.ListOfObjectPropertyReferences: - bv.Value = &BACnetDeviceObjectPropertyReference{} - length, err = bv.Value.(*BACnetDeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + bv.Value = &DeviceObjectPropertyReference{} + length, err = bv.Value.(*DeviceObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -433,8 +433,8 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.BelongsTo, encoding.LastAccessPoint, encoding.EnergyMeterRef: - bv.Value = &BACnetDeviceObjectReference{} - length1, err := bv.Value.(*BACnetDeviceObjectReference).Decode(buffer, offset+length, apduLen-length) + bv.Value = &DeviceObjectReference{} + length1, err := bv.Value.(*DeviceObjectReference).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -443,42 +443,42 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod encoding.InputReference, encoding.ManipulatedVariableReference, encoding.ControlledVariableReference: - bv.Value = &BACnetObjectPropertyReference{} - length1, err := bv.Value.(*BACnetObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) + bv.Value = &ObjectPropertyReference{} + length1, err := bv.Value.(*ObjectPropertyReference).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.LoggingRecord: - bv.Value = &BACnetAccumulatorRecord{} - length, err = bv.Value.(*BACnetAccumulatorRecord).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AccumulatorRecord{} + length, err = bv.Value.(*AccumulatorRecord).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } - case encoding.Action: - bv.Value = &BACnetActionList{} - length1, err := bv.Value.(*BACnetActionList).Decode(buffer, offset+length, apduLen-length) + case encoding.PropertyIdentifierAction: + bv.Value = &ActionList{} + length1, err := bv.Value.(*ActionList).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.Scale: - bv.Value = &BACnetScale{} - length1, err := bv.Value.(*BACnetScale).Decode(buffer, offset+length, apduLen-length) + bv.Value = &Scale{} + length1, err := bv.Value.(*Scale).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.LightingCommand: - bv.Value = &BACnetLightingCommand{} - length1, err := bv.Value.(*BACnetLightingCommand).Decode(buffer, offset+length, apduLen-length) + bv.Value = &LightingCommand{} + length1, err := bv.Value.(*LightingCommand).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.Prescale: - bv.Value = &BACnetPrescale{} - length1, err := bv.Value.(*BACnetPrescale).Decode(buffer, offset+length, apduLen-length) + bv.Value = &Prescale{} + length1, err := bv.Value.(*Prescale).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -486,8 +486,8 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod case encoding.RequestedShedLevel, encoding.ExpectedShedLevel, encoding.ActualShedLevel: - bv.Value = &BACnetShedLevel{} - length1, err := bv.Value.(*BACnetShedLevel).Decode(buffer, offset+length, apduLen-length) + bv.Value = &ShedLevel{} + length1, err := bv.Value.(*ShedLevel).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -495,23 +495,23 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod case encoding.LogBuffer: switch *objType { case encoding.TrendLog: - bv.Value = &BACnetLogRecord{} - length1, err := bv.Value.(*BACnetLogRecord).Decode(buffer, offset+length, apduLen-length, nil, nil) + bv.Value = &LogRecord{} + length1, err := bv.Value.(*LogRecord).Decode(buffer, offset+length, apduLen-length, nil, nil) if err != nil { return -1, err } length += length1 case encoding.EventLog: - bv.Value = &BACnetEventLogRecord{} - length1, err := bv.Value.(*BACnetEventLogRecord).Decode(buffer, offset+length, apduLen-length) + bv.Value = &EventLogRecord{} + length1, err := bv.Value.(*EventLogRecord).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 } case encoding.DateList: - bv.Value = &BACnetCalendarEntry{} - length1, err := bv.Value.(*BACnetCalendarEntry).Decode(buffer, offset+length, apduLen-length) + bv.Value = &CalendarEntry{} + length1, err := bv.Value.(*CalendarEntry).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } @@ -526,101 +526,101 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod } length += length1 case encoding.Channel: - bv.Value = &BACnetChannelValue{} - length += bv.Value.(*BACnetChannelValue).Decode(buffer, offset+length, apduLen-length) + bv.Value = &ChannelValue{} + length += bv.Value.(*ChannelValue).Decode(buffer, offset+length, apduLen-length) case encoding.GlobalGroup: - bv.Value = &BACnetPropertyAccessResult{} - length += bv.Value.(*BACnetPropertyAccessResult).Decode(buffer, offset+length, apduLen-length) + bv.Value = &PropertyAccessResult{} + length += bv.Value.(*PropertyAccessResult).Decode(buffer, offset+length, apduLen-length) case encoding.CredentialDataInput: - bv.Value = &BACnetAuthenticationFactor{} - length += bv.Value.(*BACnetAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AuthenticationFactor{} + length += bv.Value.(*AuthenticationFactor).Decode(buffer, offset+length, apduLen-length) } case encoding.NegativeAccessRules, encoding.PositiveAccessRules: - bv.Value = &BACnetAccessRule{} - length += bv.Value.(*BACnetAccessRule).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AccessRule{} + length += bv.Value.(*AccessRule).Decode(buffer, offset+length, apduLen-length) case encoding.Tags: - bv.Value = &BACnetNameValue{} - length1, err := bv.Value.(*BACnetNameValue).Decode(buffer, offset+length, apduLen-length) + bv.Value = &NameValue{} + length1, err := bv.Value.(*NameValue).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.SubordinateTags: - bv.Value = &BACnetNameValueCollection{} - length1, err := bv.Value.(*BACnetNameValueCollection).Decode(buffer, offset+length, apduLen-length) + bv.Value = &NameValueCollection{} + length1, err := bv.Value.(*NameValueCollection).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.NetworkAccessSecurityPolicies: - bv.Value = &BACnetNetworkSecurityPolicy{} - length1, err := bv.Value.(*BACnetNetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) + bv.Value = &NetworkSecurityPolicy{} + length1, err := bv.Value.(*NetworkSecurityPolicy).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.PortFilter: - bv.Value = &BACnetPortPermission{} - length1, err := bv.Value.(*BACnetPortPermission).Decode(buffer, offset+length, apduLen-length) + bv.Value = &PortPermission{} + length1, err := bv.Value.(*PortPermission).Decode(buffer, offset+length, apduLen-length) if err != nil { return -1, err } length += length1 case encoding.PriorityArray: - bv.Value = &BACnetPriorityArray{} - length += bv.Value.(*BACnetPriorityArray).Decode(buffer, offset+length, apduLen-length) + bv.Value = &PriorityArray{} + length += bv.Value.(*PriorityArray).Decode(buffer, offset+length, apduLen-length) case encoding.ProcessIdentifierFilter: - bv.Value = &BACnetProcessIdSelection{} - length += bv.Value.(*BACnetProcessIdSelection).Decode(buffer, offset+length, apduLen-length) + bv.Value = &ProcessIdSelection{} + length += bv.Value.(*ProcessIdSelection).Decode(buffer, offset+length, apduLen-length) case encoding.SetpointReference: - bv.Value = &BACnetSetpointReference{} - length += bv.Value.(*BACnetSetpointReference).Decode(buffer, offset+length, apduLen-length) + bv.Value = &SetpointReference{} + length += bv.Value.(*SetpointReference).Decode(buffer, offset+length, apduLen-length) case encoding.ExceptionSchedule: - bv.Value = &BACnetSpecialEvent{} - length += bv.Value.(*BACnetSpecialEvent).Decode(buffer, offset+length, apduLen-length) + bv.Value = &SpecialEvent{} + length += bv.Value.(*SpecialEvent).Decode(buffer, offset+length, apduLen-length) case encoding.StateChangeValues: - bv.Value = &BACnetTimerStateChangeValue{} - length += bv.Value.(*BACnetTimerStateChangeValue).Decode(buffer, offset+length, apduLen-length) + bv.Value = &TimerStateChangeValue{} + length += bv.Value.(*TimerStateChangeValue).Decode(buffer, offset+length, apduLen-length) case encoding.ValueSource, encoding.ValueSourceArray: - bv.Value = &BACnetValueSource{} - length += bv.Value.(*BACnetValueSource).Decode(buffer, offset+length, apduLen-length) + bv.Value = &ValueSource{} + length += bv.Value.(*ValueSource).Decode(buffer, offset+length, apduLen-length) case encoding.VirtualMacAddressTable: - bv.Value = &BACnetVMACEntry{} - length += bv.Value.(*BACnetVMACEntry).Decode(buffer, offset+length, apduLen-length) + bv.Value = &VMACEntry{} + length += bv.Value.(*VMACEntry).Decode(buffer, offset+length, apduLen-length) case encoding.AssignedAccessRights: - bv.Value = &BACnetAssignedAccessRights{} - length += bv.Value.(*BACnetAssignedAccessRights).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AssignedAccessRights{} + length += bv.Value.(*AssignedAccessRights).Decode(buffer, offset+length, apduLen-length) case encoding.AssignedLandingCalls: - bv.Value = &BACnetAssignedLandingCalls{} - length += bv.Value.(*BACnetAssignedLandingCalls).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AssignedLandingCalls{} + length += bv.Value.(*AssignedLandingCalls).Decode(buffer, offset+length, apduLen-length) case encoding.AccessEventAuthenticationFactor: - bv.Value = &BACnetAuthenticationFactor{} - length += bv.Value.(*BACnetAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AuthenticationFactor{} + length += bv.Value.(*AuthenticationFactor).Decode(buffer, offset+length, apduLen-length) case encoding.SupportedFormats: - bv.Value = &BACnetAuthenticationFactorFormat{} - length += bv.Value.(*BACnetAuthenticationFactorFormat).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AuthenticationFactorFormat{} + length += bv.Value.(*AuthenticationFactorFormat).Decode(buffer, offset+length, apduLen-length) case encoding.AuthenticationPolicyList: - bv.Value = &BACnetAuthenticationPolicy{} - length += bv.Value.(*BACnetAuthenticationPolicy).Decode(buffer, offset+length, apduLen-length) + bv.Value = &AuthenticationPolicy{} + length += bv.Value.(*AuthenticationPolicy).Decode(buffer, offset+length, apduLen-length) case encoding.ActiveCovSubscriptions: - bv.Value = &BACnetCOVSubscription{} - length += bv.Value.(*BACnetCOVSubscription).Decode(buffer, offset+length, apduLen-length) + bv.Value = &COVSubscription{} + length += bv.Value.(*COVSubscription).Decode(buffer, offset+length, apduLen-length) case encoding.AuthenticationFactors: - bv.Value = &BACnetCredentialAuthenticationFactor{} - length += bv.Value.(*BACnetCredentialAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) + bv.Value = &CredentialAuthenticationFactor{} + length += bv.Value.(*CredentialAuthenticationFactor).Decode(buffer, offset+length, apduLen-length) case encoding.WeeklySchedule: - bv.Value = &BACnetDailySchedule{} - length += bv.Value.(*BACnetDailySchedule).Decode(buffer, offset+length, apduLen-length) + bv.Value = &DailySchedule{} + length += bv.Value.(*DailySchedule).Decode(buffer, offset+length, apduLen-length) case encoding.SubscribedRecipients: - bv.Value = &BACnetEventNotificationSubscription{} - length += bv.Value.(*BACnetEventNotificationSubscription).Decode(buffer, offset+length, apduLen-length) + bv.Value = &EventNotificationSubscription{} + length += bv.Value.(*EventNotificationSubscription).Decode(buffer, offset+length, apduLen-length) case encoding.EventParameters: - bv.Value = &BACnetEventParameter{} - length += bv.Value.(*BACnetEventParameter).Decode(buffer, offset+length, apduLen-length) + bv.Value = &EventParameter{} + length += bv.Value.(*EventParameter).Decode(buffer, offset+length, apduLen-length) case encoding.FaultParameters: - bv.Value = &BACnetFaultParameter{} - length += bv.Value.(*BACnetFaultParameter).Decode(buffer, offset+length, apduLen-length) + bv.Value = &FaultParameter{} + length += bv.Value.(*FaultParameter).Decode(buffer, offset+length, apduLen-length) default: bv.Value = nil } @@ -628,7 +628,7 @@ func (bv *BACnetValue) Decode(buffer []byte, offset, apduLen int, objType *encod return length, nil } -func (bv *BACnetValue) Encode() []byte { +func (bv *Value) Encode() []byte { if bv.Tag == nil { return nil } else { @@ -647,7 +647,7 @@ func (bv *BACnetValue) Encode() []byte { return encoding.EncodeApplicationOctetString(bv.Value.([]byte), 0, len(bv.Value.([]byte))) case CharacterString: return encoding.EncodeApplicationCharacterString(bv.Value.(string)) - case BitString: + case ApplicationTagsBitString: return encoding.EncodeApplicationBitString(bv.Value) case Enumerated: return encoding.EncodeApplicationEnumerated(bv.Value.(uint32)) @@ -669,10 +669,10 @@ func (bv *BACnetValue) Encode() []byte { } // BACnetRouterEntryStatus is an enumeration for the status of BACnetRouterEntry. -type BACnetRouterEntryStatus int +type RouterEntryStatus int const ( - Available BACnetRouterEntryStatus = iota + Available RouterEntryStatus = iota BACnetRouterEntryStatusBusy Disconnected ) @@ -681,7 +681,7 @@ const ( type RouterEntry struct { NetworkNumber uint32 MACAddress []byte - Status BACnetRouterEntryStatus + Status RouterEntryStatus PerformanceIndex uint32 } @@ -730,7 +730,7 @@ func (entry *RouterEntry) Decode(buffer []byte, offset, apduLen int) (int, error return -1, err } length += length1 - entry.Status = BACnetRouterEntryStatus(Val) + entry.Status = RouterEntryStatus(Val) // performance_index (optional) if offset < apduLen { @@ -751,40 +751,40 @@ func (entry *RouterEntry) Decode(buffer []byte, offset, apduLen int) (int, error return length, nil } -type BACnetVTSession struct { +type VTSession struct { LocalVTSessionID int RemoteVTSessionID int - RemoteVTAddress BACnetAddress + RemoteVTAddress Address } -// decode method for BACnetVTSession -func (b *BACnetVTSession) Decode(buffer []byte, offset, apduLen int) int { +// Decode method for BACnetVTSession +func (b *VTSession) Decode(buffer []byte, offset, apduLen int) int { // Implement decode logic here return -1 } // BACnetAccessThreatLevel struct definition -type BACnetAccessThreatLevel struct { +type AccessThreatLevel struct { Value int } // decode method for BACnetAccessThreatLevel -func (b *BACnetAccessThreatLevel) Decode(buffer []byte, offset, apduLen int) int { +func (b *AccessThreatLevel) Decode(buffer []byte, offset, apduLen int) int { // Implement decode logic here return -1 } -type BACnetDestination struct { - ValidDays *BACnetDaysOfWeek +type Destination struct { + ValidDays *DaysOfWeek FromTime time.Time ToTime time.Time - Recipient *BACnetRecipient + Recipient *Recipient ProcessIdentifier uint32 IssueConfirmedNotifications bool - Transitions *BACnetEventTransitionBits + Transitions *EventTransitionBits } -func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (b *Destination) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) @@ -795,7 +795,7 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, return -1, errInvalidTagNumber } leng += leng1 - b.ValidDays = &BACnetDaysOfWeek{} + b.ValidDays = &DaysOfWeek{} leng1 = b.ValidDays.Decode(buffer, offset+leng, int(lenValue)) @@ -828,7 +828,7 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, leng += leng1 - b.Recipient = &BACnetRecipient{} + b.Recipient = &Recipient{} leng1, err = b.Recipient.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -877,7 +877,7 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, } leng += leng1 - b.Transitions = &BACnetEventTransitionBits{} + b.Transitions = &EventTransitionBits{} leng1 = b.Transitions.Decode(buffer, offset+leng, int(lenValue)) if leng1 < 0 { return -1, errInvalidMessageLength @@ -887,9 +887,9 @@ func (b *BACnetDestination) Decode(buffer []byte, offset int, apduLen int) (int, return leng, nil } -type BACnetDaysOfWeek struct { +type DaysOfWeek struct { unusedBits byte - bitString BACnetBitString + bitString BitString monday bool tuesday bool wednesday bool @@ -899,19 +899,19 @@ type BACnetDaysOfWeek struct { sunday bool } -func NewBACnetDaysOfWeek() *BACnetDaysOfWeek { - return &BACnetDaysOfWeek{ +func NewBACnetDaysOfWeek() *DaysOfWeek { + return &DaysOfWeek{ unusedBits: 1, bitString: *NewBACnetBitString(1, *internal.NewBitArray(8)), } } -func (d *BACnetDaysOfWeek) Decode(buffer []byte, offset int, apduLen int) int { - d.bitString = BACnetBitString{} +func (d *DaysOfWeek) Decode(buffer []byte, offset int, apduLen int) int { + d.bitString = BitString{} return d.bitString.Decode(buffer, offset, apduLen) } -func (d *BACnetDaysOfWeek) SetDay(day int, value bool) error { +func (d *DaysOfWeek) SetDay(day int, value bool) error { if day < 0 || day > 6 { return fmt.Errorf("Day index out of range") } @@ -919,26 +919,26 @@ func (d *BACnetDaysOfWeek) SetDay(day int, value bool) error { return nil } -func (d *BACnetDaysOfWeek) GetDay(day int) (bool, error) { +func (d *DaysOfWeek) GetDay(day int) (bool, error) { if day < 0 || day > 6 { return false, fmt.Errorf("Day index out of range") } return d.bitString.Value.Get(day) } -type BACnetBitString struct { +type BitString struct { UnusedBits byte Value internal.BitArray } -func NewBACnetBitString(unusedBits byte, value internal.BitArray) *BACnetBitString { - return &BACnetBitString{ +func NewBACnetBitString(unusedBits byte, value internal.BitArray) *BitString { + return &BitString{ UnusedBits: unusedBits, Value: value, } } -func (b *BACnetBitString) Decode(buffer []byte, offset, apduLen int) int { +func (b *BitString) Decode(buffer []byte, offset, apduLen int) int { leng := 0 if apduLen > 0 { b.UnusedBits = buffer[offset] @@ -955,11 +955,11 @@ func (b *BACnetBitString) Decode(buffer []byte, offset, apduLen int) int { return apduLen } -type BACnetRecipient struct { +type Recipient struct { Value interface{} } -func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (br *Recipient) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) if err != nil { @@ -977,8 +977,8 @@ func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) (int, erro leng += leng1 } else if tagNumber == 1 { // address - br.Value = &BACnetAddress{} - leng1, err = br.Value.(*BACnetAddress).Decode(buffer, offset+leng, int(lenValue)) + br.Value = &Address{} + leng1, err = br.Value.(*Address).Decode(buffer, offset+leng, int(lenValue)) if err != nil { return -1, err } @@ -991,21 +991,21 @@ func (br *BACnetRecipient) Decode(buffer []byte, offset, apduLen int) (int, erro } // BACnetEventTransitionBits represents a BACnet event transition bits structure. -type BACnetEventTransitionBits struct { +type EventTransitionBits struct { UnusedBits uint8 - BitString *BACnetBitString + BitString *BitString } // NewBACnetEventTransitionBits creates a new BACnet event transition bits instance. -func NewBACnetEventTransitionBits() *BACnetEventTransitionBits { - return &BACnetEventTransitionBits{ +func NewBACnetEventTransitionBits() *EventTransitionBits { + return &EventTransitionBits{ UnusedBits: 5, BitString: NewBACnetBitString(5, *internal.NewBitArray(5)), } } // Decode decodes the bit string from a buffer. -func (e *BACnetEventTransitionBits) Decode(buffer []byte, offset, apduLen int) int { +func (e *EventTransitionBits) Decode(buffer []byte, offset, apduLen int) int { bitString := NewBACnetBitString(0, internal.BitArray{}) decodedLen := bitString.Decode(buffer, offset, apduLen) @@ -1014,39 +1014,39 @@ func (e *BACnetEventTransitionBits) Decode(buffer []byte, offset, apduLen int) i } // ToOffNormal returns the value of ToOffNormal property. -func (e *BACnetEventTransitionBits) ToOffNormal() (bool, error) { +func (e *EventTransitionBits) ToOffNormal() (bool, error) { return e.BitString.Value.Get(0) } // SetToOffNormal sets the value of ToOffNormal property. -func (e *BACnetEventTransitionBits) SetToOffNormal(a bool) { +func (e *EventTransitionBits) SetToOffNormal(a bool) { e.BitString.Value.Set(0, a) } // ToFault returns the value of ToFault property. -func (e *BACnetEventTransitionBits) ToFault() (bool, error) { +func (e *EventTransitionBits) ToFault() (bool, error) { return e.BitString.Value.Get(1) } // SetToFault sets the value of ToFault property. -func (e *BACnetEventTransitionBits) SetToFault(a bool) { +func (e *EventTransitionBits) SetToFault(a bool) { e.BitString.Value.Set(1, a) } // ToNormal returns the value of ToNormal property. -func (e *BACnetEventTransitionBits) ToNormal() (bool, error) { +func (e *EventTransitionBits) ToNormal() (bool, error) { return e.BitString.Value.Get(2) } // SetToNormal sets the value of ToNormal property. -func (e *BACnetEventTransitionBits) SetToNormal(a bool) { +func (e *EventTransitionBits) SetToNormal(a bool) { e.BitString.Value.Set(2, a) } // BACnetStatusFlags represents a BACnet status flags. -type BACnetStatusFlags struct { +type StatusFlags struct { unusedbits int - bitstring BACnetBitString + bitstring BitString inalarm bool fault bool overridden bool @@ -1054,8 +1054,8 @@ type BACnetStatusFlags struct { } // NewBACnetStatusFlags creates a new BACnetStatusFlags instance. -func NewBACnetStatusFlags() *BACnetStatusFlags { - return &BACnetStatusFlags{ +func NewBACnetStatusFlags() *StatusFlags { + return &StatusFlags{ unusedbits: 4, bitstring: *NewBACnetBitString(4, *internal.NewBitArrayFromByte(0x00)), inalarm: false, @@ -1066,60 +1066,60 @@ func NewBACnetStatusFlags() *BACnetStatusFlags { } // decode decodes BACnetStatusFlags from a buffer. -func (s *BACnetStatusFlags) Decode(buffer []byte, offset, apduLen int) int { +func (s *StatusFlags) Decode(buffer []byte, offset, apduLen int) int { s.bitstring = *NewBACnetBitString(byte(s.unusedbits), *internal.NewBitArrayFromByte(0x00)) return s.bitstring.Decode(buffer, offset, apduLen) } // InAlarm returns the inalarm property. -func (s *BACnetStatusFlags) InAlarm() (bool, error) { +func (s *StatusFlags) InAlarm() (bool, error) { return s.bitstring.Value.Get(0) } // SetInAlarm sets the inalarm property. -func (s *BACnetStatusFlags) SetInAlarm(a bool) { +func (s *StatusFlags) SetInAlarm(a bool) { s.bitstring.Value.Set(0, a) } // Fault returns the fault property. -func (s *BACnetStatusFlags) Fault() (bool, error) { +func (s *StatusFlags) Fault() (bool, error) { return s.bitstring.Value.Get(1) } // SetFault sets the fault property. -func (s *BACnetStatusFlags) SetFault(a bool) { +func (s *StatusFlags) SetFault(a bool) { s.bitstring.Value.Set(1, a) } // Overridden returns the overridden property. -func (s *BACnetStatusFlags) Overridden() (bool, error) { +func (s *StatusFlags) Overridden() (bool, error) { return s.bitstring.Value.Get(2) } // SetOverridden sets the overridden property. -func (s *BACnetStatusFlags) SetOverridden(a bool) { +func (s *StatusFlags) SetOverridden(a bool) { s.bitstring.Value.Set(2, a) } // OutOfService returns the outofservice property. -func (s *BACnetStatusFlags) OutOfService() (bool, error) { +func (s *StatusFlags) OutOfService() (bool, error) { return s.bitstring.Value.Get(3) } // SetOutOfService sets the outofservice property. -func (s *BACnetStatusFlags) SetOutOfService(a bool) { +func (s *StatusFlags) SetOutOfService(a bool) { s.bitstring.Value.Set(3, a) } -type BACnetLimitEnable struct { +type LimitEnable struct { unusedBits uint8 - bitString BACnetBitString + bitString BitString lowLimitEnable bool highLimitEnable bool } -func NewBACnetLimitEnable() *BACnetLimitEnable { - return &BACnetLimitEnable{ +func NewBACnetLimitEnable() *LimitEnable { + return &LimitEnable{ unusedBits: 6, bitString: *NewBACnetBitString(6, *internal.NewBitArrayFromByte(0x00)), lowLimitEnable: false, @@ -1127,30 +1127,30 @@ func NewBACnetLimitEnable() *BACnetLimitEnable { } } -func (b *BACnetLimitEnable) Decode(buffer []byte, offset, apduLen int) int { +func (b *LimitEnable) Decode(buffer []byte, offset, apduLen int) int { b.bitString = *NewBACnetBitString(0, *internal.NewBitArrayFromByte(0x00)) return b.bitString.Decode(buffer, offset, apduLen) } -func (b *BACnetLimitEnable) LowLimitEnable() (bool, error) { +func (b *LimitEnable) LowLimitEnable() (bool, error) { return b.bitString.Value.Get(0) } -func (b *BACnetLimitEnable) SetLowLimitEnable(a bool) { +func (b *LimitEnable) SetLowLimitEnable(a bool) { b.bitString.Value.Set(0, a) } -func (b *BACnetLimitEnable) HighLimitEnable() (bool, error) { +func (b *LimitEnable) HighLimitEnable() (bool, error) { return b.bitString.Value.Get(1) } -func (b *BACnetLimitEnable) SetHighLimitEnable(a bool) { +func (b *LimitEnable) SetHighLimitEnable(a bool) { b.bitString.Value.Set(1, a) } -type BACnetObjectTypesSupported struct { +type ObjectTypesSupported struct { unusedbits uint8 - bitstring BACnetBitString + bitstring BitString } type ObjectTypesSupportedProperty int @@ -1164,28 +1164,28 @@ const ( // TODO Add other properties here ) -func NewBACnetObjectTypesSupported() *BACnetObjectTypesSupported { - return &BACnetObjectTypesSupported{ +func NewBACnetObjectTypesSupported() *ObjectTypesSupported { + return &ObjectTypesSupported{ unusedbits: 3, bitstring: *NewBACnetBitString(3, *internal.NewBitArray(64)), } } -func (b *BACnetObjectTypesSupported) Set(property ObjectTypesSupportedProperty, value bool) { +func (b *ObjectTypesSupported) Set(property ObjectTypesSupportedProperty, value bool) { b.bitstring.Value.Set(int(property), value) } -func (b *BACnetObjectTypesSupported) Get(property ObjectTypesSupportedProperty) (bool, error) { +func (b *ObjectTypesSupported) Get(property ObjectTypesSupportedProperty) (bool, error) { return b.bitstring.Value.Get(int(property)) } -func (b *BACnetObjectTypesSupported) Decode(buf []byte, offset, apduLen int) int { +func (b *ObjectTypesSupported) Decode(buf []byte, offset, apduLen int) int { return b.bitstring.Decode(buf, offset, apduLen) } -type BACnetServicesSupported struct { +type ServicesSupported struct { unusedbits uint8 - bitstring BACnetBitString + bitstring BitString } type ServicesSupportedProperty int @@ -1237,33 +1237,33 @@ const ( whoIs ) -func NewBACnetServicesSupported() *BACnetServicesSupported { - return &BACnetServicesSupported{ +func NewBACnetServicesSupported() *ServicesSupported { + return &ServicesSupported{ unusedbits: 7, bitstring: *NewBACnetBitString(7, *internal.NewBitArrayFromByte(0x00000000000000)), } } -func (b *BACnetServicesSupported) Set(property ServicesSupportedProperty, value bool) { +func (b *ServicesSupported) Set(property ServicesSupportedProperty, value bool) { b.bitstring.Value.Set(int(property), value) } -func (b *BACnetServicesSupported) Get(property ServicesSupportedProperty) (bool, error) { +func (b *ServicesSupported) Get(property ServicesSupportedProperty) (bool, error) { return b.bitstring.Value.Get(int(property)) } -func (b *BACnetServicesSupported) Decode(buf []byte, offset, apduLen int) int { +func (b *ServicesSupported) Decode(buf []byte, offset, apduLen int) int { return b.bitstring.Decode(buf, offset, apduLen) } // BACnetDateRange is a struct representing a date range in BACnet. -type BACnetDateRange struct { +type DateRange struct { StartDate time.Time EndDate time.Time } // Decode decodes a BACnetDateRange from the given buffer, offset, and length. -func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (dr *DateRange) Decode(buffer []byte, offset, apduLen int) (int, error) { var leng int leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) @@ -1296,12 +1296,12 @@ func (dr *BACnetDateRange) Decode(buffer []byte, offset, apduLen int) (int, erro return leng, nil } -type BACnetAddressBinding struct { +type AddressBinding struct { DeviceIdentifier ObjectIdentifier - DeviceAddress BACnetAddress + DeviceAddress Address } -func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (binding *AddressBinding) Decode(buffer []byte, offset int, apduLen int) (int, error) { length := 0 length1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+length) if err != nil { @@ -1327,7 +1327,7 @@ func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen i } if tagNumber == byte(UnsignedInt) { - binding.DeviceAddress = BACnetAddress{} + binding.DeviceAddress = Address{} leng1, err := binding.DeviceAddress.Decode(buffer, offset+length, int(lenValue)) if err != nil { return -1, err @@ -1340,19 +1340,19 @@ func (binding *BACnetAddressBinding) Decode(buffer []byte, offset int, apduLen i return length, nil } -type BACnetHostNPort struct { - Host *BACnetHostAddress +type HostNPort struct { + Host *HostAddress Port uint32 } -func (b *BACnetHostNPort) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (b *HostNPort) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 if !encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { return -1, errors.New("Invalid opening tag") } leng++ - b.Host = &BACnetHostAddress{} + b.Host = &HostAddress{} hostLen, err := b.Host.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -1382,11 +1382,11 @@ func (b *BACnetHostNPort) Decode(buffer []byte, offset, apduLen int) (int, error return leng, nil } -type BACnetHostAddress struct { +type HostAddress struct { Value interface{} } -func (b *BACnetHostAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (b *HostAddress) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) if err != nil { @@ -1414,14 +1414,14 @@ func (b *BACnetHostAddress) Decode(buffer []byte, offset, apduLen int) (int, err return leng, nil } -type BACnetSecurityKeySet struct { +type SecurityKeySet struct { KeyRevision uint32 ActivationTime *DateTime ExpirationTime *DateTime - KeyIDs []*BACnetKeyIdentifier + KeyIDs []*KeyIdentifier } -func (b *BACnetSecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (b *SecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // key_revision @@ -1464,11 +1464,11 @@ func (b *BACnetSecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, return -1, errors.New("Invalid opening tag for expiration_time") } - b.KeyIDs = make([]*BACnetKeyIdentifier, 0) + b.KeyIDs = make([]*KeyIdentifier, 0) if encoding.IsOpeningTagNumber(buffer, offset+leng, 3) && leng < apduLen { leng++ for !encoding.IsClosingTagNumber(buffer, offset+leng, 3) { - bValue := &BACnetKeyIdentifier{} + bValue := &KeyIdentifier{} leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -1484,12 +1484,12 @@ func (b *BACnetSecurityKeySet) Decode(buffer []byte, offset, apduLen int) (int, return leng, nil } -type BACnetKeyIdentifier struct { +type KeyIdentifier struct { Algorithm uint32 KeyID uint32 } -func (b *BACnetKeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (b *KeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // algorithm @@ -1535,11 +1535,11 @@ func (b *BACnetKeyIdentifier) Decode(buffer []byte, offset, apduLen int) (int, e return leng, nil } -type BACnetTimeStamp struct { +type TimeStamp struct { Value interface{} } -func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (b *TimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 2) { // BACnetDateTime @@ -1593,12 +1593,12 @@ func (b *BACnetTimeStamp) Decode(buffer []byte, offset, apduLen int) (int, error return leng, nil } -func (b *BACnetTimeStamp) Encode() []byte { +func (b *TimeStamp) Encode() []byte { // Implement the encoding logic as needed for your specific application. return nil } -func (b *BACnetTimeStamp) EncodeContext(tagNumber encoding.BACnetApplicationTag) []byte { +func (b *TimeStamp) EncodeContext(tagNumber encoding.BACnetApplicationTag) []byte { tmp := b.Encode() return append(encoding.EncodeTag(tagNumber, true, len(tmp)), tmp...) } @@ -1606,7 +1606,7 @@ func (b *BACnetTimeStamp) EncodeContext(tagNumber encoding.BACnetApplicationTag) // ReadAccessSpecification represents a BACnet Read Access Specification. type ReadAccessSpecification struct { ObjectIdentifier ObjectIdentifier - ListOfPropertyReferences []BACnetPropertyReference + ListOfPropertyReferences []PropertyReference } // Decode decodes the ReadAccessSpecification from the buffer. @@ -1625,10 +1625,10 @@ func (ras *ReadAccessSpecification) Decode(buffer []byte, offset, apduLen int) ( if buffer[offset+leng] == 0x30 { // Check for opening tag (0x30) leng++ - ras.ListOfPropertyReferences = make([]BACnetPropertyReference, 0) + ras.ListOfPropertyReferences = make([]PropertyReference, 0) for apduLen-leng > 1 && buffer[offset+leng] != 0x00 { // Check for closing tag (0x00) - bValue := BACnetPropertyReference{} + bValue := PropertyReference{} leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -1646,14 +1646,14 @@ func (ras *ReadAccessSpecification) Decode(buffer []byte, offset, apduLen int) ( return leng, nil } -// BACnetPropertyReference represents a BACnet property reference. -type BACnetPropertyReference struct { +// PropertyReference represents a BACnet property reference. +type PropertyReference struct { PropertyIdentifier interface{} PropertyArrayIndex uint32 } -// Decode decodes the BACnetPropertyReference from the buffer. -func (ref *BACnetPropertyReference) Decode(buffer []byte, offset, apduLen int) (int, error) { +// Decode decodes the PropertyReference from the buffer. +func (ref *PropertyReference) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // propertyIdentifier @@ -1691,14 +1691,14 @@ func (ref *BACnetPropertyReference) Decode(buffer []byte, offset, apduLen int) ( return leng, nil } -type BACnetDeviceObjectPropertyReference struct { +type DeviceObjectPropertyReference struct { ObjectIdentifier ObjectIdentifier PropertyIdentifier interface{} PropertyArrayIndex uint32 DeviceIdentifier ObjectIdentifier } -func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bdopr *DeviceObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // tag 0 objectidentifier @@ -1761,12 +1761,12 @@ func (bdopr *BACnetDeviceObjectPropertyReference) Decode(buffer []byte, offset i return leng, nil } -type BACnetDeviceObjectReference struct { +type DeviceObjectReference struct { DeviceIdentifier ObjectIdentifier ObjectIdentifier ObjectIdentifier } -func (bdor *BACnetDeviceObjectReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bdor *DeviceObjectReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // tag 0 device-identifier optional @@ -1793,13 +1793,13 @@ func (bdor *BACnetDeviceObjectReference) Decode(buffer []byte, offset int, apduL return leng, nil } -type BACnetObjectPropertyReference struct { +type ObjectPropertyReference struct { ObjectIdentifier ObjectIdentifier PropertyIdentifier interface{} PropertyArrayIndex uint32 } -func (bopr *BACnetObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bopr *ObjectPropertyReference) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // tag 0 objectidentifier @@ -1849,24 +1849,24 @@ func (bopr *BACnetObjectPropertyReference) Decode(buffer []byte, offset int, apd return leng, nil } -type BACnetAccumulatorRecord struct { - Timestamp BACnetTimeStamp +type AccumulatorRecord struct { + Timestamp TimeStamp PresentValue uint32 AccumulatedValue uint32 - AccumulatorStatus BACnetAccumulatorStatus + AccumulatorStatus AccumulatorStatus } -type BACnetAccumulatorStatus int +type AccumulatorStatus int const ( - AccumulatorStatusNormal BACnetAccumulatorStatus = iota + AccumulatorStatusNormal AccumulatorStatus = iota AccumulatorStatusStarting AccumulatorStatusRecovered AccumulatorStatusAbnormal AccumulatorStatusFailed ) -func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bar *AccumulatorRecord) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // 0 timestamp @@ -1876,7 +1876,7 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in return -1, err } leng += leng1 - bar.Timestamp = BACnetTimeStamp{} + bar.Timestamp = TimeStamp{} leng1, err = bar.Timestamp.Decode(buffer, offset+leng, int(lenValue)) if err != nil { return -1, err @@ -1928,7 +1928,7 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in if err != nil { return -1, err } - bar.AccumulatorStatus = BACnetAccumulatorStatus(statusValue) + bar.AccumulatorStatus = AccumulatorStatus(statusValue) leng += leng1 } else { return -1, errors.New("Missing tag 3") @@ -1937,19 +1937,19 @@ func (bar *BACnetAccumulatorRecord) Decode(buffer []byte, offset int, apduLen in return leng, nil } -type BACnetActionList struct { - Action []BACnetActionCommand +type ActionList struct { + Action []ActionCommand } -func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bal *ActionList) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // SEQUENCE OF BACnetActionCommand if encoding.IsOpeningTagNumber(buffer, offset+leng, 0) { leng += 1 - bal.Action = make([]BACnetActionCommand, 0) + bal.Action = make([]ActionCommand, 0) for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { - bac := BACnetActionCommand{} + bac := ActionCommand{} leng1, err := bac.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -1966,19 +1966,19 @@ func (bal *BACnetActionList) Decode(buffer []byte, offset int, apduLen int) (int return leng, nil } -type BACnetActionCommand struct { +type ActionCommand struct { DeviceIdentifier ObjectIdentifier ObjectIdentifier ObjectIdentifier PropertyIdentifier interface{} PropertyArrayIndex int - PropertyValue []BACnetValue + PropertyValue []Value Priority int PostDelay int QuitOnFailure bool WriteSuccessful bool } -func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bac *ActionCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // 0 device_identifier optional @@ -2040,9 +2040,9 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) ( // tag 4 property-value if encoding.IsOpeningTagNumber(buffer, offset+leng, 4) { leng += 1 - bac.PropertyValue = []BACnetValue{} + bac.PropertyValue = []Value{} for !encoding.IsClosingTagNumber(buffer, offset+leng, 4) && leng < apduLen { - bv := BACnetValue{} + bv := Value{} propID := bac.PropertyIdentifier.(encoding.PropertyIdentifier) leng1, _ := bv.Decode(buffer, offset+leng, apduLen-leng, &bac.ObjectIdentifier.Type, &propID) if leng1 < 0 { @@ -2129,11 +2129,11 @@ func (bac *BACnetActionCommand) Decode(buffer []byte, offset int, apduLen int) ( return leng, nil } -type BACnetScale struct { +type Scale struct { Value interface{} } -func (bs *BACnetScale) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bs *Scale) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { @@ -2161,8 +2161,8 @@ func (bs *BACnetScale) Decode(buffer []byte, offset int, apduLen int) (int, erro return leng, nil } -type BACnetLightingCommand struct { - Operation BACnetLightingOperation +type LightingCommand struct { + Operation LightingOperation TargetLevel float32 RampRate float32 StepIncrement float32 @@ -2170,10 +2170,10 @@ type BACnetLightingCommand struct { Priority uint32 } -type BACnetLightingOperation uint32 +type LightingOperation uint32 const ( - LightingOperationUnknown BACnetLightingOperation = iota + LightingOperationUnknown LightingOperation = iota LightingOperationOff LightingOperationOn LightingOperationToggle @@ -2181,7 +2181,7 @@ const ( LightingOperationIncrement ) -func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (blc *LightingCommand) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // operation @@ -2196,7 +2196,7 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) return -1, err } leng += leng1 - blc.Operation = BACnetLightingOperation(uVal) + blc.Operation = LightingOperation(uVal) } else { return -1, errInvalidTagNumber } @@ -2275,12 +2275,12 @@ func (blc *BACnetLightingCommand) Decode(buffer []byte, offset int, apduLen int) return leng, nil } -type BACnetPrescale struct { +type Prescale struct { Multiplier uint32 ModuloDivide uint32 } -func (bp *BACnetPrescale) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bp *Prescale) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 // multiplier @@ -2318,20 +2318,20 @@ func (bp *BACnetPrescale) Decode(buffer []byte, offset int, apduLen int) (int, e return leng, nil } -type BACnetShedLevelChoice int +type ShedLevelChoice int const ( - BACnetShedLevelChoicePercent BACnetShedLevelChoice = iota + BACnetShedLevelChoicePercent ShedLevelChoice = iota BACnetShedLevelChoiceLevel BACnetShedLevelChoiceAmount ) -type BACnetShedLevel struct { - Choice BACnetShedLevelChoice +type ShedLevel struct { + Choice ShedLevelChoice Value interface{} } -func (bsl *BACnetShedLevel) Decode(buffer []byte, offset int, apduLen int) (int, error) { +func (bsl *ShedLevel) Decode(buffer []byte, offset int, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { @@ -2377,10 +2377,10 @@ func (bsl *BACnetShedLevel) Decode(buffer []byte, offset int, apduLen int) (int, return leng, nil } -type BACnetLogRecordChoice int +type LogRecordChoice int const ( - BACnetLogRecordChoiceLogStatus BACnetLogRecordChoice = iota + BACnetLogRecordChoiceLogStatus LogRecordChoice = iota BACnetLogRecordChoiceBooleanValue BACnetLogRecordChoiceRealValue BACnetLogRecordChoiceEnumeratedValue @@ -2393,13 +2393,13 @@ const ( BACnetLogRecordChoiceAnyValue ) -type BACnetLogRecord struct { - Timestamp BACnetTimeStamp +type LogRecord struct { + Timestamp TimeStamp LogDatum interface{} - StatusFlags BACnetStatusFlags + StatusFlags StatusFlags } -func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { +func (blr *LogRecord) Decode(buffer []byte, offset, apduLen int, objType *encoding.ObjectType, propID *encoding.PropertyIdentifier) (int, error) { leng := 0 // timestamp @@ -2409,7 +2409,7 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * return -1, err } leng += leng1 - blr.Timestamp = BACnetTimeStamp{} + blr.Timestamp = TimeStamp{} leng1, err = blr.Timestamp.Decode(buffer, offset+leng, int(lenValue)) if err != nil { return -1, err @@ -2426,10 +2426,10 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * } leng += leng1 - switch BACnetLogRecordChoice(tagNumber) { + switch LogRecordChoice(tagNumber) { case BACnetLogRecordChoiceLogStatus: - blr.LogDatum = &BACnetLogStatus{} - leng += blr.LogDatum.(*BACnetLogStatus).Decode(buffer, offset+leng, int(lenValue)) + blr.LogDatum = &LogStatus{} + leng += blr.LogDatum.(*LogStatus).Decode(buffer, offset+leng, int(lenValue)) case BACnetLogRecordChoiceBooleanValue: blr.LogDatum = buffer[offset+leng] > 0 leng++ @@ -2456,14 +2456,14 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * leng += leng1 blr.LogDatum = logValue case BACnetLogRecordChoiceBitstringValue: - blr.LogDatum = &BACnetBitString{} - leng += blr.LogDatum.(*BACnetBitString).Decode(buffer, offset+leng, int(lenValue)) + blr.LogDatum = &BitString{} + leng += blr.LogDatum.(*BitString).Decode(buffer, offset+leng, int(lenValue)) case BACnetLogRecordChoiceNullValue: blr.LogDatum = nil leng++ case BACnetLogRecordChoiceFailure: - blr.LogDatum = &BACnetError{} - leng1, err = blr.LogDatum.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + blr.LogDatum = &Error{} + leng1, err = blr.LogDatum.(*Error).Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err } @@ -2478,15 +2478,15 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * leng += leng1 blr.LogDatum = logValue case BACnetLogRecordChoiceAnyValue: - blr.LogDatum = []BACnetValue{} + blr.LogDatum = []Value{} for !encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceAnyValue)) && leng < apduLen { - bValue := BACnetValue{} + bValue := Value{} leng1, _ := bValue.Decode(buffer, offset+leng, apduLen-leng, objType, propID) if leng1 < 0 { return -1, errInvalidMessageLength } leng += leng1 - blr.LogDatum = append(blr.LogDatum.([]BACnetValue), bValue) + blr.LogDatum = append(blr.LogDatum.([]Value), bValue) } if encoding.IsClosingTagNumber(buffer, offset+leng, byte(BACnetLogRecordChoiceAnyValue)) { leng++ @@ -2508,7 +2508,7 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * return -1, err } leng += leng1 - blr.StatusFlags = BACnetStatusFlags{} + blr.StatusFlags = StatusFlags{} leng += blr.StatusFlags.Decode(buffer, offset+leng, int(lenValue)) } } @@ -2516,53 +2516,53 @@ func (blr *BACnetLogRecord) Decode(buffer []byte, offset, apduLen int, objType * return leng, nil } -type BACnetLogStatus struct { +type LogStatus struct { UnusedBits uint8 - BitString *BACnetBitString + BitString *BitString } -func NewBACnetLogStatus() BACnetLogStatus { - return BACnetLogStatus{ +func NewBACnetLogStatus() LogStatus { + return LogStatus{ UnusedBits: 5, BitString: NewBACnetBitString(5, *internal.NewBitArrayFromByte(0x00)), } } -func (bls *BACnetLogStatus) Decode(buffer []byte, offset, apduLen int) int { +func (bls *LogStatus) Decode(buffer []byte, offset, apduLen int) int { bls.BitString = NewBACnetBitString(5, *internal.NewBitArrayFromByte(0x00)) return bls.BitString.Decode(buffer, offset, apduLen) } -func (bls *BACnetLogStatus) SetLogDisabled(a bool) { +func (bls *LogStatus) SetLogDisabled(a bool) { bls.BitString.Value.Set(0, a) } -func (bls *BACnetLogStatus) SetBufferPurged(a bool) { +func (bls *LogStatus) SetBufferPurged(a bool) { bls.BitString.Value.Set(1, a) } -func (bls *BACnetLogStatus) SetLogInterrupted(a bool) { +func (bls *LogStatus) SetLogInterrupted(a bool) { bls.BitString.Value.Set(2, a) } -func (bls *BACnetLogStatus) LogDisabled() (bool, error) { +func (bls *LogStatus) LogDisabled() (bool, error) { return bls.BitString.Value.Get(0) } -func (bls *BACnetLogStatus) BufferPurged() (bool, error) { +func (bls *LogStatus) BufferPurged() (bool, error) { return bls.BitString.Value.Get(1) } -func (bls *BACnetLogStatus) LogInterrupted() (bool, error) { +func (bls *LogStatus) LogInterrupted() (bool, error) { return bls.BitString.Value.Get(2) } -type BACnetError struct { +type Error struct { ErrorClass ErrorClassEnum ErrorCode ErrorCodeEnum } -func (be *BACnetError) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (be *Error) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Decode error_class @@ -2602,11 +2602,11 @@ func (be *BACnetError) Decode(buffer []byte, offset, apduLen int) (int, error) { return leng, nil } -type BACnetCalendarEntry struct { +type CalendarEntry struct { Value interface{} } -func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (ce *CalendarEntry) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 leng1, tagNumber, lenValue, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) if err != nil { @@ -2617,15 +2617,15 @@ func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) (int, leng1, ce.Value = encoding.DecodeDateSafe(buffer, offset+leng, int(lenValue)) leng += leng1 } else if tagNumber == 1 { - ce.Value = &BACnetDateRange{} - leng1, err := ce.Value.(*BACnetDateRange).Decode(buffer, offset+leng, int(lenValue)) + ce.Value = &DateRange{} + leng1, err := ce.Value.(*DateRange).Decode(buffer, offset+leng, int(lenValue)) if err != nil { return -1, err } leng += leng1 } else if tagNumber == 2 { - ce.Value = &BACnetWeekNDay{} - leng += ce.Value.(*BACnetWeekNDay).Decode(buffer, offset+leng, int(lenValue)) + ce.Value = &WeekNDay{} + leng += ce.Value.(*WeekNDay).Decode(buffer, offset+leng, int(lenValue)) } else { return -1, errInvalidTagNumber } @@ -2633,12 +2633,12 @@ func (ce *BACnetCalendarEntry) Decode(buffer []byte, offset, apduLen int) (int, return leng, nil } -type BACnetEventLogRecord struct { +type EventLogRecord struct { Timestamp DateTime LogDatum interface{} } -func (elr *BACnetEventLogRecord) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (elr *EventLogRecord) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 if encoding.IsContextTag(buffer, offset+leng, 0) { leng1, _, _, err := encoding.DecodeTagNumberAndValue(buffer, offset+leng) @@ -2655,13 +2655,13 @@ func (elr *BACnetEventLogRecord) Decode(buffer []byte, offset, apduLen int) (int return leng, nil } -type BACnetWeekNDay struct { +type WeekNDay struct { Month int WeekOfMonth int DayOfWeek int } -func (wnd *BACnetWeekNDay) Decode(buffer []byte, offset, apduLen int) int { +func (wnd *WeekNDay) Decode(buffer []byte, offset, apduLen int) int { if apduLen >= 3 { wnd.Month = int(buffer[offset]) wnd.WeekOfMonth = int(buffer[offset+1]) @@ -2715,8 +2715,8 @@ func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen in if leng < apduLen { if encoding.IsOpeningTagNumber(buffer, offset+leng, 4) { - rarr.ReadResult = &BACnetValue{} - leng1, err := rarr.ReadResult.(*BACnetValue).Decode(buffer, offset+leng, apduLen-leng, nil, nil) + rarr.ReadResult = &Value{} + leng1, err := rarr.ReadResult.(*Value).Decode(buffer, offset+leng, apduLen-leng, nil, nil) if err != nil { return -1, err } @@ -2727,8 +2727,8 @@ func (rarr *ReadAccessResultReadResult) Decode(buffer []byte, offset, apduLen in return -1, errInvalidTagNumber } } else if encoding.IsOpeningTagNumber(buffer, offset+leng, 5) { - rarr.ReadResult = &BACnetError{} - leng1, err := rarr.ReadResult.(*BACnetError).Decode(buffer, offset+leng, apduLen-leng) + rarr.ReadResult = &Error{} + leng1, err := rarr.ReadResult.(*Error).Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err } @@ -2789,38 +2789,38 @@ func (rar *ReadAccessResult) Decode(buffer []byte, offset, apduLen int) (int, er return leng, nil } -type BACnetAccessRule struct { - TimeRangeSpecifier BACnetTimeRangeSpecifierChoice - TimeRange BACnetDeviceObjectPropertyReference - LocationSpecifier BACnetLocationSpecifierChoice - Location BACnetDeviceObjectReference +type AccessRule struct { + TimeRangeSpecifier TimeRangeSpecifierChoice + TimeRange DeviceObjectPropertyReference + LocationSpecifier LocationSpecifierChoice + Location DeviceObjectReference Enable bool } -type BACnetTimeRangeSpecifierChoice int +type TimeRangeSpecifierChoice int const ( - Specified BACnetTimeRangeSpecifierChoice = iota + Specified TimeRangeSpecifierChoice = iota Always ) -type BACnetLocationSpecifierChoice int +type LocationSpecifierChoice int const ( - SpecifiedLocation BACnetLocationSpecifierChoice = iota + SpecifiedLocation LocationSpecifierChoice = iota All ) -func (bar *BACnetAccessRule) Decode(buffer []byte, offset, apduLen int) int { +func (bar *AccessRule) Decode(buffer []byte, offset, apduLen int) int { return -1 } -type BACnetNameValue struct { +type NameValue struct { Name string - Value BACnetValue + Value Value } -func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (bnv *NameValue) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Name @@ -2846,14 +2846,14 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) (int, err switch ApplicationTags(tagNumber) { case Null: - bnv.Value = BACnetValue{Value: nil} + bnv.Value = Value{Value: nil} decodeLen = 0 // Fixme: fix null type nothing else to do, some Error occurs!!!! case Boolean: if lenValue > 0 { - bnv.Value = BACnetValue{Value: true} + bnv.Value = Value{Value: true} } else { - bnv.Value = BACnetValue{Value: false} + bnv.Value = Value{Value: false} } case UnsignedInt: decodeLen, bnv.Value.Value, err = encoding.DecodeUnsigned(buffer, offset+leng, int(lenValue)) @@ -2870,8 +2870,8 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) (int, err decodeLen, bnv.Value.Value = encoding.DecodeOctetString(buffer, offset+leng, int(lenValue)) case CharacterString: decodeLen, bnv.Value.Value = encoding.DecodeCharacterString(buffer, offset+leng, apduLen-leng, int(lenValue)) - case BitString: - bitValue := BACnetBitString{} + case ApplicationTagsBitString: + bitValue := BitString{} decodeLen = bitValue.Decode(buffer, offset+leng, int(lenValue)) bnv.Value.Value = bitValue case Enumerated: @@ -2909,11 +2909,11 @@ func (bnv *BACnetNameValue) Decode(buffer []byte, offset, apduLen int) (int, err return leng, nil } -type BACnetNameValueCollection struct { - Members []BACnetNameValue +type NameValueCollection struct { + Members []NameValue } -func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (bnc *NameValueCollection) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // Check if it's an opening tag number @@ -2922,10 +2922,10 @@ func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) } leng += 1 - bnc.Members = make([]BACnetNameValue, 0) + bnc.Members = make([]NameValue, 0) for !encoding.IsClosingTagNumber(buffer, offset+leng, 0) { - bValue := BACnetNameValue{} + bValue := NameValue{} leng1, err := bValue.Decode(buffer, offset+leng, apduLen-leng) if err != nil { return -1, err @@ -2941,14 +2941,14 @@ func (bnc *BACnetNameValueCollection) Decode(buffer []byte, offset, apduLen int) return leng, nil } -type BACnetSecurityPolicy int +type SecurityPolicy int -type BACnetNetworkSecurityPolicy struct { +type NetworkSecurityPolicy struct { PortID int - SecurityLevel BACnetSecurityPolicy + SecurityLevel SecurityPolicy } -func (bns *BACnetNetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (bns *NetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // port_id @@ -2979,17 +2979,17 @@ func (bns *BACnetNetworkSecurityPolicy) Decode(buffer []byte, offset, apduLen in return -1, err } leng += leng1 - bns.SecurityLevel = BACnetSecurityPolicy(uVal) + bns.SecurityLevel = SecurityPolicy(uVal) return leng, nil } -type BACnetPortPermission struct { +type PortPermission struct { PortID int Enabled bool } -func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) (int, error) { +func (bpp *PortPermission) Decode(buffer []byte, offset, apduLen int) (int, error) { leng := 0 // port_id @@ -3027,25 +3027,25 @@ func (bpp *BACnetPortPermission) Decode(buffer []byte, offset, apduLen int) (int return leng, nil } -type BACnetPriorityValue struct { +type PriorityValue struct { Value interface{} } -func (bpv *BACnetPriorityValue) Decode(buffer []byte, offset, apduLen int) int { +func (bpv *PriorityValue) Decode(buffer []byte, offset, apduLen int) int { // TODO Implement decoding logic for BACnetPriorityValue return -1 } -type BACnetPriorityArray struct { - Value [16]BACnetPriorityValue +type PriorityArray struct { + Value [16]PriorityValue } -func (bpa *BACnetPriorityArray) Decode(buffer []byte, offset, apduLen int) int { +func (bpa *PriorityArray) Decode(buffer []byte, offset, apduLen int) int { leng := 0 i := 0 for leng < apduLen && i < 16 { - bpa.Value[i] = BACnetPriorityValue{} + bpa.Value[i] = PriorityValue{} leng += bpa.Value[i].Decode(buffer, offset+leng, apduLen-leng) i++ } @@ -3053,16 +3053,16 @@ func (bpa *BACnetPriorityArray) Decode(buffer []byte, offset, apduLen int) int { return leng } -type BACnetProcessIdSelection struct { +type ProcessIdSelection struct { Value interface{} // You can specify the type you expect here } -func (bps *BACnetProcessIdSelection) Decode(buffer []byte, offset, apduLen int) int { +func (bps *ProcessIdSelection) Decode(buffer []byte, offset, apduLen int) int { // TODO Implement decoding logic for BACnetProcessIdSelection return -1 } -type BACnetPropertyAccessResult struct { +type PropertyAccessResult struct { ObjectIdentifier ObjectIdentifier PropertyIdentifier encoding.PropertyIdentifier PropertyArrayIndex int @@ -3070,202 +3070,202 @@ type BACnetPropertyAccessResult struct { AccessResult interface{} } -func (bpar *BACnetPropertyAccessResult) Decode(buffer []byte, offset, apduLen int) int { +func (bpar *PropertyAccessResult) Decode(buffer []byte, offset, apduLen int) int { // TODO Implement decoding logic for BACnetPropertyAccessResult here return -1 } -type BACnetSetpointReference struct { +type SetpointReference struct { Value interface{} } -func (bsr *BACnetSetpointReference) Decode(buffer []byte, offset, apduLen int) int { +func (bsr *SetpointReference) Decode(buffer []byte, offset, apduLen int) int { // TODO Implement decoding logic for BACnetSetpointReference here return 0 } -type BACnetSpecialEvent struct { +type SpecialEvent struct { Period interface{} ListOfTimeValues []interface{} EventPriority int } -func (bse *BACnetSpecialEvent) Decode(buffer []byte, offset, apduLen int) int { +func (bse *SpecialEvent) Decode(buffer []byte, offset, apduLen int) int { // TODO Implement decoding logic for BACnetSpecialEvent here return 0 } -type BACnetTimerStateChangeValue struct { +type TimerStateChangeValue struct { Value interface{} } -func (scv *BACnetTimerStateChangeValue) Decode([]byte, int, int) int { +func (scv *TimerStateChangeValue) Decode([]byte, int, int) int { // TODO implement decoder return -1 } -type BACnetValueSource struct { +type ValueSource struct { Value interface{} } -func (scv *BACnetValueSource) Decode([]byte, int, int) int { +func (scv *ValueSource) Decode([]byte, int, int) int { // TODO implement decoder return -1 } -type BACnetVMACEntry struct { +type VMACEntry struct { VirtualMacAddress interface{} NativeMacAddress interface{} } -func (scv *BACnetVMACEntry) Decode([]byte, int, int) int { +func (scv *VMACEntry) Decode([]byte, int, int) int { // TODO implement decoder return -1 } -type BACnetAssignedAccessRights struct { - AssignedAccessRights BACnetDeviceObjectReference +type AssignedAccessRights struct { + AssignedAccessRights DeviceObjectReference Enable bool } -func (scv *BACnetAssignedAccessRights) Decode([]byte, int, int) int { +func (scv *AssignedAccessRights) Decode([]byte, int, int) int { // TODO implement decoder return -1 } -type BACnetAssignedLandingCalls struct { +type AssignedLandingCalls struct { LandingCalls []landingCall } type landingCall struct { FloorNumber int - Direction BACnetLiftCarDirection + Direction LiftCarDirection } -func (balc *BACnetAssignedLandingCalls) Decode(buffer []byte, offset, apduLen int) int { +func (balc *AssignedLandingCalls) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetAssignedLandingCalls return 0 } -type BACnetLiftCarDirection int +type LiftCarDirection int -type BACnetAuthenticationFactor struct { - FormatType BACnetAuthenticationFactorType +type AuthenticationFactor struct { + FormatType AuthenticationFactorType FormatClass int Value []byte } -func (baf *BACnetAuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { +func (baf *AuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetAuthenticationFactor return 0 } -type BACnetAuthenticationFactorType int +type AuthenticationFactorType int -type BACnetAuthenticationFactorFormat struct { - FormatType BACnetAuthenticationFactorType +type AuthenticationFactorFormat struct { + FormatType AuthenticationFactorType VendorID int VendorFormat int } -func (baff *BACnetAuthenticationFactorFormat) Decode(buffer []byte, offset, apduLen int) int { - // Implement decoding logic for BACnetAuthenticationFactorFormat +func (baff *AuthenticationFactorFormat) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for AuthenticationFactorFormat return 0 } -type BACnetAuthenticationPolicy struct { +type AuthenticationPolicy struct { Policies []policy OrderEnforced bool Timeout int } type policy struct { - CredentialDataInput BACnetDeviceObjectReference + CredentialDataInput DeviceObjectReference Index int } -func (bap *BACnetAuthenticationPolicy) Decode(buffer []byte, offset, apduLen int) int { - // Implement decoding logic for BACnetAuthenticationPolicy +func (bap *AuthenticationPolicy) Decode(buffer []byte, offset, apduLen int) int { + // Implement decoding logic for AuthenticationPolicy return 0 } -type BACnetBDTEntry struct { - // Define BACnetBDTEntry structure here +type BDTEntry struct { + // Define BDTEntry structure here } -type BACnetChannelValue struct { +type ChannelValue struct { Value interface{} } -func (bcv *BACnetChannelValue) Decode(buffer []byte, offset, apduLen int) int { +func (bcv *ChannelValue) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetChannelValue return 0 } -type BACnetCOVSubscription struct { - Recipient BACnetRecipientProcess - MonitoredPropertyReference BACnetObjectPropertyReference +type COVSubscription struct { + Recipient RecipientProcess + MonitoredPropertyReference ObjectPropertyReference IssueConfirmedNotifications bool TimeRemaining int COVIncrement float64 } -func (bcs *BACnetCOVSubscription) Decode(buffer []byte, offset, apduLen int) int { +func (bcs *COVSubscription) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetCOVSubscription return 0 } -type BACnetAccessAuthenticationFactorDisable int +type AccessAuthenticationFactorDisable int -type BACnetCredentialAuthenticationFactor struct { - Disable BACnetAccessAuthenticationFactorDisable - AuthenticationFactor BACnetAuthenticationFactor +type CredentialAuthenticationFactor struct { + Disable AccessAuthenticationFactorDisable + AuthenticationFactor AuthenticationFactor } -func (bcaf *BACnetCredentialAuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { +func (bcaf *CredentialAuthenticationFactor) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetCredentialAuthenticationFactor return 0 } -type BACnetDailySchedule struct { +type DailySchedule struct { DaySchedule []interface{} } -func (bds *BACnetDailySchedule) Decode(buffer []byte, offset, apduLen int) int { +func (bds *DailySchedule) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetDailySchedule return 0 } -type BACnetRecipientProcess struct { +type RecipientProcess struct { // Define BACnetRecipientProcess structure here } -type BACnetEventNotificationSubscription struct { - Recipient BACnetRecipient +type EventNotificationSubscription struct { + Recipient Recipient ProcessIdentifier int IssueConfirmedNotifications bool TimeRemaining int } -func (bens *BACnetEventNotificationSubscription) Decode(buffer []byte, offset, apduLen int) int { +func (bens *EventNotificationSubscription) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetEventNotificationSubscription return 0 } -type BACnetEventParameter struct { +type EventParameter struct { Value interface{} } -func (bep *BACnetEventParameter) Decode(buffer []byte, offset, apduLen int) int { +func (bep *EventParameter) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetEventParameter return 0 } -type BACnetFaultParameter struct { +type FaultParameter struct { Value interface{} } -func (bfp *BACnetFaultParameter) Decode(buffer []byte, offset, apduLen int) int { +func (bfp *FaultParameter) Decode(buffer []byte, offset, apduLen int) int { // Implement decoding logic for BACnetFaultParameter return 0 } diff --git a/pkg/encoding/date_time.go b/pkg/encoding/date_time.go index a47f305..9502011 100644 --- a/pkg/encoding/date_time.go +++ b/pkg/encoding/date_time.go @@ -28,6 +28,7 @@ func decodeDate(buf []byte, offset int) (int, time.Time) { if month == 0xFF && day == 0xFF && wday == 0xFF && year == 0xFF { return 4, time.Time{} } + //BACnet year starts in 1900 return 4, time.Date(int(year)+1900, time.Month(month), int(day), 0, 0, 0, 0, nil) } diff --git a/pkg/encoding/property.go b/pkg/encoding/property.go index 4457cae..8213937 100644 --- a/pkg/encoding/property.go +++ b/pkg/encoding/property.go @@ -1,9 +1,9 @@ package encoding -type BACnetNetworkType int +type NetworkType int const ( - Ethernet BACnetNetworkType = iota + Ethernet NetworkType = iota ARCnet MSTP PTP @@ -81,522 +81,522 @@ const ( Staging ) -// BACnetPropertyIdentifier represents BACnet property identifiers. +// PropertyIdentifier represents property identifiers. type PropertyIdentifier int const ( - AckedTransitions PropertyIdentifier = 0 - AckRequired PropertyIdentifier = 1 - Action PropertyIdentifier = 2 - ActionText PropertyIdentifier = 3 - ActiveText PropertyIdentifier = 4 - ActiveVtSessions PropertyIdentifier = 5 - AlarmValue PropertyIdentifier = 6 - AlarmValues PropertyIdentifier = 7 - All PropertyIdentifier = 8 - AllWritesSuccessful PropertyIdentifier = 9 - ApduSegmentTimeout PropertyIdentifier = 10 - ApduTimeout PropertyIdentifier = 11 - ApplicationSoftwareVersion PropertyIdentifier = 12 - Archive PropertyIdentifier = 13 - Bias PropertyIdentifier = 14 - ChangeOfStateCount PropertyIdentifier = 15 - ChangeOfStateTime PropertyIdentifier = 16 - NotificationClass PropertyIdentifier = 17 - Blank1 PropertyIdentifier = 18 - ControlledVariableReference PropertyIdentifier = 19 - ControlledVariableUnits PropertyIdentifier = 20 - ControlledVariableValue PropertyIdentifier = 21 - CovIncrement PropertyIdentifier = 22 - DateList PropertyIdentifier = 23 - DaylightSavingsStatus PropertyIdentifier = 24 - Deadband PropertyIdentifier = 25 - DerivativeConstant PropertyIdentifier = 26 - DerivativeConstantUnits PropertyIdentifier = 27 - Description PropertyIdentifier = 28 - DescriptionOfHalt PropertyIdentifier = 29 - DeviceAddressBinding PropertyIdentifier = 30 - DeviceType PropertyIdentifier = 31 - EffectivePeriod PropertyIdentifier = 32 - ElapsedActiveTime PropertyIdentifier = 33 - ErrorLimit PropertyIdentifier = 34 - EventEnable PropertyIdentifier = 35 - EventState PropertyIdentifier = 36 - EventType PropertyIdentifier = 37 - ExceptionSchedule PropertyIdentifier = 38 - FaultValues PropertyIdentifier = 39 - FeedbackValue PropertyIdentifier = 40 - FileAccessMethod PropertyIdentifier = 41 - FileSize PropertyIdentifier = 42 - FileType PropertyIdentifier = 43 - FirmwareRevision PropertyIdentifier = 44 - HighLimit PropertyIdentifier = 45 - InactiveText PropertyIdentifier = 46 - InProcess PropertyIdentifier = 47 - InstanceOf PropertyIdentifier = 48 - IntegralConstant PropertyIdentifier = 49 - IntegralConstantUnits PropertyIdentifier = 50 - IssueConfirmedNotifications PropertyIdentifier = 51 - LimitEnable PropertyIdentifier = 52 - ListOfGroupMembers PropertyIdentifier = 53 - ListOfObjectPropertyReferences PropertyIdentifier = 54 - ListOfSessionKeys PropertyIdentifier = 55 - LocalDate PropertyIdentifier = 56 - LocalTime PropertyIdentifier = 57 - Location PropertyIdentifier = 58 - LowLimit PropertyIdentifier = 59 - ManipulatedVariableReference PropertyIdentifier = 60 - MaximumOutput PropertyIdentifier = 61 - MaxApduLengthAccepted PropertyIdentifier = 62 - MaxInfoFrames PropertyIdentifier = 63 - MaxMaster PropertyIdentifier = 64 - MaxPresValue PropertyIdentifier = 65 - MinimumOffTime PropertyIdentifier = 66 - MinimumOnTime PropertyIdentifier = 67 - MinimumOutput PropertyIdentifier = 68 - MinPresValue PropertyIdentifier = 69 - ModelName PropertyIdentifier = 70 - ModificationDate PropertyIdentifier = 71 - NotifyType PropertyIdentifier = 72 - NumberOfApduRetries PropertyIdentifier = 73 - NumberOfStates PropertyIdentifier = 74 - ObjectIdentifierPI PropertyIdentifier = 75 - ObjectList PropertyIdentifier = 76 - ObjectName PropertyIdentifier = 77 - ObjectPropertyReference PropertyIdentifier = 78 - ObjectTypePI PropertyIdentifier = 79 - Optional PropertyIdentifier = 80 - OutOfService PropertyIdentifier = 81 - OutputUnits PropertyIdentifier = 82 - EventParameters PropertyIdentifier = 83 - Polarity PropertyIdentifier = 84 - PresentValue PropertyIdentifier = 85 - Priority PropertyIdentifier = 86 - PriorityArray PropertyIdentifier = 87 - PriorityForWriting PropertyIdentifier = 88 - ProcessIdentifier PropertyIdentifier = 89 - ProgramChange PropertyIdentifier = 90 - ProgramLocation PropertyIdentifier = 91 - ProgramState PropertyIdentifier = 92 - ProportionalConstant PropertyIdentifier = 93 - ProportionalConstantUnits PropertyIdentifier = 94 - ProtocolConformanceClass PropertyIdentifier = 95 - ProtocolObjectTypesSupported PropertyIdentifier = 96 - ProtocolServicesSupported PropertyIdentifier = 97 - ProtocolVersion PropertyIdentifier = 98 - ReadOnly PropertyIdentifier = 99 - ReasonForHalt PropertyIdentifier = 100 - Recipient PropertyIdentifier = 101 - RecipientList PropertyIdentifier = 102 - Reliability PropertyIdentifier = 103 - RelinquishDefault PropertyIdentifier = 104 - Required PropertyIdentifier = 105 - Resolution PropertyIdentifier = 106 - SegmentationSupported PropertyIdentifier = 107 - Setpoint PropertyIdentifier = 108 - SetpointReference PropertyIdentifier = 109 - StateText PropertyIdentifier = 110 - StatusFlags PropertyIdentifier = 111 - SystemStatus PropertyIdentifier = 112 - TimeDelay PropertyIdentifier = 113 - TimeOfActiveTimeReset PropertyIdentifier = 114 - TimeOfStateCountReset PropertyIdentifier = 115 - TimeSynchronizationRecipients PropertyIdentifier = 116 - Units PropertyIdentifier = 117 - UpdateInterval PropertyIdentifier = 118 - UtcOffset PropertyIdentifier = 119 - VendorIdentifier PropertyIdentifier = 120 - VendorName PropertyIdentifier = 121 - VtClassesSupported PropertyIdentifier = 122 - WeeklySchedule PropertyIdentifier = 123 - AttemptedSamples PropertyIdentifier = 124 - AverageValue PropertyIdentifier = 125 - BufferSize PropertyIdentifier = 126 - ClientCovIncrement PropertyIdentifier = 127 - CovResubscriptionInterval PropertyIdentifier = 128 - CurrentNotifyTime PropertyIdentifier = 129 - EventTimeStamps PropertyIdentifier = 130 - LogBuffer PropertyIdentifier = 131 - LogDeviceObjectProperty PropertyIdentifier = 132 - Enable PropertyIdentifier = 133 - LogInterval PropertyIdentifier = 134 - MaximumValue PropertyIdentifier = 135 - MinimumValue PropertyIdentifier = 136 - NotificationThreshold PropertyIdentifier = 137 - PreviousNotifyTime PropertyIdentifier = 138 - ProtocolRevision PropertyIdentifier = 139 - RecordsSinceNotification PropertyIdentifier = 140 - RecordCount PropertyIdentifier = 141 - StartTime PropertyIdentifier = 142 - StopTime PropertyIdentifier = 143 - StopWhenFull PropertyIdentifier = 144 - TotalRecordCount PropertyIdentifier = 145 - ValidSamples PropertyIdentifier = 146 - WindowInterval PropertyIdentifier = 147 - WindowSamples PropertyIdentifier = 148 - MaximumValueTimestamp PropertyIdentifier = 149 - MinimumValueTimestamp PropertyIdentifier = 150 - VarianceValue PropertyIdentifier = 151 - ActiveCovSubscriptions PropertyIdentifier = 152 - BackupFailureTimeout PropertyIdentifier = 153 - ConfigurationFiles PropertyIdentifier = 154 - DatabaseRevision PropertyIdentifier = 155 - DirectReading PropertyIdentifier = 156 - LastRestoreTime PropertyIdentifier = 157 - MaintenanceRequired PropertyIdentifier = 158 - MemberOf PropertyIdentifier = 159 - Mode PropertyIdentifier = 160 - OperationExpected PropertyIdentifier = 161 - Setting PropertyIdentifier = 162 - Silenced PropertyIdentifier = 163 - TrackingValue PropertyIdentifier = 164 - ZoneMembers PropertyIdentifier = 165 - LifeSafetyAlarmValues PropertyIdentifier = 166 - MaxSegmentsAccepted PropertyIdentifier = 167 - ProfileName PropertyIdentifier = 168 - AutoSlaveDiscovery PropertyIdentifier = 169 - ManualSlaveAddressBinding PropertyIdentifier = 170 - SlaveAddressBinding PropertyIdentifier = 171 - SlaveProxyEnable PropertyIdentifier = 172 - LastNotifyRecord PropertyIdentifier = 173 - ScheduleDefault PropertyIdentifier = 174 - AcceptedModes PropertyIdentifier = 175 - AdjustValue PropertyIdentifier = 176 - Count PropertyIdentifier = 177 - CountBeforeChange PropertyIdentifier = 178 - CountChangeTime PropertyIdentifier = 179 - CovPeriod PropertyIdentifier = 180 - InputReference PropertyIdentifier = 181 - LimitMonitoringInterval PropertyIdentifier = 182 - LoggingObject PropertyIdentifier = 183 - LoggingRecord PropertyIdentifier = 184 - Prescale PropertyIdentifier = 185 - PulseRate PropertyIdentifier = 186 - Scale PropertyIdentifier = 187 - ScaleFactor PropertyIdentifier = 188 - UpdateTime PropertyIdentifier = 189 - ValueBeforeChange PropertyIdentifier = 190 - ValueSet PropertyIdentifier = 191 - ValueChangeTime PropertyIdentifier = 192 - AlignIntervals PropertyIdentifier = 193 - IntervalOffset PropertyIdentifier = 195 - LastRestartReason PropertyIdentifier = 196 - LoggingType PropertyIdentifier = 197 - RestartNotificationRecipients PropertyIdentifier = 202 - TimeOfDeviceRestart PropertyIdentifier = 203 - TimeSynchronizationInterval PropertyIdentifier = 204 - Trigger PropertyIdentifier = 205 - UtcTimeSynchronizationRecipients PropertyIdentifier = 206 - NodeSubtype PropertyIdentifier = 207 - NodeType PropertyIdentifier = 208 - StructuredObjectList PropertyIdentifier = 209 - SubordinateAnnotations PropertyIdentifier = 210 - SubordinateList PropertyIdentifier = 211 - ActualShedLevel PropertyIdentifier = 212 - DutyWindow PropertyIdentifier = 213 - ExpectedShedLevel PropertyIdentifier = 214 - FullDutyBaseline PropertyIdentifier = 215 - RequestedShedLevel PropertyIdentifier = 218 - ShedDuration PropertyIdentifier = 219 - ShedLevelDescriptions PropertyIdentifier = 220 - ShedLevels PropertyIdentifier = 221 - StateDescription PropertyIdentifier = 222 - DoorAlarmState PropertyIdentifier = 226 - DoorExtendedPulseTime PropertyIdentifier = 227 - DoorMembers PropertyIdentifier = 228 - DoorOpenTooLongTime PropertyIdentifier = 229 - DoorPulseTime PropertyIdentifier = 230 - DoorStatus PropertyIdentifier = 231 - DoorUnlockDelayTime PropertyIdentifier = 232 - LockStatus PropertyIdentifier = 233 - MaskedAlarmValues PropertyIdentifier = 234 - SecuredStatus PropertyIdentifier = 235 - AbsenteeLimit PropertyIdentifier = 244 - AccessAlarmEvents PropertyIdentifier = 245 - AccessDoors PropertyIdentifier = 246 - AccessEvent PropertyIdentifier = 247 - AccessEventAuthenticationFactor PropertyIdentifier = 248 - AccessEventCredential PropertyIdentifier = 249 - AccessEventTime PropertyIdentifier = 250 - AccessTransactionEvents PropertyIdentifier = 251 - Accompaniment PropertyIdentifier = 252 - AccompanimentTime PropertyIdentifier = 253 - ActivationTime PropertyIdentifier = 254 - ActiveAuthenticationPolicy PropertyIdentifier = 255 - AssignedAccessRights PropertyIdentifier = 256 - AuthenticationFactors PropertyIdentifier = 257 - AuthenticationPolicyList PropertyIdentifier = 258 - AuthenticationPolicyNames PropertyIdentifier = 259 - AuthenticationStatus PropertyIdentifier = 260 - AuthorizationMode PropertyIdentifier = 261 - BelongsTo PropertyIdentifier = 262 - CredentialDisable PropertyIdentifier = 263 - CredentialStatus PropertyIdentifier = 264 - Credentials PropertyIdentifier = 265 - CredentialsInZone PropertyIdentifier = 266 - DaysRemaining PropertyIdentifier = 267 - EntryPoints PropertyIdentifier = 268 - ExitPoints PropertyIdentifier = 269 - ExpiryTime PropertyIdentifier = 270 - ExtendedTimeEnable PropertyIdentifier = 271 - FailedAttemptEvents PropertyIdentifier = 272 - FailedAttempts PropertyIdentifier = 273 - FailedAttemptsTime PropertyIdentifier = 274 - LastAccessEvent PropertyIdentifier = 275 - LastAccessPoint PropertyIdentifier = 276 - LastCredentialAdded PropertyIdentifier = 277 - LastCredentialAddedTime PropertyIdentifier = 278 - LastCredentialRemoved PropertyIdentifier = 279 - LastCredentialRemovedTime PropertyIdentifier = 280 - LastUseTime PropertyIdentifier = 281 - Lockout PropertyIdentifier = 282 - LockoutRelinquishTime PropertyIdentifier = 283 - MasterExemption PropertyIdentifier = 284 - MaxFailedAttempts PropertyIdentifier = 285 - Members PropertyIdentifier = 286 - MusterPoint PropertyIdentifier = 287 - NegativeAccessRules PropertyIdentifier = 288 - NumberOfAuthenticationPolicies PropertyIdentifier = 289 - OccupancyCount PropertyIdentifier = 290 - OccupancyCountAdjust PropertyIdentifier = 291 - OccupancyCountEnable PropertyIdentifier = 292 - OccupancyExemption PropertyIdentifier = 293 - OccupancyLowerLimit PropertyIdentifier = 294 - OccupancyLowerLimitEnforced PropertyIdentifier = 295 - OccupancyState PropertyIdentifier = 296 - OccupancyUpperLimit PropertyIdentifier = 297 - OccupancyUpperLimitEnforced PropertyIdentifier = 298 - PassbackExemption PropertyIdentifier = 299 - PassbackMode PropertyIdentifier = 300 - PassbackTimeout PropertyIdentifier = 301 - PositiveAccessRules PropertyIdentifier = 302 - ReasonForDisable PropertyIdentifier = 303 - SupportedFormats PropertyIdentifier = 304 - SupportedFormatClasses PropertyIdentifier = 305 - ThreatAuthority PropertyIdentifier = 306 - ThreatLevel PropertyIdentifier = 307 - TraceFlag PropertyIdentifier = 308 - TransactionNotificationClass PropertyIdentifier = 309 - UserExternalIdentifier PropertyIdentifier = 310 - UserInformationReference PropertyIdentifier = 311 - UserName PropertyIdentifier = 317 - UserType PropertyIdentifier = 318 - UsesRemaining PropertyIdentifier = 319 - ZoneFrom PropertyIdentifier = 320 - ZoneTo PropertyIdentifier = 321 - AccessEventTag PropertyIdentifier = 322 - GlobalIdentifier PropertyIdentifier = 323 - VerificationTime PropertyIdentifier = 326 - BaseDeviceSecurityPolicy PropertyIdentifier = 327 - DistributionKeyRevision PropertyIdentifier = 328 - DoNotHide PropertyIdentifier = 329 - KeySets PropertyIdentifier = 330 - LastKeyServer PropertyIdentifier = 331 - NetworkAccessSecurityPolicies PropertyIdentifier = 332 - PacketReorderTime PropertyIdentifier = 333 - SecurityPduTimeout PropertyIdentifier = 334 - SecurityTimeWindow PropertyIdentifier = 335 - SupportedSecurityAlgorithm PropertyIdentifier = 336 - UpdateKeySetTimeout PropertyIdentifier = 337 - BackupAndRestoreState PropertyIdentifier = 338 - BackupPreparationTime PropertyIdentifier = 339 - RestoreCompletionTime PropertyIdentifier = 340 - RestorePreparationTime PropertyIdentifier = 341 - BitMask PropertyIdentifier = 342 - BitText PropertyIdentifier = 343 - IsUtc PropertyIdentifier = 344 - GroupMembers PropertyIdentifier = 345 - GroupMemberNames PropertyIdentifier = 346 - MemberStatusFlags PropertyIdentifier = 347 - RequestedUpdateInterval PropertyIdentifier = 348 - CovuPeriod PropertyIdentifier = 349 - CovuRecipients PropertyIdentifier = 350 - EventMessageTexts PropertyIdentifier = 351 - EventMessageTextsConfig PropertyIdentifier = 352 - EventDetectionEnable PropertyIdentifier = 353 - EventAlgorithmInhibit PropertyIdentifier = 354 - EventAlgorithmInhibitRef PropertyIdentifier = 355 - TimeDelayNormal PropertyIdentifier = 356 - ReliabilityEvaluationInhibit PropertyIdentifier = 357 - FaultParameters PropertyIdentifier = 358 - FaultType PropertyIdentifier = 359 - LocalForwardingOnly PropertyIdentifier = 360 - ProcessIdentifierFilter PropertyIdentifier = 361 - SubscribedRecipients PropertyIdentifier = 362 - PortFilter PropertyIdentifier = 363 - AuthorizationExemptions PropertyIdentifier = 364 - AllowGroupDelayInhibit PropertyIdentifier = 365 - ChannelNumber PropertyIdentifier = 366 - ControlGroups PropertyIdentifier = 367 - ExecutionDelay PropertyIdentifier = 368 - LastPriority PropertyIdentifier = 369 - WriteStatus PropertyIdentifier = 370 - PropertyList PropertyIdentifier = 371 - SerialNumber PropertyIdentifier = 372 - BlinkWarnEnable PropertyIdentifier = 373 - DefaultFadeTime PropertyIdentifier = 374 - DefaultRampRate PropertyIdentifier = 375 - DefaultStepIncrement PropertyIdentifier = 376 - EgressTime PropertyIdentifier = 377 - InProgress PropertyIdentifier = 378 - InstantaneousPower PropertyIdentifier = 379 - LightingCommand PropertyIdentifier = 380 - LightingCommandDefaultPriority PropertyIdentifier = 381 - MaxActualValue PropertyIdentifier = 382 - MinActualValue PropertyIdentifier = 383 - Power PropertyIdentifier = 384 - Transition PropertyIdentifier = 385 - EgressActive PropertyIdentifier = 386 - InterfaceValue PropertyIdentifier = 387 - FaultHighLimit PropertyIdentifier = 388 - FaultLowLimit PropertyIdentifier = 389 - LowDiffLimit PropertyIdentifier = 390 - StrikeCount PropertyIdentifier = 391 - TimeOfStrikeCountReset PropertyIdentifier = 392 - DefaultTimeout PropertyIdentifier = 393 - InitialTimeout PropertyIdentifier = 394 - LastStateChange PropertyIdentifier = 395 - StateChangeValues PropertyIdentifier = 396 - TimerRunning PropertyIdentifier = 397 - TimerState PropertyIdentifier = 398 - ApduLength PropertyIdentifier = 399 - IpAddress PropertyIdentifier = 400 - IpDefaultGateway PropertyIdentifier = 401 - IpDhcpEnable PropertyIdentifier = 402 - IpDhcpLeaseTime PropertyIdentifier = 403 - IpDhcpLeaseTimeRemaining PropertyIdentifier = 404 - IpDhcpServer PropertyIdentifier = 405 - IpDnsServer PropertyIdentifier = 406 - BacnetIpGlobalAddress PropertyIdentifier = 407 - BacnetIpMode PropertyIdentifier = 408 - BacnetIpMulticastAddress PropertyIdentifier = 409 - BacnetIpNatTraversal PropertyIdentifier = 410 - IpSubnetMask PropertyIdentifier = 411 - BacnetIpUdpPort PropertyIdentifier = 412 - BbmdAcceptFdRegistrations PropertyIdentifier = 413 - BbmdBroadcastDistributionTable PropertyIdentifier = 414 - BbmdForeignDeviceTable PropertyIdentifier = 415 - ChangesPending PropertyIdentifier = 416 - Command PropertyIdentifier = 417 - FdBbmdAddress PropertyIdentifier = 418 - FdSubscriptionLifetime PropertyIdentifier = 419 - LinkSpeed PropertyIdentifier = 420 - LinkSpeeds PropertyIdentifier = 421 - LinkSpeedAutonegotiate PropertyIdentifier = 422 - MacAddress PropertyIdentifier = 423 - NetworkInterfaceName PropertyIdentifier = 424 - NetworkNumber PropertyIdentifier = 425 - NetworkNumberQuality PropertyIdentifier = 426 - NetworkType PropertyIdentifier = 427 - RoutingTable PropertyIdentifier = 428 - VirtualMacAddressTable PropertyIdentifier = 429 - CommandTimeArray PropertyIdentifier = 430 - CurrentCommandPriority PropertyIdentifier = 431 - LastCommandTime PropertyIdentifier = 432 - ValueSource PropertyIdentifier = 433 - ValueSourceArray PropertyIdentifier = 434 - BacnetIpv6Mode PropertyIdentifier = 435 - Ipv6Address PropertyIdentifier = 436 - Ipv6PrefixLength PropertyIdentifier = 437 - BacnetIpv6UdpPort PropertyIdentifier = 438 - Ipv6DefaultGateway PropertyIdentifier = 439 - BacnetIpv6MulticastAddress PropertyIdentifier = 440 - Ipv6DnsServer PropertyIdentifier = 441 - Ipv6AutoAddressingEnable PropertyIdentifier = 442 - Ipv6DhcpLeaseTime PropertyIdentifier = 443 - Ipv6DhcpLeaseTimeRemaining PropertyIdentifier = 444 - Ipv6DhcpServer PropertyIdentifier = 445 - Ipv6ZoneIndex PropertyIdentifier = 446 - AssignedLandingCalls PropertyIdentifier = 447 - CarAssignedDirection PropertyIdentifier = 448 - CarDoorCommand PropertyIdentifier = 449 - CarDoorStatus PropertyIdentifier = 450 - CarDoorText PropertyIdentifier = 451 - CarDoorZone PropertyIdentifier = 452 - CarDriveStatus PropertyIdentifier = 453 - CarLoad PropertyIdentifier = 454 - CarLoadUnits PropertyIdentifier = 455 - CarMode PropertyIdentifier = 456 - CarMovingDirection PropertyIdentifier = 457 - CarPosition PropertyIdentifier = 458 - ElevatorGroup PropertyIdentifier = 459 - EnergyMeter PropertyIdentifier = 460 - EnergyMeterRef PropertyIdentifier = 461 - EscalatorMode PropertyIdentifier = 462 - FloorText PropertyIdentifier = 464 - GroupId PropertyIdentifier = 465 - GroupMode PropertyIdentifier = 467 - HigherDeck PropertyIdentifier = 468 - InstallationId PropertyIdentifier = 469 - LandingCalls PropertyIdentifier = 470 - LandingCallControl PropertyIdentifier = 471 - LandingDoorStatus PropertyIdentifier = 472 - LowerDeck PropertyIdentifier = 473 - MachineRoomId PropertyIdentifier = 474 - MakingCarCall PropertyIdentifier = 475 - NextStoppingFloor PropertyIdentifier = 476 - OperationDirection PropertyIdentifier = 477 - PassengerAlarm PropertyIdentifier = 478 - PowerMode PropertyIdentifier = 479 - RegisteredCarCall PropertyIdentifier = 480 - ActiveCovMultipleSubscriptions PropertyIdentifier = 481 - ProtocolLevel PropertyIdentifier = 482 - ReferencePort PropertyIdentifier = 483 - DeployedProfileLocation PropertyIdentifier = 484 - ProfileLocation PropertyIdentifier = 485 - Tags PropertyIdentifier = 486 - SubordinateNodeTypes PropertyIdentifier = 487 - SubordinateRelationships PropertyIdentifier = 489 - SubordinateTags PropertyIdentifier = 488 - DefaultSubordinateRelationship PropertyIdentifier = 490 - Represents PropertyIdentifier = 491 - DefaultPresentValue PropertyIdentifier = 492 - PresentStage PropertyIdentifier = 493 - Stages PropertyIdentifier = 494 - StageNames PropertyIdentifier = 495 - TargetReferences PropertyIdentifier = 496 - FaultSignals PropertyIdentifier = 463 -) - -type BACnetSegmentation int - -const ( - SegmentedBoth BACnetSegmentation = iota + AckedTransitions PropertyIdentifier = 0 + AckRequired PropertyIdentifier = 1 + PropertyIdentifierAction PropertyIdentifier = 2 + ActionText PropertyIdentifier = 3 + ActiveText PropertyIdentifier = 4 + ActiveVtSessions PropertyIdentifier = 5 + AlarmValue PropertyIdentifier = 6 + AlarmValues PropertyIdentifier = 7 + All PropertyIdentifier = 8 + AllWritesSuccessful PropertyIdentifier = 9 + ApduSegmentTimeout PropertyIdentifier = 10 + ApduTimeout PropertyIdentifier = 11 + ApplicationSoftwareVersion PropertyIdentifier = 12 + Archive PropertyIdentifier = 13 + Bias PropertyIdentifier = 14 + ChangeOfStateCount PropertyIdentifier = 15 + ChangeOfStateTime PropertyIdentifier = 16 + NotificationClass PropertyIdentifier = 17 + Blank1 PropertyIdentifier = 18 + ControlledVariableReference PropertyIdentifier = 19 + ControlledVariableUnits PropertyIdentifier = 20 + ControlledVariableValue PropertyIdentifier = 21 + CovIncrement PropertyIdentifier = 22 + DateList PropertyIdentifier = 23 + DaylightSavingsStatus PropertyIdentifier = 24 + Deadband PropertyIdentifier = 25 + DerivativeConstant PropertyIdentifier = 26 + DerivativeConstantUnits PropertyIdentifier = 27 + Description PropertyIdentifier = 28 + DescriptionOfHalt PropertyIdentifier = 29 + DeviceAddressBinding PropertyIdentifier = 30 + DeviceType PropertyIdentifier = 31 + EffectivePeriod PropertyIdentifier = 32 + ElapsedActiveTime PropertyIdentifier = 33 + ErrorLimit PropertyIdentifier = 34 + EventEnable PropertyIdentifier = 35 + PropertyIdentifierEventState PropertyIdentifier = 36 + PropertyIdentifierEventType PropertyIdentifier = 37 + ExceptionSchedule PropertyIdentifier = 38 + FaultValues PropertyIdentifier = 39 + FeedbackValue PropertyIdentifier = 40 + PropertyIdentifierFileAccessMethod PropertyIdentifier = 41 + FileSize PropertyIdentifier = 42 + FileType PropertyIdentifier = 43 + FirmwareRevision PropertyIdentifier = 44 + HighLimit PropertyIdentifier = 45 + InactiveText PropertyIdentifier = 46 + InProcess PropertyIdentifier = 47 + InstanceOf PropertyIdentifier = 48 + IntegralConstant PropertyIdentifier = 49 + IntegralConstantUnits PropertyIdentifier = 50 + IssueConfirmedNotifications PropertyIdentifier = 51 + LimitEnable PropertyIdentifier = 52 + ListOfGroupMembers PropertyIdentifier = 53 + ListOfObjectPropertyReferences PropertyIdentifier = 54 + ListOfSessionKeys PropertyIdentifier = 55 + LocalDate PropertyIdentifier = 56 + LocalTime PropertyIdentifier = 57 + Location PropertyIdentifier = 58 + LowLimit PropertyIdentifier = 59 + ManipulatedVariableReference PropertyIdentifier = 60 + MaximumOutput PropertyIdentifier = 61 + MaxApduLengthAccepted PropertyIdentifier = 62 + MaxInfoFrames PropertyIdentifier = 63 + MaxMaster PropertyIdentifier = 64 + MaxPresValue PropertyIdentifier = 65 + MinimumOffTime PropertyIdentifier = 66 + MinimumOnTime PropertyIdentifier = 67 + MinimumOutput PropertyIdentifier = 68 + MinPresValue PropertyIdentifier = 69 + ModelName PropertyIdentifier = 70 + ModificationDate PropertyIdentifier = 71 + PropertyIdentifierNotifyType PropertyIdentifier = 72 + NumberOfApduRetries PropertyIdentifier = 73 + NumberOfStates PropertyIdentifier = 74 + ObjectIdentifierPI PropertyIdentifier = 75 + ObjectList PropertyIdentifier = 76 + ObjectName PropertyIdentifier = 77 + ObjectPropertyReference PropertyIdentifier = 78 + ObjectTypePI PropertyIdentifier = 79 + Optional PropertyIdentifier = 80 + OutOfService PropertyIdentifier = 81 + OutputUnits PropertyIdentifier = 82 + EventParameters PropertyIdentifier = 83 + PropertyIdentifierPolarity PropertyIdentifier = 84 + PresentValue PropertyIdentifier = 85 + Priority PropertyIdentifier = 86 + PriorityArray PropertyIdentifier = 87 + PriorityForWriting PropertyIdentifier = 88 + ProcessIdentifier PropertyIdentifier = 89 + ProgramChange PropertyIdentifier = 90 + ProgramLocation PropertyIdentifier = 91 + PropertyIdentifierProgramState PropertyIdentifier = 92 + ProportionalConstant PropertyIdentifier = 93 + ProportionalConstantUnits PropertyIdentifier = 94 + ProtocolConformanceClass PropertyIdentifier = 95 + ProtocolObjectTypesSupported PropertyIdentifier = 96 + ProtocolServicesSupported PropertyIdentifier = 97 + ProtocolVersion PropertyIdentifier = 98 + ReadOnly PropertyIdentifier = 99 + ReasonForHalt PropertyIdentifier = 100 + Recipient PropertyIdentifier = 101 + RecipientList PropertyIdentifier = 102 + PropertyIdentifierReliability PropertyIdentifier = 103 + RelinquishDefault PropertyIdentifier = 104 + Required PropertyIdentifier = 105 + Resolution PropertyIdentifier = 106 + SegmentationSupported PropertyIdentifier = 107 + Setpoint PropertyIdentifier = 108 + SetpointReference PropertyIdentifier = 109 + StateText PropertyIdentifier = 110 + StatusFlags PropertyIdentifier = 111 + SystemStatus PropertyIdentifier = 112 + TimeDelay PropertyIdentifier = 113 + TimeOfActiveTimeReset PropertyIdentifier = 114 + TimeOfStateCountReset PropertyIdentifier = 115 + TimeSynchronizationRecipients PropertyIdentifier = 116 + Units PropertyIdentifier = 117 + UpdateInterval PropertyIdentifier = 118 + UtcOffset PropertyIdentifier = 119 + VendorIdentifier PropertyIdentifier = 120 + VendorName PropertyIdentifier = 121 + VtClassesSupported PropertyIdentifier = 122 + WeeklySchedule PropertyIdentifier = 123 + AttemptedSamples PropertyIdentifier = 124 + AverageValue PropertyIdentifier = 125 + BufferSize PropertyIdentifier = 126 + ClientCovIncrement PropertyIdentifier = 127 + CovResubscriptionInterval PropertyIdentifier = 128 + CurrentNotifyTime PropertyIdentifier = 129 + EventTimeStamps PropertyIdentifier = 130 + LogBuffer PropertyIdentifier = 131 + LogDeviceObjectProperty PropertyIdentifier = 132 + Enable PropertyIdentifier = 133 + LogInterval PropertyIdentifier = 134 + MaximumValue PropertyIdentifier = 135 + MinimumValue PropertyIdentifier = 136 + NotificationThreshold PropertyIdentifier = 137 + PreviousNotifyTime PropertyIdentifier = 138 + ProtocolRevision PropertyIdentifier = 139 + RecordsSinceNotification PropertyIdentifier = 140 + RecordCount PropertyIdentifier = 141 + StartTime PropertyIdentifier = 142 + StopTime PropertyIdentifier = 143 + StopWhenFull PropertyIdentifier = 144 + TotalRecordCount PropertyIdentifier = 145 + ValidSamples PropertyIdentifier = 146 + WindowInterval PropertyIdentifier = 147 + WindowSamples PropertyIdentifier = 148 + MaximumValueTimestamp PropertyIdentifier = 149 + MinimumValueTimestamp PropertyIdentifier = 150 + VarianceValue PropertyIdentifier = 151 + ActiveCovSubscriptions PropertyIdentifier = 152 + BackupFailureTimeout PropertyIdentifier = 153 + ConfigurationFiles PropertyIdentifier = 154 + DatabaseRevision PropertyIdentifier = 155 + DirectReading PropertyIdentifier = 156 + LastRestoreTime PropertyIdentifier = 157 + MaintenanceRequired PropertyIdentifier = 158 + MemberOf PropertyIdentifier = 159 + Mode PropertyIdentifier = 160 + OperationExpected PropertyIdentifier = 161 + Setting PropertyIdentifier = 162 + Silenced PropertyIdentifier = 163 + TrackingValue PropertyIdentifier = 164 + ZoneMembers PropertyIdentifier = 165 + LifeSafetyAlarmValues PropertyIdentifier = 166 + MaxSegmentsAccepted PropertyIdentifier = 167 + ProfileName PropertyIdentifier = 168 + AutoSlaveDiscovery PropertyIdentifier = 169 + ManualSlaveAddressBinding PropertyIdentifier = 170 + SlaveAddressBinding PropertyIdentifier = 171 + SlaveProxyEnable PropertyIdentifier = 172 + LastNotifyRecord PropertyIdentifier = 173 + ScheduleDefault PropertyIdentifier = 174 + AcceptedModes PropertyIdentifier = 175 + AdjustValue PropertyIdentifier = 176 + Count PropertyIdentifier = 177 + CountBeforeChange PropertyIdentifier = 178 + CountChangeTime PropertyIdentifier = 179 + CovPeriod PropertyIdentifier = 180 + InputReference PropertyIdentifier = 181 + LimitMonitoringInterval PropertyIdentifier = 182 + LoggingObject PropertyIdentifier = 183 + LoggingRecord PropertyIdentifier = 184 + Prescale PropertyIdentifier = 185 + PulseRate PropertyIdentifier = 186 + Scale PropertyIdentifier = 187 + ScaleFactor PropertyIdentifier = 188 + UpdateTime PropertyIdentifier = 189 + ValueBeforeChange PropertyIdentifier = 190 + ValueSet PropertyIdentifier = 191 + ValueChangeTime PropertyIdentifier = 192 + AlignIntervals PropertyIdentifier = 193 + IntervalOffset PropertyIdentifier = 195 + LastRestartReason PropertyIdentifier = 196 + PropertyIdentifierLoggingType PropertyIdentifier = 197 + RestartNotificationRecipients PropertyIdentifier = 202 + TimeOfDeviceRestart PropertyIdentifier = 203 + TimeSynchronizationInterval PropertyIdentifier = 204 + Trigger PropertyIdentifier = 205 + UtcTimeSynchronizationRecipients PropertyIdentifier = 206 + NodeSubtype PropertyIdentifier = 207 + PropertyIdentifierNodeType PropertyIdentifier = 208 + StructuredObjectList PropertyIdentifier = 209 + SubordinateAnnotations PropertyIdentifier = 210 + SubordinateList PropertyIdentifier = 211 + ActualShedLevel PropertyIdentifier = 212 + DutyWindow PropertyIdentifier = 213 + ExpectedShedLevel PropertyIdentifier = 214 + FullDutyBaseline PropertyIdentifier = 215 + RequestedShedLevel PropertyIdentifier = 218 + ShedDuration PropertyIdentifier = 219 + ShedLevelDescriptions PropertyIdentifier = 220 + ShedLevels PropertyIdentifier = 221 + StateDescription PropertyIdentifier = 222 + PropertyIdentifierDoorAlarmState PropertyIdentifier = 226 + DoorExtendedPulseTime PropertyIdentifier = 227 + DoorMembers PropertyIdentifier = 228 + DoorOpenTooLongTime PropertyIdentifier = 229 + DoorPulseTime PropertyIdentifier = 230 + PropertyIdentifierDoorStatus PropertyIdentifier = 231 + DoorUnlockDelayTime PropertyIdentifier = 232 + PropertyIdentifierLockStatus PropertyIdentifier = 233 + MaskedAlarmValues PropertyIdentifier = 234 + SecuredStatus PropertyIdentifier = 235 + AbsenteeLimit PropertyIdentifier = 244 + AccessAlarmEvents PropertyIdentifier = 245 + AccessDoors PropertyIdentifier = 246 + PropertyIdentifierAccessEvent PropertyIdentifier = 247 + AccessEventAuthenticationFactor PropertyIdentifier = 248 + AccessEventCredential PropertyIdentifier = 249 + AccessEventTime PropertyIdentifier = 250 + AccessTransactionEvents PropertyIdentifier = 251 + Accompaniment PropertyIdentifier = 252 + AccompanimentTime PropertyIdentifier = 253 + ActivationTime PropertyIdentifier = 254 + ActiveAuthenticationPolicy PropertyIdentifier = 255 + AssignedAccessRights PropertyIdentifier = 256 + AuthenticationFactors PropertyIdentifier = 257 + AuthenticationPolicyList PropertyIdentifier = 258 + AuthenticationPolicyNames PropertyIdentifier = 259 + PropertyIdentifierAuthenticationStatus PropertyIdentifier = 260 + PropertyIdentifierAuthorizationMode PropertyIdentifier = 261 + BelongsTo PropertyIdentifier = 262 + CredentialDisable PropertyIdentifier = 263 + CredentialStatus PropertyIdentifier = 264 + Credentials PropertyIdentifier = 265 + CredentialsInZone PropertyIdentifier = 266 + DaysRemaining PropertyIdentifier = 267 + EntryPoints PropertyIdentifier = 268 + ExitPoints PropertyIdentifier = 269 + ExpiryTime PropertyIdentifier = 270 + ExtendedTimeEnable PropertyIdentifier = 271 + FailedAttemptEvents PropertyIdentifier = 272 + FailedAttempts PropertyIdentifier = 273 + FailedAttemptsTime PropertyIdentifier = 274 + LastAccessEvent PropertyIdentifier = 275 + LastAccessPoint PropertyIdentifier = 276 + LastCredentialAdded PropertyIdentifier = 277 + LastCredentialAddedTime PropertyIdentifier = 278 + LastCredentialRemoved PropertyIdentifier = 279 + LastCredentialRemovedTime PropertyIdentifier = 280 + LastUseTime PropertyIdentifier = 281 + Lockout PropertyIdentifier = 282 + LockoutRelinquishTime PropertyIdentifier = 283 + MasterExemption PropertyIdentifier = 284 + MaxFailedAttempts PropertyIdentifier = 285 + Members PropertyIdentifier = 286 + MusterPoint PropertyIdentifier = 287 + NegativeAccessRules PropertyIdentifier = 288 + NumberOfAuthenticationPolicies PropertyIdentifier = 289 + OccupancyCount PropertyIdentifier = 290 + OccupancyCountAdjust PropertyIdentifier = 291 + OccupancyCountEnable PropertyIdentifier = 292 + OccupancyExemption PropertyIdentifier = 293 + OccupancyLowerLimit PropertyIdentifier = 294 + OccupancyLowerLimitEnforced PropertyIdentifier = 295 + OccupancyState PropertyIdentifier = 296 + OccupancyUpperLimit PropertyIdentifier = 297 + OccupancyUpperLimitEnforced PropertyIdentifier = 298 + PassbackExemption PropertyIdentifier = 299 + PassbackMode PropertyIdentifier = 300 + PassbackTimeout PropertyIdentifier = 301 + PositiveAccessRules PropertyIdentifier = 302 + ReasonForDisable PropertyIdentifier = 303 + SupportedFormats PropertyIdentifier = 304 + SupportedFormatClasses PropertyIdentifier = 305 + ThreatAuthority PropertyIdentifier = 306 + ThreatLevel PropertyIdentifier = 307 + TraceFlag PropertyIdentifier = 308 + TransactionNotificationClass PropertyIdentifier = 309 + UserExternalIdentifier PropertyIdentifier = 310 + UserInformationReference PropertyIdentifier = 311 + UserName PropertyIdentifier = 317 + UserType PropertyIdentifier = 318 + UsesRemaining PropertyIdentifier = 319 + ZoneFrom PropertyIdentifier = 320 + ZoneTo PropertyIdentifier = 321 + AccessEventTag PropertyIdentifier = 322 + GlobalIdentifier PropertyIdentifier = 323 + VerificationTime PropertyIdentifier = 326 + BaseDeviceSecurityPolicy PropertyIdentifier = 327 + DistributionKeyRevision PropertyIdentifier = 328 + DoNotHide PropertyIdentifier = 329 + KeySets PropertyIdentifier = 330 + LastKeyServer PropertyIdentifier = 331 + NetworkAccessSecurityPolicies PropertyIdentifier = 332 + PacketReorderTime PropertyIdentifier = 333 + SecurityPduTimeout PropertyIdentifier = 334 + SecurityTimeWindow PropertyIdentifier = 335 + SupportedSecurityAlgorithm PropertyIdentifier = 336 + UpdateKeySetTimeout PropertyIdentifier = 337 + BackupAndRestoreState PropertyIdentifier = 338 + BackupPreparationTime PropertyIdentifier = 339 + RestoreCompletionTime PropertyIdentifier = 340 + RestorePreparationTime PropertyIdentifier = 341 + BitMask PropertyIdentifier = 342 + BitText PropertyIdentifier = 343 + IsUtc PropertyIdentifier = 344 + GroupMembers PropertyIdentifier = 345 + GroupMemberNames PropertyIdentifier = 346 + MemberStatusFlags PropertyIdentifier = 347 + RequestedUpdateInterval PropertyIdentifier = 348 + CovuPeriod PropertyIdentifier = 349 + CovuRecipients PropertyIdentifier = 350 + EventMessageTexts PropertyIdentifier = 351 + EventMessageTextsConfig PropertyIdentifier = 352 + EventDetectionEnable PropertyIdentifier = 353 + EventAlgorithmInhibit PropertyIdentifier = 354 + EventAlgorithmInhibitRef PropertyIdentifier = 355 + TimeDelayNormal PropertyIdentifier = 356 + ReliabilityEvaluationInhibit PropertyIdentifier = 357 + FaultParameters PropertyIdentifier = 358 + PropertyIdentifierFaultType PropertyIdentifier = 359 + LocalForwardingOnly PropertyIdentifier = 360 + ProcessIdentifierFilter PropertyIdentifier = 361 + SubscribedRecipients PropertyIdentifier = 362 + PortFilter PropertyIdentifier = 363 + AuthorizationExemptions PropertyIdentifier = 364 + AllowGroupDelayInhibit PropertyIdentifier = 365 + ChannelNumber PropertyIdentifier = 366 + ControlGroups PropertyIdentifier = 367 + ExecutionDelay PropertyIdentifier = 368 + LastPriority PropertyIdentifier = 369 + PropertyIdentifierWriteStatus PropertyIdentifier = 370 + PropertyList PropertyIdentifier = 371 + SerialNumber PropertyIdentifier = 372 + BlinkWarnEnable PropertyIdentifier = 373 + DefaultFadeTime PropertyIdentifier = 374 + DefaultRampRate PropertyIdentifier = 375 + DefaultStepIncrement PropertyIdentifier = 376 + EgressTime PropertyIdentifier = 377 + InProgress PropertyIdentifier = 378 + InstantaneousPower PropertyIdentifier = 379 + LightingCommand PropertyIdentifier = 380 + LightingCommandDefaultPriority PropertyIdentifier = 381 + MaxActualValue PropertyIdentifier = 382 + MinActualValue PropertyIdentifier = 383 + Power PropertyIdentifier = 384 + Transition PropertyIdentifier = 385 + EgressActive PropertyIdentifier = 386 + InterfaceValue PropertyIdentifier = 387 + FaultHighLimit PropertyIdentifier = 388 + FaultLowLimit PropertyIdentifier = 389 + LowDiffLimit PropertyIdentifier = 390 + StrikeCount PropertyIdentifier = 391 + TimeOfStrikeCountReset PropertyIdentifier = 392 + DefaultTimeout PropertyIdentifier = 393 + InitialTimeout PropertyIdentifier = 394 + LastStateChange PropertyIdentifier = 395 + StateChangeValues PropertyIdentifier = 396 + TimerRunning PropertyIdentifier = 397 + PropertyIdentifierTimerState PropertyIdentifier = 398 + ApduLength PropertyIdentifier = 399 + IpAddress PropertyIdentifier = 400 + IpDefaultGateway PropertyIdentifier = 401 + IpDhcpEnable PropertyIdentifier = 402 + IpDhcpLeaseTime PropertyIdentifier = 403 + IpDhcpLeaseTimeRemaining PropertyIdentifier = 404 + IpDhcpServer PropertyIdentifier = 405 + IpDnsServer PropertyIdentifier = 406 + BacnetIpGlobalAddress PropertyIdentifier = 407 + BacnetIpMode PropertyIdentifier = 408 + BacnetIpMulticastAddress PropertyIdentifier = 409 + BacnetIpNatTraversal PropertyIdentifier = 410 + IpSubnetMask PropertyIdentifier = 411 + BacnetIpUdpPort PropertyIdentifier = 412 + BbmdAcceptFdRegistrations PropertyIdentifier = 413 + BbmdBroadcastDistributionTable PropertyIdentifier = 414 + BbmdForeignDeviceTable PropertyIdentifier = 415 + ChangesPending PropertyIdentifier = 416 + Command PropertyIdentifier = 417 + FdBbmdAddress PropertyIdentifier = 418 + FdSubscriptionLifetime PropertyIdentifier = 419 + LinkSpeed PropertyIdentifier = 420 + LinkSpeeds PropertyIdentifier = 421 + LinkSpeedAutonegotiate PropertyIdentifier = 422 + MacAddress PropertyIdentifier = 423 + NetworkInterfaceName PropertyIdentifier = 424 + NetworkNumber PropertyIdentifier = 425 + PropertyIdentifierNetworkNumberQuality PropertyIdentifier = 426 + PropertyIdentifierNetworkType PropertyIdentifier = 427 + RoutingTable PropertyIdentifier = 428 + VirtualMacAddressTable PropertyIdentifier = 429 + CommandTimeArray PropertyIdentifier = 430 + CurrentCommandPriority PropertyIdentifier = 431 + LastCommandTime PropertyIdentifier = 432 + ValueSource PropertyIdentifier = 433 + ValueSourceArray PropertyIdentifier = 434 + BacnetIpv6Mode PropertyIdentifier = 435 + Ipv6Address PropertyIdentifier = 436 + Ipv6PrefixLength PropertyIdentifier = 437 + BacnetIpv6UdpPort PropertyIdentifier = 438 + Ipv6DefaultGateway PropertyIdentifier = 439 + BacnetIpv6MulticastAddress PropertyIdentifier = 440 + Ipv6DnsServer PropertyIdentifier = 441 + Ipv6AutoAddressingEnable PropertyIdentifier = 442 + Ipv6DhcpLeaseTime PropertyIdentifier = 443 + Ipv6DhcpLeaseTimeRemaining PropertyIdentifier = 444 + Ipv6DhcpServer PropertyIdentifier = 445 + Ipv6ZoneIndex PropertyIdentifier = 446 + AssignedLandingCalls PropertyIdentifier = 447 + CarAssignedDirection PropertyIdentifier = 448 + CarDoorCommand PropertyIdentifier = 449 + CarDoorStatus PropertyIdentifier = 450 + CarDoorText PropertyIdentifier = 451 + CarDoorZone PropertyIdentifier = 452 + CarDriveStatus PropertyIdentifier = 453 + CarLoad PropertyIdentifier = 454 + CarLoadUnits PropertyIdentifier = 455 + CarMode PropertyIdentifier = 456 + CarMovingDirection PropertyIdentifier = 457 + CarPosition PropertyIdentifier = 458 + ElevatorGroup PropertyIdentifier = 459 + EnergyMeter PropertyIdentifier = 460 + EnergyMeterRef PropertyIdentifier = 461 + PropertyIdentifierEscalatorMode PropertyIdentifier = 462 + FloorText PropertyIdentifier = 464 + GroupId PropertyIdentifier = 465 + GroupMode PropertyIdentifier = 467 + HigherDeck PropertyIdentifier = 468 + InstallationId PropertyIdentifier = 469 + LandingCalls PropertyIdentifier = 470 + LandingCallControl PropertyIdentifier = 471 + LandingDoorStatus PropertyIdentifier = 472 + LowerDeck PropertyIdentifier = 473 + MachineRoomId PropertyIdentifier = 474 + MakingCarCall PropertyIdentifier = 475 + NextStoppingFloor PropertyIdentifier = 476 + OperationDirection PropertyIdentifier = 477 + PassengerAlarm PropertyIdentifier = 478 + PowerMode PropertyIdentifier = 479 + RegisteredCarCall PropertyIdentifier = 480 + ActiveCovMultipleSubscriptions PropertyIdentifier = 481 + PropertyIdentifierProtocolLevel PropertyIdentifier = 482 + ReferencePort PropertyIdentifier = 483 + DeployedProfileLocation PropertyIdentifier = 484 + ProfileLocation PropertyIdentifier = 485 + Tags PropertyIdentifier = 486 + SubordinateNodeTypes PropertyIdentifier = 487 + SubordinateRelationships PropertyIdentifier = 489 + SubordinateTags PropertyIdentifier = 488 + DefaultSubordinateRelationship PropertyIdentifier = 490 + Represents PropertyIdentifier = 491 + DefaultPresentValue PropertyIdentifier = 492 + PresentStage PropertyIdentifier = 493 + Stages PropertyIdentifier = 494 + StageNames PropertyIdentifier = 495 + TargetReferences PropertyIdentifier = 496 + FaultSignals PropertyIdentifier = 463 +) + +type Segmentation int + +const ( + SegmentedBoth Segmentation = iota SegmentedTransmit SegmentedReceive NoSegmentation ) -type BACnetEventType int +type EventType int const ( - ChangeOfBitstring BACnetEventType = 0 - ChangeOfState BACnetEventType = 1 - ChangeOfValue BACnetEventType = 2 - CommandFailure BACnetEventType = 3 - FloatingLimit BACnetEventType = 4 - OutOfRange BACnetEventType = 5 - Complex BACnetEventType = 6 - ChangeOfLifeSafety BACnetEventType = 8 - Extended BACnetEventType = 9 - BufferReady BACnetEventType = 10 - UnsignedRange BACnetEventType = 11 - BACnetEventTypeAccessEvent BACnetEventType = 13 - DoubleOutOfRange BACnetEventType = 14 - SignedOutOfRange BACnetEventType = 15 - UnsignedOutOfRange BACnetEventType = 16 - ChangeOfCharacterstring BACnetEventType = 17 - ChangeOfStatusFlag BACnetEventType = 18 - ChangeOfReliability BACnetEventType = 19 - None BACnetEventType = 20 - ChangeOfDiscreteValue BACnetEventType = 21 - ChangeOfTimer BACnetEventType = 22 + ChangeOfBitstring EventType = 0 + ChangeOfState EventType = 1 + ChangeOfValue EventType = 2 + CommandFailure EventType = 3 + FloatingLimit EventType = 4 + OutOfRange EventType = 5 + Complex EventType = 6 + ChangeOfLifeSafety EventType = 8 + Extended EventType = 9 + BufferReady EventType = 10 + UnsignedRange EventType = 11 + BACnetEventTypeAccessEvent EventType = 13 + DoubleOutOfRange EventType = 14 + SignedOutOfRange EventType = 15 + UnsignedOutOfRange EventType = 16 + ChangeOfCharacterstring EventType = 17 + ChangeOfStatusFlag EventType = 18 + ChangeOfReliability EventType = 19 + None EventType = 20 + ChangeOfDiscreteValue EventType = 21 + ChangeOfTimer EventType = 22 ) -type BACnetFaultType int +type FaultType int const ( - BacnetFaultTypeNone BACnetFaultType = iota + BacnetFaultTypeNone FaultType = iota FaultCHARACTERSTRING FaultEXTENDED FaultLIFE_SAFETY @@ -606,18 +606,18 @@ const ( FaultListed ) -type BACnetNotifyType int +type NotifyType int const ( - ALARM BACnetNotifyType = iota + ALARM NotifyType = iota EVENT ACK_NOTIFICATION ) -type BACnetEventState int +type EventState int const ( - Normal BACnetEventState = iota + Normal EventState = iota Fault OffNormal BACnetEventStateHighLimit @@ -625,10 +625,10 @@ const ( LifeSafetyAlarm ) -type BACnetAccessCredentialDisableReason int +type AccessCredentialDisableReason int const ( - Disabled BACnetAccessCredentialDisableReason = iota + Disabled AccessCredentialDisableReason = iota DisabledNeedsProvisioning DisabledUnassigned DisabledNotYetActive @@ -640,35 +640,35 @@ const ( DisabledManual ) -type BACnetAccessCredentialDisable int +type AccessCredentialDisable int const ( - BACnetAccessCredentialDisableNone BACnetAccessCredentialDisable = iota + BACnetAccessCredentialDisableNone AccessCredentialDisable = iota Disable DisableManual DisableLockout ) -type BACnetAccessPassbackMode int +type AccessPassbackMode int const ( - PassbackOff BACnetAccessPassbackMode = iota + PassbackOff AccessPassbackMode = iota HardPassback SoftPassback ) -type BACnetAccessUserType int +type AccessUserType int const ( - Asset BACnetAccessUserType = iota + Asset AccessUserType = iota BACnetAccessUserTypeGroup Person ) -type BACnetAccessZoneOccupancyState int +type AccessZoneOccupancyState int const ( - BACnetAccessZoneOccupancyStateNormal BACnetAccessZoneOccupancyState = iota + BACnetAccessZoneOccupancyStateNormal AccessZoneOccupancyState = iota BelowLowerLimit AtLowerLimit AtUpperLimit @@ -677,42 +677,42 @@ const ( NotSupported ) -type BACnetAction int +type Action int const ( - Direct BACnetAction = iota + Direct Action = iota Reverse ) -type BACnetNetworkNumberQuality int +type NetworkNumberQuality int const ( - Unknown BACnetNetworkNumberQuality = iota + Unknown NetworkNumberQuality = iota Learned LearnedConfigured Configured ) -type BACnetBinaryPV int +type BinaryPV int const ( - Inactive BACnetBinaryPV = iota + Inactive BinaryPV = iota Active ) -type BACnetDoorValue int +type DoorValue int const ( - Lock BACnetDoorValue = iota + Lock DoorValue = iota Unlock PulseUnlock ExtendedPulseUnlock ) -type BACnetAuthenticationStatus int +type AuthenticationStatus int const ( - NotReady BACnetAuthenticationStatus = iota + NotReady AuthenticationStatus = iota Ready BACnetAuthenticationStatusDisabled WaitingForAuthenticationFactor @@ -721,10 +721,10 @@ const ( BACnetAuthenticationStatusInProgress ) -type BACnetAuthorizationExemption int +type AuthorizationExemption int const ( - Passback BACnetAuthorizationExemption = iota + Passback AuthorizationExemption = iota OccupancyCheck BACnetAuthorizationExemptionAccessRights BACnetAuthorizationExemptionLockout @@ -733,10 +733,10 @@ const ( AuthorizationDelay ) -type BACnetAuthorizationMode int +type AuthorizationMode int const ( - Authorize BACnetAuthorizationMode = iota + Authorize AuthorizationMode = iota GrantActive DenyAll VerificationRequired @@ -744,20 +744,20 @@ const ( BACnetAuthorizationModeNone ) -type BACnetBackupState int +type BackupState int const ( - Idle BACnetBackupState = iota + Idle BackupState = iota PreparingForBackup PreparingForRestor PerformingABACKUP PerformingARestor ) -type BACnetBinaryLightingPV int +type BinaryLightingPV int const ( - Off BACnetBinaryLightingPV = iota + Off BinaryLightingPV = iota On Warn WarnOff @@ -765,10 +765,10 @@ const ( Stop ) -type BACnetDeviceStatus int +type DeviceStatus int const ( - Operational BACnetDeviceStatus = iota + Operational DeviceStatus = iota OperationalReadOnly DownloadRequired DownloadInProgress @@ -776,10 +776,10 @@ const ( BackupInProgress ) -type BACnetDoorAlarmState int +type DoorAlarmState int const ( - BACnetDoorAlarmStateNormal BACnetDoorAlarmState = iota + BACnetDoorAlarmStateNormal DoorAlarmState = iota Alarm DoorOpenTooLong ForcedOpen @@ -790,18 +790,18 @@ const ( EgressOpen ) -type BACnetDoorSecuredStatus int +type DoorSecuredStatus int const ( - Secured BACnetDoorSecuredStatus = iota + Secured DoorSecuredStatus = iota UNSecured BACnetDoorSecuredStatusUnknown ) -type BACnetDoorStatus int +type DoorStatus int const ( - CLOSED BACnetDoorStatus = iota + CLOSED DoorStatus = iota OPENED UNKNOWN DOOR_FAULT @@ -813,278 +813,278 @@ const ( LIMITED_OPENED ) -type BACnetEngineeringUnits int - -const ( - metersPerSecondPerSecond BACnetEngineeringUnits = 166 - SquareMeters BACnetEngineeringUnits = 0 - SquareCentimeters BACnetEngineeringUnits = 116 - SquareFeet BACnetEngineeringUnits = 1 - SquareInches BACnetEngineeringUnits = 115 - Currency1 BACnetEngineeringUnits = 105 - Currency2 BACnetEngineeringUnits = 106 - Currency3 BACnetEngineeringUnits = 107 - Currency4 BACnetEngineeringUnits = 108 - Currency5 BACnetEngineeringUnits = 109 - Currency6 BACnetEngineeringUnits = 110 - Currency7 BACnetEngineeringUnits = 111 - Currency8 BACnetEngineeringUnits = 112 - Currency9 BACnetEngineeringUnits = 113 - Currency10 BACnetEngineeringUnits = 114 - Milliamperes BACnetEngineeringUnits = 2 - Amperes BACnetEngineeringUnits = 3 - AmperesPerMeter BACnetEngineeringUnits = 167 - AmperesPerSquareMeter BACnetEngineeringUnits = 168 - AmpereSquareMeters BACnetEngineeringUnits = 169 - Decibels BACnetEngineeringUnits = 199 - DecibelsMillivolt BACnetEngineeringUnits = 200 - DecibelsVolt BACnetEngineeringUnits = 201 - Farads BACnetEngineeringUnits = 170 - Henrys BACnetEngineeringUnits = 171 - Ohms BACnetEngineeringUnits = 4 - OhmMeters BACnetEngineeringUnits = 172 - Milliohms BACnetEngineeringUnits = 145 - Kilohms BACnetEngineeringUnits = 122 - Megohms BACnetEngineeringUnits = 123 - Microsiemens BACnetEngineeringUnits = 190 - Millisiemens BACnetEngineeringUnits = 202 - Siemens BACnetEngineeringUnits = 173 - SiemensPerMeter BACnetEngineeringUnits = 174 - Teslas BACnetEngineeringUnits = 175 - Volts BACnetEngineeringUnits = 5 - Millivolts BACnetEngineeringUnits = 124 - Kilovolts BACnetEngineeringUnits = 6 - Megavolts BACnetEngineeringUnits = 7 - VoltAmperes BACnetEngineeringUnits = 8 - KilovoltAmperes BACnetEngineeringUnits = 9 - MegavoltAmperes BACnetEngineeringUnits = 10 - VoltAmperesReactive BACnetEngineeringUnits = 11 - KilovoltAmperesReactive BACnetEngineeringUnits = 12 - MegavoltAmperesReactive BACnetEngineeringUnits = 13 - VoltsPerDegreeKelvin BACnetEngineeringUnits = 176 - VoltsPerMeter BACnetEngineeringUnits = 177 - DegreesPhase BACnetEngineeringUnits = 14 - PowerFactor BACnetEngineeringUnits = 15 - Webers BACnetEngineeringUnits = 178 - Joules BACnetEngineeringUnits = 16 - Kilojoules BACnetEngineeringUnits = 17 - KilojoulesPerKilogram BACnetEngineeringUnits = 125 - Megajoules BACnetEngineeringUnits = 126 - WattHours BACnetEngineeringUnits = 18 - KilowattHours BACnetEngineeringUnits = 19 - MegawattHours BACnetEngineeringUnits = 146 - WattHoursReactive BACnetEngineeringUnits = 203 - KilowattHoursReactive BACnetEngineeringUnits = 204 - MegawattHoursReactive BACnetEngineeringUnits = 205 - Btus BACnetEngineeringUnits = 20 - KiloBtus BACnetEngineeringUnits = 147 - MegaBtus BACnetEngineeringUnits = 148 - Therms BACnetEngineeringUnits = 21 - TonHours BACnetEngineeringUnits = 22 - JoulesPerKilogramDryAir BACnetEngineeringUnits = 23 - KilojoulesPerKilogramDryAir BACnetEngineeringUnits = 149 - MegajoulesPerKilogramDryAir BACnetEngineeringUnits = 150 - BtusPerPoundDryAir BACnetEngineeringUnits = 24 - BtusPerPound BACnetEngineeringUnits = 117 - JoulesPerDegreeKelvin BACnetEngineeringUnits = 127 - KilojoulesPerDegreeKelvin BACnetEngineeringUnits = 151 - MegajoulesPerDegreeKelvin BACnetEngineeringUnits = 152 - JoulesPerKilogramDegreeKelvin BACnetEngineeringUnits = 128 - Newton BACnetEngineeringUnits = 153 - CyclesPerHour BACnetEngineeringUnits = 25 - CyclesPerMinute BACnetEngineeringUnits = 26 - Hertz BACnetEngineeringUnits = 27 - Kilohertz BACnetEngineeringUnits = 129 - Megahertz BACnetEngineeringUnits = 130 - PerHour BACnetEngineeringUnits = 131 - GramsOfWaterPerKilogramDryAir BACnetEngineeringUnits = 28 - PercentRelativeHumidity BACnetEngineeringUnits = 29 - Micrometers BACnetEngineeringUnits = 194 - Millimeters BACnetEngineeringUnits = 30 - Centimeters BACnetEngineeringUnits = 118 - Kilometers BACnetEngineeringUnits = 193 - Meters BACnetEngineeringUnits = 31 - Inches BACnetEngineeringUnits = 32 - Feet BACnetEngineeringUnits = 33 - Candelas BACnetEngineeringUnits = 179 - CandelasPerSquareMeter BACnetEngineeringUnits = 180 - WattsPerSquareFoot BACnetEngineeringUnits = 34 - WattsPerSquareMeter BACnetEngineeringUnits = 35 - Lumens BACnetEngineeringUnits = 36 - Luxes BACnetEngineeringUnits = 37 - FootCandles BACnetEngineeringUnits = 38 - Milligrams BACnetEngineeringUnits = 196 - Grams BACnetEngineeringUnits = 195 - Kilograms BACnetEngineeringUnits = 39 - PoundsMass BACnetEngineeringUnits = 40 - Tons BACnetEngineeringUnits = 41 - GramsPerSecond BACnetEngineeringUnits = 154 - GramsPerMinute BACnetEngineeringUnits = 155 - KilogramsPerSecond BACnetEngineeringUnits = 42 - KilogramsPerMinute BACnetEngineeringUnits = 43 - KilogramsPerHour BACnetEngineeringUnits = 44 - PoundsMassPerSecond BACnetEngineeringUnits = 119 - PoundsMassPerMinute BACnetEngineeringUnits = 45 - PoundsMassPerHour BACnetEngineeringUnits = 46 - TonsPerHour BACnetEngineeringUnits = 156 - Milliwatts BACnetEngineeringUnits = 132 - Watts BACnetEngineeringUnits = 47 - Kilowatts BACnetEngineeringUnits = 48 - Megawatts BACnetEngineeringUnits = 49 - BtusPerHour BACnetEngineeringUnits = 50 - KiloBtusPerHour BACnetEngineeringUnits = 157 - Horsepower BACnetEngineeringUnits = 51 - TonsRefrigeration BACnetEngineeringUnits = 52 - Pascals BACnetEngineeringUnits = 53 - Hectopascals BACnetEngineeringUnits = 133 - Kilopascals BACnetEngineeringUnits = 54 - Millibars BACnetEngineeringUnits = 134 - Bars BACnetEngineeringUnits = 55 - PoundsForcePerSquareInch BACnetEngineeringUnits = 56 - MillimetersOfWater BACnetEngineeringUnits = 206 - CentimetersOfWater BACnetEngineeringUnits = 57 - InchesOfWater BACnetEngineeringUnits = 58 - MillimetersOfMercury BACnetEngineeringUnits = 59 - CentimetersOfMercury BACnetEngineeringUnits = 60 - InchesOfMercury BACnetEngineeringUnits = 61 - DegreesCelsius BACnetEngineeringUnits = 62 - DegreesKelvin BACnetEngineeringUnits = 63 - DegreesKelvinPerHour BACnetEngineeringUnits = 181 - DegreesKelvinPerMinute BACnetEngineeringUnits = 182 - DegreesFahrenheit BACnetEngineeringUnits = 64 - DegreeDaysCelsius BACnetEngineeringUnits = 65 - DegreeDaysFahrenheit BACnetEngineeringUnits = 66 - DeltaDegreesFahrenheit BACnetEngineeringUnits = 120 - DeltaDegreesKelvin BACnetEngineeringUnits = 121 - Years BACnetEngineeringUnits = 67 - Months BACnetEngineeringUnits = 68 - Weeks BACnetEngineeringUnits = 69 - Days BACnetEngineeringUnits = 70 - Hours BACnetEngineeringUnits = 71 - Minutes BACnetEngineeringUnits = 72 - Seconds BACnetEngineeringUnits = 73 - HundredthsSeconds BACnetEngineeringUnits = 158 - Milliseconds BACnetEngineeringUnits = 159 - NewtonMeters BACnetEngineeringUnits = 160 - MillimetersPerSecond BACnetEngineeringUnits = 161 - MillimetersPerMinute BACnetEngineeringUnits = 162 - MetersPerSecond BACnetEngineeringUnits = 74 - MetersPerMinute BACnetEngineeringUnits = 163 - MetersPerHour BACnetEngineeringUnits = 164 - KilometersPerHour BACnetEngineeringUnits = 75 - FeetPerSecond BACnetEngineeringUnits = 76 - FeetPerMinute BACnetEngineeringUnits = 77 - MilesPerHour BACnetEngineeringUnits = 78 - CubicFeet BACnetEngineeringUnits = 79 - CubicMeters BACnetEngineeringUnits = 80 - ImperialGallons BACnetEngineeringUnits = 81 - Milliliters BACnetEngineeringUnits = 197 - Liters BACnetEngineeringUnits = 82 - UsGallons BACnetEngineeringUnits = 83 - CubicFeetPerSecond BACnetEngineeringUnits = 142 - CubicFeetPerMinute BACnetEngineeringUnits = 84 - MillionCubicFeetPerMinute BACnetEngineeringUnits = 254 - CubicFeetPerHour BACnetEngineeringUnits = 191 - StandardCubicFeetPerDay BACnetEngineeringUnits = 47808 - MillionStandardCubicFeetPerDay BACnetEngineeringUnits = 47809 - ThousandCubicFeetPerDay BACnetEngineeringUnits = 47810 - ThousandStandardCubicFeetPerDay BACnetEngineeringUnits = 47811 - PoundsMassPerDay BACnetEngineeringUnits = 47812 - CubicMetersPerSecond BACnetEngineeringUnits = 85 - CubicMetersPerMinute BACnetEngineeringUnits = 165 - CubicMetersPerHour BACnetEngineeringUnits = 135 - ImperialGallonsPerMinute BACnetEngineeringUnits = 86 - MillilitersPerSecond BACnetEngineeringUnits = 198 - LitersPerSecond BACnetEngineeringUnits = 87 - LitersPerMinute BACnetEngineeringUnits = 88 - LitersPerHour BACnetEngineeringUnits = 136 - UsGallonsPerMinute BACnetEngineeringUnits = 89 - UsGallonsPerHour BACnetEngineeringUnits = 192 - DegreesAngular BACnetEngineeringUnits = 90 - DegreesCelsiusPerHour BACnetEngineeringUnits = 91 - DegreesCelsiusPerMinute BACnetEngineeringUnits = 92 - DegreesFahrenheitPerHour BACnetEngineeringUnits = 93 - DegreesFahrenheitPerMinute BACnetEngineeringUnits = 94 - JouleSeconds BACnetEngineeringUnits = 183 - KilogramsPerCubicMeter BACnetEngineeringUnits = 186 - KwHoursPerSquareMeter BACnetEngineeringUnits = 137 - KwHoursPerSquareFoot BACnetEngineeringUnits = 138 - MegajoulesPerSquareMeter BACnetEngineeringUnits = 139 - MegajoulesPerSquareFoot BACnetEngineeringUnits = 140 - NoUnits BACnetEngineeringUnits = 95 - NewtonSeconds BACnetEngineeringUnits = 187 - NewtonsPerMeter BACnetEngineeringUnits = 188 - PartsPerMillion BACnetEngineeringUnits = 96 - PartsPerBillion BACnetEngineeringUnits = 97 - Percent BACnetEngineeringUnits = 98 - PercentObscurationPerFoot BACnetEngineeringUnits = 143 - PercentObscurationPerMeter BACnetEngineeringUnits = 144 - PercentPerSecond BACnetEngineeringUnits = 99 - PerMinute BACnetEngineeringUnits = 100 - PerSecond BACnetEngineeringUnits = 101 - PsiPerDegreeFahrenheit BACnetEngineeringUnits = 102 - Radians BACnetEngineeringUnits = 103 - RadiansPerSecond BACnetEngineeringUnits = 184 - RevolutionsPerMinute BACnetEngineeringUnits = 104 - SquareMetersPerNewton BACnetEngineeringUnits = 185 - WattsPerMeterPerDegreeKelvin BACnetEngineeringUnits = 189 - WattsPerSquareMeterDegreeKelvin BACnetEngineeringUnits = 141 - PerMille BACnetEngineeringUnits = 207 - GramsPerGram BACnetEngineeringUnits = 208 - KilogramsPerKilogram BACnetEngineeringUnits = 209 - GramsPerKilogram BACnetEngineeringUnits = 210 - MilligramsPerGram BACnetEngineeringUnits = 211 - MilligramsPerKilogram BACnetEngineeringUnits = 212 - GramsPerMilliliter BACnetEngineeringUnits = 213 - GramsPerLiter BACnetEngineeringUnits = 214 - MilligramsPerLiter BACnetEngineeringUnits = 215 - MicrogramsPerLiter BACnetEngineeringUnits = 216 - GramsPerCubicMeter BACnetEngineeringUnits = 217 - MilligramsPerCubicMeter BACnetEngineeringUnits = 218 - MicrogramsPerCubicMeter BACnetEngineeringUnits = 219 - NanogramsPerCubicMeter BACnetEngineeringUnits = 220 - GramsPerCubicCentimeter BACnetEngineeringUnits = 221 - Becquerels BACnetEngineeringUnits = 222 - Kilobecquerels BACnetEngineeringUnits = 223 - Megabecquerels BACnetEngineeringUnits = 224 - Gray BACnetEngineeringUnits = 225 - Milligray BACnetEngineeringUnits = 226 - Microgray BACnetEngineeringUnits = 227 - Sieverts BACnetEngineeringUnits = 228 - Millisieverts BACnetEngineeringUnits = 229 - Microsieverts BACnetEngineeringUnits = 230 - MicrosievertsPerHour BACnetEngineeringUnits = 231 - Millirems BACnetEngineeringUnits = 47814 - MilliremsPerHour BACnetEngineeringUnits = 47815 - DecibelsA BACnetEngineeringUnits = 232 - NephelometricTurbidityUnit BACnetEngineeringUnits = 233 - Ph BACnetEngineeringUnits = 234 - GramsPerSquareMeter BACnetEngineeringUnits = 235 - MinutesPerDegreeKelvin BACnetEngineeringUnits = 236 - MeterSquaredPerMeter BACnetEngineeringUnits = 237 - AmpereSeconds BACnetEngineeringUnits = 238 - VoltAmpereHours BACnetEngineeringUnits = 239 - KilovoltAmpereHours BACnetEngineeringUnits = 240 - MegavoltAmpereHours BACnetEngineeringUnits = 241 - VoltAmpereHoursReactive BACnetEngineeringUnits = 242 - KilovoltAmpereHoursReactive BACnetEngineeringUnits = 243 - MegavoltAmpereHoursReactive BACnetEngineeringUnits = 244 - VoltSquareHours BACnetEngineeringUnits = 245 - AmpereSquareHours BACnetEngineeringUnits = 246 - JoulePerHours BACnetEngineeringUnits = 247 - CubicFeetPerDay BACnetEngineeringUnits = 248 - CubicMetersPerDay BACnetEngineeringUnits = 249 - WattHoursPerCubicMeter BACnetEngineeringUnits = 250 - JoulesPerCubicMeter BACnetEngineeringUnits = 251 - MolePercent BACnetEngineeringUnits = 252 - PascalSeconds BACnetEngineeringUnits = 253 - MillionStandardCubicFeetPerMinute BACnetEngineeringUnits = 254 -) - -type BACnetEscalatorMode int - -const ( - BacnetescalatorModeUnknown BACnetEscalatorMode = iota +type EngineeringUnits int + +const ( + metersPerSecondPerSecond EngineeringUnits = 166 + SquareMeters EngineeringUnits = 0 + SquareCentimeters EngineeringUnits = 116 + SquareFeet EngineeringUnits = 1 + SquareInches EngineeringUnits = 115 + Currency1 EngineeringUnits = 105 + Currency2 EngineeringUnits = 106 + Currency3 EngineeringUnits = 107 + Currency4 EngineeringUnits = 108 + Currency5 EngineeringUnits = 109 + Currency6 EngineeringUnits = 110 + Currency7 EngineeringUnits = 111 + Currency8 EngineeringUnits = 112 + Currency9 EngineeringUnits = 113 + Currency10 EngineeringUnits = 114 + Milliamperes EngineeringUnits = 2 + Amperes EngineeringUnits = 3 + AmperesPerMeter EngineeringUnits = 167 + AmperesPerSquareMeter EngineeringUnits = 168 + AmpereSquareMeters EngineeringUnits = 169 + Decibels EngineeringUnits = 199 + DecibelsMillivolt EngineeringUnits = 200 + DecibelsVolt EngineeringUnits = 201 + Farads EngineeringUnits = 170 + Henrys EngineeringUnits = 171 + Ohms EngineeringUnits = 4 + OhmMeters EngineeringUnits = 172 + Milliohms EngineeringUnits = 145 + Kilohms EngineeringUnits = 122 + Megohms EngineeringUnits = 123 + Microsiemens EngineeringUnits = 190 + Millisiemens EngineeringUnits = 202 + Siemens EngineeringUnits = 173 + SiemensPerMeter EngineeringUnits = 174 + Teslas EngineeringUnits = 175 + Volts EngineeringUnits = 5 + Millivolts EngineeringUnits = 124 + Kilovolts EngineeringUnits = 6 + Megavolts EngineeringUnits = 7 + VoltAmperes EngineeringUnits = 8 + KilovoltAmperes EngineeringUnits = 9 + MegavoltAmperes EngineeringUnits = 10 + VoltAmperesReactive EngineeringUnits = 11 + KilovoltAmperesReactive EngineeringUnits = 12 + MegavoltAmperesReactive EngineeringUnits = 13 + VoltsPerDegreeKelvin EngineeringUnits = 176 + VoltsPerMeter EngineeringUnits = 177 + DegreesPhase EngineeringUnits = 14 + PowerFactor EngineeringUnits = 15 + Webers EngineeringUnits = 178 + Joules EngineeringUnits = 16 + Kilojoules EngineeringUnits = 17 + KilojoulesPerKilogram EngineeringUnits = 125 + Megajoules EngineeringUnits = 126 + WattHours EngineeringUnits = 18 + KilowattHours EngineeringUnits = 19 + MegawattHours EngineeringUnits = 146 + WattHoursReactive EngineeringUnits = 203 + KilowattHoursReactive EngineeringUnits = 204 + MegawattHoursReactive EngineeringUnits = 205 + Btus EngineeringUnits = 20 + KiloBtus EngineeringUnits = 147 + MegaBtus EngineeringUnits = 148 + Therms EngineeringUnits = 21 + TonHours EngineeringUnits = 22 + JoulesPerKilogramDryAir EngineeringUnits = 23 + KilojoulesPerKilogramDryAir EngineeringUnits = 149 + MegajoulesPerKilogramDryAir EngineeringUnits = 150 + BtusPerPoundDryAir EngineeringUnits = 24 + BtusPerPound EngineeringUnits = 117 + JoulesPerDegreeKelvin EngineeringUnits = 127 + KilojoulesPerDegreeKelvin EngineeringUnits = 151 + MegajoulesPerDegreeKelvin EngineeringUnits = 152 + JoulesPerKilogramDegreeKelvin EngineeringUnits = 128 + Newton EngineeringUnits = 153 + CyclesPerHour EngineeringUnits = 25 + CyclesPerMinute EngineeringUnits = 26 + Hertz EngineeringUnits = 27 + Kilohertz EngineeringUnits = 129 + Megahertz EngineeringUnits = 130 + PerHour EngineeringUnits = 131 + GramsOfWaterPerKilogramDryAir EngineeringUnits = 28 + PercentRelativeHumidity EngineeringUnits = 29 + Micrometers EngineeringUnits = 194 + Millimeters EngineeringUnits = 30 + Centimeters EngineeringUnits = 118 + Kilometers EngineeringUnits = 193 + Meters EngineeringUnits = 31 + Inches EngineeringUnits = 32 + Feet EngineeringUnits = 33 + Candelas EngineeringUnits = 179 + CandelasPerSquareMeter EngineeringUnits = 180 + WattsPerSquareFoot EngineeringUnits = 34 + WattsPerSquareMeter EngineeringUnits = 35 + Lumens EngineeringUnits = 36 + Luxes EngineeringUnits = 37 + FootCandles EngineeringUnits = 38 + Milligrams EngineeringUnits = 196 + Grams EngineeringUnits = 195 + Kilograms EngineeringUnits = 39 + PoundsMass EngineeringUnits = 40 + Tons EngineeringUnits = 41 + GramsPerSecond EngineeringUnits = 154 + GramsPerMinute EngineeringUnits = 155 + KilogramsPerSecond EngineeringUnits = 42 + KilogramsPerMinute EngineeringUnits = 43 + KilogramsPerHour EngineeringUnits = 44 + PoundsMassPerSecond EngineeringUnits = 119 + PoundsMassPerMinute EngineeringUnits = 45 + PoundsMassPerHour EngineeringUnits = 46 + TonsPerHour EngineeringUnits = 156 + Milliwatts EngineeringUnits = 132 + Watts EngineeringUnits = 47 + Kilowatts EngineeringUnits = 48 + Megawatts EngineeringUnits = 49 + BtusPerHour EngineeringUnits = 50 + KiloBtusPerHour EngineeringUnits = 157 + Horsepower EngineeringUnits = 51 + TonsRefrigeration EngineeringUnits = 52 + Pascals EngineeringUnits = 53 + Hectopascals EngineeringUnits = 133 + Kilopascals EngineeringUnits = 54 + Millibars EngineeringUnits = 134 + Bars EngineeringUnits = 55 + PoundsForcePerSquareInch EngineeringUnits = 56 + MillimetersOfWater EngineeringUnits = 206 + CentimetersOfWater EngineeringUnits = 57 + InchesOfWater EngineeringUnits = 58 + MillimetersOfMercury EngineeringUnits = 59 + CentimetersOfMercury EngineeringUnits = 60 + InchesOfMercury EngineeringUnits = 61 + DegreesCelsius EngineeringUnits = 62 + DegreesKelvin EngineeringUnits = 63 + DegreesKelvinPerHour EngineeringUnits = 181 + DegreesKelvinPerMinute EngineeringUnits = 182 + DegreesFahrenheit EngineeringUnits = 64 + DegreeDaysCelsius EngineeringUnits = 65 + DegreeDaysFahrenheit EngineeringUnits = 66 + DeltaDegreesFahrenheit EngineeringUnits = 120 + DeltaDegreesKelvin EngineeringUnits = 121 + Years EngineeringUnits = 67 + Months EngineeringUnits = 68 + Weeks EngineeringUnits = 69 + Days EngineeringUnits = 70 + Hours EngineeringUnits = 71 + Minutes EngineeringUnits = 72 + Seconds EngineeringUnits = 73 + HundredthsSeconds EngineeringUnits = 158 + Milliseconds EngineeringUnits = 159 + NewtonMeters EngineeringUnits = 160 + MillimetersPerSecond EngineeringUnits = 161 + MillimetersPerMinute EngineeringUnits = 162 + MetersPerSecond EngineeringUnits = 74 + MetersPerMinute EngineeringUnits = 163 + MetersPerHour EngineeringUnits = 164 + KilometersPerHour EngineeringUnits = 75 + FeetPerSecond EngineeringUnits = 76 + FeetPerMinute EngineeringUnits = 77 + MilesPerHour EngineeringUnits = 78 + CubicFeet EngineeringUnits = 79 + CubicMeters EngineeringUnits = 80 + ImperialGallons EngineeringUnits = 81 + Milliliters EngineeringUnits = 197 + Liters EngineeringUnits = 82 + UsGallons EngineeringUnits = 83 + CubicFeetPerSecond EngineeringUnits = 142 + CubicFeetPerMinute EngineeringUnits = 84 + MillionCubicFeetPerMinute EngineeringUnits = 254 + CubicFeetPerHour EngineeringUnits = 191 + StandardCubicFeetPerDay EngineeringUnits = 47808 + MillionStandardCubicFeetPerDay EngineeringUnits = 47809 + ThousandCubicFeetPerDay EngineeringUnits = 47810 + ThousandStandardCubicFeetPerDay EngineeringUnits = 47811 + PoundsMassPerDay EngineeringUnits = 47812 + CubicMetersPerSecond EngineeringUnits = 85 + CubicMetersPerMinute EngineeringUnits = 165 + CubicMetersPerHour EngineeringUnits = 135 + ImperialGallonsPerMinute EngineeringUnits = 86 + MillilitersPerSecond EngineeringUnits = 198 + LitersPerSecond EngineeringUnits = 87 + LitersPerMinute EngineeringUnits = 88 + LitersPerHour EngineeringUnits = 136 + UsGallonsPerMinute EngineeringUnits = 89 + UsGallonsPerHour EngineeringUnits = 192 + DegreesAngular EngineeringUnits = 90 + DegreesCelsiusPerHour EngineeringUnits = 91 + DegreesCelsiusPerMinute EngineeringUnits = 92 + DegreesFahrenheitPerHour EngineeringUnits = 93 + DegreesFahrenheitPerMinute EngineeringUnits = 94 + JouleSeconds EngineeringUnits = 183 + KilogramsPerCubicMeter EngineeringUnits = 186 + KwHoursPerSquareMeter EngineeringUnits = 137 + KwHoursPerSquareFoot EngineeringUnits = 138 + MegajoulesPerSquareMeter EngineeringUnits = 139 + MegajoulesPerSquareFoot EngineeringUnits = 140 + NoUnits EngineeringUnits = 95 + NewtonSeconds EngineeringUnits = 187 + NewtonsPerMeter EngineeringUnits = 188 + PartsPerMillion EngineeringUnits = 96 + PartsPerBillion EngineeringUnits = 97 + Percent EngineeringUnits = 98 + PercentObscurationPerFoot EngineeringUnits = 143 + PercentObscurationPerMeter EngineeringUnits = 144 + PercentPerSecond EngineeringUnits = 99 + PerMinute EngineeringUnits = 100 + PerSecond EngineeringUnits = 101 + PsiPerDegreeFahrenheit EngineeringUnits = 102 + Radians EngineeringUnits = 103 + RadiansPerSecond EngineeringUnits = 184 + RevolutionsPerMinute EngineeringUnits = 104 + SquareMetersPerNewton EngineeringUnits = 185 + WattsPerMeterPerDegreeKelvin EngineeringUnits = 189 + WattsPerSquareMeterDegreeKelvin EngineeringUnits = 141 + PerMille EngineeringUnits = 207 + GramsPerGram EngineeringUnits = 208 + KilogramsPerKilogram EngineeringUnits = 209 + GramsPerKilogram EngineeringUnits = 210 + MilligramsPerGram EngineeringUnits = 211 + MilligramsPerKilogram EngineeringUnits = 212 + GramsPerMilliliter EngineeringUnits = 213 + GramsPerLiter EngineeringUnits = 214 + MilligramsPerLiter EngineeringUnits = 215 + MicrogramsPerLiter EngineeringUnits = 216 + GramsPerCubicMeter EngineeringUnits = 217 + MilligramsPerCubicMeter EngineeringUnits = 218 + MicrogramsPerCubicMeter EngineeringUnits = 219 + NanogramsPerCubicMeter EngineeringUnits = 220 + GramsPerCubicCentimeter EngineeringUnits = 221 + Becquerels EngineeringUnits = 222 + Kilobecquerels EngineeringUnits = 223 + Megabecquerels EngineeringUnits = 224 + Gray EngineeringUnits = 225 + Milligray EngineeringUnits = 226 + Microgray EngineeringUnits = 227 + Sieverts EngineeringUnits = 228 + Millisieverts EngineeringUnits = 229 + Microsieverts EngineeringUnits = 230 + MicrosievertsPerHour EngineeringUnits = 231 + Millirems EngineeringUnits = 47814 + MilliremsPerHour EngineeringUnits = 47815 + DecibelsA EngineeringUnits = 232 + NephelometricTurbidityUnit EngineeringUnits = 233 + Ph EngineeringUnits = 234 + GramsPerSquareMeter EngineeringUnits = 235 + MinutesPerDegreeKelvin EngineeringUnits = 236 + MeterSquaredPerMeter EngineeringUnits = 237 + AmpereSeconds EngineeringUnits = 238 + VoltAmpereHours EngineeringUnits = 239 + KilovoltAmpereHours EngineeringUnits = 240 + MegavoltAmpereHours EngineeringUnits = 241 + VoltAmpereHoursReactive EngineeringUnits = 242 + KilovoltAmpereHoursReactive EngineeringUnits = 243 + MegavoltAmpereHoursReactive EngineeringUnits = 244 + VoltSquareHours EngineeringUnits = 245 + AmpereSquareHours EngineeringUnits = 246 + JoulePerHours EngineeringUnits = 247 + CubicFeetPerDay EngineeringUnits = 248 + CubicMetersPerDay EngineeringUnits = 249 + WattHoursPerCubicMeter EngineeringUnits = 250 + JoulesPerCubicMeter EngineeringUnits = 251 + MolePercent EngineeringUnits = 252 + PascalSeconds EngineeringUnits = 253 + MillionStandardCubicFeetPerMinute EngineeringUnits = 254 +) + +type EscalatorMode int + +const ( + BacnetescalatorModeUnknown EscalatorMode = iota BacnetescalatorModeStop BACnetEscalatorModeUp BACnetEscalatorModeDown @@ -1092,10 +1092,10 @@ const ( BacnetescalatorModeOutOfService ) -type BACnetEscalatorOperationDirection int +type EscalatorOperationDirection int const ( - BacnetEscalatorOperationDirectionUnknown BACnetEscalatorOperationDirection = iota + BacnetEscalatorOperationDirectionUnknown EscalatorOperationDirection = iota BACnetEscalatorOperationDirectionStopped UpRatedSpeed UpReducedSpeed @@ -1103,25 +1103,25 @@ const ( DownReducedSpeed ) -type BACnetFileAccessMethod int +type FileAccessMethod int const ( - RecordAccess BACnetFileAccessMethod = iota + RecordAccess FileAccessMethod = iota StreamAccess ) -type BACnetIPMode int +type IPMode int const ( - BacnetIPModeNormal BACnetIPMode = iota + BacnetIPModeNormal IPMode = iota Foreign Bbmd ) -type BACnetLifeSafetyMode int +type LifeSafetyMode int const ( - BacnetLifeSafetyModeOff BACnetLifeSafetyMode = iota + BacnetLifeSafetyModeOff LifeSafetyMode = iota Lon Test Manned @@ -1138,10 +1138,10 @@ const ( Default ) -type BACnetLifeSafetyOperation int +type LifeSafetyOperation int const ( - BacnetLifeSafetyOperationNone BACnetLifeSafetyOperation = iota + BacnetLifeSafetyOperationNone LifeSafetyOperation = iota Silence SilenceAudible SilenceVisual @@ -1153,10 +1153,10 @@ const ( UnsilenceVisual ) -type BACnetLifeSafetyState int +type LifeSafetyState int const ( - Quiet BACnetLifeSafetyState = iota + Quiet LifeSafetyState = iota PreAlarm BacnetlifesafetystateAlarm BacnetlifesafetystateFault @@ -1182,10 +1182,10 @@ const ( TestSupervisory ) -type BACnetLiftCarDirection int +type LiftCarDirection int const ( - BacnetliftcardirectionUnknown BACnetLiftCarDirection = iota + BacnetliftcardirectionUnknown LiftCarDirection = iota BacnetliftcardirectionNone Stopped Up @@ -1193,18 +1193,18 @@ const ( UpAndDown ) -type BACnetLiftCarDoorCommand int +type LiftCarDoorCommand int const ( - BACnetLiftCarDoorCommandNone BACnetLiftCarDoorCommand = iota + BACnetLiftCarDoorCommandNone LiftCarDoorCommand = iota Open Close ) -type BACnetLiftCarDriveStatus int +type LiftCarDriveStatus int const ( - BACnetLiftCarDriveStatusUnknown BACnetLiftCarDriveStatus = iota + BACnetLiftCarDriveStatusUnknown LiftCarDriveStatus = iota Stationary Braking Accelerate @@ -1216,10 +1216,10 @@ const ( MultiFloorJump ) -type BACnetLiftCarMode int +type LiftCarMode int const ( - BACnetLiftCarModeUnknown BACnetLiftCarMode = iota + BACnetLiftCarModeUnknown LiftCarMode = iota BACnetLiftCarModeNormal Vip Homing @@ -1235,10 +1235,10 @@ const ( OccupantEvacuation ) -type BACnetLiftFault int +type LiftFault int const ( - ControllerFault BACnetLiftFault = iota + ControllerFault LiftFault = iota DriveAndMotorFault GovernorAndSafetyGearFault LiftShaftDeviceFault @@ -1257,10 +1257,10 @@ const ( LoadMeasurementFault ) -type BACnetLiftGroupMode int +type LiftGroupMode int const ( - BACnetLiftGroupModeUnknown BACnetLiftGroupMode = iota + BACnetLiftGroupModeUnknown LiftGroupMode = iota BACnetLiftGroupModeNormal DownPeak TwoWay @@ -1269,27 +1269,27 @@ const ( UpPeak ) -type BACnetLoggingType int +type LoggingType int const ( - Polled BACnetLoggingType = iota + Polled LoggingType = iota Cov Triggered ) -type BACnetMaintenance int +type Maintenance int const ( - BACnetMaintenanceNone BACnetMaintenance = iota + BACnetMaintenanceNone Maintenance = iota PeriodicTest NeedServiceOperational NeedServiceInoperative ) -type BACnetNetworkPortCommand int +type NetworkPortCommand int const ( - BACnetNetworkPortCommandIdle BACnetNetworkPortCommand = iota + BACnetNetworkPortCommandIdle NetworkPortCommand = iota DiscardChanges RenewFdRegistration RestartSlaveDiscovery @@ -1299,10 +1299,10 @@ const ( RestartPort ) -type BACnetNodeType int +type NodeType int const ( - BACnetNodeTypeUnknown BACnetNodeType = iota + BACnetNodeTypeUnknown NodeType = iota System Network BACnetNodeTypeDevice @@ -1326,10 +1326,10 @@ const ( Zone ) -type BACnetRelationship int +type Relationship int const ( - BACnetRelationshipUnknown BACnetRelationship = iota + BACnetRelationshipUnknown Relationship = iota BACnetRelationshipDefault Contains ContainedBy @@ -1361,10 +1361,10 @@ const ( ReceivesSteam ) -type BACnetReliability int +type Reliability int const ( - NoFaultDetected BACnetReliability = iota + NoFaultDetected Reliability = iota NoSensor OverRange UnderRange @@ -1375,7 +1375,7 @@ const ( ProcessError MultiStateFault ConfigurationError - CommunicationFailure BACnetReliability = iota + 1 + CommunicationFailure Reliability = iota + 1 MemberFault MonitoredObjectFault Tripped @@ -1390,10 +1390,10 @@ const ( ReferencedObjectFault ) -type BACnetRestartReason int +type RestartReason int const ( - BACnetRestartReasonUnknown BACnetRestartReason = iota + BACnetRestartReasonUnknown RestartReason = iota ColdStart WarmStart DetectedPowerLost @@ -1403,10 +1403,10 @@ const ( Suspended ) -type BACnetSecurityLevel int +type SecurityLevel int const ( - Incapable BACnetSecurityLevel = iota + Incapable SecurityLevel = iota Plain Signed Encrypted @@ -1414,43 +1414,43 @@ const ( EncryptedEndToEnd ) -type BACnetPolarity int +type Polarity int const ( - BACnetPolarityNormal BACnetPolarity = iota + BACnetPolarityNormal Polarity = iota BACnetPolarityReverse ) -type BACnetProtocolLevel int +type ProtocolLevel int const ( - Physical BACnetProtocolLevel = iota + Physical ProtocolLevel = iota BACnetProtocolLevelProtocol BACnetApplication NonBACnetApplication ) -type BACnetSilencedState int +type SilencedState int const ( - Unsilenced BACnetSilencedState = iota + Unsilenced SilencedState = iota AudibleSilenced VisibleSilenced AllSilenced ) -type BACnetTimerState int +type TimerState int const ( - BACnetTimerStateIdle BACnetTimerState = iota + BACnetTimerStateIdle TimerState = iota Running Expired ) -type BACnetTimerTransition int +type TimerTransition int const ( - BACnetTimerTransitionNone BACnetTimerTransition = iota + BACnetTimerTransitionNone TimerTransition = iota IdleToRunning RunningToIdle RunningToRunning @@ -1460,10 +1460,10 @@ const ( ExpiredToRunning ) -type BACnetVTClass int +type VTClass int const ( - DefaultTerminal BACnetVTClass = iota + DefaultTerminal VTClass = iota ANSI_X3_64 DEC_VT52 DEC_VT100 @@ -1472,10 +1472,10 @@ const ( IBM_3130 ) -type BACnetAccessEvent int +type AccessEvent int const ( - BACnetAccessEventNone BACnetAccessEvent = iota + BACnetAccessEventNone AccessEvent = iota Granted Muster PassbackDetected @@ -1492,7 +1492,7 @@ const ( BACnetAccessEventAuthorizationDelayed BACnetAccessEventVerificationRequired NoEntryAfterGrant - DeniedDenyAll BACnetAccessEvent = iota + 111 + DeniedDenyAll AccessEvent = iota + 111 DeniedUnknownCredential DeniedAuthenticationUnavailable DeniedAuthenticationFactorTimeout @@ -1531,20 +1531,20 @@ const ( DeniedOther ) -type BACnetLightingInProgress int +type LightingInProgress int const ( - BACnetLightingInProgressIdle BACnetLightingInProgress = iota + BACnetLightingInProgressIdle LightingInProgress = iota FadeActive RampActive NotControlled BACnetLightingInProgressOther ) -type BACnetLightingOperation int +type LightingOperation int const ( - BACnetLightingOperationNone BACnetLightingOperation = iota + BACnetLightingOperationNone LightingOperation = iota FadeTo RampTo StepUp @@ -1557,28 +1557,28 @@ const ( BACnetLightingOperationStop ) -type BACnetLightingTransition int +type LightingTransition int const ( - BACnetLightingTransitionNone BACnetLightingTransition = iota + BACnetLightingTransitionNone LightingTransition = iota Fade Ramp ) -type BACnetLockStatus int +type LockStatus int const ( - Locked BACnetLockStatus = iota + Locked LockStatus = iota Unlocked LockFault Unused BACnetLockStatusUnknown ) -type BACnetEscalatorFault int +type EscalatorFault int const ( - BACnetescalatorfaultControllerFault BACnetEscalatorFault = iota + BACnetescalatorfaultControllerFault EscalatorFault = iota BACnetescalatorfaultDriveAndMotorFault MechanicalComponentFault OverspeedFault @@ -1589,7 +1589,7 @@ const ( CombPlateFault ) -type BACnetProgramError int +type ProgramError int const ( BACnetProgramErrorNormal = iota @@ -1599,7 +1599,7 @@ const ( BACnetProgramErrorOther ) -type BACnetProgramRequest int +type ProgramRequest int const ( BACnetProgramRequestReady = iota @@ -1610,10 +1610,10 @@ const ( Unload ) -type BACnetProgramState int +type ProgramState int const ( - BACnetProgramStateIdle BACnetProgramState = iota + BACnetProgramStateIdle ProgramState = iota Loading BACnetProgramStateRunning Waiting @@ -1621,19 +1621,19 @@ const ( Unloading ) -type BACnetShedState int +type ShedState int const ( - BACnetShedStateInactive BACnetShedState = iota + BACnetShedStateInactive ShedState = iota RequestPending Compliant NonCompliant ) -type BACnetWriteStatus int +type WriteStatus int const ( - BACnetWriteStatusIdle BACnetWriteStatus = iota + BACnetWriteStatusIdle WriteStatus = iota BACnetWriteStatusInProgress Successful Failed @@ -1649,187 +1649,187 @@ func DecodeEnumerated(buffer []byte, offset int, lenValue uint32, objType *Objec if propID != nil { switch *propID { case SegmentationSupported: - val = BACnetSegmentation(value) + val = Segmentation(value) case PropertyList: val = PropertyIdentifier(value) - case EventType: - val = BACnetEventType(value) - case NotifyType: - val = BACnetNotifyType(value) - case FaultType: - val = BACnetFaultType(value) - case EventState: - val = BACnetEventState(value) + case PropertyIdentifierEventType: + val = EventType(value) + case PropertyIdentifierNotifyType: + val = NotifyType(value) + case PropertyIdentifierFaultType: + val = FaultType(value) + case PropertyIdentifierEventState: + val = EventState(value) case ObjectTypePI: val = ObjectType(value) case ReasonForDisable: - val = BACnetAccessCredentialDisableReason(value) + val = AccessCredentialDisableReason(value) case CredentialDisable: - val = BACnetAccessCredentialDisable(value) + val = AccessCredentialDisable(value) case PassbackMode: - val = BACnetAccessPassbackMode(value) + val = AccessPassbackMode(value) case UserType: - val = BACnetAccessUserType(value) - case NetworkNumberQuality: - val = BACnetNetworkNumberQuality(value) + val = AccessUserType(value) + case PropertyIdentifierNetworkNumberQuality: + val = NetworkNumberQuality(value) case OccupancyState: - val = BACnetAccessZoneOccupancyState(value) - case Action: + val = AccessZoneOccupancyState(value) + case PropertyIdentifierAction: if *objType == Loop { - val = BACnetAction(value) + val = Action(value) } case PresentValue, AlarmValue, FeedbackValue, RelinquishDefault: switch *objType { case BinaryInput, BinaryOutput, BinaryValue: - val = BACnetBinaryPV(value) + val = BinaryPV(value) case AccessDoor: - val = BACnetDoorValue(value) + val = DoorValue(value) case LifeSafetyPoint, LifeSafetyZone: - val = BACnetLifeSafetyState(value) + val = LifeSafetyState(value) case LightingOutput: - val = BACnetBinaryLightingPV(value) + val = BinaryLightingPV(value) case LoadControl: - val = BACnetShedState(value) + val = ShedState(value) } - case AuthenticationStatus: - val = BACnetAuthenticationStatus(value) + case PropertyIdentifierAuthenticationStatus: + val = AuthenticationStatus(value) case AuthorizationExemptions: - val = BACnetAuthorizationExemption(value) - case AuthorizationMode: - val = BACnetAuthorizationMode(value) + val = AuthorizationExemption(value) + case PropertyIdentifierAuthorizationMode: + val = AuthorizationMode(value) case BackupAndRestoreState: - val = BACnetBackupState(value) + val = BackupState(value) case SystemStatus: - val = BACnetDeviceStatus(value) + val = DeviceStatus(value) case SecuredStatus: - val = BACnetDoorSecuredStatus(value) - case DoorStatus, CarDoorStatus: - val = BACnetDoorStatus(value) + val = DoorSecuredStatus(value) + case PropertyIdentifierDoorStatus, CarDoorStatus: + val = DoorStatus(value) case Units, CarLoadUnits: - val = BACnetEngineeringUnits(value) - case EscalatorMode: - val = BACnetEscalatorMode(value) + val = EngineeringUnits(value) + case PropertyIdentifierEscalatorMode: + val = EscalatorMode(value) case OperationDirection: - val = BACnetEscalatorOperationDirection(value) - case FileAccessMethod: - val = BACnetFileAccessMethod(value) + val = EscalatorOperationDirection(value) + case PropertyIdentifierFileAccessMethod: + val = FileAccessMethod(value) case OperationExpected: - val = BACnetLifeSafetyOperation(value) + val = LifeSafetyOperation(value) case CarDoorCommand: - val = BACnetLiftCarDoorCommand(value) + val = LiftCarDoorCommand(value) case CarDriveStatus: - val = BACnetLiftCarDriveStatus(value) + val = LiftCarDriveStatus(value) case CarMode: - val = BACnetLiftCarMode(value) + val = LiftCarMode(value) case GroupMode: - val = BACnetLiftGroupMode(value) - case LoggingType: - val = BACnetLoggingType(value) - case Reliability: - val = BACnetReliability(value) + val = LiftGroupMode(value) + case PropertyIdentifierLoggingType: + val = LoggingType(value) + case PropertyIdentifierReliability: + val = Reliability(value) case LastRestartReason: - val = BACnetRestartReason(value) - case NetworkType: - val = BACnetNetworkType(value) + val = RestartReason(value) + case PropertyIdentifierNetworkType: + val = NetworkType(value) case BaseDeviceSecurityPolicy: - val = BACnetSecurityLevel(value) + val = SecurityLevel(value) case CarMovingDirection, CarAssignedDirection: - val = BACnetLiftCarDirection(value) + val = LiftCarDirection(value) case BacnetIpMode, BacnetIpv6Mode: - val = BACnetIPMode(value) + val = IPMode(value) case MaintenanceRequired: - val = BACnetMaintenance(value) - case Polarity: - val = BACnetPolarity(value) - case ProtocolLevel: - val = BACnetProtocolLevel(value) + val = Maintenance(value) + case PropertyIdentifierPolarity: + val = Polarity(value) + case PropertyIdentifierProtocolLevel: + val = ProtocolLevel(value) case Silenced: - val = BACnetSilencedState(value) - case AccessEvent, AccessAlarmEvents, AccessTransactionEvents, FailedAttemptEvents: + val = SilencedState(value) + case PropertyIdentifierAccessEvent, AccessAlarmEvents, AccessTransactionEvents, FailedAttemptEvents: if *objType == AccessPoint { - val = BACnetAccessEvent(value) + val = AccessEvent(value) } case LastAccessEvent: if *objType == AccessCredential { - val = BACnetAccessEvent(value) + val = AccessEvent(value) } case CredentialStatus: if *objType == AccessCredential { - val = BACnetBinaryPV(value) + val = BinaryPV(value) } - case LockStatus: + case PropertyIdentifierLockStatus: if *objType == AccessDoor { - val = BACnetLockStatus(value) + val = LockStatus(value) } - case DoorAlarmState, MaskedAlarmValues, AlarmValues, FaultValues: + case PropertyIdentifierDoorAlarmState, MaskedAlarmValues, AlarmValues, FaultValues: switch *objType { case AccessDoor: - val = BACnetDoorAlarmState(value) + val = DoorAlarmState(value) case LifeSafetyPoint, LifeSafetyZone: - val = BACnetLifeSafetyState(value) + val = LifeSafetyState(value) case Timer: - val = BACnetTimerState(value) + val = TimerState(value) } case Mode, AcceptedModes: if *objType == LifeSafetyPoint || *objType == LifeSafetyZone { - val = BACnetLifeSafetyMode(value) + val = LifeSafetyMode(value) } case TrackingValue, LifeSafetyAlarmValues: if *objType == LifeSafetyPoint || *objType == LifeSafetyZone { - val = BACnetLifeSafetyState(value) + val = LifeSafetyState(value) } case FaultSignals: switch *objType { case Escalator: - val = BACnetEscalatorFault(value) + val = EscalatorFault(value) case Lift: - val = BACnetLiftFault(value) + val = LiftFault(value) } case InProgress: if *objType == LightingOutput { - val = BACnetLightingInProgress(value) + val = LightingInProgress(value) } case Transition: if *objType == LightingOutput { - val = BACnetLightingTransition(value) + val = LightingTransition(value) } case Command: if *objType == NetworkPort { - val = BACnetNetworkPortCommand(value) + val = NetworkPortCommand(value) } - case NodeType, SubordinateNodeTypes: + case PropertyIdentifierNodeType, SubordinateNodeTypes: if *objType == StructuredView { - val = BACnetNodeType(value) + val = NodeType(value) } case SubordinateRelationships, DefaultSubordinateRelationship: if *objType == StructuredView { - val = BACnetRelationship(value) + val = Relationship(value) } case ReasonForHalt: if *objType == Program { - val = BACnetProgramError(value) + val = ProgramError(value) } case ProgramChange: if *objType == Program { - val = BACnetProgramRequest(value) + val = ProgramRequest(value) } - case ProgramState: + case PropertyIdentifierProgramState: if *objType == Program { - val = BACnetProgramState(value) + val = ProgramState(value) } - case TimerState: + case PropertyIdentifierTimerState: if *objType == Timer { - val = BACnetTimerState(value) + val = TimerState(value) } case LastStateChange: if *objType == Timer { - val = BACnetTimerTransition(value) + val = TimerTransition(value) } case VtClassesSupported: - val = BACnetVTClass(value) - case WriteStatus: + val = VTClass(value) + case PropertyIdentifierWriteStatus: if *objType == Channel { - val = BACnetWriteStatus(value) + val = WriteStatus(value) } default: val = VendorSpecificValue(value) diff --git a/pkg/transport/udp/broadcast.go b/pkg/transport/udp/broadcast.go index 56db012..91031b4 100644 --- a/pkg/transport/udp/broadcast.go +++ b/pkg/transport/udp/broadcast.go @@ -11,17 +11,17 @@ import ( const globalBroadcast = "255.255.255.255" // GetBroadcasrAddress returns the broadcast address given the local address and port. -func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, error) { +func GetBroadcastAddress(localEndpoint string, port int) (bacnet.Address, error) { broadcast := globalBroadcast interfaces, err := net.Interfaces() if err != nil { - return bacnet.BACnetAddress{}, err + return bacnet.Address{}, err } for _, iface := range interfaces { addrs, err := iface.Addrs() if err != nil { - return bacnet.BACnetAddress{}, err + return bacnet.Address{}, err } for _, addr := range addrs { @@ -36,6 +36,6 @@ func GetBroadcastAddress(localEndpoint string, port int) (bacnet.BACnetAddress, } } netType := encoding.IPV4 - return *bacnet.NewBACnetAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil + return *bacnet.NewAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil } From b64c033c24d0876e7b408a7500ef61d6797002fa Mon Sep 17 00:00:00 2001 From: SammyOina Date: Wed, 20 Sep 2023 21:29:26 +0300 Subject: [PATCH 23/24] Fix address creation in readProperty and whois.go - Fix address creation in readProperty.go and whois.go to pass the correct parameters to the bacnet.NewAddress function. - In readProperty.go, change `bacnet.NewAddress(0, nil, "127.0.0.6:47809", &netType)` to `bacnet.NewAddress(0, nil, "127.0.0.6:47809", &netType)`. - In whois.go, change `*bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType)` to `bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType)`. This commit fixes the address creation in the readProperty and whois.go files by passing the correct parameters to the bacnet.NewAddress function. Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 2 +- example/whoIs/whois.go | 2 +- pkg/bacnet/network.go | 4 ++-- pkg/bacnet/npdu.go | 8 ++++---- pkg/transport/udp/broadcast.go | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go index e8ffacd..f7ce431 100644 --- a/example/readProperty/readProperty.go +++ b/example/readProperty/readProperty.go @@ -14,7 +14,7 @@ import ( func main() { netType := encoding.IPV4 destination := bacnet.NewAddress(0, nil, "127.0.0.6:47809", &netType) - npdu := bacnet.NewNPDU(destination, nil, nil, nil) + npdu := bacnet.NewNPDU(&destination, nil, nil, nil) npdu.Control.SetDataExpectingReply(true) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) diff --git a/example/whoIs/whois.go b/example/whoIs/whois.go index 9cc4e48..aa8abad 100644 --- a/example/whoIs/whois.go +++ b/example/whoIs/whois.go @@ -21,7 +21,7 @@ func main() { whoisBytes := req.Encode() netType := encoding.IPV4 - broads := *bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) + broads := bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) npdu := bacnet.NewNPDU(&broads, nil, nil, nil) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) diff --git a/pkg/bacnet/network.go b/pkg/bacnet/network.go index 9db460e..b5a98a2 100644 --- a/pkg/bacnet/network.go +++ b/pkg/bacnet/network.go @@ -44,8 +44,8 @@ type Address struct { MacAddress []byte } -func NewAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *encoding.NetworkType) *Address { - addr := &Address{ +func NewAddress(networkNumber uint32, macAddress []byte, address interface{}, netType *encoding.NetworkType) Address { + addr := Address{ NetworkNumber: networkNumber, MacAddress: macAddress, } diff --git a/pkg/bacnet/npdu.go b/pkg/bacnet/npdu.go index be94b91..f1277fc 100644 --- a/pkg/bacnet/npdu.go +++ b/pkg/bacnet/npdu.go @@ -14,11 +14,11 @@ type NPDU struct { DNET uint16 DLEN uint8 DADR []byte - Destination *Address + Destination Address SNET uint16 SLEN uint8 SADR []byte - Source *Address + Source Address MessageType byte HopCount byte VendorID uint16 @@ -155,8 +155,8 @@ func NewNPDU(destination *Address, source *Address, hopCount *uint8, vendorID *u npdu := &NPDU{ Version: 1, Control: *NewNPDUControlInformation(), - Destination: destination, - Source: source, + Destination: *destination, + Source: *source, } switch hopCount { case nil: diff --git a/pkg/transport/udp/broadcast.go b/pkg/transport/udp/broadcast.go index 91031b4..90c1941 100644 --- a/pkg/transport/udp/broadcast.go +++ b/pkg/transport/udp/broadcast.go @@ -10,7 +10,7 @@ import ( const globalBroadcast = "255.255.255.255" -// GetBroadcasrAddress returns the broadcast address given the local address and port. +// GetBroadcastAddress returns the broadcast address given the local address and port. func GetBroadcastAddress(localEndpoint string, port int) (bacnet.Address, error) { broadcast := globalBroadcast interfaces, err := net.Interfaces() @@ -36,6 +36,6 @@ func GetBroadcastAddress(localEndpoint string, port int) (bacnet.Address, error) } } netType := encoding.IPV4 - return *bacnet.NewAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil + return bacnet.NewAddress(0xFFFF, nil, broadcast+":"+strconv.Itoa(port), &netType), nil } From c9cc370230dc827f00b6fd77b10be7d9bac786f5 Mon Sep 17 00:00:00 2001 From: SammyOina Date: Fri, 29 Sep 2023 13:04:30 +0300 Subject: [PATCH 24/24] address comments Signed-off-by: SammyOina --- example/readProperty/readProperty.go | 13 ++++++------- example/whoIs/whois.go | 17 ++++++++--------- internal/bitarray.go | 6 +++--- pkg/bacnet/apdu.go | 23 ++++++++++++++++------- pkg/bacnet/bvlc.go | 5 ++++- pkg/encoding/encoding.go | 24 ++++++++++++------------ 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/example/readProperty/readProperty.go b/example/readProperty/readProperty.go index f7ce431..c68734c 100644 --- a/example/readProperty/readProperty.go +++ b/example/readProperty/readProperty.go @@ -12,8 +12,10 @@ import ( ) func main() { + serverIp := "127.0.0.6:47809" + serverLocalAddr := "127.0.0.1:0" netType := encoding.IPV4 - destination := bacnet.NewAddress(0, nil, "127.0.0.6:47809", &netType) + destination := bacnet.NewAddress(0, nil, serverIp, &netType) npdu := bacnet.NewNPDU(&destination, nil, nil, nil) npdu.Control.SetDataExpectingReply(true) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) @@ -51,14 +53,13 @@ func main() { blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) message := append(blvcBytes, mes...) - // Define the BACnet broadcast address (255.255.255.255:47808) - remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") + remoteAddr, err := net.ResolveUDPAddr("udp", serverIp) if err != nil { fmt.Println("Error resolving remote address:", err) return } - localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") + localAddr, err := net.ResolveUDPAddr("udp", serverLocalAddr) if err != nil { fmt.Println("Error: ", err) return @@ -72,7 +73,6 @@ func main() { } defer conn.Close() - // Send the WhoIsRequest packet _, err = conn.Write(message) if err != nil { log.Fatal("Error sending WhoIsRequest:", err) @@ -94,9 +94,8 @@ func main() { break } - // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] - blvc := bacnet.BVLC{BVLLTypeBACnetIP: 0x81} + blvc := bacnet.BVLC{BVLLTypeBACnetIP: blvc.BVLLTypeBACnetIP} headerLength, function, msgLength, err := blvc.Decode(response, 0) if err != nil { log.Fatal(err) diff --git a/example/whoIs/whois.go b/example/whoIs/whois.go index aa8abad..bc77856 100644 --- a/example/whoIs/whois.go +++ b/example/whoIs/whois.go @@ -12,6 +12,8 @@ import ( ) func main() { + serverIp := "127.0.0.6:47809" + serverLocalAddr := "127.0.0.1:0" var highLimit, lowLimit uint32 = 4000000, 0 req := bacnet.WhoIs{ @@ -21,7 +23,7 @@ func main() { whoisBytes := req.Encode() netType := encoding.IPV4 - broads := bacnet.NewAddress(0xFFFF, nil, "127.0.0.255:47809", &netType) + broads := bacnet.NewAddress(encoding.MaxUint16-1, nil, serverIp, &netType) npdu := bacnet.NewNPDU(&broads, nil, nil, nil) npdu.Control.SetNetworkPriority(bacnet.NormalMessage) @@ -47,29 +49,27 @@ func main() { if err != nil { log.Fatal(err) } - blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+4)) + + blvcBytes := blvc.Encode(bacnet.BVLCOriginalBroadcastNPDU, uint16(len(mes)+int(blvc.BVLCHeaderLength))) message := append(blvcBytes, mes...) - // Define the BACnet broadcast address (255.255.255.255:47808) - remoteAddr, err := net.ResolveUDPAddr("udp", "127.0.0.6:47809") + remoteAddr, err := net.ResolveUDPAddr("udp", serverIp) if err != nil { log.Fatal("Error resolving remote address:", err) } - localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") + localAddr, err := net.ResolveUDPAddr("udp", serverLocalAddr) if err != nil { log.Fatal("Error: ", err) return } - // Create a UDP connectionBACnetAddress conn, err := net.DialUDP("udp", localAddr, remoteAddr) if err != nil { log.Fatal("Error creating UDP connection:", err) } defer conn.Close() - // Send the WhoIsRequest packet _, err = conn.Write(message) if err != nil { log.Fatal("Error sending WhoIsRequest:", err) @@ -91,10 +91,9 @@ func main() { break } - // Process the response (you'll need to parse BACnet responses here) response := buffer[:n] log.Printf("Received response: %X\n", response) - blvc := bacnet.BVLC{BVLLTypeBACnetIP: 0x81} + blvc := bacnet.BVLC{BVLLTypeBACnetIP: blvc.BVLLTypeBACnetIP} headerLength, function, msgLength, err := blvc.Decode(response, 0) if err != nil { log.Fatal(err) diff --git a/internal/bitarray.go b/internal/bitarray.go index b844815..0054b2b 100644 --- a/internal/bitarray.go +++ b/internal/bitarray.go @@ -45,9 +45,9 @@ func (ba *BitArray) ToByte() (byte, error) { } var byteValue byte - for j := 0; j < 8; j++ { - if ba.bits[j] { - byteValue |= 1 << uint(7-j) + for i := 0; i < 8; i++ { + if ba.bits[i] { + byteValue |= 1 << uint(7-i) } } diff --git a/pkg/bacnet/apdu.go b/pkg/bacnet/apdu.go index 190bb95..f5a0523 100644 --- a/pkg/bacnet/apdu.go +++ b/pkg/bacnet/apdu.go @@ -2,12 +2,21 @@ package bacnet import "errors" +// errUnknownPDU is an error returned when an unknown PDU type is encountered. var errUnknownPDU = errors.New("unkown PDU type") +// BACnetConfirmedServiceChoice represents BACnet confirmed service choices. type BACnetConfirmedServiceChoice int +// BACnetUnconfirmedServiceChoice represents BACnet unconfirmed service choices. type BACnetUnconfirmedServiceChoice int +const ( + segmentedMessageMask = 0x10 + moreFollowsMask = 0x20 + segmentedResponseAcceptedMask = 0x40 +) + const ( // Alarm and Event Services AcknowledgeAlarm BACnetConfirmedServiceChoice = 0 @@ -87,13 +96,13 @@ func (a APDU) Encode() ([]byte, error) { tmp := byte(a.PduType) if a.SegmentedMessage { - tmp |= 0x10 + tmp |= segmentedMessageMask } if a.MoreFollows { - tmp |= 0x20 + tmp |= moreFollowsMask } if a.SegmentedResponseAccepted { - tmp |= 0x40 + tmp |= segmentedResponseAcceptedMask } switch a.PduType { @@ -131,9 +140,9 @@ func (a *APDU) Decode(buffer []byte, offset int) (int, error) { switch a.PduType { case PDUTypeConfirmedServiceRequest: - a.SegmentedMessage = tmp&0x10 != 0 - a.MoreFollows = tmp&0x20 != 0 - a.SegmentedResponseAccepted = tmp&0x40 != 0 + a.SegmentedMessage = tmp&segmentedMessageMask != 0 + a.MoreFollows = tmp&moreFollowsMask != 0 + a.SegmentedResponseAccepted = tmp&segmentedResponseAcceptedMask != 0 a.MaxSegmentsAccepted = MaxSegments(buffer[offset+length] & 0xF0) a.MaxApduLengthAccepted = MaxAPDU(buffer[offset+length] & 0x0F) length++ @@ -156,7 +165,7 @@ func (a *APDU) Decode(buffer []byte, offset int) (int, error) { a.ServiceChoice = buffer[offset+length] length++ case PDUTypeComplexAck: - a.SegmentedMessage = tmp&0x10 != 0 + a.SegmentedMessage = tmp&segmentedMessageMask != 0 a.InvokeID = buffer[offset+length] length++ a.ServiceChoice = buffer[offset+length] diff --git a/pkg/bacnet/bvlc.go b/pkg/bacnet/bvlc.go index 80f57a6..f3b8794 100644 --- a/pkg/bacnet/bvlc.go +++ b/pkg/bacnet/bvlc.go @@ -43,6 +43,9 @@ const ( MaxAPDU1476 ) +// BVLL for BACnet/IPv4 +const BVLLTypeBACnetIP = 0x81 + // BACnet Virtual Link Control type BVLC struct { BVLLTypeBACnetIP byte @@ -53,7 +56,7 @@ type BVLC struct { // NewBVLC creates a new BVLC with the given transport. func NewBVLC(transprt transport.Transport) (*BVLC, error) { bvlc := &BVLC{ - BVLLTypeBACnetIP: 0x81, + BVLLTypeBACnetIP: BVLLTypeBACnetIP, BVLCHeaderLength: 4, } diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index 9b7b910..6c19d8c 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -15,22 +15,22 @@ const ( NoPriority = 0 MinPriority = 1 MaxPriority = 16 - maxUint8 = 0x100 - maxUint16 = 0x10000 - maxUint24 = 0x1000000 + MaxUint8 = 0x100 + MaxUint16 = 0x10000 + MaxUint24 = 0x1000000 ) func EncodeUnsigned(value uint32) []byte { switch { - case value < maxUint8: + case value < MaxUint8: buf := make([]byte, 1) buf[0] = uint8(value) return buf - case value < maxUint16: + case value < MaxUint16: buf := make([]byte, 2) binary.BigEndian.PutUint16(buf, uint16(value)) return buf - case value < maxUint24: + case value < MaxUint24: buf := make([]byte, 3) buf[0] = byte((value & 0xff0000) >> 16) buf[1] = byte((value & 0x00ff00) >> 8) @@ -45,15 +45,15 @@ func EncodeUnsigned(value uint32) []byte { func EncodeSigned(value int32) []byte { switch { - case value < maxUint8: + case value < MaxUint8: buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, uint8(value)) return buf.Bytes() - case value < maxUint16: + case value < MaxUint16: buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, uint16(value)) return buf.Bytes() - case value < maxUint24: + case value < MaxUint24: buf := make([]byte, 3) buf[0] = byte((value & 0xff0000) >> 16) buf[1] = byte((value & 0x00ff00) >> 8) @@ -69,11 +69,11 @@ func EncodeSigned(value int32) []byte { func EncodeContextUnsigned(tagNum BACnetApplicationTag, val uint32) []byte { len := 0 switch { - case val < maxUint8: + case val < MaxUint8: len = 1 - case val < maxUint16: + case val < MaxUint16: len = 2 - case val < maxUint24: + case val < MaxUint24: len = 3 default: len = 4