AF_DataRequest()

/*********************************************************************

 * @fn      AF_DataRequest

 *

 * @brief   Common functionality for invoking APSDE_DataReq() for both

 *          SendMulti and MSG-Send.

 *

 * input parameters

 *

 * @param  *dstAddr - Full ZB destination address: Nwk Addr + End Point.     //网络地址??

 * @param  *srcEP - Origination (i.e. respond to or ack to) End Point Descr.

 * @param   cID - A valid cluster ID as specified by the Profile.

 * @param   len - Number of bytes of data pointed to by next param.

 * @param  *buf - A pointer to the data bytes to send.

 * @param  *transID - A pointer to a byte which can be modified and which will

 *                    be used as the transaction sequence number of the msg.

 * @param   options - Valid bit mask of Tx options.

 * @param   radius - Normally set to AF_DEFAULT_RADIUS.

 *

 * output parameters

 *

 * @param  *transID - Incremented by one if the return value is success.

 *

 * @return  afStatus_t - See previous definition of afStatus_... types.

 */

uint8 AF_DataRequestDiscoverRoute = TRUE;

afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,

                           uint16 cID, uint16 len, uint8 *buf, uint8 *transID,

                           uint8 options, uint8 radius )

{

  pDescCB pfnDescCB;

  ZStatus_t stat;

  APSDE_DataReq_t req;

  afDataReqMTU_t mtu;

 

  // Verify source end point

//源端点 是否有效

  if ( srcEP == NULL )

  {

    return afStatus_INVALID_PARAMETER;

  }

 

//AddrNotPresent检查是否未开启绑定功能

#if !defined( REFLECTOR )

  if ( dstAddr->addrMode == afAddrNotPresent )

  {

    return afStatus_INVALID_PARAMETER;

  }

#endif

 

  // Check if route is available before sending data

//AddrNotPresent检查是否未开启绑定功能

  if ( options & AF_LIMIT_CONCENTRATOR  )

  {

    if ( dstAddr->addrMode != afAddr16Bit )     //仅对单播 进行检查

    {

      return ( afStatus_INVALID_PARAMETER );

    }

 

// First, make sure the destination is not its self, then check for an existing route.

//确认其目的地址 不是 本节点地址且 检查链路

    if ( (dstAddr->addr.shortAddr != NLME_GetShortAddr())

        && (RTG_CheckRtStatus( dstAddr->addr.shortAddr, RT_ACTIVE, (MTO_ROUTE | NO_ROUTE_CACHE) ) != RTG_SUCCESS) )

    {

      // A valid route to a concentrator wasn't found

      return ( afStatus_NO_ROUTE );

    }

  }

 

  // Validate broadcasting

//检验目标地址是否广播地址,如果地址和模式有冲突,修正广播地址

//仅对单播和广播模式进行检查

  if ( ( dstAddr->addrMode == afAddr16Bit     ) ||

       ( dstAddr->addrMode == afAddrBroadcast )    )

  {

    // Check for valid broadcast values

    if( ADDR_NOT_BCAST != NLME_IsAddressBroadcast( dstAddr->addr.shortAddr )  )

    {

      // Force mode to broadcast

      dstAddr->addrMode = afAddrBroadcast;

    }

    else

    {

      // Address is not a valid broadcast type

      if ( dstAddr->addrMode == afAddrBroadcast )

      {

        return afStatus_INVALID_PARAMETER;

      }

    }

  }

  else if ( dstAddr->addrMode != afAddr64Bit &&

            dstAddr->addrMode != afAddrGroup &&

            dstAddr->addrMode != afAddrNotPresent )

  {

    return afStatus_INVALID_PARAMETER;

  }

 

  // Set destination address

//根据地址模式 选择 扩展地址还是网络地址通讯

  req.dstAddr.addrMode = dstAddr->addrMode;

  if ( dstAddr->addrMode == afAddr64Bit )

    osal_cpyExtAddr( req.dstAddr.addr.extAddr, dstAddr->addr.extAddr );

  else

    req.dstAddr.addr.shortAddr = dstAddr->addr.shortAddr;

 

//规范ID选择

  req.profileID = ZDO_PROFILE_ID;

// 如果源端点有回调函数,调用回调函数修改规范ID

  if ( (pfnDescCB = afGetDescCB( srcEP )) )

  {

    uint16 *pID = (uint16 *)(pfnDescCB(

                                 AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint ));

    if ( pID )

    {

      req.profileID = *pID;

      osal_mem_free( pID );

    }

  }

//如果端点有简单描述符,覆盖掉默认规范ID

  else if ( srcEP->simpleDesc )

  {

    req.profileID = srcEP->simpleDesc->AppProfId;

  }

 

//检查txOption

//AF_ACK_REQUEST    0x10 要求APS应答,仅在单播时使用(会多出一个APS层的应答数据帧)。

//AF_DISCV_ROUTE 0x20 总要包含这个选项

//AF_SKIP_ROUTING 0x80 设置这个选项将导致设备跳过路由而直接发送消息。终点设备将不向其父亲发送消息。在单播和广播消息时很好用(测试情况需要在通讯范围内的两个节点才能完成直接通讯)。

 

 req.txOptions = 0;

//单播条件下的应答

  if ( ( options & AF_ACK_REQUEST              ) &&

       ( req.dstAddr.addrMode != AddrBroadcast ) &&

       ( req.dstAddr.addrMode != AddrGroup     )    )

  {

    req.txOptions |=  APS_TX_OPTIONS_ACK;

  }

//绕过父路由

  if ( options & AF_SKIP_ROUTING )

  {

    req.txOptions |=  APS_TX_OPTIONS_SKIP_ROUTING;

  }

//安全选项

  if ( options & AF_EN_SECURITY )

  {

    req.txOptions |= APS_TX_OPTIONS_SECURITY_ENABLE;

    mtu.aps.secure = TRUE;

  }

  else

  {

    mtu.aps.secure = FALSE;

  }

 

  if ( options & AF_PREPROCESS )

  {

    req.txOptions |=  APS_TX_OPTIONS_PREPROCESS;

  }

 

  mtu.kvp = FALSE;

//应用层各项参数配置

  req.transID       = *transID;

  req.srcEP         = srcEP->endPoint;

  req.dstEP         = dstAddr->endPoint;

  req.clusterID     = cID;

  req.asduLen       = len;

  req.asdu          = buf;

  req.discoverRoute = AF_DataRequestDiscoverRoute;//(uint8)((options & AF_DISCV_ROUTE) ? 1 : 0);

  req.radiusCounter = radius;

#if defined ( INTER_PAN )

  req.dstPanId      = dstAddr->panId;

 

  if ( StubAPS_InterPan( dstAddr->panId, dstAddr->endPoint ) )

  {

    if ( len > INTERP_DataReqMTU() )

    {

      stat = afStatus_INVALID_PARAMETER;

    }

    else

    {

      stat = INTERP_DataReq( &req );

    }

  }

  else

#endif // INTER_PAN

  {

//基于输入参数的最大可发送字节数,根据长度选择发送方式 

//uint8 afDataReqMTU( afDataReqMTU_t* fields 返回能发送的最大字节数

//fields -要发送的消息类型参数

 

    if (len > afDataReqMTU( &mtu ) )

    {

      if (apsfSendFragmented)

      {

        stat = (*apsfSendFragmented)( &req );  //分割发送?

      }

      else

      {

        stat = afStatus_INVALID_PARAMETER;

      }

    }

    else

    {

      stat = APSDE_DataReq( &req );   //应用层数据发送

    }

  }

 

  /*

   * If this is an EndPoint-to-EndPoint message on the same device, it will not

   * get added to the NWK databufs. So it will not go OTA and it will not get

   * a MACCB_DATA_CONFIRM_CMD callback. Thus it is necessary to generate the

   * AF_DATA_CONFIRM_CMD here. Note that APSDE_DataConfirm() only generates one

   * message with the first in line TransSeqNumber, even on a multi message.

   * Also note that a reflected msg will not have its confirmation generated

   * here.

   */

/*对于点对点通讯且目的地址是其本身,则不需要将数据写入NWK层的数据缓冲区,即不需要触发无线而引起MACCB_DATA_CONFIRM_CMD回调。

在该处产生响应的 AF_DATA_CONFIRM_CMD 消息命令,且不会产生附带的消息。

*/

  if ( (req.dstAddr.addrMode == Addr16Bit) &&

       (req.dstAddr.addr.shortAddr == NLME_GetShortAddr()) )

  {

    afDataConfirm( srcEP->endPoint, *transID, stat );

  }

 

//如果应用层发送成功 时间戳 自加1

  if ( stat == afStatus_SUCCESS )

  {

    (*transID)++;

  }

  return (afStatus_t)stat;

}


参考链接:http://blog.sina.com.cn/s/blog_70b26edc0100mgu7.html

                http://www.feibit.com/forum.php?mod=viewthread&tid=3598

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值