首页 > 学院 > 开发设计 > 正文

12 关于端点(Endpoint)、簇(clusterId)以及规范(ProfileID)

2019-11-08 03:09:10
字体:
来源:转载
供稿:网友

Endpoint

1、他是一个字节编号的,数据收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点。

2、端点要使用必须要和模块里的某个任务挂钩定义;

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

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

结合代码,定义端点和任务挂钩在基础实验的代码里是那些代码

SimonApp.c

void SimonApp_Init( byte task_id ) //定义了10号端点并且和这个模块的应用层任务挂钩

{..// Fill out the endpoint description. SimonApp_epDesc.endPoint = 10;//SimonApp_ENDPOINT; 此端点编号为10 SimonApp_epDesc.task_id = &SimonApp_TaskID; 和我们应用层任务挂钩 SimonApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc;//更加详细的描述这个端点一些情况就像我们定义一个编号房间,描述房间里大概有多少人之类的信息。 SimonApp_epDesc.latencyReq = noLatencyReqs;//差不多 // Register the endpoint description with the AF afRegister( &SimonApp_epDesc );//这个函数必须要调用才能完成整个挂钩操作..}

端点描述符,代码里一个结构体SimonApp_epDesc

所以,基本实验是0xA406 10 <—–>0x0000 10 无线数据包发出去以后,首先目标协调器模块的网络地址0x0000对上了,协调器可以拿到这个无线数据包。在底层任务,判断10号端点房间已经定义且和应用层任务挂钩,那么这个无线数据包发送一个消息到们应用层任务 。

case AF_INCOMING_MSG_CMD: SimonApp_MessageMSGCB( MSGpkt ); break;

在消息处理里,把hello Simon 通过串口送出去 Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);

端点就相当于一个房间的门牌号!!!

簇 ClusterID

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

结合代码发送模块: 在发送模块里,我们用的数据发送源端点,也是10,所以我们也定义这个10端点也挂钩应用层任务,原则上,外部给我们终端模块10号端点来数据,也会进入终端应用层任务事件处理 函数里。而我们这个端点仅仅这里作为发送模块,但是我们要实用10端点,必须要挂钩定义。

发送帧里面的东西在代码里体现:

byte SimonApp_TransID; // This is the unique message ID (counter) SimonApp.c全局变量,记录我们应用层任务发送的数据包的个数

