1、MS/TP帧格式
例如数据(hex):55 FF 01 03 02 00 00 D7
0x55 | 0xff | 0x01 | 0x03 | 0x02 | 0x00 | 0x00 | 0xD7 | BACnet数据 | BACnet数据CRC |
帧头 | 帧类型 | 目的地址 | 源地址 | BACnet数据长度,大端 | CRC | ||||
2、帧类型
帧类型目前定义为 0-7,8-127 为 ASHRAE 保留。帧类型 128-255 可供供应商用于非 BACnet 帧,数据的前两个字节表示供应商标识符。
当前定义的帧为
令牌 (0)、
主站轮询 (1)、
主站轮询回复 (2)、
测试请求 (3)、
测试响应 (4)、
BACnet 数据等待回复 (5)、
BACnet 数据不等待回复 (6)
回复推迟 (7)。
目标站地址可以是 0-127(用于发送到主节点)、0-254(用于发送到从属节点)和 255(用于向所有节点广播)
3、令牌传递过程
测试环境:
在win10,使用模拟工具Yabe BACnet 模拟设备。
使用正点原子开发板,移植了BACnet的mstp。
监控的485上的数据,逐条分析。
55 FF 01 00 02 00 00 4F //设备地址02轮询,源地址02 问目的地 00 在不在 没回复
55 FF 01 01 02 00 00 C6 //设备地址02轮询,源地址02 问目的地 01 在不在 没回复
55 FF 01 03 02 00 00 D7 //设备地址02轮询,源地址02 问目的地 03 在
55 FF 02 02 03 00 00 4F //设备地址03回复,源地址03 回复给 02
55 FF 00 03 02 00 00 51 //传递令牌,源地址02,02把令牌传递给03
55 FF 06 FF 03 00 08 B6 01 20 FF FF 00 FF 10 08 15 B6 //BACnet数据不等待回复,03广播数据 Who-Is
55 FF 01 00 03 00 00 D7 //设备地址03轮询,源地址03 问目的地 00 在不在 没回复
55 FF 01 01 03 00 00 5E //设备地址03轮询,源地址03 问目的地 01 在不在 没回复
55 FF 01 02 03 00 00 C6 //设备地址03轮询,源地址03 问目的地 02 在
55 FF 02 03 02 00 00 5E //设备地址02轮询回复,源地址02 回复给 03
55 FF 00 02 03 00 00 40 //传递令牌,源地址03,把令牌传递给02
55 FF 06 FF 02 00 15 25 01 20 FF FF 00 FF 10 00 C4 02 00 00 67 22 01 E0 91 03 22 01 04 DA EE //BACnet数据不等待回复,02广播数据I-Am
4、Who-Is 数据结构
如下:
//Who-Is
55 FF //帧头
06 //帧类型 BACnet数据,不等待回应
FF //目的地值 FF广播数据
03 //源地址
00 08 //BACnet数据长度
B6 //帧头CRC//NPDU
01 //协议版本号
20 //网络控制八位字节(第 6.2.2 条)bit7=0: 指示 NPDU 是否包含 BACnet APDU。此值为 0,表示该 NPDU 包含 APDU。bit6=0: 保留位,必须为 0。bit5=1: 目的地址标识符为 DNET、DLEN 和 Hop Count,这表明该帧有目的网络信息。bit4=0: 保留位,必须为 0。bit3=0: 源地址字段缺失。bit2=0: 无需期待应答。bit1=0: 该消息的优先级为普通消息。bit0=0: 此位为优先级控制字段,值为 0,表示这不是一个生命安全或关键设备消息。
FF FF //目的地址 65535 广播数据
00 //目的mac 长度 0
FF //Hop Count//APDU
10 //APDU 类型 1:未确认的请求
08 //服务选择 8: Who Is15 B6 //Data CRC-16
5、I-Am 数据结构
如下:
I-Am
55 FF //帧头
06 //帧类型 BACnet数据,不等待回应
FF //目的地值 FF广播数据
02 //源地址
00 15 //BACnet数据长度
25 //帧头CRC//NPDU
01 //协议版本号
20 //网络控制八位字节(第 6.2.2 条)bit7=0: 指示 NPDU 是否包含 BACnet APDU。此值为 0,表示该 NPDU 包含 APDU。bit6=0: 保留位,必须为 0。bit5=1: 目的地址标识符为 DNET、DLEN 和 Hop Count,这表明该帧有目的网络信息。bit4=0: 保留位,必须为 0。bit3=0: 源地址字段缺失。bit2=0: 无需期待应答。bit1=0: 该消息的优先级为普通消息。bit0=0: 此位为优先级控制字段,值为 0,表示这不是一个生命安全或关键设备消息。
FF FF //目的地址 65535 广播数据
00 //目的mac 长度 0
FF //Hop Count//APDU
10 //APDU 类型 1:未确认的请求
00 //服务选择 0: I-Am
C4 //应用程序标记 12(对象标识符),长度 4;高4bit是对象标识符,低4bit是长度4,//1100 .... = Application Tag Number: BACnetObjectIdentifier (12)//.... 0... = Tag Class: Application Tag//.... .100 = 4 Length Value Type: 4
02 00 00 67 // 对象标识符指示了设备对象,
高10bit是类型,=0b0000 0010 00 = 8 为 类型device,
低22bit为实例号,为=0b00 0000 0000 0000 0110 0111 = 0x67 = 103 该标识符用于唯一标识网络中的设备。
22 //Application Tag 2 (Unsigned Integer), length 2,高4bit表示数据类型(Unsigned Integer),低4bit数据长度
01 E0 //最大 APDU 长度: 480
91 //Application Tag 9 (Enumerated), length 1,高4bit表示数据类型(Enumerated枚举),低4bit数据长度
03 //segmentation: no-segmentation
22 //Application Tag 2 (Unsigned Integer), length 2,高4bit表示数据类型(Unsigned Integer),低4bit数据长度
01 04 //Vendor Identifier 为 260,标识符表示该设备的供应商为 BACnet Stack at
DA EE //Data CRC-16
6、BACnet-Confirmed-Request-PDU
NPDU数据结构
//NPDU
01 //协议版本号
04 //网络控制八位字节(第 6.2.2 条)bit7=0: 指示 NPDU 是否包含 BACnet APDU。此值为 0,表示该 NPDU 包含 APDU。bit6=0: 保留位,必须为 0。bit5=0: 目的地说明符:DNET、DLEN、DADR 和跳数不存在。bit4=0: 保留位,必须为 0。bit3=0: 源地址字段缺失。bit2=1: 期待答复:BACnet-Confirmed-Request-PDU,BACnet-ComplexACK-PDU 或网络消息的一个片段,期待答复。bit1=0: 该消息的优先级为普通消息。bit0=0: 此位为优先级控制字段,值为 0,表示这不是一个生命安全或关键设备消息。
APDU数据结构
注解
PDU Type :无符号(0..15),-- 0 表示此 PDU 类型
SEG:分段信息(segmented-message),如果这是一条分段消息,则为 TRUE,否则为 FALSE。
MOR:more-follows BOOLEAN,如果这是一条分段消息,并且这不是最终分段,则为 TRUE。否则为 FALSE。
SA:分段消息接受(segmented-message-accepted)BOOLEAN,如果请求者接受分段 BACnet-Complex-ACK-PDU 作为响应,则为 TRUE,否则为 FALSE。
Max Segs:接受的最大响应段数。
Max Resp:可接受的最大 ADPU 大小。
Invoke ID :请求者用来将响应与请求关联的消息“序列号”。分段请求的所有段必须具有相同的invokeID。invokeID 应该为每个新的 BACnet-Confirmed-Request-PDU 递增。这便于调试,因为它允许将响应与导致响应的请求相关联。
Sequence Number:包序号,标识分段的 BACnet-Confirmed-Request-PDU 的段。不存在于未分段的请求中,只有当SEG=1,才会有这个值。
Proposed Window Size:指定发送分段 BACnet-Confirmed-Request-PDU 的请求者可接受的最大分段窗口大小。未分段的请求中不存在该值;只有当SEG=1,才会有这个值。
Service Choice:服务选择被定义为 BACnetConfirmedServiceChoice 类型,该类型在第 21 条中被定义为枚举。readProperty 的值为十进制的 12。
Service Request:
ReadProperty-Request ::= SEQUENCE {
objectIdentifier | [0] BACnetObjectIdentifier, |
}
这些项目包括“objectIdentifier”,带有上下文标签 0,类型为
BACnetObjectIdentifier;
“propertyIdentifier”,带有上下文标签 1,类型为 BACnetPropertyIdentifier;“propertyArrayIndex”,一个可选的无符号整数,带有上下文标签 2。由于模拟输入对象的当前值不是数组,因此本例中不会出现“propertyArrayIndex”。
BACnet-Confirmed-Request
55 FF //帧头
05 //帧类型 BACnet数据,等待回应
02 //目的地值02
03 //源地址
00 0D //BACnet数据长度
22 //帧头CRC//NPDU
01 //协议版本号
04 //网络控制八位字节(第 6.2.2 条)bit7=0: 指示 NPDU 是否包含 BACnet APDU。此值为 0,表示该 NPDU 包含 APDU。bit6=0: 保留位,必须为 0。bit5=0: 目的地说明符:DNET、DLEN、DADR 和跳数不存在。bit4=0: 保留位,必须为 0。bit3=0: 源地址字段缺失。bit2=1: 期待答复:BACnet-Confirmed-Request-PDU,BACnet-ComplexACK-PDU 或网络消息的一个片段,期待答复。bit1=0: 该消息的优先级为普通消息。bit0=0: 此位为优先级控制字段,值为 0,表示这不是一个生命安全或关键设备消息。//APDU
02 //PDU Type = 0, SEG=0,MOR=0, SA=1
73 //Max Segs = 7,Max Resp =3;
00 //Invoke ID = 0
0C //Service Choice = 12,表示readProperty//ObjectIdentifier: device, 103
0C //0000 .... = Context Tag Number: 0;bit3 =1;//.... 1... = Tag Class: Context Specific Tag//.... .100 = 4 Length Value Type: 4
02 00 00 67 // 对象标识符指示了设备对象,// 高10bit是类型,=0b0000 0010 00 = 8 为 类型device,// 低22bit为实例号,为=0b00 0000 0000 0000 0110 0111 = 0x67 = 103 该标识符用于唯一标识网络中的设备。
19 //Context Tag 1, length 1: BACnetPropertyIdentifier
D1 //数据:属性 209:现值
8C B1 //Data CRC-16
7、BACnet-ComplexACK-PDU
APDU数据结构
注解
PDU Type :无符号(0..15),-- 0 表示此 PDU 类型
SEG:分段信息(segmented-message),如果这是一条分段消息,则为 TRUE,否则为 FALSE。
MOR:more-follows BOOLEAN,如果这是一条分段消息,并且这不是最终分段,则为 TRUE。否则为 FALSE。
Original Invoke ID:与请求包一致
Sequence Number:包序号,标识分段的 BACnet-Confirmed-Request-PDU 的段。不存在于未分段的请求中,只有当SEG=1,才会有这个值。
Proposed Window Size:指定发送分段 BACnet-Confirmed-Request-PDU 的请求者可接受的最大分段窗口大小。未分段的请求中不存在该值;只有当SEG=1,才会有这个值。
Service ACK Choice:service-ACK-choice 定义为 BACnetConfirmedServiceChoice 类型,该类型在第 350 页定义为枚举。readProperty 的值为十进制 12。
service-ACK
ReadProperty-ACK ::= SEQUENCE {
objectIdentifier propertyIdentifier propertyArrayIndex propertyValue | [0] BACnetObjectIdentifier, [1] BACnetPropertyIdentifier, [2] Unsigned OPTIONAL, --used only with array datatype -- if omitted with an array the entire array is referenced [3] ABSTRACT-SYNTAX.&Type |
}