Wednesday, October 7, 2009

BACnet tagging rules

This morning there was an old, familiar question on the BACnet-L mailing list:

"can we assume that values (data types) with application tag will always be enveloped by an open tag and close tag?"

Unfortunately not. BACnet's tagging rules are not that easy to figure out initially and a lot of developers get them wrong at first. But once understood the rules are not difficult.


This is why in my "BACnet for Developers" class I take some extra time to explain the tagging rules, to make sure the developers start off on the right foot. As a service to the BACnet community I have posted the slides on tagging below.



We’ll take a short spin through ASN.1, sufficient for reading productions. There are additional rules for writing BACnet ASN.1 productions, but they are out of the scope of this course.


Taking the production (as it is called in ASN.1) ReadProperty-Request, we identify its various elements as follows:


1) The production’s name, followed by “::=“.


2) The type of structure represented by the production; these seven types are all that are used in BACnet. Most of these should be obvious; “SEQUENCE OF” refers to a list or array, “SEQUENCE SIZE (n) OF” is an array whose size is set by the standard.
3) The name of the datum: a short description of what is represented by the datum.


4) A “context tag”; a numerical tag that identifies (in the context of the production) the particular datum. For several reasons context-tagged data is preferred over data that is not context-tagged, or “primitive-tagged”. (We’ll be looking at tagging shortly.)


5) The datatype of the datum. This can be “primitive” or “application” data (CharacterString, BOOLEAN, etc.), or it can be “constructed” data – another production in this production, or a reference to another production.


6) The optional OPTIONAL keyword. “OPTIONAL” here refers to elements of service requests that may be absent depending upon the form or intent of the service, or absent due to some other condition.


7) Comments, preceded by two dashes.







In BACnet there are only 7 types of structures in ASN.1 productions.


- The BITSTRING datatype should be self-evident: a series of flags, each indicating something.


- CHOICE should also be self-evident: one of the options presented.


- ENUMERATED is also simple: each of the numeric values presented represents something.


- SEQUENCE, as the name suggests, is a series of items. (Note that some of the items could be OPTIONAL.)


- SEQUENCE OF and SEQUENCE SIZE (n) OF are relatively infrequent constructs in BACnet: they represent a series of some item, a list or an array. “SIZE (n)” indicates an array whose size is fixed in the standard.


- Finally, there is the OCTET STRING datatype.







While it’s in front of us, we need to take a moment to look at this complex-looking datatype called “ABSTRACT-SYNTAX.&Type.” All it really means, within the context of BACnet, is that the variable which has this datatype can take on any value. This is stated in Clause 20.2.19.






Looking at the BACnetPriorityValue production, we see a CHOICE with a number of basic datatypes in it. This is a good time to see how the data in such a production is represented “on the wire,” in its binary form and with the identifying tags.


In BACnet there are three kinds of tags (technically BACnet defines only two, but it’s easier to understand if you break them out into three).


- The first is the “application” tag (or “primitive”; both terms appear in the standard). This tag identifies the basic datatype (Unsigned, Double, Date, etc.) and its length.


- The second is the “context” tag. This conveys the “context number” from the production, the number in square brackets, and the length of the data contained. The datatype of the tagged data is determined by the context (production) in which it appears; without the context one cannot tell if a data item with four bytes is an INTEGER, Unsigned, REAL, Date, or Time, for example.


- The third type are two variants of the context tag we call a “PD Open” and “PD Close” tags (or together “PD tags”), based on some terminology in the standard. As their names imply, these tags always appear in pairs, carrying the context number but with no length information. These are used in encoding lists, arrays and ANY datatypes and contain zero or more tagged items.


Which kind of tag would be used on “constructedValue” in the production here?






The application/primitive tag is used to encode the basic underlying BACnet datatypes, of this there are 13. These are defined in the standard in Clauses 20.2.2 through 20.2.14, with the rules and examples of their encoding.


Let’s quickly go through the exercise of encoding a REAL value of zero (4 bytes of zero). Looking at the initial octet of the tag, we assign the datatype to the “Tag Number”, the class is zero (application tag) and the length of the data following is 4. Therefore the tag is X’44’ and the entire data item is X’4400000000’.


There is a special case when encoding the BOOLEAN data with an application tag:
FALSE is encoded X’10’ and TRUE X’11’. This rule does NOT apply when a BOOLEAN is encoded with context tags. (See Clause 20.2.3.)






The context tag (my term) is used when you see a square bracket with a number in it in a production, and a primitive datatype specified. To encode a ‘deadband’ value of zero in this production (the values sent with an OUT_OF_RANGE event notification), one would encode the tag number in ‘Tag Number’, set the ‘Class’ bit to 1, and set ‘Length’ to 4, giving a tag of X’3C’.





The PD Open / PD Close (my term, based on the standard) tags are a subclass of context tags in that they convey the context tag number. These always appear in pairs.


In the examples given, it should be noted that in BACnet the first day of the week is Monday.






No doubt you will have noted there are some apparent limitations to the data tag. The tag number can only go to 15, and the length to 5 on context-tagged data (7 on application-tagged data). This is not the case. Tag numbers can go up to 254, and length up to 232-1; these are done by extending the tag per Clause 20.2.1.


Rule 1: Tag numbers 0 through 14 are encoded in the tag number field. 15 through 254 is encoded with X’F’ in the Tag Number, and the byte following holds the length.


Rule 2: Length 0 through 4 is encoded in the length field. Length 5 through 253 have the length field value X’5’, and the byte following this byte, or the length extension if it is present, has the length. For lengths 254 through 65535, set the extension to 254 and the subsequent two bytes hold the length. For lengths 65536 through 232-1, set the extension to 255 and the subsequent four bytes hold the length.



And there you have it.

1 comment:

  1. rsoza@site-controls.com19 October, 2009 14:50

    Do you still offer the "BACnet for Developers" class, if so how and where can I sign up?

    ReplyDelete