您的位置:首页 > 产品设计 > UI/UE

AF_DataRequest()

2018-01-09 10:50 423 查看
/*********************************************************************

 * @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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: