如何进入发送数据的过程在这里不讨论,直接看如何发送数据的。
void zb_HandleOsalEvent( uint16 event )
{
uint8 pData[2];
...
if ( event & MY_REPORT_TEMP_EVT )
{
pData[0] = TEMP_REPORT;//数据类型
pData[1] = myApp_ReadTemperature();//具体数据
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, 2, pData, 0, AF_ACK_REQUEST, 0 );
//0XFFFE为绑定地址,SENSOR_REPORT_CMD_ID为具簇标识,AF_ACK_REQUEST代表需要数据接收节点的应答
osal_start_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod );
//再次启动MY_REPORT_TEMP_EVT事件,进行下次数据的发送,这样达到循环的目的
HalLedSet (HAL_LED_1, HAL_LED_MODE_TOGGLE);
}
...
}
接下来看zb_SendDataRequest这个函数
void zb_SendDataRequest ( uint16 destination, uint16 commandId, uint8 len,
uint8 *pData, uint8 handle, uint8 txOptions, uint8 radius )
{
afStatus_t status;
afAddrType_t dstAddr;
txOptions |= AF_DISCV_ROUTE;//将所有的数据发送过程都加上路由发现过程
// Set the destination address
if (destination == ZB_BINDING_ADDR)//如果为绑定地址
{
dstAddr.addrMode = afAddrNotPresent;
}
else
{
// Use short address
dstAddr.addr.shortAddr = destination;
dstAddr.addrMode = afAddr16Bit;
if ( ADDR_NOT_BCAST != NLME_IsAddressBroadcast( destination ) )
{
txOptions &= ~AF_ACK_REQUEST;//广播不支持响应 因为很多节点可以收到广播消息 接收那个广播消息的响应呢,没办法确定的
}
}
dstAddr.panId = 0; // Not an inter-pan message. 不理解,请高人指点
dstAddr.endPoint = sapi_epDesc.simpleDesc->EndPoint; // Set the endpoint不理解,请高人指点
// Send the message
status = AF_DataRequest(&dstAddr, &sapi_epDesc, commandId, len,
pData, &handle, txOptions, radius);
if (status != afStatus_SUCCESS)//如果status发送不成功
{
//status代表的是发送节点是否将数据发送出去的状态,只要发送出去了,不管接收节点是否收到,其状态都是afStatus_SUCCESS
SAPI_SendCback( SAPICB_DATA_CNF, status, handle );
}
}
下面的分两条线路来讨论
一、发送节点数据发送失败(不管接收节点是否收到数据)
void SAPI_SendCback( uint8 event, uint8 status, uint16 data )
{
sapi_CbackEvent_t *pMsg;
pMsg = (sapi_CbackEvent_t *)osal_msg_allocate( sizeof(sapi_CbackEvent_t) );
if( pMsg )
{
pMsg->hdr.event = event;
pMsg->hdr.status = status;
pMsg->data = data;
osal_msg_send( sapi_TaskID, (uint8 *)pMsg );
}
}
上面函数中将data(0),event(SAPICB_DATA_CNF),status(不成功)这三个数据进行消息封装,发送到应用层,接下来我们到应用层去看如何处理这个消息的。应用层的系统消息事件里有如下代码。
case SAPICB_DATA_CNF:
SAPI_SendDataConfirm( (uint8)((sapi_CbackEvent_t *)pMsg)->data,
((sapi_CbackEvent_t *)pMsg)->hdr.status );
break;
将通过消息传送过来的data(0),status(不成功)继续向下传送。
void SAPI_SendDataConfirm( uint8 handle, uint8 status )
{
...
{
#if ( SAPI_CB_FUNC )
zb_SendDataConfirm( handle, status );
#endif
}
}
void zb_SendDataConfirm( uint8 handle, uint8 status )
{
(void)handle; // Intentionally unreferenced parameter 在这里可以修改代码,针对handle这个数据进行处理
if ( status != ZSuccess )//如果发送数据的状态不成功
{
// Remove bindings to the existing collector 删除绑定
zb_BindDevice( FALSE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL );
myAppState = APP_START;//应用状态回滚
myApp_StopReporting();//停止发送数据
// Start process of finding new collector with minimal delay
osal_start_timerEx( sapi_TaskID, MY_FIND_COLLECTOR_EVT, 1 );//重新发起绑定
}
else //发送成功,可以根据需要自行修改
{
}
}
二、发送节点发送数据成功,并且接收节点已经接收到数据,因为开启了应用请求,故接收节点对发送节点的应答会在下面这个函数进行处理:zb_SendDataConfirm。zb_SendDataConfirm这个函数就是上面的分析的函数,故两条线路最终都归结到同一个函数来处理了,第一条线可以根据应用的需要进行更改。但是本条线路协议栈在后台做了很多事情,屏蔽了很多代码,大家只要知道发送响应在这个函数里进行处理即可。
说明:
(1)上面分析仅是个人理解,没有经过验证,不正确的地方,请高手指正,我会在第一时间进行修改。
(2)本帖为原创,转载请注明出去。
|