zigbee__AF_DataRequest函数详解

来源:互联网 发布:网络云盘哪个最好用 编辑:程序博客网 时间:2024/05/22 13:48

*********************************************************************
 * @fn      AF_DataRequest

     *dstAddr--发送目的地址+端点地址(端点号)和传送模式 
     *srcEP --源(答复或确认)终端的描述(比如操作系统中任务ID等)源EP 
     cID      --被Profile指定的有效的集群号 
     len       --发送数据长度 
     *buf      --发送数据缓冲区 
     *transID --任务ID号 
     options  --有效位掩码的发送选项 
     radius    --传送跳数,通常设置为AF_DEFAULT_RADIUS 
 */
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;
  }

#if !defined( REFLECTOR )
  if ( dstAddr->addrMode == afAddrNotPresent )
  {
    return afStatus_INVALID_PARAMETER;
  }
#endif

  // 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;
  
  req.profileID = ZDO_PROFILE_ID;

  if ( (pfnDescCB = afGetDescCB( srcEP )) )
  {
    uint16 *pID = (uint16 *)(pfnDescCB(
                                 AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint ));
    if ( pID )
    {
      req.profileID = *pID;
      osal_mem_free( pID );
    }
  }
  else if ( srcEP->simpleDesc )
  {
    req.profileID = srcEP->simpleDesc->AppProfId;
  }

  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;
  }

  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
  {
    if (len > afDataReqMTU( &mtu ) )
    {
      if (apsfSendFragmented)
      {
        stat = (*apsfSendFragmented)( &req );
      }
      else
      {
        stat = afStatus_INVALID_PARAMETER;
      }
    }
    else
    {
      stat = APSDE_DataReq( &req );
    }
  }


参数详解如下:

     其中 

1、afAddrType_t   *dstAddr 
     af地址类型
typedefstruct 
  union 
  { 
     uint16 shortAddr;             //短地址 
  }addr; 
  afAddrMode_t   addrMode;  //传送模式 
  byte     endPoint;                 //端点号 
}afAddrType_t; 


2、endPointDesc_t  *srcEP   
     端点描述
typedefstruct 
  byteendPoint;      //端点号 
  byte*task_id;      //那一个任务的端点号 (调用任务的ID)
  SimpleDescriptionFormat_t          *simpleDesc;  //简单的端点描述 
  afNetworkLatencyReq_tlatencyReq; 
}endPointDesc_t; 

3、SimpleDescriptionFormat_t 
      简单描述格式
typedefstruct 
  byte            EndPoint;                   //EP 
  uint16          AppProfId;                 //应用规范ID 
  uint16          AppDeviceId;              //特定规范ID的设备类型 
  byte            AppDevVer:4;              //特定规范ID的设备的版本 
  byte            Reserved:4;                 //AF_V1_SUPPORTusesforAppFlags:4. 
  byte            AppNumInClusters;       //输入簇ID的个数 
  cId_t          *pAppInClusterList;       //输入簇ID的列表 
  byte           AppNumOutClusters;        //输出簇ID的个数 
  cId_t          *pAppOutClusterList;      //输出簇ID的列表 
}SimpleDescriptionFormat_t; 

4、uint16   cID 

   ClusterID--具体应用串ID 

5、uint8            options 

    发送模式选项有如下选项 
    #defineAF_FRAGMENTED                                0x01 
    #defineAF_ACK_REQUEST                              0x10 
    #defineAF_DISCV_ROUTE                               0x20 
    #defineAF_EN_SECURITY                               0x40 
    #defineAF_SKIP_ROUTING                              0x80 
    其中AF_ACK_REQUEST为发送后需要接收方的确认 

6、uint8      radius 

   传输跳数或传输半径,默认值为10 


 
AF_DataRequest( &SampleApp_Flash_DstAddr, zigbee地址 Nwk Addr+End Point
&SampleApp_epDesc,End Point Descr
SAMPLEAPP_FLASH_CLUSTERID,cluster ID
3,  len
buffer, *buf
&SampleApp_TransID,*transID
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )


