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

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

  1. 填充端点,和应用挂钩

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 );

  ... ...
}
  1. 处理按键事件
    按键通过自定义的中断函数设置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);
  }

协调器–接收

  1. 填充端点、绑定应用层任务
    SimonAPP.c

void 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 );

... ... 

}
  1. 接收到数据以后,判断是属于哪一个端点、属于哪一个簇
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;
      }
  }
}

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

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值