1) 消息的注册
首先我们需要申请注册,协议栈将我们的申请备案保存,然后当有消息事件时,会通知申请过的任务ID。
在函数void ZDApp_RegisterCBs( void )【ZDApp.c】中进行注册,由函数ZDO_RegisterForZDOMsg()【ZDProfile.c】将cluster ID(即OTA接收到的消息,如NWK_addr_rsp)和任务ID进行注册,当有响应消息时会触发ZDO_CB_MSG事件通知应用层。
/*********************************************************************
* @fn ZDO_RegisterForZDOMsg
*
* @brief Call this function to register of an incoming over the air ZDO message - probably a response message but requests can also be received. Messages are delivered to the task with ZDO_CB_MSG as the message ID.
* @param taskID - Where you would like the message delivered
* @param clusterID - What message?
*
* @return ZSuccess - successful, ZMemError if not
*/
ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID )
{
ZDO_MsgCB_t *pList;
ZDO_MsgCB_t *pLast;
ZDO_MsgCB_t *pNew;
// Look for duplicate
pList = pLast = zdoMsgCBs; //指针指向ZDO消息列表
while ( pList ) //先查找,如果有注册则返回成功
{
if ( pList->taskID == taskID && pList->clusterID == clusterID )
return ( ZSuccess );
pLast = pList;
pList = (ZDO_MsgCB_t *)pList->next; //指向下一个链表节点
}
// Add to the list 如果原ZDO消息列表中无注册,添加一个新的注册记录
pNew = (ZDO_MsgCB_t *)osal_mem_alloc( sizeof ( ZDO_MsgCB_t ) );
if ( pNew ) //若分配空间成功
{
pNew->taskID = taskID;
pNew->clusterID = clusterID;
pNew->next = NULL;
if ( zdoMsgCBs ) //若原来的链表非空,在链表后面添加
{
pLast->next = pNew;
}
else //若原来的链表为空,作为链表的第一项
zdoMsgCBs = pNew;
return ( ZSuccess );
}
else
return ( ZMemError );
}
该函数在中ZDApp_RegisterCBs调用:
/*********************************************************************
* @fn ZDApp_RegisterCBs()
* @brief Process response messages
* @param none
* @return none
*/
void ZDApp_RegisterCBs( void )
{
#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );
#endif
#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );
#endif
#if ZG_BUILD_COORDINATOR_TYPE
ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );
ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );
ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );
#endif
#if defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );
ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );
#endif
}
ZDO_RegisterForZDOMsg()
Call this function to request an over-the-air message. A copy of the message will be sent to a task in an OSALmessage. The task receiving the message can either parse the message themselves or call a ZDO Parser function toparse the message. Only response messages have a ZDO Parser function.After registering for a message, and the message is received (OTA), the message is sent to the application/task as aZDO_CB_MSG (OSAL Msg). The body of the message (zdoIncomingMsg_t – defined in ZDProfile.h) contains the
OTA message.
程序原型(prototype)
ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID );
参数详解(Parameter Details)
taskID – the application’s task ID. This will be used to send the OSAL message.
clusterID – the over the air message’s clusterID that you would like to receive (example: NWK_addr_rsp).
These are defined in ZDProfile.h.
Return
ZStatus_t –status values defined in ZStatus_t in ZComDef.h,
2) 去掉ZDO消息的注册
/*********************************************************************
* @fn ZDO_RemoveRegisteredCB
* @brief Call this function if you don't want to receive the incoming message.
* @param taskID - Where the messages are being delivered.
* @param clusterID - What message?
* @return ZSuccess - successful, ZFailure if not found
*/
ZStatus_t ZDO_RemoveRegisteredCB( uint8 taskID, uint16 clusterID )
{
3) 向注册的taskID发送消息ZDO_CB_MSG
/*********************************************************************
* @fn ZDO_SendMsgCBs
*
* @brief This function sends messages to registered tasks.
* Local to ZDO and shouldn't be called outside of ZDO.
*
* @param inMsg - incoming message
*
* @return TRUE if sent to at least 1 task, FALSE if not
*/
uint8 ZDO_SendMsgCBs( zdoIncomingMsg_t *inMsg )
{
uint8 ret = FALSE;
ZDO_MsgCB_t *pList = zdoMsgCBs;
while ( pList )
{
if ( pList->clusterID == inMsg->clusterID )
{
zdoIncomingMsg_t *msgPtr;
// Send the address to the task
msgPtr = (zdoIncomingMsg_t *)osal_msg_allocate( sizeof( zdoIncomingMsg_t ) + inMsg->asduLen );
if ( msgPtr )
{
// copy struct
osal_memcpy( msgPtr, inMsg, sizeof( zdoIncomingMsg_t ));
if ( inMsg->asduLen )
{
msgPtr->asdu = (byte*)(((byte*)msgPtr) + sizeof( zdoIncomingMsg_t ));
osal_memcpy( msgPtr->asdu, inMsg->asdu, inMsg->asduLen );
}
msgPtr->hdr.event = ZDO_CB_MSG;
osal_msg_send( pList->taskID, (uint8 *)msgPtr );
ret = TRUE;
}
}
pList = (ZDO_MsgCB_t *)pList->next;
}
return ( ret );
}
4) 消息处理GenericApp_ProcessZDOMsgs()【在应用层源文件中】
switch ( MSGpkt->hdr.event )
{
case ZDO_CB_MSG:
GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
注意SampleApp_MessageMSGCB()【SampleApp.c应用对应的源文件】函数一般是对应消息AF_INCOMING_MSG_CMD的处理函数
switch ( MSGpkt->hdr.event )
{
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;