关于ZStack-CC2530-2.3.0-1.4.0中simpleApp例子的 终端节点入网以及绑定操作(三)

上一节讲到终端节点向协调器发送一个绑定请求,在此之前呢,我们需要将协调器的绑定允许,这样终端节点才可以绑定成功~。好,我们选择workplace为simpleCollectorEB,然后我们按下s2键。在sapi层找到处理该事件的函数,找到SAPI_ProcessEvent中的如下代码:

 

 case KEY_CHANGE:
#if ( SAPI_CB_FUNC )
         zb_HandleKeys( ((keyChange_t *)pMsg)->state,((keyChange_t *)pMsg)->keys );
#endif
         break;

 

进入到zb_HandleKeys处理键盘事件的函数中去看看:

 

  if ( keys & HAL_KEY_SW_2)
    {
     if ( myAppState == APP_INIT )//这时应用状态已经不是初始化状态了,而是APP_START,执行else语句
     {
       // In the init state, keys are used to indicate the logicalmode.
       // Key 2 starts device as a router

       zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8),&logicalType );
       if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
       {
         logicalType = ZG_DEVICETYPE_ROUTER;
         zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8),&logicalType);
       }

       zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8),&startOptions );
       startOptions = ZCD_STARTOPT_AUTO_START;
       zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8),&startOptions );
       zb_SystemReset();
     }
     else
     {
       // Turn OFF Allow Bind mode indefinitely
       zb_AllowBind( 0xff );//执行允许绑定函数
       HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );//关闭LED_1
     }
    }

 

进入允许绑定函数中,看看源代码:

 

void zb_AllowBind ( uint8 timeout )
{

  osal_stop_timerEx(sapi_TaskID,ZB_ALLOW_BIND_TIMER);//停止ZB_ALLOW_BIND_TIMER事件

  if ( timeout == 0 )//不成立,执行else中的语句
  {
   afSetMatch(sapi_epDesc.simpleDesc->EndPoint,FALSE);
  }
  else
  {
   afSetMatch(sapi_epDesc.simpleDesc->EndPoint,TRUE);//执行次函数,即允许设置匹配描述符。绑定的实质呢就是寻找匹配的描述符,允许设置匹配描述符就是允许绑定
    if ( timeout!= 0xFF )
    {
     if ( timeout > 64 )
     {
       timeout = 64;
     }
     osal_start_timerEx(sapi_TaskID, ZB_ALLOW_BIND_TIMER,timeout*1000);
    }
  }
  return;
}

好,协调器允许绑定以后,我们要看一下终端节点怎么绑定协调器的,选择workplace为simpleSensorEB,终端节点在zb_StartConfirm函数时向sapi层发送了一个MY_FIND_COLLECTOR_EVT事件,来绑定一个协调器,我们看看具体代码,MY_FIND_COLLECTOR_EVT事件是在用户事件中,并找到:

 

if ( event & MY_FIND_COLLECTOR_EVT )
  {
    // Find andbind to a collector device
   zb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL);//该函数的作用就是找到并且绑定协调器
  }

 

我们可以进去看看源代码:

 