void SimonApp_Init( byte task_id ){.. SimonApp_TransID = 0;..} if(0==P1_1) {//按钮3按下 char theMessageData[] ="Hello lao da"; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000;//接收模块的网络地址 // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint =SimonApp_ENDPOINT ;//接收模块的端点房间号 //SimonApp_epDesc 结构体 端点描述符有源端点的信息,也是10 AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, SimonApp_CLUSTERID,//目标端点镞,房间里的接收人数据宏是1,2个字节,所以在射频帧里面是0x0001 (byte)osal_strlen( theMessageData ) + 1,//发送字符串的长度 (byte *)&theMessageData,//字符串内容数组的首地址 &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); P1SEL &=0Xfe;// 1111 1110 P1DIR |=0X01; P1_0 ^=1;

再发送方总体框架:

if ( events & SimonApp_MY_EVT ) { if(0==P1_1) {//按钮3按下 char theMessageData[] ={3}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 7; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0001, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } if(0==P2_0) {//按钮4按下 char theMessageData[] ={4}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 7; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0002, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } if(0==P0_5) {//按钮5按下 char theMessageData[] ={5}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 6; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0001, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } return (events ^ SimonApp_MY_EVT); }

在接收方可使用如下代码识别具体端点、具体簇:

void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ){ if ( 7 == pkt->endPoint ) { switch ( pkt->clusterId ) { case 0x0001: // "the" message #if defined( LCD_SUPPORTED ) HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" ); #elif defined( WIN32 ) WPRINTSTR( pkt->cmd.Data ); #endif Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED1 ^= 1; break; case 0x0002: Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED2 ^= 1; break; } } if ( 6 == pkt->endPoint ) { switch ( pkt->clusterId ) { case 0x0001: // "the" message #if defined( LCD_SUPPORTED ) HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" ); #elif defined( WIN32 ) WPRINTSTR( pkt->cmd.Data ); #endif Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED3 ^= 1; break; } }}

初始化函数里面有如下语句用来填充端点描述符和簇信息:

>// Fill out the endpoint description. SimonApp_epDesc.endPoint = 11;//SimonApp_ENDPOINT; SimonApp_epDesc.task_id = &SimonApp_TaskID; SimonApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc; SimonApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SimonApp_epDesc );

其中的

SimonApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc;

完成了簇信息表的构建,因为簇信息封装在SimonApp_SimpleDesc里面,这里面却只是起到一个信息表的作用!方便数据到来的时候查询相关信息表!但真正的一个房间(端点)有多少人(簇),却是在SimonApp_MessageMSGCB函数中判断数据包携带的clusterId成员时决定的!!!

具体的SimonApp_SimpleDesc相关定义如下:

// This list should be filled with application specific Cluster IDs.const cId_t SimonApp_ClusterList[SimonApp_MAX_CLUSTERS] ={ SimonApp_CLUSTERID};const SimpleDescriptionFormat_t SimonApp_SimpleDesc ={ SimonApp_ENDPOINT, // int Endpoint; SimonApp_PROFID, // uint16 AppProfId[2]; SimonApp_DEVICEID, // uint16 AppDeviceId[2]; SimonApp_DEVICE_VERSION, // int AppDevVer:4; SimonApp_FLAGS, // int AppFlags:4; SimonApp_MAX_CLUSTERS, // byte AppNumInClusters; (cId_t *)SimonApp_ClusterList, // byte *pAppInClusterList; SimonApp_MAX_CLUSTERS, // byte AppNumInClusters; (cId_t *)SimonApp_ClusterList // byte *pAppInClusterList;};

规范

也叫作属性(ProfileID),实际上他就是代表不同类型的应用具有不同的ProfileID,这些表现在有效载荷里面!所以不同协议栈版本主要区别就是这个属性不同而已!!!

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

#define SimonApp_PROFID 0x0F04 在端点描述符里有提到,所以在无线数据包(抓包)里有看到相关的信息!!

综合实例

终端节点–发送

Enddevice.c

填充端点,和应用挂钩void SimonApp_Init( byte task_id ){ SimonApp_TaskID = task_id; SimonApp_NwkState = DEV_INIT; SimonApp_TransID = 0; ... ... // Fill out the endpoint description. SimonApp_epDesc.endPoint = 11;//SimonApp_ENDPOINT; SimonApp_epDesc.task_id = &SimonApp_TaskID; SimonApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc; SimonApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SimonApp_epDesc ); ... ...}处理按键事件 按键通过自定义的中断函数设置SimonApp_MY_EVT 事件,导致调用以下代码:if ( events & SimonApp_MY_EVT ) { if(0==P1_1) {//按钮3按下 char theMessageData[] ={3}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 7; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0001, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } if(0==P2_0) {//按钮4按下 char theMessageData[] ={4}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 7; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0002, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } if(0==P0_5) {//按钮5按下 char theMessageData[] ={5}; SimonApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SimonApp_DstAddr.addr.shortAddr = 0x0000; // Take the first endpoint, Can be changed to search through endpoints SimonApp_DstAddr.endPoint = 6; AF_DataRequest( &SimonApp_DstAddr, &SimonApp_epDesc, 0x0001, 1,//(byte)osal_strlen( theMessageData ) + 1, (byte *)&theMessageData, &SimonApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); } return (events ^ SimonApp_MY_EVT); }

协调器–接收

填充端点、绑定应用层任务 SimonAPP.cvoid SimonApp_Init( byte task_id ){... ...// Fill out the endpoint description. SimonApp_epDesc.endPoint = 7;//SimonApp_ENDPOINT; SimonApp_epDesc.task_id = &SimonApp_TaskID; SimonApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc; SimonApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SimonApp_epDesc ); /*=========================================================================*/ // Fill out the endpoint description. SimonApp_epDesc1.endPoint = 6;//SimonApp_ENDPOINT; SimonApp_epDesc1.task_id = &SimonApp_TaskID; SimonApp_epDesc1.simpleDesc = (SimpleDescriptionFormat_t *)&SimonApp_SimpleDesc; SimonApp_epDesc1.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SimonApp_epDesc1 );... ... }接收到数据以后,判断是属于哪一个端点、属于哪一个簇void SimonApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ){ if ( 7 == pkt->endPoint ) { switch ( pkt->clusterId ) { case 0x0001: Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED1 ^= 1; break; case 0x0002: Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED2 ^= 1; break; } } if ( 6 == pkt->endPoint ) { switch ( pkt->clusterId ) { case 0x0001: // "the" message #if defined( LCD_SUPPORTED ) HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" ); #elif defined( WIN32 ) WPRINTSTR( pkt->cmd.Data ); #endif Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength); LS164_BYTE(pkt->cmd.Data[0]); MYLED3 ^= 1; break; } }}

这里才是真正的判断一个房间有哪些人,具体数据又属于谁!!实际上与初始化的时候指定的簇数组无关!!!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表