端点(endPoint)

一个端点就是一个应用

  1. 一个字节编号,数据收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点。
  2. 端点要使用必须要和模块里的某个任务挂钩定义;

首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数 来取这个无线数据包里面的有用数据。

3、一个端点只能挂钩在一个任务上,而一个任务可以挂钩多个端点,且端点对所有的任务是公用的,定义一个少一个。

一个端点加入可以挂钩在多个任务上,那么接收模块接到无线数据时候,这个时候同一个端点有多个任务事件处理函数去处理,不合理;一个任务上挂多个端点(6 7 挂应用层任务),发送给协调器模块的6 7端点的数据都会进入到应用层任务事件处理函数里来,仅仅做个判断到底是投递到6房间还是7号房间就可以了。

簇(ClusterID)

  1. 一类应用会包含多个应用,每个应用都有独特的属性和命令,通常按照应用把最相关的一些属性和命令归到一起,称为簇(Cluster)

  2. 簇就是相当于端点房间里面的人,是接收最终的目标。这东西是2个字节编号,在射频发送的时候,必须要指定接收模块的簇,发送模块不需要指定。

属性

属性就是在应用层有用的数据载荷,做专门规定最小单元

结合发送代码分析

端点定义

image-20231127225321299

1
2
3
4
5
6
7
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 );//这个函数必须要调用才能完成整个挂钩操作

发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
}

抓包分析

image-20231127225506265

  • 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亮灭

image-20231127230753825

实现代码

在之前【Z-stack协议栈使用】的代码基础上,完成本次案例

发送模块

将之前在UINT16 TestAPP_ProcessEvent( byte task_id, UINT16 events )函数中,自己新添加的TestAPP_EVT事件响应的内容替换为下面的内容

image-20231127232124339

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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);
}

接收模块

  1. 定义一个变量

image-20231127231733432

  1. 端点绑定,在TestAPP_Init函数中,做如下修改

image-20231127231641888

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//端点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 );
  1. void TestAPP_MessageMSGCB( afIncomingMSGPacket_t *pkt )函数中的内容换成下面的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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;
}
}
}

image-20231127232237859