Data Types
In the automation interface and via ADS complex properties are coded as byte arrays. This section explains how the BACnet data concepts are mapped to C data structures within TwinCAT BACnet/IP, and how they can be used during configuration via the automation interface or ADS. Section 21 of the BACnet standard ("FORMAL DESCRIPTION OF APPLICATION PROTOCOL DATA UNITS") specifies the BACnet data structures.
Apart from a few exceptions, the mapping from BACnet to C is based on the BACnet specification. Exceptions are dynamic data, which are mapped to lists or AnyTypes. The type of a property can generally be determined with the aid of the TwinCAT System Manager. The data type of each property, including the structure (by expanding the property data), can be seen in the Type column in the Settings and Online tabs. Data type names in the Type column ending in "[]" are arrays, names ending in List are lists. Choice-based data types can be recognised by the selection combo box in the Type column, data types with optional fields by a checkbox in the ID field.
Primitive data types
0 = zero | Mapped through a data length of 0. |
1 = Boolean | Mapped to ULONG (4 bytes) with the values 0x00000001 for TRUE and 0x00000000 for FALSE |
2 = Unsigned Integer | Mapped to ULONG (4 bytes). An optimised variant can be used, whereby integer values up to 255 are shown as 1 byte and integer values up to 65535 as 2 bytes (USHORT). |
3 = Signed Integer | Mapped to LONG (4 bytes) |
4 = Real | Mapped to FLOAT (4 bytes) |
5 = Double | Currently not used |
6 = Octet String | Mapped to BYTE[] |
7 = Character String | Mapped to CHAR[]. I.e. 0-terminated ISO 8859-1 strings. Currently TwinCAT BACnet/IP supports strings of length 256. |
8 = Bit String | Mapped to BYTE[]. The highest-value (most significant) byte contains the number of bits that are not used in the following byte ( 0..7 ). The highest-value bit of the subsequent byte contains the first Boolean value. Apart from a few exceptions, bit strings have a length of 2 bytes. |
9 = Enumerated | Mapped to C enumerations ( 4 bytes ), starting from 0. |
10 = Date | Mapped to: struct BACnetDate |
11 = Time | Mapped to: struct BACnetTime |
12 = BACnetObjectIdentifier | Mapped to a 4-byte ObjektIdentifier with 10 bits for the object type and a 22-bit object instance struct BACnetObjectIdentifier |
Structures
BACnet sequences without optional fields are mapped to structures. An example is shown below.
BACnetPrescale ::= | struct BACnetPrescale |
Optional fields
BACnet sequences with optional fields are mapped to structures with an additional field validFields. The additional field indicates which fields are active in the structure. Bit 0 of validFields indicates whether the next field (ObjectIdentifier in the example) is active. For non-optional fields the respective bit always must be set.
BACnetObjectPropertyReference ::= SEQUENCE | struct BACnetObjectPropertyReference |
Choice
A BACnet choice is mapped to a structure with the field choiceField and a union. The choiceField determines which field of the union is active. The length of the data is determined by the largest field of the union. The choiceField is an enumeration (4 bytes).
BACnetRecipient ::= | enum BACnetRecipient_Choice |
Arrays
BACnet arrays with fixed data sizes are mapped to C arrays. Some BACnet arrays may contain data of variable length (lists or AnyTypes). In this case BACnet arrays are mapped to lists, as described in the following section.
Lists
BACnet lists and some BACnet arrays are mapped to a special list structure. Each list element has a header (ListEntryHdr), followed immediately by the element data. The highest bit of nEntrySize (nEntrySize & 0x80000000) indicates whether a further element follows ( bit 31 = 1 ), or whether it is the last list element (bit 31 = 0). The size of the subsequent data is coded in the lower 31 bit of nEntrySize as the number of bytes. The header contains a further internally used reserved field, followed by the data. The following list element starts at a 4-byte-aligned boundary, which follows the data.
struct
_ListEntryHdr
{
DWORD nEntrySize;
DWORD reserved;
}
For example, if a list contains a first element of length 1 with value 1, the list is coded as follows: 08 00 00 01 00 00 00 00 01, followed by 3 alignment bytes 00 00 00. If the next list element is the last element of the list with 1 byte of data with the value 3: 00 00 00 01 00 00 00 00 03. The data length of the example list would be 24 bytes since the last element is followed by 3 alignment bytes.
An empty list is coded as (4 bytes): 00 00 00 00.
AnyTypes
BACnet data of type ABSTRACT-SYNTAX.&Type are mapped through the structure AnyType. The field nSize contains the size of the following data, including the field dataType (4 bytes). The actual data therefore have the size nSize-4. The field dataType indicates the data type of the data element. A list of data types is provided below.
struct
AnyType
{
ULONG nSize;
BACnetDataTypes dataType; //... Data
}
The data type codings used for AnyTypes are listed below:
#define ARRAYTYPE 0x100
#define LISTTYPE 0x200
enum BACnet DataTypes
{
// Primitive Data
DataTypeNull = 0,
DataTypeBool = 1,
DataTypeCharacterStringExt = 2,
DataTypeUnsignedInteger = 3,
DataTypeSignedInteger = 4,
DataTypeReal = 5,
DataTypeDouble = 6,
DataTypeOctetString = 7,
DataTypeEnumerated = 8,
DataTypeBACnetObjectIdentifier = 9,
DataTypeAddressBinding = 10,
DataTypeBitString = 11,
DataTypeDate = 12,
DataTypeTime = 13,
// Complex Data
DataTypeDateTime = 14,
DataTypeArrayIndex = 15,
DataTypeBACnetCalendarEntry = 16,
DataTypeBACnetObjectType = 17,
DataTypeBACnetEventTransitionBits = 18,
DataTypeBACnetStatusFlags = 20,
DataTypeBACnetEventState = 21,
DataTypeBACnetReliability = 22,
DataTypeBACnetPolarity = 23,
DataTypeBACnetDateTime = 24,
DataTypeBACnetEngineeringUnits = 25,
DataTypeBACnetPriorityValue = 26,
DataTypeBACnetLimitEnable = 27,
DataTypeBACnetNotifyType = 29,
DataTypeBACnetTimeStamp = 30,
DataTypeBACnetDeviceObjectPropertyReference = 31,
DataTypeBACnetDeviceStatus = 32,
DataTypeBACnetServicesSupported = 33,
DataTypeBACnetObjectTypesSupported = 34,
DataTypeBACnetSegmentation = 35,
DataTypeBACnetVTClass = 36,
DataTypeBACnetVTSession = 37,
DataTypeBACnetSessionKey = 38,
DataTypeBACnetRecipient = 39,
DataTypeBACnetAddressBinding = 40,
DataTypeBACnetCOVSubscription = 41,
DataTypeBACnetEventType = 42,
DataTypeBACnetEventParameter = 43,
DataTypeBACnetFileAccessMethod = 44,
DataTypeReadAccessSpecification = 45,
DataTypeReadAccessResult = 46,
DataTypeBACnetObjectPropertyReference = 47,
DataTypeBACnetSetpointReference = 48,
DataTypeBACnetDestination = 49,
DataTypeBACnetProgramState = 50,
DataTypeBACnetProgramRequest = 51,
DataTypeBACnetProgramError = 52,
DataTypeBACnetDateRange = 53,
DataTypeBACnetDailySchedule = 54,
DataTypeBACnetSpecialEvent = 55,
DataTypeBACnetClientCOV = 56,
DataTypeBACnetLogRecord = 57,
DataTypeBACnetLifeSafetyState = 58,
DataTypeBACnetLifeSafetyMode = 59,
DataTypeBACnetSilencedState = 60,
DataTypeBACnetLifeSafetyOperation = 61,
DataTypeBACnetBinaryPV = 62,
DataTypeBACnetDaysOfWeek = 63,
DataTypeBACnetWeekNDay = 64,
DataTypeBACnetTimeValue = 65,
DataTypeBACnetValue = 66,
DataTypeBACnetAddress = 67,
DataTypeBACnetPropertyIdentifier = 68,
DataTypeEnumerationValueType = 69,
DataTypeBitFieldBit = 70,
DataTypeBACnetLogDatum = 71,
DataTypeAnyType = 72,
DataTypePresentValue = 73,
DataTypeContextTag = 74,
DataTypeValueChoice = 75,
DataTypeBACnetLogStatus = 76,
DataTypeBACnetRecipientProcess = 77,
DataTypeSubscribeCOVPropertyRequest = 78,
DataTypeBACnetPropertyReference = 79,
DataTypeBACnetPropertyResult = 80,
DataTypeBACnetDeviceObjectPropertyValue = 81,
DataTypeCOVNotificationRequest = 82,
DataTypeEventNotificationRequest = 83,
DataTypeBACnetNotificationParameters = 84,
DataTypeChange_of_Bitstring = 85,
DataTypeChange_of_State=86,
DataTypeChange_of_Value=87,
DataTypeCommand_failure=88,
DataTypeFloating_limit=89,
DataTypeOut_of_Range =90,
DataTypeBACnetPropertyValue=91,
DataTypeComplex_Tag=92,
DataTypeChange_of_life_safety = 93,
DataTypeExtended=94,
DataTypeBuffer_ready =95,
DataTypeUnsigned_range = 96,
DataTypeBACnetPropertyResultValue = 97,
DataTypeServiceCOVPropSubscription = 98,
DataTypeServiceCOVSubscription = 99,
DataTypeCOVNotification = 100,
DataTypeAcknowledgeAlarmRequest = 101,
DataTypeBACnetVTOpenRequest = 102,
DataTypeBACnetPrescale = 103,
DataTypeBACnetScale = 104,
DataTypeBACnetAction = 105,
DataTypeBACnetError = 106,
DataTypeBacnetErrorType = 107,
DataTypeErrorClass = 108,
DataTypeErrorCode = 109,
DataTypeBACnetRejectReason = 110,
DataTypeBACnetAbortReason = 111,
DataTypeBDTEntry = 112,
DataTypeIpEntry = 113,
DataTypeMaskEntry = 114,
DataTypeBACnetEthernetAddress = 115,
DataTypeBACnetLonTalkAddress = 116,
DataTypeBACnetLonTalkNeuronId = 117,
DataTypeBACnetNodeType = 118,
DataTypeBACnetDeviceObjectReference = 119,
DataTypeBACnetActionCommand = 120,
DataTypeGetEventInformation = 121,
DataTypeGetEnrollmentSummaryCriteria = 122,
DataTypeGetEnrollmentSummaryCriteriaResponse = 123,
DataTypeDeviceCommunicationControl = 124,
DataTypeInt16 = 125,
DataTypeUInt16 = 126,
DataTypeUInt8 = 127,
DataTypeInt8 = 128,
DataTypeByte = 129,
DataTypeFDTEntry = 130,
DataTypeBACnetAddress_3 = 131,
DataTypeBACnetAddress_4 = 132,
DataTypeBACnetAddress_5 = 133,
DataTypePersistentDataState = 134,
DataTypeFallbackRealValue = 135,
DataTypeFallbackBinaryValue = 136,
DataTypeRealNull = 137, // PresentValue in AnalogObj
DataTypeEnumeratedNull = 138, // PresentValue in BinaryObj
DataTypeUnsignedIntegerNull = 139, // PresentValue in Multistate
DataTypeUnknown = 140,
DataTypeBACnetDiagnosisPerformance = 200,
DataTypeBACnetDiagnosisEthStatistics = 201,
DataTypeBACnetFrameStatistics = 202,
DataTypeBACnetInfo = 203,
DataTypeBACnetDiagnosis = 204,
DataTypeTcIoEthStatistic = 205,
DataTypeTcIoEthTxRxErrorCount = 206,
DataTypeTcIoEthPortStatistic = 207,
DataTypeBACnetServerStatistics = 208,
DataTypeBACnetFrameServicesDiag = 209,
// Array types
DataTypeBACnetCalendarEntryArr = ARRAYTYPE + DataTypeBACnetCalendarEntry,
DataTypeBACnetObjectIdentifierArr = ARRAYTYPE + DataTypeBACnetObjectIdentifier,
DataTypeCharacterStringExtArr = ARRAYTYPE + DataTypeCharacterStringExt,
DataTypeBACnetPriorityValueArr = ARRAYTYPE + DataTypeBACnetPriorityValue,
DataTypeBACnetTimeStampArr = ARRAYTYPE + DataTypeBACnetTimeStamp,
DataTypeBACnetVTClassArr = ARRAYTYPE + DataTypeBACnetVTClass,
DataTypeBACnetVTSessionArr = ARRAYTYPE + DataTypeBACnetVTSession,
DataTypeBACnetSessionKeyArr = ARRAYTYPE + DataTypeBACnetSessionKey,
DataTypeBACnetRecipientArr = ARRAYTYPE + DataTypeBACnetRecipient,
DataTypeBACnetAddressBindingArr = ARRAYTYPE + DataTypeBACnetAddressBinding,
DataTypeBACnetCOVSubscriptionArr = ARRAYTYPE + DataTypeBACnetCOVSubscription,
DataTypeUnsignedIntegerArr = ARRAYTYPE + DataTypeUnsignedInteger,
DataTypeBACnetDestinationArr = ARRAYTYPE + DataTypeBACnetDestination,
DataTypeBACnetDeviceObjectPropertyReferenceArr = ARRAYTYPE + DataTypeBACnetDeviceObjectPropertyReference,
DataTypeBACnetLifeSafetyStateArr = ARRAYTYPE + DataTypeBACnetLifeSafetyState,
DataTypeEnumeratedArr = ARRAYTYPE + DataTypeEnumerated,
DataTypeReadAccessSpecificationArr = ARRAYTYPE + DataTypeReadAccessSpecification,
DataTypeReadAccessResultArr = ARRAYTYPE + DataTypeReadAccessResult,
DataTypeBACnetSpecialEventArr = ARRAYTYPE + DataTypeBACnetSpecialEvent,
DataTypeBACnetLogRecordArr = ARRAYTYPE + DataTypeBACnetLogRecord,
DataTypeBACnetTimeValueArr = ARRAYTYPE + DataTypeBACnetTimeValue,
DataTypeBACnetDeviceObjectReferenceArr = ARRAYTYPE + DataTypeBACnetDeviceObjectReference,
// Listes
DataTypeBACnetTimeValueList = LISTTYPE + DataTypeBACnetTimeValue,
DataTypeBACnetSpecialEventList = LISTTYPE + DataTypeBACnetSpecialEvent,
DataTypeBACnetDailyScheduleList = LISTTYPE + DataTypeBACnetTimeValueList,
DataTypeCharacterStringExtList = LISTTYPE + DataTypeCharacterStringExt,
DataTypeBACnetLogRecordList = LISTTYPE + DataTypeBACnetLogRecord,
DataTypeUnsignedIntegerList = LISTTYPE + DataTypeUnsignedInteger,
DataTypeReadAccessResultList = LISTTYPE + DataTypeReadAccessResult,
DataTypeReadAccessSpecificationList = LISTTYPE + DataTypeReadAccessSpecification,
DataTypeBACnetValueList = LISTTYPE + DataTypeBACnetValue,
DataTypeBACnetLogDatumList = LISTTYPE + DataTypeBACnetLogDatum,
DataTypeBACnetPropertyResultList = LISTTYPE + DataTypeBACnetPropertyResult,
DataTypeBACnetPropertyReferenceList = LISTTYPE + DataTypeBACnetPropertyReference,
DataTypeCOVNotificationRequestList = LISTTYPE + DataTypeCOVNotificationRequest,
DataTypeEventNotificationRequestList = LISTTYPE + DataTypeEventNotificationRequest,
DataTypeBACnetPropertyValueList = LISTTYPE + DataTypeBACnetPropertyValue,
DataTypeBACnetActionList = LISTTYPE + DataTypeBACnetActionCommand,
DataTypeBACnetActionListList = LISTTYPE + DataTypeBACnetActionList,
};