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;