查看: 6742|回复: 8

关于协议栈中绑定流程的一点认识(二)

[复制链接]
shaomengchao 发表于 2010-12-8 01:29:55 | 显示全部楼层 |阅读模式
本帖最后由 shaomengchao 于 2010-12-8 01:36 编辑

在ZDApp_ProcessMsgCBs中首先调用的是ZDO_ParseEndDeviceBindReq处理消息,其实这个就是将inMsg里的封装信息传到bindReq里。为我们后面的关键ZDO_MatchEndDeviceBind调用做准备。下面我们仔细分析ZDO_MatchEndDeviceBind函数。
     void ZDO_MatchEndDeviceBind( ZDEndDeviceBind_t *bindReq )
{
  zAddrType_t dstAddr;
  uint8 sendRsp = FALSE;
  uint8 status;

  // Is this the first request?
  if ( matchED == NULL ) // 假设之前没有节点提出End_Device_Bind_req,这个match是空的
  {
    // Create match info structure
    matchED = (ZDMatchEndDeviceBind_t *)osal_mem_alloc( sizeof ( ZDMatchEndDeviceBind_t ) );
    if ( matchED )
    {
      // Clear the structure
      osal_memset( (uint8 *)matchED, 0, sizeof ( ZDMatchEndDeviceBind_t ) );

      // Copy the first request's information
      if ( !ZDO_CopyMatchInfo( &(matchED->ed1), bindReq ) )
      {

        status = ZDP_NO_ENTRY;
        sendRsp = TRUE;
      }
/*
matched是个关键的结构体,里面包含了coordinator节点存储的bind表的信息
typedef struct
{
  ZDEndDeviceBind_t ed1;  
  ZDEndDeviceBind_t ed2;
  uint8  state;            // One of the above states
  uint8  sending;         // 0 - not sent, 1 - unbind, 2 bind - expecting response
  uint8  transSeq;
  uint8  ed1numMatched;
  uint16 *ed1Matched;
  uint8  ed2numMatched;
  uint16 *ed2Matched;
}
上面的函数将我们从bindReq获取的bind节点1的信息也就是我们之前说的节点1的nwk地址、ieee地址、ep和簇列表存入了ed1

*/

    }
    else
    {
      status = ZDP_NO_ENTRY; //分配失败 立即发送End_Device_Bind_rsp帧,当然帧里面status 是 ZDP_NO_ENTRY
      sendRsp = TRUE;
    }

    if ( !sendRsp )
    {
      // Set into the correct state      
      matchED->state = ZDMATCH_WAIT_REQ; //如果成功了当前状态为等待节点2的End_Device_Bind_req请求

      // Setup the timeout
      APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB );//定时
    }   
  }
  else //这里就是节点2在节点1发出End_Device_Bind_req请求后重复之前的过程进入的部分
  {
      matchED->state = ZDMATCH_SENDING_BINDS; //节点1已经在matched表里面了

      // Copy the 2nd request's information
      if ( !ZDO_CopyMatchInfo( &(matchED->ed2), bindReq ) )
      {
        status = ZDP_NO_ENTRY;
        sendRsp = TRUE;
      }

      // Make a source match for ed1
      matchED->ed1numMatched = ZDO_CompareClusterLists(
                  matchED->ed1.numOutClusters, matchED->ed1.outClusters,
                  matchED->ed2.numInClusters, matchED->ed2.inClusters, ZDOBuildBuf );
      if ( matchED->ed1numMatched )
      {
        // Save the match list
        matchED->ed1Matched = osal_mem_alloc( (short)(matchED->ed1numMatched * sizeof ( uint16 )) );
        if ( matchED->ed1Matched )
        {
          osal_memcpy( matchED->ed1Matched, ZDOBuildBuf, (matchED->ed1numMatched * sizeof ( uint16 )) );
        }
        else
        {
          // Allocation error, stop
          status = ZDP_NO_ENTRY;
          sendRsp = TRUE;
        }
      }

      // Make a source match for ed2
      matchED->ed2numMatched = ZDO_CompareClusterLists(
                  matchED->ed2.numOutClusters, matchED->ed2.outClusters,
                  matchED->ed1.numInClusters, matchED->ed1.inClusters, ZDOBuildBuf );
      if ( matchED->ed2numMatched )
      {
        // Save the match list
        matchED->ed2Matched = osal_mem_alloc( (short)(matchED->ed2numMatched * sizeof ( uint16 )) );
        if ( matchED->ed2Matched )
        {
          osal_memcpy( matchED->ed2Matched, ZDOBuildBuf, (matchED->ed2numMatched * sizeof ( uint16 )) );
        }
        else
        {
          // Allocation error, stop
          status = ZDP_NO_ENTRY;
          sendRsp = TRUE;
        }
      }
这里是比较节点1和节点2的输入和输出簇列表,节点1输出簇列表和节点2输入簇列表簇号相同的将存入matchED->ed1Matched里
而节点2输出簇列表和节点1输入簇列表簇号相同的将存入matchED->ed2Matched,如果没有分配成功的则发出
End_Device_Bind_rsp帧,帧状态为 ZDP_NO_ENTRY
      if ( (sendRsp == FALSE) && (matchED->ed1numMatched || matchED->ed2numMatched) )
      {
        // Do the first unbind/bind state 之前如果一切顺利的话我们会进入这里
        ZDMatchSendState( ZDMATCH_REASON_START, ZDP_SUCCESS, 0 );
      }
      else
      {//如果没有匹配的则发出End_Device_Bind_rsp帧,帧状态为 ZDP_NO_MATCH
        status = ZDP_NO_MATCH;
        sendRsp = TRUE;
      }
  }

  if ( sendRsp )
  {
    // send response to this requester
    dstAddr.addrMode = Addr16Bit;
    dstAddr.addr.shortAddr = bindReq->srcAddr;
//
    ZDP_EndDeviceBindRsp( bindReq->TransSeq, &dstAddr, status, bindReq->SecurityUse );

    if ( matchED->state == ZDMATCH_SENDING_BINDS )
    {//发送End_Device_Bind_rsp帧
      // send response to first requester
      dstAddr.addrMode = Addr16Bit;
      dstAddr.addr.shortAddr = matchED->ed1.srcAddr;
      ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, status, matchED->ed1.SecurityUse );
    }

    // Process ended - release memory used
  //移除marched里的内容
    ZDO_RemoveMatchMemory();
  }
}
End_Device_Bind_rep绑定就是总体来说就是节点1的某个endpoint如果想与其他节点具有相同簇id的endpoint绑定,它先向coordinator发出请求,让coordinator将它的endpoint内容存入matched。如果在规定时间内有节点2做了同样的事,而它们的簇列表刚好有相同簇号的簇,于是它们就是能绑定了。具体绑定实现在 ZDMatchSendState里实现。而ZDMatchSendState真是个另人蛋疼的函数,里面利用它实现绑定,我们至少要3次调用它,真是麻烦死了。所以我们留到下次再说。
wuxiujiang 发表于 2010-12-8 09:44:30 | 显示全部楼层
支持!  来学习了……
outman 发表于 2010-12-8 10:05:01 | 显示全部楼层
本帖最后由 shaomengchao 于 2010-12-8 01:36 编辑


楼主这么晚还在写东西,佩服、佩服!
 楼主| shaomengchao 发表于 2010-12-8 17:51:02 | 显示全部楼层
回复 3# outman


    其实我每天中午12点起,晚上3点睡。熬夜不过是种习惯而已,让奥特曼见笑了。
xiaoyige 发表于 2011-1-27 16:40:39 | 显示全部楼层
顶顶顶顶顶顶
ylxren 发表于 2012-7-31 22:55:14 | 显示全部楼层
{:soso_e100:}
lizheng86312 发表于 2012-8-29 12:08:10 | 显示全部楼层
学到东西了。顶。。。
ccc_ccccc 发表于 2013-3-16 13:13:32 | 显示全部楼层
好复杂啊,亲……不过讲解的很好,赞一个
tlk214 发表于 2013-8-12 13:03:30 | 显示全部楼层
zigbee绑定流程学习(二),楼主万岁!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表