bacnet 协议栈 源码 研究 (记录)
bacnet 协议栈 源码 研究 (记录)
https://github.com/bacnet-stack/bacnet-stack
https://github.com/bacnet-stack/bacnet-stack/archive/refs/tags/bacnet-stack-1.0.0.tar.gz
http://bacnet.sourceforge.net/
bacnet 协议
ASHRAE135-2016Standard135-2016–BACnet-ADataCommunicationProtocolforBuildingAutomationandControl.pdf
python版本
python 版本和C版本不是一个作者
所以他们的版本之间也没有什么对应关系
This project has moved to `GitHub <https://github.com/JoelBender/bacpypes>

111
支持 多网卡,选中一个网卡进行bacnet通信
解压之后
执行如下命令:
/home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0
Linux/Unix/Cygwin
$ make clean all
cd apps/whois/
./bacwi
另起一个putty窗口:
sudo tcpdump broadcast and host 192.168.99.31

who is 发送的广播 是 使用的 47808 端口,是指向 192.168.99.255 这个地址
192.168.99.255
192.168.99.255是一个子网的广播地址
一般来说一个子网的广播包是不能通过路由器传播到另一个子网
测试:




使用port 47808 作为过滤条件
使用 过滤条件 : host 192.168.99.31 and broadcast 不能过滤,
原因是 192.168.99.215 发送的是广播包,不是针对192.168.99.31这个地址的。


关于modbus协议开发与wireshark相关抓包方法可以参考清华大学出版社的:
《Modbus软件开发实践》和
《Wireshark数据包分析实战详解》
在windows 下面运行
bacnet-tools-1.0.0\bacserv.exe 没有和 上面的测试环境 通信成功,具体原因不知
如何debug呢?
make 依赖信息 如何打印?
make 编译到的文件,如何打印?
make 详细信息 如何打印?
printf("%s %s %d\n",__func__,__FILE__,__LINE__);
默认的
#elif defined(BACDL_BIP)
#include "bacnet/datalink/bip.h"
#include "bacnet/datalink/bvlc.h"
#include "bacnet/basic/bbmd/h_bbmd.h"
#define datalink_init bip_init
#define datalink_send_pdu bip_send_pdu
#define datalink_receive bip_receive
#define datalink_cleanup bip_cleanup
#define datalink_get_broadcast_address bip_get_broadcast_address
[jack@jack-desktop: bacnet-stack-bacnet-stack-1.0.0]$./bin/bacwi
whois main main main.c
whois main main main.c 403
/home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 152
;Device MAC (hex) SNET SADR (hex) APDU
;-------- -------------------- ----- -------------------- ----
;
; Total Devices: 0
Send_WhoIs_To_Network
datalink_send_pdu
bip_send_pdu
双网卡可以用的
enp4s0 上外网
enp3s0 是内网 连接 bacnet 设备



设置环境变量,如果没有设置BACNET_IFACE ,会按照route -n的路由表,选择 enp4s0
export BACNET_IFACE=enp3s0
运行
[jack@jack-desktop: bacnet-stack-bacnet-stack-1.0.0]$./bin/bacwi
whois main main main.c
whois main main main.c 403
func file line: bip_get_broadcast_address /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 153
dlenv_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 422
bip_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 771 --
BIP_Port = 49338,ifname = enp3s0
BIP: Interface: enp3s0
BIP: Address: 10.0.0.101
BIP: Broadcast Address: 10.0.0.255
BIP: UDP Port: 0xBAC0 [47808]
dlenv_network_port_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 249
dlenv_register_as_foreign_device /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 128
bip_send_pdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 413
bip_send_mpdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 272
BIP: Sending MPDU-> 10.0.0.255:47808 (12 bytes)
BIP: Received MPDU-> 10.0.0.101:47808 (12 bytes)
BIP: Received MPDU-> 10.0.0.111:47808 (25 bytes)
BIP: Received NPDU-> 10.0.0.111:47808 (21 bytes)
;Device MAC (hex) SNET SADR (hex) APDU
;-------- -------------------- ----- -------------------- ----
2 0A:00:00:6F:BA:C0 0 00 1024
;
; Total Devices: 1
[jack@jack-desktop: bacnet-stack-bacnet-stack-1.0.0]$
测试广播包是否在 enp4s0网卡上也有,可以通过
sudo tcpdump -i enp3s0 broadcast and port 47808
sudo tcpdump -i enp4s0 broadcast and port 47808
sudo tcpdump -i any broadcast 有问题,运行不了
10.0.0.111 上面是 VTS模拟的一个设备

route -n
ip配置
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
auto enp3s0
auto enp4s0
iface enp4s0 inet static
address 192.168.99.31
netmask 255.255.255.0
gateway 192.168.99.1
dns-nameserver 192.168.99.1
如果修改为下面这个样子
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
auto enp3s0
iface enp3s0 inet static
address 10.0.0.102
netmask 255.255.255.0
auto enp4s0
iface enp4s0 inet static
address 192.168.99.31
netmask 255.255.255.0
gateway 192.168.99.1
dns-nameserver 192.168.99.1
enp3s0 没有设置gateway
路由表是下面的样子

export BACNET_IFACE=enp3s0
同样可以
[jack@jack-desktop: bacnet-stack-bacnet-stack-1.0.0]$./bin/bacwi
whois main main main.c
whois main main main.c 403
func file line: bip_get_broadcast_address /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 153
dlenv_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 422
bip_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 771 --
BIP_Port = 49338,ifname = enp3s0
BIP: Interface: enp3s0
BIP: Address: 10.0.0.102
BIP: Broadcast Address: 10.0.0.255
BIP: UDP Port: 0xBAC0 [47808]
dlenv_network_port_init /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 249
dlenv_register_as_foreign_device /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/src/bacnet/datalink/dlenv.c 128
bip_send_pdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 413
bip_send_mpdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 272
BIP: Sending MPDU-> 10.0.0.255:47808 (12 bytes)
BIP: Received MPDU-> 10.0.0.102:47808 (12 bytes)
BIP: Received MPDU-> 10.0.0.111:47808 (25 bytes)
BIP: Received NPDU-> 10.0.0.111:47808 (21 bytes)
;Device MAC (hex) SNET SADR (hex) APDU
;-------- -------------------- ----- -------------------- ----
2 0A:00:00:6F:BA:C0 0 00 1024
;
; Total Devices: 1
[jack@jack-desktop: bacnet-stack-bacnet-stack-1.0.0]$
源码查看
11
使用sendTo 加dest地址的方式,发送的udp 广播,这样就会自动使用对应的网卡。
接收的时候是全局接收
/* load destination IP address */
bip_dest.sin_family = AF_INET;
memcpy(&bip_dest.sin_addr.s_addr, &dest->address[0], 4);
bip_dest.sin_port = htons(dest->port);
/* Send the packet */
debug_print_ipv4(
"Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port, mtu_len);
return sendto(BIP_Socket, (char *)mtu, mtu_len, 0,
(struct sockaddr *)&bip_dest, sizeof(struct sockaddr));
22
sent = self.socket.sendto(pdu.pduData, pdu.pduDestination)

linux 环境下 c程序 如何 debug 单步调试
linux 环境下 python 程序 如何 debug 单步调试

发送是sendto加目的地址,接收呢?

bip_send_pdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 415
bip_send_mpdu /home/jack/general_work/bacnet_tst/bacnet-stack-bacnet-stack-1.0.0/ports/linux/bip-init.c 274
BIP: Sending MPDU-> 10.0.0.255:47808 (12 bytes)
BIP: Received MPDU-> 10.0.0.102:47808 (12 bytes)
#define datalink_receive bip_receive





设置路由
sudo route add -net 10.0.0.255 netmask 255.255.255.0 gw 10.0.0.1 dev enp3s0
不确定
0A 00 00 00 ---- 10.0.0.0 ----- 167772160
0A 00 00 66 ---- 10.0.0.102 ----- 167772262
FF FF FF 00 ---- 255.255.255.0 ----- 4294967040

socket.inet_ntoa
1
(venv) [jack@jack-desktop: samples]$python ReadProperty.py
> read 192.168.99.219:47808 device 2 objectName
> TD
> read 192.168.99.219:47808 analogInput 0 presentValue
> 222.0




netstat -anp

广播是使用的 udp通信
读写数据也是使用的udp,没有使用 tcp通信
bacnet
python
进入命令行之后
使用
buggers 罗列所有的可以debug log的模块
然后bugin 某个被罗列的模块
然后 执行命令
就会 打印对应模块的信息
read 192.168.99.219:47808 device 2 objectName
read 3002:2 device 2 objectName

buggers bacpypes.netservice
bugin bacpypes.netservice.NetworkServiceAccessPoint
udp通信 模型
有4个 bacnet 路由器,这4个路由器的ip地址不同,
程序向4个 bacnet 路由器分别发送读点指令。
分别读取他们返回的读点信息。
bacnet 路由器 支持 多个点一起读,
或者是他管控下的所有点一起读吗?
bacnet协议里面有说吗?
whois iam 路由表看一下
read 192.168.99.181 analogInput 0 presentValue
read 192.168.99.183 device 0 objectName
read 192.168.99.183 device 0 objectName
read 3002:7 device 25113 objectList
read 3002:20 analogInput 28 presentValue
read 192.168.5.21:47808 device 26265 objectName
read 192.168.5.21:47808 device 26265 objectList
read 192.168.5.21:47808 analogInput 0 presentValue
read 3002:7 device 25113 objectList
read 3002:20 device 3025094 objectList
read 3002:20 analogInput 28 presentValue
read 1021:26 analogInput 2 presentValue
read 1021:26 device 1005724 objectList
> read 1021:26 analogInput 2 presentValue
> 37.2999992371
> read 1021:26 device 3200115 objectList
> [('device', 3200115), ('file', 1), ('program', 37), ('program', 34), ('program', 31), ('program', 27), ('program', 26), ('program', 23), ('program', 61), ('program', 24), ('program', 33), ('analogInput', 2), ('analogInput', 4), ('analogInput', 1), ('analogInput', 5), ('analogOutput', 3), ('binaryOutput', 7), ('analogOutput', 6), ('analogOutput', 12), ('analogValue', 8), ('analogValue', 11), ('analogValue', 10), ('binaryValue', 19), ('binaryValue', 20), ('binaryValue', 21), ('binaryValue', 22), ('analogValue', 13), ('analogValue', 9), ('analogValue', 18), ('analogValue', 14), ('analogValue', 30)]
read 1021:26 device 3200115 objectName
> read 1021:26 device 3200115 objectName
read 1021:26 analogInput 2 presentValue
> read 1021:26 device 1005724 objectName
注意一下
whoisrouter.py
通过bugin命令 多打开几个模块
> irt 192.168.5.21
>
sudo tcpdump -i ens4 broadcast -XX -vvv -nn
详细信息
tcpdump udp port 18290 -XX -vvv -nn
-v:当分析和打印的时候,产生详细的输出。
-vv:产生比-v更详细的输出。
-vvv:产生比-vv更详细的输出。
-XX:输出包的头部数据,会以16进制和ASCII两种方式同时输出。
-nn :直接以IP以及PORT number显示,而非主机名与服务名称
sudo tcpdump -i ens4 port 40815 and net 192.168.5.255 -XX -vvv -nn
VTS发送一个iam消息

sudo tcpdump -i ens4 broadcast and port 47808 -XX -vvv -nn
VTS 工具源码
Visual Test Shell for BACnet
BACnet Tester
Brought to you by: duffy399, jimbutlerma, johnhartman, ltribble, and 2 others
https://sourceforge.net/projects/vts/files/

linux/windows下udp测试小工具
<>

