Zstack的SerialApp 例子中,是怎么接受空气中的信息以及是怎样对信息进行处理的?接收了信息最终要用下面这个函数来处理,但是在哪使taskArrs[]中相对应的元素置为非零呢?也就是在哪产生了SYS_EVENT_MSG事件,并且附带消息为ZDO_CB_MSG。
/*********************************************************************
* @fn SerialApp_ProcessEvent
*
* @brief Generic Application Task event processor.
*
* @param task_id - The OSAL assigned task ID.
* @param events - Bit map of events to process.
*
* @return Event flags of all unprocessed events.
*/
UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
{
(void)task_id; // Intentionally unreferenced parameter
#if defined ( AUTO_BIND )
zAddrType_t txAddr;
#endif
if ( events & SYS_EVENT_MSG )
{
afIncomingMSGPacket_t *MSGpkt;
while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SerialApp_TaskID )) )
{
switch ( MSGpkt->hdr.event )
{
case ZDO_CB_MSG:
SerialApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
case KEY_CHANGE:
SerialApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
break;
case AF_INCOMING_MSG_CMD:
SerialApp_ProcessMSGCmd( MSGpkt );
break;
#if defined ( AUTO_BIND )
case ZDO_STATE_CHANGE:
SerialApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SerialApp_NwkState == DEV_ZB_COORD)
|| (SerialApp_NwkState == DEV_ROUTER)
|| (SerialApp_NwkState == DEV_END_DEVICE) )
{
HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
// Initiate an End Device Bind Request for the mandatory endpoint
txAddr.addrMode = Addr16Bit;
txAddr.addr.shortAddr = 0x0000; // Coordinator
ZDP_EndDeviceBindReq( &txAddr, NLME_GetShortAddr(),
SerialApp_epDesc.endPoint,
SERIALAPP_PROFID,
SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
FALSE );
}
break;
#endif
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt );
}
return ( events ^ SYS_EVENT_MSG );
}
if ( events & SERIALAPP_SEND_EVT )
{
SerialApp_Send();
return ( events ^ SERIALAPP_SEND_EVT );
}
if ( events & SERIALAPP_RESP_EVT )
{
SerialApp_Resp();
return ( events ^ SERIALAPP_RESP_EVT );
}
return ( 0 ); // Discard unknown events.
}
/*********************************************************************
* @fn SerialApp_ProcessZDOMsgs()
*
* @brief Process response messages
*
* @param none
*
* @return none
*/
static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
switch ( inMsg->clusterID )
{
case End_Device_Bind_rsp:
if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
{
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
#if defined(BLINK_LEDS)
else
{
// Flash LED to show failure
HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
}
#endif
break;
case Match_Desc_rsp:
{
ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
if ( pRsp )
{
if ( pRsp->status == ZSuccess && pRsp->cnt )
{
SerialApp_TxAddr.addrMode = (afAddrMode_t)Addr16Bit;
SerialApp_TxAddr.addr.shortAddr = pRsp->nwkAddr;
// Take the first endpoint, Can be changed to search through endpoints
SerialApp_TxAddr.endPoint = pRsp->epList[0];
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
osal_mem_free( pRsp );
}
}
break;
}
}
在哪里注册了函数要用SerialApp_ProcessEvent来处理空气中发来的消息???发出了SYS_EVENT_MSG事件,消息为ZDO_CB_MSG,在哪注册了???
在void SerialApp_Init( uint8 task_id )中明明写着,
ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );//
ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );
#define End_Device_Bind_rsp (End_Device_Bind_req | ZDO_RESPONSE_BIT)
#define End_Device_Bind_req ((uint16)0x0020)
#define ZDO_RESPONSE_BIT ((uint16)0x8000)
#define Match_Desc_rsp (Match_Desc_req | ZDO_RESPONSE_BIT)
#define Match_Desc_req ((uint16)0x0006)
#define ZDO_CB_MSG 0xD3 // ZDO incoming message callback
/*********************************************************************
* @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;
while ( pList )
{
if ( pList->taskID == taskID && pList->clusterID == clusterID )
return ( ZSuccess );
pLast = pList;
pList = (ZDO_MsgCB_t *)pList->next;
}
// Add to the list
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 );
}
typedef struct
{
void *next;
uint8 taskID;
uint16 clusterID;
} ZDO_MsgCB_t;
ZDO_MsgCB_t *zdoMsgCBs = (ZDO_MsgCB_t *)NULL;
uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr )该函数应该被调用后,然后才能执行UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events ),我是这样认为的!
貌似要有突破!!
void ZDApp_Init( uint8 task_id )
{
// Save the task ID
ZDAppTaskID = task_id;
// Initialize the ZDO global device short address storage
ZDAppNwkAddr.addrMode = Addr16Bit;
ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
// Check for manual "Hold Auto Start"
ZDAppCheckForHoldKey();
// Initialize ZDO items and setup the device - type of device to create.
ZDO_Init();
// Register the endpoint description with the AF
// This task doesn't have a Simple description, but we still need
// to register the endpoint.
afRegister( (endPointDesc_t *)&ZDApp_epDesc );
#if defined( ZDO_USERDESC_RESPONSE )
ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
// Start the device?
if ( devState != DEV_HOLD )
{
ZDOInitDevice( 0 );
}
else
{
ZDOInitDevice( ZDO_INIT_HOLD_NWK_START );
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, 0, 50, 500 );
}
// Initialize the ZDO callback function pointers zdoCBFunc[]
ZDApp_InitZdoCBFunc();
ZDApp_RegisterCBs();
} /* ZDApp_Init() */
。。。。好吧暂时没搞出来!
这个函数包括了对不同IDcluster的处理,以及回应。
void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
uint8 stat;
uint8 seqnb;
uint8 delay;
switch ( pkt->clusterId )
{
// A message with a serial data block to be transmitted on the serial port.
case SERIALAPP_CLUSTERID1:
// Store the address for sending and retrying.
osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
seqnb = pkt->cmd.Data[0];
// Keep message if not a repeat packet
if ( (seqnb > SerialApp_RxSeq) || // Normal
((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
{
// Transmit the data on the serial port.
if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
{
// Save for next incoming message
SerialApp_RxSeq = seqnb;
stat = OTA_SUCCESS;
}
else
{
stat = OTA_SER_BUSY;
}
}
else
{
stat = OTA_DUP_MSG;
}
// Select approproiate OTA flow-control delay.
delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;
// Build & send OTA response message.
SerialApp_RspBuf[0] = stat;
SerialApp_RspBuf[1] = seqnb;
SerialApp_RspBuf[2] = LO_UINT16( delay );
SerialApp_RspBuf[3] = HI_UINT16( delay );
osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT );
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
break;
// A response to a received serial data block.
case SERIALAPP_CLUSTERID2:
if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&
((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG)))
{
SerialApp_TxLen = 0;// 准备下一次发送
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT);
}
else
{
// Re-start timeout according to delay sent from other device.
delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay );
}
break;
default:
break;
}
}
参考:http://blog.163.com/a_hui8/blog/static/205830307201282085853248/
序列号问题:
第一种情况:
// Keep message if not a repeat packet
if ( (seqnb > SerialApp_RxSeq) || // Normal正常,是否是最新的数据
((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around不过还是不太懂??
第二种情况:
// A response to a received serial data block.
if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&//正常
((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG))) //成功或过期
static uint8 SerialApp_RxSeq;
SerialApp_RxSeq = 0xC3;