您现在的位置是:首页 >技术教程 >KNX IP 协议分析网站首页技术教程
KNX IP 协议分析
KNXnet/IP
KNXnet/IP是KNX总线与外部网络设备的通信协议,允许外部设备通过UDP与KNX系统进行连接,并发送消息控制设备,读取设备状态等。
在系统集成的过程中,第三方系统可以通过KNX-IP协议与knx系统进行对接(需要knx ip网关设备),但是由于协议文档描述过于理论化,对于现场开发人员来讲(crestron、amx控制系统开发人员),读懂都是有些困难的,实现也无从谈起。这种复杂性也给了一些第三方产品一些机会,他们开发了串口的knx网关,并简化了外部的协议,使中控开发人员很快就可以实现对knx系统的控制。
但是对KNX-IP协议的学习还是有必要的,还有很多的场景我们需要它。我不打算把协议的分层模型摆上来讲,而是直接分析数据包的格式,连接数据包是什么样的,心跳包是什么样的,便于我们通过代码实现,有了基本的概念后,你可以再去读读文档,并反过来不断完善优化代码。
连接请求数据包
客户端首先要做的是连接到knx ip网关(以下简称网关),由于是UDP通讯,不需要建立连接的过程,直接向网关的端口3671发送数据即可。我们把这个连接的数据包称为连接请求数据包,连接成功后网关返回一个channlID用于后续的通信。
连接请求数据包格式如下,我们逐一分析各个部分的含义。
IP Header | HAPI | HAPI | CRI |
---|
IP Header:
ip数据包的信息头,固定为6个字节,这个信息头是任何一种数据包都需要的,后面会经常使用到,6个字节的含义如下
Byte0: 信息头的长度,目前的版本固定为0x06,即信息头为6个字节长度
Byte1: knx ip协议版本号, 目前为0x10
Byte2-3: 服务类型, 表示数据包的用途,这个服务类型并不多,大概10几种类型,对于简单的应用需要的更少,我们只需要了解用到的类型,其他暂时不管。在连接请求数据包中,这个值为0x0205。
Byte4-5: 整个数据包长度,这个长度要包含信息头的长度
HAPI Control:
客户端地址信息,8个字节。
HAPI data:
网关的地址信息,8个字节。
这两个部分的都是HAPI格式的,HAPI专门用于描述主机的信息,便于连接双方互相了解对方的一些关键信息。HAPI格式8个字节的含义如下:
Byte0: HAPI数据的长度,固定为0x08
Byte1: 使用的通讯协议, 目前为0x01,表示UDP
Byte2-5: ip地址,4个字节
Byte6-7: 端口号,2个字节
CRI:
连接请求信息,4个字节,这个不做过多解释,先简单使用固定值。0x04, 0x04, 0x02, 0x00
连接请求数据包一共26个字节,其中信息头,HAPI在后面还会用到,是通用的,CRI是只出现在请求数据包内的。2个HAPI是可以为空的(都为0),至少我在以前的一个测试中是这样的,可以正常通信,并不受影响。如果有问题请填充正确的IP及端口信息。用UDP将这个数据包发送到网关的3671端口,向网关请求连接,如果通信正常,网关返回请求响应数据包。
连接请求响应数据包
连接请求响应是比较简单的,除去IP信息头以外只有两个字节,格式如下:
IP Header | ChannelID | Status |
---|
IP Header:
ip数据包的信息头,我们只关心表示服务类型的两个字节,在请求响应数据包中这个值是0x0206, 我们根据这个判断数据包类型。
ChannelID:
通道号,后面的通信都要用到这个通道号,作为与网关通信的一个连接标识。
Status:
连接请求的返回状态,
0x00:表示连接成功
0x24:表示连接错误,网关的客户端数量达到了上限,说明有其他设备连接到了网关。
连接状态请求
这个是维持连接用的,连接成功后,每60s内必须发送一次以保持当前的连接,否则网关会断开这个连接,channelID也就失效了,无法再用来通信了。格式如下:
IP Header | ChannelID | 0x00 | HPAI |
---|
IP Header:这个上面已经讲过了,把服务类型设为0x0207即可
ChannelID:连接成功时返回的通道号
0x00: 保留字节
HPAI:客户端地址信息,格式上面讲过了,内容为客户端的ip或端口信息
连接状态请求响应
这个数据包比较简单,一个channelID和一个状态信息
ChannelID | Status |
---|
ChannelID:
当前使用的通道号
Status:
状态请求的返回状态
0x00: 无错误,连接状态正常
0x21: channelID错误,如果收到这个错误,我们要重新连接网关
Tunnel请求
已经连接到网关了,并能够保持连接了,我们就可以发送具体的命令来控制设备了,所有向knx组地址发送的指令全部通过Tunnel请求实现,格式如下:
IP Header:
ip数据包的信息头,服务类型为0x0420
Connect Header:
连接头,4个字节,各个字节含义如下
Byte0: 连接头的长度,固定为0x04
Byte1: channelID, 连接通道号,即连接成功时返回的通道号
Byte2: 顺序号,每发送一个Tunnel请求,值加1,由于只有1个字节,到255时回绕到0
Byte3 :固定为0x00
Cemi:
通用的外部通信接口,就是向knx发送控制信息的格式,指定了源组地址,目的组地址,发的命令是什么,参数是什么等等,以及一些控制信息。这个格式里面就会有很多的关于knx相关的信息了,是整个协议的核心部分。格式如下:
Message Code | Add.Info Length | Control Field 1 | Control Field 2 | Source Address | Dest. Address | Data Length | APDU |
---|
Message Code: 消息类型,一个字节,我们会用到三个值
0x11 请求类型消息
0x2e 反馈类型消息
0x29 通知类型消息
Add.Info Length:附件消息长度,目前没有附加消息,此值为0x00
Control Field 1:控制字段1,固定为0xbc, 具体含义先不解释
Control Field 2:控制字段2,固定为0xe0, 具体含义先不解释
Source Address:源组地址,2个字节,为0x0000,我们不用填写具体的地址信息
Dest. Address:目的组地址,2个字节,就是我们的信息要发给哪个组地址
Data Length:载荷的数据长度,就是后面字段APDU部分的长度
APDU:数据单元,就是我们发送的开关值,温度值或亮度值,就放在这个里面。具体放不同类型的值时,APDU的占用的长度不一样,我们放在具体实现时再去解释。
Tunnel请求响应
成功发送一个Tunnel请求后,网关会返回一个响应,简单情况下,我们可以不处理这个响应。格式如下:
IP Header:ip数据包的信息头,服务类型为0x0421
Connect Header: 连接头,4个字节,格式前面讲过了
最后
开发一个简单的KNXnet/IP客户端,能够把上面的实现就可以了,实现基本的控制完全没有问题。后面我们会根据本篇文章的内容在amx控制系统上实现一个简单的knx客户端,实现amx与knx的对接。