使用python分析bacnet协议字段

本文介绍了一种使用Python解析BACnet协议字段的方法,通过Wireshark抓包获取数据,然后通过dpkt、socket和json库进行处理。代码示例展示了如何将十六进制转换为二进制,解析BACnet协议的虚拟链路控制、自动化和控制网络NPDU、APDU等部分,提取关键信息如服务类型、对象标识符和属性值等。
摘要由CSDN通过智能技术生成

本文描述了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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值