开发者学堂课程【嵌入式之RFID开发与应用2020版:Zigbee 控制节点数据收发流程】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/665/detail/11140
Zigbee 控制节点数据收发流程
Zigbee 控制节点数据收发流程
刚刚提到了本地的数据,包括串口还有按键的数据处理,接下来是网络数据的处理,网络数据包括数据的发送和接收的基本流程。首先第一,假如需要发送数据应该如何操作?刚才当按下按键 KEYBOARD,那么下面四句话都是在进行发数据的流程。
debug("key1
down\n");
my_SendPointToPointMessage(SAMPLEAPP_SENSOR_CLUSTERID,SET_TEMP_ADJUST_OPEN);
my _SendPointToPointMessage(SAMPLEAPP_SENSO_CLUSTERID,SET _HUMI _ADJUST_OPEN);
my _SendPointToPointMessage(SAMPLEAPP_CTRL_CLUSTERID,SET_TEMP_ADJUST_OPEN);
my _SendPointToPointMessage(SAMPLEAPP_CTRL_CLUSTERID,SET_HUMI_ADJUST_OPEN);
只有以下三行代码是在完成本地点灯的操作。
LOCAL
_
LED1 = SWITCH
_
LED
_
OPEN;
LOCAL
_
LED2 = SWITCH
_
LED
_
OPEN;
SWITCH
_
LED = SWITCH
_
LED
_
OPEN;
并且操作完之后会进行返回 return(events ^ DEMO_KEYBOARD_)。从这个结果可以看出轮循事件,这里已经处理完此事件,剩下的事件交由下一次处理。
到底应该怎样完成数据的发送?这里书写了发送点到点的函数接口,其需要两个参数。第一是发送的对象是什么类型,这里简单做了约定:传感器规定为1,控制器规定为2,以及发送的内容,将所有的内容全部设定为字符串,其实字符串的处理,更能提高其通用性。
整个的内容,分为温度与湿度。temp 是对温度的调节,例如打开加热器(open)或者关闭了加热器(close),humi 是对湿度的调节,例如打开加湿器(open)或者关闭加湿器(close),那么当然还可以分为自动控制(auto)和手动控制(manual),大概就是这几种控制方法。
接下来看第一个发送的是将温度调节开关打开,查看发送的目标,点击进去之后,第一件事情需要明确,程序比较乱,主要原因是其把协调器的代码,终端的代码,甚至是路由器的代码,包括控制器的代码,传感器的代码,全部融入到这一个程序里面,这样看起来就比较费劲。这里是可以分开的,分开的操作就是将其分成多个文件,比如其中一个文件,表示的是传感器。另一个表示的是控制器,再另一个则是表示协调器,这样的话就可以将其分开。
先按照这样来看,这里有一个函数,有一个全局变量,这是为了给自己提供当前身份的辨识,比如在程序运行的过程中,会混淆自己当前的身份,那么这个全局变量,能够告诉当前身份手机是设备、协调器、还是路由器。所以在发送此接口的此函数时,此函数有可能被协调器调用,有可能被传感器调用,也有可能被控制器调用,那么不管怎么样,如果现在调用此函数的调用者是 DEV_END_DEVICE 就表示是设备在调用,那么其会将 cid 设成传感器(sensor),控制器与传感器都为终端,然而不是控制器的原因是:控制器一般不往外发送数据,就是控制器是执行机构,没有必要对外发送数据。但传感器不行,其需要对外发送数据,也需要接受数据,需要去采集。
将地址设成零的原因是:如果数据需要发送给协调器,协调器的短地址默认都是零,只有加入网络的其他普通设备的地址才是非零,并且由协调器分配,所以其永远为零。只要为零,就表示数据肯定已经发送给协调器,这就是 CLUSTERID。
接下来看协调器,协调器具体如下代码。
if(obj== SAMPLEAPP_SENSOR_CLUSTERID{
my_DstAddr.addr.shortAddr =join_addr[SAMPLEAPP SENSOR CLUSTERID-1].addr;
cid=SAMPLEAPP SENSORCLUSTERID;
}else if(obj== SAMPLEAPP CTRL CLUSTERID)!
my_DstAddr.addr.shortAddr=join_addr[SAMPLEAPP CTRLCLUSTERID-1].addr;
cid=SAMPIFAPP_CTRL_CLUSTERID:
先不考虑协调器的问题,先看终端。终端如果需要发送数据,(例子这里路由器没有实现,如果实现可以在方面直接加上,此次演示先不进行演示。)发送需要了解地址,地址决定发送的目标,cid 就是命令。因为存在很多功能,这里功能分成两种功能:第一个是 SENSOR,另一个是 CTRL,也就是控制和采集折两种功能。
#define SAMPLEAPP_SENSOR_CLUSTERID 1
#define SAMPLEAPP_CTRL _CLUSTERID 2
#define SAMPLEAPP_MAX_CLUSTERS 2
最后需要调用函数,调用 AF_DataRequest 函数,在课件里面有详细介绍,例如源端点,簇命令(cid),就是刚才提到的 SENSOR,然后长度等等一些参数,基本都很容易能明确这些参数。
注册函数:
afRegister(endPointDesc_t*epDesc)
注册过程就是向端点应用链表 epList 增加一个节点
发数据函数:
AF DataRequest(
afAddrTypet*dstAddr//目标地址
endPointDesct*srcEP//源端点
uint16clD//族命令 ID,对于接收方可以通过该命令来区分数据包 uint16len,//发送数据的长度
uint8*buf//发送数据的起始地址
uint8*transID.//事务 ID,可以是包计数器,用于信息确认
uint8options,//告知 AF 层做的一此预处理,一般为 AF DISCV ROUTE uint8radius)//转发数据最多经过的路由深度(AF DEFAULT RADIUS)
填好之后,函数会发送到协调器,而协调器就会收到数据,协调器收到数据的现象是什么?回到 My_process event 页面,协调器收到数据,首先收到了 SYS_EVENT_MSG,有事件。然后在下面看到Incomeing_msg,这表示协调器已经收到数据,然后再从 MSGpkt 里提取数据,可以从这里看到数据的长度,数据的内容。内容拿出来之后,首先将内容进行打印,就是收到是数据是什么类型,然后判断 clusterID,clusterID 就是控制的方式:控制器以及传感器。因为这里仅仅制作了这两种控制器,先不看控制器,因为刚是传感器传输的,传感器如下代码所示。
debug("采集终端入网地址:0x%x\n",pkt->srcAddr.addr.shortAddr);
join addrSAMPLEAPP SENSOR CLUSTERID-11.type =SAMPLEAPP SENSOR CLUSTERID;
Join_addr[SAMPLEAPP_SENSOR_CLUSTERID-11.addr=pkt->srcAddr.addr.shortAddr;
break;//收集完地址退出
其实这里的控制器有点多余,如果为协调器发出控制,是有益的,但是对控制节点,其实没必要发控制信号。
如果是传感器应该怎么做:首先判断当前接收数据的节点是不是协调器,如果是协调器,判断是不是确认信号,如果是确认信号,会做确认信号的事情,如果不是确认信号,那么会判断收到的数据是温度湿度调节打开还是关闭,是否为周期性的采集数据,也或者要获取传感器的温湿度。所以这里做了些分解,刚才发的是温度调节开关的打开,那时候其会将 switch_led 打开。发送和接受都看完了,现在要进行捎代码了,将程序捎进去。但这里出现了问题。如果此数据发给协调器,让协调器去开关灯的意义不是很大,所以这里让协调器将数据发给控制器,因为控制器本来就是专门负责控制设备。流程其实一样,就是发送方,比如当前协调器,(这里全部发送)如果发给控制器,其调用的接口,不是 END_DEVICE,而是协调器。那么协调器在发数据时,这里要提前说一个问题,当不管是传感器还是控制器,加入网络之后,首先设备的地址其实是动态分配的,所以协调器最好是能够建立数组(join_addr)。数组应该可以维护加入到网络的每一个设备,这样便于后期管理。
这里包含了两个信息:第一个,设备的类型,是传感器 SENSOR,还是控制器 CTRL,以及其地址是多少,记录到数组里。
先看数据的收发。其得到的 cid,如果是控制类的就是 CTRL,然后 cid,此过程就不进行重复了,与刚才过程一样,此数据会发给控制器。
接下来重新编译,首先是协调器的代码,此代码刚才已经编译并下载。所以没有必要再重新下载协调器的内容。
现在应该下载控制器,但控制器存在问题:因为代码是控制器和传感器共用的,所以在头文件里有个说明,例如将宏定义成1表示控制节点,如果为0是温湿度采集节点。
#define CTRL_OR_GATHER
1//0表示温湿度采集节点。1表示控制节点
#define CLIENT_AFFIRM “affirm”
#define SAMPLEAPP_PROFID 0x0F08
#define SAMPLEAPP_DEVICEID 0x0001
#define SAMPLEAPP_DEVICE_VERSION 0
#define SAMPLEAPP_FLAGS 0
这决定协调器在确认加入者身份时,也就是通过 send_coord_affirm(发送身份确认),确认其身份是控制器还是传感器,这与协调器发的内容不同,所以这里需要稍微更改,就是不同的设备可能不一样。接下来将其改成 END_DEVICE,重新编译。编译完成后,先把下载的拔下来,插到继电器上,然后就给其下载程序,下载完成后把串口打开,然后复位,可以看到协调器建立网络成功。
成功之后,把另外控制器打开,马上就会检测到控制终端入网。而且入网地址是动态分配,接下来按键,观察到继电器的灯亮了,继电器也发出了声音,表示信号已经传输成功,试验其关闭、打开功能可以正常使用。
整个过程其实就是协调器给控制器发数据,控制器收数据的过程。所以说整个过程也是控制器的数据收发过程,那么后面再去看数据采集的过程。