application tag:应用标记
context specific tag:上下文标记
BACnet标记的编码结构图
_________________________________________________
| Tag Number(4 bit) | Class(1 bit) | Length/Value/Type(3 bit) |
| 标记编号 | 类别 | 长度/值/类型 |
—————————————————————————————————
当类型是构造类型时,“标记编号”表示在构造类型中的次序即位置。其他意义不变,并且同样遵守
下面的这些约定(规定)。
如果是构造类型,一般LVT域表示的是后续字节的长度。
构造编码是指编码数据中有其他标记的编码,用于构造类型数据的编码。构造编码由下面三个部分组成:
1>"开始标记"。该标记标识构造编码开始,其标记字节的Class域为B'1',LVT域为B'110'
2>构造元素编码。构造类型数据的各个构造元素编码
3>"结束标记"标识构造编码的结束。其标记字节的Class域为B'1',LVT域为B'111'
在构造编码中,允许多重嵌套。
值得说明的是,简单类型的应用标记编号是由BACnet标准规定的,且固定不变。但
简单类型数据的上下文标记编号在构造类型数据中不是固定的,其具体编码在不同
ASN.1定义上下文中是不同的,并通常由ASN.1定义中的或位置确定。
NULL编码:
无论是简单编码还是构造编码,均用一个字节编码。
简单编码
应用标记编号=0
编码=B'0000,0000'
构造编码
上下文标记编号=5(也可以是其他值)
编码=B'0101,1000'
BOOLEAN编码
简单编码中,BOOLEAN用一个字节编码,如果BOOLEAN值为FALSE,则L/V/T域为B'000'
如果为TRUE,则L/V/T域为B'001'
构造编码中,BOOLEAN数据用两个字节编码,第一个字节的Class域为B'1',LVT域表示附加字节的
长度,其编码为B'001',如果BOOLEAN值为F,则第二个字节编码为B‘0000,0000’,如果为T,则第二个
字节编码为B'0000,0001'
简单编码:
ASN.1=T
应用标记编号=1
编码=X'11'
构造编码:
ASN.1=T
上下文标记编号=5
编码=X'59 01',即class=1;
Unsigned Integer编码
Unsigned Integer数据如果用L(>=1)个字节时,则其值为0~(2L*81)。当该类型数据的值一定时,
则应使L最小。即用多个字节表示数据时,第一个数据字节不能为X'00'
简单编码
值=72
应用标记编号=2
标记字节编码=X'21'
数据字节编码=X'48'
构造编码
值=72
上下文标记字节编号=5
标记字节编码=X'59',即Class域为1,只要是构造类型,都为1。
数据字节编码=X'48'
Signed Integer编码
Signed Integer数据如果用L(>=1)个字节表示,则其值为-2(L*8-1)~2(L*8)-1,用多个字节表示时
如果为正整数,则第一个数据字节不能为X'00',如果为负数,则第一个字节不能为X'FF'.
简单编码
值=-72
应用标记编号=3
标记字节编码=X'31'
数据字节编码=X'B8',即用补码表示的-72
构造编码
值=-72
上下文标记编号=5
标记字节编码=X'59'
数据字节编码=X'B8'
Real编码
采用ANSI/IEEE 754-1985标准,用4个字节编码,其中,第一位表示S,紧接其后的8位表示E,后23位表示F
简单编码
值=72
应用标记=4
标记字节编码=X'44'
数据字节编码=X'42 90 00 00',转换为此编码还是按modbus到OPC的那种转换,已经试过了,可以。
构造编码
值=-33.3
上下文标记编号=5
标记字节编码=X'5C'
数据字节编码=X'C2 05 33 33'
Double编码
采用ANSI/IEEE 754-1985标准,用8个字节进行编码
其中,S为1位,e为11位,f为52位
简单编码
值=72.0
应用标记=5
标记字节编码=X'55',//此处的“55”中的后面那个“5”参见简单类型的LVT域的说明。
扩展长度字节=X'08'
数据字节编码=X'42 90 00 00,00 00 00 00',
构造编码
值=-33.3
上下文标记编号=5
标记字节编码=X'5D',此处的“5D”中的“D”参见简单类型的LVT域的说明。
扩展长度字节=X'08'
数据字节编码=X'C0 40 A6 66,66 66 66 66'
//当LVT>=4时,分两种情况讨论,一是简单类型,一是构造类型
//当LVT<4时,分两种情况,还是如上,
//总之,不超过4时,不管Class为何,LVT都等于后面的字节长度。
OCTET STRING编码
1个编码字节可以表示两个字符,因而它的编码效率比字符串编码提高了一倍。
简单编码
值=6F4A3C
应用标记编号=6
标记字节编码=X'63'
数据字节编码=X'6F4A3C',
构造编码
值=6F4A3C
上下文标记编号=5
标记字节编码=X'5B'
数据字节编码=X'6F4A3C'
Character String编码
BACnet对如下标准字符集进行了编码,并在数据编码字节的第一个字节(或多个字节)
表示所采用的标准字符集编码。数据字节编码长度为标准字符集编码字节数(1个或多个字节)
与字符串编码字节数之和。
X'00' ANSI X3.4
X'01' IBM/MICROSOFT DBCS
X'02' JIS C 6226
X'03' ISO 10646(UCS-4)
X'04' ISO 10646(UCS-2)
X'05' ISO 8859-1
例如采用ANSI X3.4字符集的编码如下,其中,字符串长度为13,标准字符集编码长度为1,编码总
长度=14
简单编码
值="BACnet string"
应用标记编号=7
标记字节编码=X'75'//当最后一位为5时,表明,后面的数据长度在5~253之间。
扩展长度字节编码=X'0E'
字符集字节编码=X'00'
数据字节编码=X'42 41 43 6E 65 74 20 73 74 72 69 6E 67',
构造编码
值="BACnet string"
上下文标记编号=5
标记字节编码=X'5D'
扩展长度字节编码=X'0E'
字符集字节编码=X'00'
数据字节编码=X'42 41 43 6E 65 74 20 73 74 72 69 6E 67'
当时IBM/Microsoft DBC字符集时,其编码有点不同,要查数据手册才行。
BIT STRING编码
BIT STIRNG数据用1个或多个字节进行编码,如果BIT STIRNG数据位位数不是8整数位,
则BIT STRING数据位与编码字节的最高位对齐,编码字节的多余的低位用‘0’填充。用‘0’
填充的位数在第一个数据编码字节中表示。编码字节长度为位串编码字节数加1.
简单编码
值='11010'
应用标记编号=8
标记字节编码=X'82'
数据字节编码=X'03 D0',
构造编码
值='11010'
上下文标记编号=5
标记字节编码=X'5A'
数据字节编码=X'03 D0'
ENUMERATED编码
可以看作为Unsigned Integer,因而其编码规则除标记编号不同外,其他规则与Usigned
Integer数据编码相同。
简单编码
值=72
应用标记编号=9
标记字节编码=X'91'
数据字节编码=X'48'
构造编码
值=72
上下文标记字节编号=5
标记字节编码=X'59'
数据字节编码=X'48'
Date编码
Date类型数据编码用4个字节进行编码,这4个字节从高字节到低字节依次分别表示年、月、
日和星期。
简单编码
值=1991年1月24日(星期四)
应用标记编号=A
标记字节编码=X'A4'
数据字节编码=X'5B 01 18 04'
构造编码
值=1991年1月24日(星期四)
上下文标记字节编号=5
标记字节编码=X'5C',
//即Class域为1,而且把应用标记编号换成了上下文标记字节编号。而且,其他的
//都一样,即从class后面的表示的意义都一样。
数据字节编码=X'5B 01 18 04'
//好像没有表示出来1991,只表示出来了是91年,而不
//知道是不是2091年。好像把世纪给省略了。
Time编码
Time类型是BACnet标准定义的专用简单类型,Time类型也是用4个字节进行编码,这4个字节
从高字节到低字节依次分别表示小时、分钟、秒钟和百分之一秒。
简单编码
值=17:35:45.17(PM)
应用标记编号=B
标记字节编码=X'B4'
数据字节编码=X'11 23 2D 11'
构造编码
值=17:35:45.17(PM)
上下文标记字节编号=5
标记字节编码=X'5C',即Class域为1,而且把应用标记编号换成了上下文标记字节编号。
数据字节编码=X'11 23 2D 11'
Object Identifier编码
是BACnet定义的专用简单类型,BACnetObjectTyep的ASN.1定义如下:
BACnetObjectType::=ENUMERATED{
analog-input (0),--模拟输入对象类型
analog-output (1),--模拟输出对象类型
analog-value (2),--模拟值对象类型
binary-input (3),--二进制输入对象类型
binary-output (4),--二进制输出对象类型
binary-value (5),--二进制值对象类型
calendar (6),--日历对象类型
command (7),--命令对象类型
device (8),--设备对象类型
event-enrollment (9),--事件登录对象类型
file (10),--文件对象类型
group (11),--组对象类型
loop (12),--环对象类型
multistate-input (13),--多态输入对象类型
multistate-output (14),--多态输出对象类型
notification-class (15),--通告类对象类型
programm (16),--程序对象类型
schedule (17),--时间安排对象类型
..
--枚举值0-127为ASHRAE保留,用于BACnet标准对象类型
--枚举值128-1023用于非标准对象类型
}
在编码时,BACnet对象类型枚举值(共10比特位)的高8位在第一个数据编码字节中进行编码,
低2位(比特位1、0)在第二个数据编码字节的高2位(比特位7、6)中进行编码。对象实例
在第二个数据编码字节余下的6位和第3、4字节中进行编码。所有编码均高位在先。
简单编码
值=(Binary input,11)
//第11 个二进制输入变量。
应用标记编号=C
标记字节编码=X'C4'
数据字节编码=X'00 C0 00 0B'
构造编码
值=(Binary input,11)
上下文标记字节编号=5
标记字节编码=X'5C',
//Class域为1,而且把应用标记编号换成了上下文标记字节编号。
数据字节编码=X'00 C0 00 0B'
构造类型数据编码
BACnet标准的构造类型只有由SEQUENCE ,SEQUENCE OF 和CHOICE三个关键词说明的类型。
SEQUENCE的构造类型
如果构造元素中不存在可选元素项,则构造元素可以不使用上下文标记。如果构造元素均简单类型
数据,则按应用类标记进行简单编码。如果构造元素存在构造类型数据,则进行构造编码。
假设有一个值为1991年1月24日,17:35:45.17的BACnetDateTime类型数据,其编码为:
第1个构造元素date:标记字节 = X'94'
数据编码字节 = X'58 01 18 05'
第2个构造元素time:标记字节 = X'A4'
数据编码字节 = X'11 23 2D 11'
如果构造元素中存在可选元素项,则构造元素必须使用上下文标记。如果构造元素存在简单类型
数据,则根据可选项是否存在,按上下文标记进行简单编码。如果构造元素存在构造类型数据,
则根据可选项是否存在,按上下文标记进行构造编码。假设一个DateTime_N类型的ASN.1定义如下:
DateTime_N::=SEQUENCE{
date [0]Date,
time [1]Time OPTIONAL,
n [2]Unsigned(0..65535)
}
并假设有一个值为(1991年1月24日,10)的DateTime_N类型的数据,因可选项缺省,帮其编码为
第1个构造元素date:标记字节 = X'0C'
数据编码字节 = X'58 01 18 05'
第2个构造元素time:标记字节 = X'29'
数据编码字节 = X'0A'
SEQUENCE OF的构造类型
SEQUENCE OF说明的构造类型为同一类型的构造元素所组成。其编码为构造元素编码的罗列。例如:
假设某一类型Series的ASN.1定义为:
Series::=SEQUENCE OF INTEGER
当Series类型值为(1,2,3)时,则其编码为
第1个构造元素date:标记字节 = X'21'
数据编码字节 = X'01'
第2个构造元素time:标记字节 = X'21'
数据编码字节 = X'02'
第3个构造元素date:标记字节 = X'21'
数据编码字节 = X'03'
又例如:若上例的类型在某一个上下文环境中的上下文标记为4,则上例中的实例编码如下:
开始标记 = X'4E'
第1个构造元素date:标记字节 = X'21'
数据编码字节 = X'01'
第2个构造元素time:标记字节 = X'21'
数据编码字节 = X'02'
第3个构造元素date:标记字节 = X'21'
数据编码字节 = X'03'
结束标记 =X'4F'
CHOICE 构造类型
说明构造类型的编码只是对选取的一个构造元素进行编码。例如:
BACnetTimeStamp类型的ASN.1定义为:
BACnetTimeStame::={
time [0]Time,
sequenceNumber [1]Unsigned(0..65535),
dateTime [2]BACnetDateTime
}
当某个BACnetTimeStamp类型数据值为17:35:45.17时,则其编码为:
上下文标记编码 = X'0C'
数据字节编码 = X'11 23 2D 11'
当类型数据在某个上下文环境中的上下文标记为2时,若数据值仍为上值,则其编码为:
开始标记编码 = X'2E'
上下文标记编码 = X'0C'
数据字节编码 = X'11 23 2D 11'
结束标记编码 = X'2F'