查看: 5122|回复: 4

SimpleApp数据发送及应答过程

[复制链接]
大愚 发表于 2012-9-30 09:53:37 | 显示全部楼层 |阅读模式
如何进入发送数据的过程在这里不讨论,直接看如何发送数据的。

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)本帖为原创,转载请注明出去。



outman 发表于 2012-9-30 15:25:58 | 显示全部楼层
楼主辛苦了,已经加V并赠送50飞币,多谢楼主的贡献
 楼主| 大愚 发表于 2012-9-30 15:48:35 | 显示全部楼层
谢谢奥特曼,这篇帖子没有验证的,还如有错误,还请高手指正!
zbee 发表于 2014-2-5 14:46:49 | 显示全部楼层
若发送成功,节点收到讯息的回应(AF_ACK_REQUEST)是在哪边做处理?一样是在zb_SendDataConfirm吗?
Hugo801122 发表于 2014-4-5 08:19:42 | 显示全部楼层
代码都贴出来,厉害!多谢!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表