void zb_BindDevice ( uint8 create, uint16 commandId, uint8*pDestination )
{
  zAddrType_t destination;
  uint8 ret = ZB_ALREADY_IN_PROGRESS;

  if ( create )//成立
  {
    if(sapi_bindInProgress ==0xffff)//初始化时确实将sapi_bindInProgress赋值为0xffff
    {
     if ( pDestination )//地址指针为空,执行下面else里的语句
     {
       destination.addrMode = Addr64Bit;
       osal_cpyExtAddr( destination.addr.extAddr, pDestination );

       ret = APSME_BindRequest( sapi_epDesc.endPoint, commandId,
                                           &destination, sapi_epDesc.endPoint );

       if ( ret == ZSuccess )
       {
         // Find nwk addr
         ZDP_NwkAddrReq(pDestination, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
         osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
       }
     }
     else
     {
       ret = ZB_INVALID_PARAMETER;
       destination.addrMode = Addr16Bit;//16位网络地址
       destination.addr.shortAddr =NWK_BROADCAST_SHORTADDR;//设置为广播地址0xffff
       if ( ZDO_AnyClusterMatches( 1, &commandId,sapi_epDesc.simpleDesc->AppNumOutClusters,
                                               sapi_epDesc.simpleDesc->pAppOutClusterList ))//该函数的作用是寻找到一个可以绑定的协调器,并且从输出簇中看看是否匹配。
       {
         // Try to match with a device in the allow bind mode
         ret = ZDP_MatchDescReq( &destination,NWK_BROADCAST_SHORTADDR,
             sapi_epDesc.simpleDesc->AppProfId, 1,&commandId, 0, (cId_t *)NULL, 0);//广播发送匹配描述符请求
       }
       else if ( ZDO_AnyClusterMatches( 1, &commandId,sapi_epDesc.simpleDesc->AppNumInClusters,
                                               sapi_epDesc.simpleDesc->pAppInClusterList )))//该函数的作用是寻找到一个可以绑定的协调器,并且从输入簇中看看是否匹配。

       {
         ret = ZDP_MatchDescReq( &destination,NWK_BROADCAST_SHORTADDR,
             sapi_epDesc.simpleDesc->AppProfId, 0, (cId_t *)NULL,1, &commandId, 0 );//广播发送匹配描述符请求
       }

       if ( ret == ZB_SUCCESS )
       {
         // 设置一段时间来保证完全绑定。

#if ( ZG_BUILD_RTR_TYPE )
         osal_start_timerEx(sapi_TaskID, ZB_BIND_TIMER,AIB_MaxBindingTime);
#else
         // AIB_MaxBindingTime is not defined for an End Device
         osal_start_timerEx(sapi_TaskID, ZB_BIND_TIMER,zgApsDefaultMaxBindingTime);
#endif
         sapi_bindInProgress = commandId;
         return; // dont send cback event
       }
     }
    }

   SAPI_SendCback( SAPICB_BIND_CNF, ret, commandId );
  }
  else
  {
    // Removelocal bindings for the commandId
   BindingEntry_t *pBind;

    // Loopthrough bindings an remove any that match the cluster
    while (pBind = bindFind( sapi_epDesc.simpleDesc->EndPoint,commandId, 0 ) )
    {
     bindRemoveEntry(pBind);
    }
   osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
  }
  return;
}

 

协调器收到此匹配描述符请求会进行处理,我们看是怎么处理的,工作空间选择为协调器。在ZDO层找到ZDApp_event_loop函数中:

if ( events & SYS_EVENT_MSG )
  {
    while ((msg_ptr = osal_msg_receive( ZDAppTaskID )) )
    {
     ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );

     // Release the memory
     osal_msg_deallocate( msg_ptr );
    }

    // Returnunprocessed events
    return(events ^ SYS_EVENT_MSG);
  }

 

进入ZDApp_ProcessOSALMsg函数中:

 

void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
  // Data Confirmation message fields
  uint8sentEP;      // This should always be 0
  uint8 sentStatus;
  afDataConfirm_t *afDataConfirm;
  uint8 tmp;

  switch ( msgPtr->event )
  {
    // IncomingZDO Message
    caseAF_INCOMING_MSG_CMD:
     ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr );
     break;

 

继续进入到ZDP_IncomingData函数中:

 

void ZDP_IncomingData( afIncomingMSGPacket_t *pData )
{

//下面是对消息进行解析
  uint8 x = 0;
  uint8 handled;
  zdoIncomingMsg_t inMsg;

  inMsg.srcAddr.addrMode = Addr16Bit;
  inMsg.srcAddr.addr.shortAddr =pData->srcAddr.addr.shortAddr;
  inMsg.wasBroadcast =pData->wasBroadcast;
  inMsg.clusterID =pData->clusterId;
  inMsg.SecurityUse =pData->SecurityUse;

  inMsg.asduLen =pData->cmd.DataLength-1;
  inMsg.asdu =pData->cmd.Data+1;
  inMsg.TransSeq =pData->cmd.Data[0];
  inMsg.macDestAddr =pData->macDestAddr;

  handled = ZDO_SendMsgCBs(&inMsg );

#if (defined MT_ZDO_CB_FUNC)
#if !defined MT_TASK
  if (zgZdoDirectCB)
#endif
  {
   MT_ZdoDirectCB( pData, &inMsg );
  }
#endif

  while ( zdpMsgProcs[x].clusterID != 0xFFFF)
  {
    if (zdpMsgProcs[x].clusterID == inMsg.clusterID)//看看有没有这种clusterID类型的请求
    {
     zdpMsgProcs[x].pFn( &inMsg);//如果有,进入到此函数中,zdpMsgProcs是个结构体数组,点击进入看看
     return;
    }
    x++;
  }

  // Handle unhandled messages
  if ( !handled )
   ZDApp_InMsgCB( &inMsg );
}

 

 

