BACnet APDU的编码说明

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'
 
 
 
 
 

 

 

 

 

 

 

  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值