关键参数说明:

SampleApp_Flash_DstAddr :目的地址,你要把数据发到哪里肯定要先知道他的地址吧,就像你要给人写信,总得先知道对方的地址吧,这里也是一样的,描述了目的设备的地址

End Point Descr : 对于这个参数,我的理解,就是一个更精确的地址,因为一个node可以有多个Endpoint,就像你写信到底给那个人一样。目的地址标识了,他在那,而这个参数就是说这个人到底是谁了。

cluster ID :关于这个参数,可以这样理解。……呃……这样吧,就是大的包裹,还是纸质的普通信封,还是……总之你要根据这个采取不同的措施,例如,比如是个大的包裹,你需要一把剪刀来打开,如果是一个普通的纸质信封,直接撕开就好,如果是一份加密信函……总之,你会根据这个参数的不同采取不同的措施

len :数据的长度,可以理解为信的内容有几页

*buf:数据内容。可以理解为信的内容

*transID: 序列号:可以理解为邮戳的日期

……那两个就不说了,是路由相关啦……

呵呵……自己说都有点绕……

[转载]发送函数AF_DataRequest(转载)

  (2012-04-01 14:14:13)
转载
标签:  

转载

 
原文地址:发送函数AF_DataRequest(转载)作者:seth

 Z-Stack 中发送数据通过在应用层调用函数void SampleApp_SendFlashMessage( uint16 flashTime )完成,其中flash Time 为发送的数据,这个函数在应用中通过调用

afStatus_t  AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,

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

                                              uint8 options, uint8 radius )

函数完成数据的发送。如果熟悉了其中的每个参数的含义,就可以很灵活的使用发送函数发送自己的数据。

     第一个参数 dstAddr,在文件AF.h,该参数是一个结构体的指针。在该参数中除了指定了网络地址外,还需要指定目的地址的模式参数。
 

typedef struct
{
  union
  {
    uint16 shortAddr;
  } addr;
  afAddrMode_t addrMode; //afAddrMode_t是一个枚举类型 模式参数

  byte endPoint; //指定的端点号 端点241—254保留端点 范围 1-240

} afAddrType_t;

下面的是 afAddrMode_t结构体的定义
 

typedef enum
{
  afAddrNotPresent = AddrNotPresent, //按照绑定表进行绑定传输

  afAddr16Bit = Addr16Bit, // 指定目标网络地址进行单薄传输 16位

  afAddrGroup = AddrGroup, // 组播传输

  afAddrBroadcast = AddrBroadcast //广播传输

} afAddrMode_t;


enum
{
  AddrNotPresent = 0,
  AddrGroup = 1,
  Addr16Bit = 2,
  Addr64Bit = 3, // 指定IEEE地址进行单播传输 64位

  AddrBroadcast = 15
};

    注意:ZigBee设备有两种类型的地址。一种是64IEEE地址(物理),即MAC地址,另一种是16位网络地址。

64位地址使全球唯一的地址,设备将在它的生命周期中一直拥有它。它通常由制造商或者被安装时设置。这些地址由IEEE来维护和分配。

16为网络地址是当设备加入网络后由协调器或路由器分配的。它在网络中是唯一的,用来在网络中鉴别设备和发送数据。

第二个参数endPointDesc_t *srcEP,也是一个结构体的指针,源网络地址描述,每个终端都必须要有一个ZigBeezz的简单描述。

 

typedef struct
{
  byte endPoint; //端点号

  byte *task_id; // Pointer to location of the Application task ID.

  SimpleDescriptionFormat_t *simpleDesc; //设备的简单描述

  afNetworkLatencyReq_t latencyReq; //枚举结构 必须用 noLatencyReqs 填充

} endPointDesc_t;

