源码地址:13.端点、簇、属性
端点(endPoint)
一个端点就是一个应用
- 一个字节编号,数据收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点。
- 端点要使用必须要和模块里的某个任务挂钩定义;
首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数 来取这个无线数据包里面的有用数据。
3、一个端点只能挂钩在一个任务上,而一个任务可以挂钩多个端点,且端点对所有的任务是公用的,定义一个少一个。
一个端点加入可以挂钩在多个任务上,那么接收模块接到无线数据时候,这个时候同一个端点有多个任务事件处理函数去处理,不合理;一个任务上挂多个端点(6 7 挂应用层任务),发送给协调器模块的6 7端点的数据都会进入到应用层任务事件处理函数里来,仅仅做个判断到底是投递到6房间还是7号房间就可以了。
簇(ClusterID)
-
一类应用会包含多个应用,每个应用都有独特的属性和命令,通常按照应用把最相关的一些属性和命令归到一起,称为簇(Cluster)
-
簇就是相当于端点房间里面的人,是接收最终的目标。这东西是2个字节编号,在射频发送的时候,必须要指定接收模块的簇,发送模块不需要指定。
属性
属性就是在应用层有用的数据载荷,做专门规定最小单元
结合发送代码分析
端点定义
SDApp_epDesc.endPoint = SDApp_ENDPOINT;//端点编号
SDApp_epDesc.task_id = &SDApp_TaskID; // 和应用层任务挂钩
SDApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;//更加详细的描述这个端点一些情况就像我们定义一个编号房间,描述房间里大概有多少人之类的信息。
SDApp_epDesc.latencyReq = noLatencyReqs;//同上,也是描述信息
afRegister( &SDApp_epDesc );//这个函数必须要调用才能完成整个挂钩操作
发送
if(0==P1_1){/*按钮3按下*/
char theMessageData[] = {3};
TestAPP_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //设置为16位地址模式
TestAPP_DstAddr.addr.shortAddr = 0x0000; // 目标网络地址
TestAPP_DstAddr.endPoint = 7; //目标端点
AF_DataRequest(&TestAPP_DstAddr, //目标地址
&TestAPP_epDesc, // 端点描述
0x0001, // 簇ID
1,// 消息数据的长度
(byte *)&theMessageData, // 字符串内容数组首地址
&TestAPP_TransID,// 发送次数计数
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS);
}
抓包分析
- APS Dest. Endpoint : 0x07 【目标地址7号端点】
- APS Cluster Id:0x0001 【7号端点的0001簇】
- APS Src. Endpoint : 0x0C 【源地址11号端点】
单播发送案例
案例描述
- 终端模块:应用层绑定端点11,有三个按键
- 按键1:按下后向协调器、端点7、簇1,发送字符3
- 按键2:按下后向协调器、端点7、簇2,发送字符4
- 按键3:按下后向协调器、端点8、簇1,发送字符5
- 协调器模块:在无线数据接收时间处理函数中,处理终端发送的数据包,判断端点、簇,然后做出响应
- 端点7,簇1:LED1亮灭
- 端点7,簇2:LED2亮灭
- 端点8,簇1:LED3亮灭
实现代码
在之前【Z-stack协议栈使用】的代码基础上,完成本次案例
发送模块
将之前在UINT16 TestAPP_ProcessEvent( byte task_id, UINT16 events )
函数中,自己新添加的TestAPP_EVT
事件响应的内容替换为下面的内容
if ( events & TestAPP_EVT ){
if(0==P1_1){/*按钮3按下*/
char theMessageData[] = {3};
TestAPP_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //设置为16位地址模式
TestAPP_DstAddr.addr.shortAddr = 0x0000; // 目标网络地址
TestAPP_DstAddr.endPoint = 7; //目标端点
AF_DataRequest(&TestAPP_DstAddr, //目标地址
&TestAPP_epDesc, // 端点描述
0x0001, // 簇ID
1,// 消息数据的长度
(byte *)&theMessageData, // 字符串内容数组首地址
&TestAPP_TransID,// 发送次数计数
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS);
}
if(0==P2_0){/*按钮4按下*/
char theMessageData[] = {4};
TestAPP_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //设置为16位地址模式
TestAPP_DstAddr.addr.shortAddr = 0x0000; // 目标网络地址
TestAPP_DstAddr.endPoint = 7; //目标端点
AF_DataRequest(&TestAPP_DstAddr, //目标地址
&TestAPP_epDesc, // 端点描述
0x0002, // 簇ID
1,// 消息数据的长度
(byte *)&theMessageData, // 字符串内容数组首地址
&TestAPP_TransID,// 发送次数计数
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS);
}
if(0==P0_5){/*按钮5按下*/
char theMessageData[] = {5};
TestAPP_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //设置为16位地址模式
TestAPP_DstAddr.addr.shortAddr = 0x0000; // 目标网络地址
TestAPP_DstAddr.endPoint = 8; //目标端点
AF_DataRequest(&TestAPP_DstAddr, //目标地址
&TestAPP_epDesc, // 端点描述
0x0001, // 簇ID
1,// 消息数据的长度
(byte *)&theMessageData, // 字符串内容数组首地址
&TestAPP_TransID,// 发送次数计数
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS);
}
return (events ^ TestAPP_EVT);
}
接收模块
- 定义一个变量
- 端点绑定,在
TestAPP_Init
函数中,做如下修改
//端点7
TestAPP_epDesc.endPoint = 7; //TestAPP_ENDPOINT;
TestAPP_epDesc.task_id = &TestAPP_TaskID;
TestAPP_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&TestAPP_SimpleDesc;
TestAPP_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &TestAPP_epDesc );
//端点8
TestAPP_epDesc_8.endPoint = 8; //TestAPP_ENDPOINT;
TestAPP_epDesc_8.task_id = &TestAPP_TaskID;
TestAPP_epDesc_8.simpleDesc
= (SimpleDescriptionFormat_t *)&TestAPP_SimpleDesc;
TestAPP_epDesc_8.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &TestAPP_epDesc_8 );
- 将
void TestAPP_MessageMSGCB( afIncomingMSGPacket_t *pkt )
函数中的内容换成下面的
void TestAPP_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
// 端点7
if(7 == pkt->endPoint){
switch(pkt->clusterId){// 判断是哪个簇
case 0x0001:
LS164_BYTE(pkt->cmd.Data[0]);
P1SEL &=0XFE;//1111 1110 LED1
P1DIR |=0X01;//
P1_0 ^=1;
break;
case 0x0002:
LS164_BYTE(pkt->cmd.Data[0]);
P0SEL &=0XFD;// 1111 1101;
P0DIR |=0X02;
P0_1 ^=1;
break;
}
}
// 端点8
if(8 == pkt->endPoint){
switch(pkt->clusterId){
case 0x0001:
LS164_BYTE(pkt->cmd.Data[0]);
P0SEL &=0XEF;// 1110 1111 LED3
P0DIR |=0X10;
P0_4 ^=1;
break;
}
}
}