typedef struct
{
 uint16               clusterID;
 pfnZDPMsgProcessor   pFn;
} zdpMsgProcItem_t;

 

CONST zdpMsgProcItem_t zdpMsgProcs[] =
{
#if ( RFD_RCVC_ALWAYS_ON==TRUE ) || ( ZG_BUILD_RTR_TYPE )
  // These aren't processed by sleeping enddevices.
  {NWK_addr_req,          zdpProcessAddrReq },
  {Device_annce,          ZDO_ProcessDeviceAnnce },
#endif
  {IEEE_addr_req,         zdpProcessAddrReq },
  {Node_Desc_req,         ZDO_ProcessNodeDescReq },
  {Power_Desc_req,        ZDO_ProcessPowerDescReq },
  {Simple_Desc_req,       ZDO_ProcessSimpleDescReq },
  {Active_EP_req,         ZDO_ProcessActiveEPReq },
  {Match_Desc_req,        ZDO_ProcessMatchDescReq},//在这找到Match_Desc_req,对应的处理函数                                                                   是ZDO_ProcessMatchDescReq
#if defined ( ZDO_MGMT_NWKDISC_RESPONSE )
  {Mgmt_NWK_Disc_req,     ZDO_ProcessMgmtNwkDiscReq },
#endif
#if defined ( ZDO_MGMT_LQI_RESPONSE )&& ( ZG_BUILD_RTR_TYPE )
  {Mgmt_Lqi_req,          ZDO_ProcessMgmtLqiReq },
#endif
#if defined ( ZDO_MGMT_RTG_RESPONSE )&& ( ZG_BUILD_RTR_TYPE )
  {Mgmt_Rtg_req,          ZDO_ProcessMgmtRtgReq },
#endif
#if defined ( ZDO_MGMT_BIND_RESPONSE )&& defined ( REFLECTOR )
  {Mgmt_Bind_req,         ZDO_ProcessMgmtBindReq },
#endif
#if defined ( ZDO_MGMT_JOINDIRECT_RESPONSE )&& ( ZG_BUILD_RTR_TYPE )
  {Mgmt_Direct_Join_req,  ZDO_ProcessMgmtDirectJoinReq },
#endif
#if defined ( ZDO_MGMT_LEAVE_RESPONSE )
  {Mgmt_Leave_req,        ZDO_ProcessMgmtLeaveReq },
#endif
#if defined ( ZDO_MGMT_PERMIT_JOIN_RESPONSE ) && ( ZG_BUILD_RTR_TYPE )
  {Mgmt_Permit_Join_req,  ZDO_ProcessMgmtPermitJoinReq },
#endif
#if defined ( ZDO_USERDESC_RESPONSE )
  {User_Desc_req,         ZDO_ProcessUserDescReq },
#endif
#if defined ( ZDO_USERDESCSET_RESPONSE )
  {User_Desc_set,         ZDO_ProcessUserDescSet },
#endif
#if defined ( ZDO_SERVERDISC_RESPONSE )
  {Server_Discovery_req,  ZDO_ProcessServerDiscReq },
#endif
  {0xFFFF, NULL} // Last
};

 

 

进入到 ZDO_ProcessMatchDescReq 函数中,看看如何对匹配描述符请求进行处理

 