目标设备的简单描述结构
typedef struct
{
  byte EndPoint; //EP ID (EP=End Point)

  uint16 AppProfId; // profile ID(剖面ID)

  uint16 AppDeviceId; // Device ID

  byte AppDevVer:4; //Device Version 0x00 为 Version 1.0

  byte Reserved:4; // AF_V1_SUPPORT uses for AppFlags:4.

  byte AppNumInClusters; //终端支持的输入簇的个数

  cId_t *pAppInClusterList;        //指向输入Cluster ID列表的指针

  byte AppNumOutClusters;    //输出簇的个数

  cId_t *pAppOutClusterList; //指向输出Cluseter ID列表的指针

} SimpleDescriptionFormat_t;

typedef enum
{
  noLatencyReqs,
  fastBeacons,
  slowBeacons
} afNetworkLatencyReq_t;


第三个参数:uint16 cID ID

第四个参数:len  要发送的数据的长度

第五个参数:uint8 *buf  指向发送数据缓冲的指针

第六个参数:uint8 *transID事务序列号指针。如果消息缓存发送,这个函数将增加这个数字

第七个参数:发送选项,可以由下面一项,或几项相或得到

AF_ACK_REQUEST 0x10 要求APS应答,这是应用层的应答,只在直接发送(单播)时使用。

AF_DISCV_ROUTE 0x20 总要包含这个选项

AF_SKIP_ROUTING 0x80 设置这个选项将导致设备跳过路由而直接发送消息。终点设备将不向其父亲发送消息。在直接发送(单播)和广播消息时很好用。

第八个参数:uint8 radius 最大的跳数,用默认值AF_DEFAULT_RADIUS

返回值:

该函数的返回值:afStatus_t类型 枚举型的,成功 

 

typedef enum
{
  afStatus_SUCCESS,
  afStatus_FAILED = 0x80,
  afStatus_MEM_FAIL,
  afStatus_INVALID_PARAMETER
} afStatus_t;

下面是这个函数完整的源代码:
 

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;
  }
  
#if !defined( REFLECTOR )
  if ( dstAddr->addrMode == afAddrNotPresent )
  {
    return afStatus_INVALID_PARAMETER;
  }
#endif 

  // Verify destination address 判断目的地址

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

  // 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 != afAddrGroup &&
            dstAddr->addrMode != afAddrNotPresent )
  {
    return afStatus_INVALID_PARAMETER;
  }
  req.dstAddr.addrMode = dstAddr->addrMode;

  req.profileID = ZDO_PROFILE_ID;

  if ( (pfnDescCB = afGetDescCB( srcEP )) )
  {
    uint16 *pID = (uint16 *)(pfnDescCB(
                                 AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint ));
    if ( pID )
    {
      req.profileID = *pID;
      osal_mem_free( pID );
    }
  }
  else if ( srcEP->simpleDesc )
  {
    req.profileID = srcEP->simpleDesc->AppProfId;
  }

  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;
  }

  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 = TRUE;//(uint8)((options & AF_DISCV_ROUTE) ? 1 : 0);

  req.radiusCounter = radius;

  if (len > afDataReqMTU( &mtu ) )
  {
    if (apsfSendFragmented)
    {
      req.txOptions |= AF_FRAGMENTED | APS_TX_OPTIONS_ACK;
      stat = (*apsfSendFragmented)( &req );
    }
    else
    {
      stat = afStatus_INVALID_PARAMETER;
    }
  }
  else
  {
    stat = APSDE_DataReq( &req );
  }

  
  if ( (req.dstAddr.addrMode == Addr16Bit) &&
       (req.dstAddr.addr.shortAddr == NLME_GetShortAddr()) )
  {
    afDataConfirm( srcEP->endPoint, *transID, stat );
  }

  if ( stat == afStatus_SUCCESS )
  {
    (*transID)++;
  }

  return (afStatus_t)stat;
}

0 0
原创粉丝点击