本文描述了python分析bacnet协议字段的方法。其他协议应该也是类似的。
bacnet协议
bacnet协议是一种工控协议。即楼宇自动化与控制网络。是用于智能建筑的通信协议。
一般楼宇自控设备从功能上讲分为两部分:一部分专门处理设备的控制功能;另一部分专门处理设备的数据通信功能。而BACnet就是要建立一种统一的数据通信标准,使得设备可以互操作。BACnet协议只是规定了设备之间通信的规则,并不涉及实现细节。
BACnet协议模型为:
(1)所有的网络设备,除基于MS/TP协议的以外,都是完全对等的(peer to peer);
(2)每个设备都是一个“对象”的实体,每个对象用其“属性”描述,并提供了在网络中识别和访问设备的方法;设备相互通信是通过读/写某些设备对象的属性,以及利用协议提供的“服务”完成;
(3)设备的完善性(Sophistication),即其实现服务请求或理解对象类型种类的能力,由设备的“一致性类别”(Conformance Class)所反映。
wireshark抓包
##python代码实现
#解析bacnet协议字段
import dpkt
import socket
import json
write_stream = "./stream/BACnet/write.txt"#数据流只截取了bacnet协议部分
write_field = "./stream/BACnet/write_field.txt"
write_field_dict = {}
#十六进制转二进制
def HexToBin(str):
temp = bin(int(str, 16))[2:]
if len(temp) < 8:
temp = (8 - len(temp)) * '0' + temp # 通过该方法获得的二进制会把前面的0省略掉,所以需要进行补全
return temp
#二进制转十六进制
def BinToDec(str):
temp = int(str, 2)
return temp
def choose(num):
if num == 129:
return 'BACnet/IP (Annex J)'
if num == 10:
return 'Original-Unicast-NPDU'
if num == 16:
return 'writePropertyMultiple'
if num == 2389:
return 'present-value'
if num == 14608:
return '(Unsigned) 16'
#解析bacnet协议
def bacnetWriteParse(msg):
msg_strs_H = msg.split(' ')
msg_strs_B = [] # 创建存放数据报二进制数据的列表
for msg_H in msg_strs_H:
temp = HexToBin(msg_H)
msg_strs_B.append(temp)
print(msg_strs_H)
print(msg_strs_B)
#开始解析字段
#bacnet协议分为三个部分
#virtual link control
type_1 = choose(BinToDec(msg_strs_B[0]))
function = choose(BinToDec(msg_strs_B[1]))
bvlc_length = BinToDec(msg_strs_B[2]+msg_strs_B[3])#表示的是三部分合起来的长度
#automation and control network NPDU
length1 = 2#第二部分
version_1 = BinToDec(msg_strs_B[4])
control_1 = BinToDec(msg_strs_B[5])
#automation and control network APDU
length2 = bvlc_length - length1#第三部分
packet = msg_strs_B[6:6+length2-1]
print("第三部分的数据包"+str(len(packet)))
type_2 = BinToDec(packet[0][0:4])
flags = BinToDec(packet[0][4:])
maximum = BinToDec(packet[1])
invoke_id = BinToDec(packet[2])
service_choice = choose(BinToDec(packet[3]))
object_identifier = BinToDec(packet[4]+packet[5]+packet[6]+packet[7]+packet[8])
txt1 = BinToDec(packet[9])
property_identifier = choose(BinToDec(packet[10]+packet[11]))
txt2 = BinToDec(packet[12])
present_value = choose(BinToDec(packet[13]+packet[14]+packet[15]+packet[16]+packet[17]))
txt3 = BinToDec(packet[18])
priority = choose(BinToDec(packet[19]+packet[20]))
others = ''
pac = packet[21:]
for i in pac:
others += i
others = BinToDec(others)
f_dict = {
'type_1': type_1,#2
'function': function,#2
'bvlc_length': bvlc_length,#4
'version_1':version_1,#2
'control_1':control_1,#2
'type_2': type_2,#2
'flags': flags,#2
'maximum':maximum,#2
'invoke_id':invoke_id,#2
'service_choice':service_choice,
'object_identifier':object_identifier,#10
'txt1':txt1,#2
'property_identifier':property_identifier,#4
'txt2':txt2,#2
'present_value':present_value,#10
'txt3':txt3,#2
'priority':priority,#4
'others':others,
}
print(f_dict)
return f_dict
write_field_list = []
#处理write数据包
def accessWriteREQ():
print("处理write REQ数据包")
#打开文件读入流
with open(write_stream, 'r') as f:
msg = f.read()
print(msg)
msglist = msg.split("\n------\n")
print(msglist)
for mess in msglist:
write_field_dict = bacnetWriteParse(mess)
write_field_list.append(write_field_dict)
#写入文件保存
with open(write_field, 'w') as f:
for msg_dict in write_field_list:
f.write(json.dumps(msg_dict))
f.write('\n')
if __name__ == "__main__":
accessWriteREQ()
输入文件内容如下:
解析的结果:
保存到txt文件end