void ZDO_ProcessMatchDescReq( zdoIncomingMsg_t *inMsg )
{
  uint8 epCnt = 0;
  uint8 numInClusters;
  uint16 *inClusters = NULL;
  uint8 numOutClusters;
  uint16 *outClusters = NULL;
  epList_t *epDesc;
  SimpleDescriptionFormat_t *sDesc = NULL;
  uint8 allocated;
  uint8 *msg;
  uint16 aoi;
  uint16 profileID;

  // Parse the incoming message
  msg = inMsg->asdu;
  aoi = BUILD_UINT16( msg[0], msg[1] );
  profileID = BUILD_UINT16( msg[2], msg[3]);
  msg += 4;

  if ( ADDR_BCAST_NOT_ME ==NLME_IsAddressBroadcast(aoi) )
  {
   ZDP_MatchDescRsp( inMsg->TransSeq,&(inMsg->srcAddr),ZDP_INVALID_REQTYPE,
                         ZDAppNwkAddr.addr.shortAddr, 0, NULL,inMsg->SecurityUse );
   return;
  }
  else if ( (ADDR_NOT_BCAST ==NLME_IsAddressBroadcast(aoi)) &&(aoi != ZDAppNwkAddr.addr.shortAddr) )
  {
   ZDP_MatchDescRsp( inMsg->TransSeq,&(inMsg->srcAddr),ZDP_INVALID_REQTYPE,
                            ZDAppNwkAddr.addr.shortAddr, 0, NULL,inMsg->SecurityUse );
   return;
  }

  if ((numInClusters = *msg++)&&
     (inClusters = (uint16*)osal_mem_alloc( numInClusters * sizeof(uint16 ) )))
  {
    msg =ZDO_ConvertOTAClusters( numInClusters, msg, inClusters );
  }
  else
  {
   numInClusters = 0;
  }

  if ((numOutClusters = *msg++)&&
     (outClusters = (uint16 *)osal_mem_alloc( numOutClusters * sizeof(uint16 ) )))
  {
    msg =ZDO_ConvertOTAClusters( numOutClusters, msg, outClusters );
  }
  else
  {
   numOutClusters = 0;
  }

  // First count the number of endpoints thatmatch.
  epDesc = epList;
  while ( epDesc )
  {
    // Don'tsearch endpoint 0 and check if response is allowed
    if (epDesc->epDesc->endPoint != ZDO_EP&&(epDesc->flags&eEP_AllowMatch))
    {
     if ( epDesc->pfnDescCB )
     {
       sDesc = (SimpleDescriptionFormat_t*)epDesc->pfnDescCB( AF_DESCRIPTOR_SIMPLE,epDesc->epDesc->endPoint );
       allocated = TRUE;
     }
     else
     {
       sDesc =epDesc->epDesc->simpleDesc;
       allocated = FALSE;
     }

     if ( sDesc &&sDesc->AppProfId == profileID )
     {
       uint8 *uint8Buf = (uint8 *)ZDOBuildBuf;

       // If there are no search input/ouput clusters - respond
       if ( ((numInClusters == 0) &&(numOutClusters == 0))
           // Are there matching input clusters?
            || (ZDO_AnyClusterMatches( numInClusters, inClusters,
                 sDesc->AppNumInClusters,sDesc->pAppInClusterList ))
           // Are there matching output clusters?
            || (ZDO_AnyClusterMatches( numOutClusters, outClusters,
                 sDesc->AppNumOutClusters,sDesc->pAppOutClusterList))    )
       {
         // 没有端点匹配处理.
         uint8 bufLen = sizeof( ZDO_MatchDescRspSent_t ) + (numOutClusters +numInClusters) * sizeof(uint16);
         ZDO_MatchDescRspSent_t *pRspSent = (ZDO_MatchDescRspSent_t *)osal_msg_allocate( bufLen );

         if (pRspSent)
         {
           pRspSent->hdr.event = ZDO_MATCH_DESC_RSP_SENT;
           pRspSent->nwkAddr =inMsg->srcAddr.addr.shortAddr;
           pRspSent->numInClusters = numInClusters;
           pRspSent->numOutClusters = numOutClusters;

           if (numInClusters)
           {
             pRspSent->pInClusters = (uint16*) (pRspSent +1);
             osal_memcpy(pRspSent->pInClusters, inClusters,numInClusters * sizeof(uint16));
           }
           else
           {
             pRspSent->pInClusters = NULL;
           }

           if (numOutClusters)
           {
             pRspSent->pOutClusters = (uint16*)(pRspSent + 1) +numInClusters;
             osal_memcpy(pRspSent->pOutClusters, outClusters,numOutClusters * sizeof(uint16));
           }
           else
           {
             pRspSent->pOutClusters = NULL;
           }

           osal_msg_send(*epDesc->epDesc->task_id, (uint8*)pRspSent );
         }

         uint8Buf[epCnt++] = sDesc->EndPoint;
       }
     }

     if ( allocated )
       osal_mem_free( sDesc );
    }
    epDesc =epDesc->nextDesc;
  }

  // 当至少有一个匹配时,发送消息

  if ( epCnt )
  {
    if (ZSuccess == ZDP_MatchDescRsp( inMsg->TransSeq,&(inMsg->srcAddr),ZDP_SUCCESS,
             ZDAppNwkAddr.addr.shortAddr, epCnt, (uint8 *)ZDOBuildBuf,inMsg->SecurityUse ) )//发送匹配描述符响应给终端节点。
    {
#if defined( LCD_SUPPORTED )
     HalLcdWriteScreen( "Match Desc Req", "Rsp Sent" );
#endif
    }
  }
  else
  {
#if defined( LCD_SUPPORTED )
   HalLcdWriteScreen( "Match Desc Req", "Non Matched" );
#endif
  }

  if ( inClusters != NULL )
   osal_mem_free( inClusters );
  if ( outClusters != NULL )
   osal_mem_free( outClusters );
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: zstack-cc2530-2.3.0-1.4.0是一个基于CC2530芯片的ZigBee协议栈版本,用于构建低功耗、无线传感器网络。它支持ZigBee协议的各种功能,如网络组建、设备发现、数据传输等。同时,它还提供了丰富的API接口和开发工具,方便开发人员进行应用开发和调试。 ### 回答2: zstack-cc2530-2.3.0-1.4.0是一款嵌入式无线协议栈软件,主要应用于物联网领域的传感器、控制设备等智能硬件,使其能够实现无线通信、数据采集和云端对接。该协议栈基于IEEE 802.15.4标准,采用Zigbee协议,支持网络拓扑结构包括星型、点对点、树状和网状等。 zstack-cc2530-2.3.0-1.4.0的特点是具有高度的可靠性、稳定性和安全性。其采用AES加密算法,能够保证通信数据的隐私安全;同时支持信号质量监测和链路质量反馈,能够实现网络拓扑的优化和故障检测等功能;此外,该协议栈还支持OTA升级和协议栈配置等高级功能,便于对智能硬件进行远程维护和管理。 除此之外,zstack-cc2530-2.3.0-1.4.0还具有易于开发和适配的特点。该协议栈提供了丰富的API接口和开发工具包,支持多种开发环境和硬件平台,方便开发人员进行二次开发和定制化,大大降低了开发成本和周期。同时,该协议栈还通过Zigbee联盟的认证,确保了其在标准兼容性、互操作性和稳定性等方面的表现。 总之,zstack-cc2530-2.3.0-1.4.0是一款功能强大、易于开发和适配、具有高可靠性和安全性的无线协议栈软件,可以广泛应用于物联网领域的智能硬件。 ### 回答3: zstack-cc2530-2.3.0-1.4.0 是一种无线通信模块,它是针对 TI 公司的 CC2530 系统级芯片设计的。该模块运行在 2.4GHz ISM 频段,可以实现高质量的数据传输,并且在无线网络实现高度的可靠性和安全性。该模块具有协同处理器、内存、收发器、MAC 和 PHY 等多种功能,可以应用于多种物联网场景。 zstack-cc2530-2.3.0-1.4.0 支持运行 ZigBee 网络协议栈,并提供了丰富的接口和 API,以便用户能够快速、轻松地开发具有丰富功能的 ZigBee 产品。该模块基于 Z-Stack 协议栈,支持 ZDO、ZCL 等多个协议,可以实现灵活、可靠、高效的无线通信。 该模块还支持 OTA(空升级)功能,可以让用户通过无线网络升级设备固件。同时,该模块还具有低功耗模式,可以使设备的电池寿命更长。 总之,zstack-cc2530-2.3.0-1.4.0 是一种高度可靠、灵活、安全性强的无线通信模块,可以为物联网应用提供强有力的支持,并且具有广泛的适用性和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值