AF_DataRequest函数 解读

作用

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

原型

afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t \*srcEP,*

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

​                       *uint8 options, uint8 radius )

参数解析

afAddrType_t *dstAddr

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

其定义如下:

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;

SimpleDescriptionFormat_t

其中,SimpleDescriptionFormat_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;
  • 端口

    • 1个字节的编号(0---255),数据接收和发送的基本单元(数据发送时必须指定接收端的某个端点),在模块通信的时候,发送和接收双方必须指定端点号和网络地址
    • 点要是用必须定义注册,并且挂钩到摸个任务(如应用层任务)
    • 1个端点只能挂钩一个任务(同一个端点的数据在多个任务里执行,这样也不合理),一个任务可以挂钩多个端点(一个任务我挂载 5 6 7三个端点 是可以的),端点对所有任务是公用的 定义一个少一个(总数是一定的,比如定义了6号端点 就不能再定义6号端点了)
    • 每个端点可以定义多个簇:端点就相当于房子,簇就相当于房子里的人

    • 发送的时候指定是哪个端点里的那个簇(相当于房子里的哪个人),簇不需要注册 发送函数如下:

    • MyApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;//设置模式
      
      MyApp_DstAddr.addr.shortAddr = 0x0000;//设置接收网络地址
      
      MyApp_DstAddr.endPoint = 12;//MyApp_ENDPOINT;//端点
      
      char theMessageData[] = "endPoint = 12 CLUSTERID=12";//数据地址
      
      AF_DataRequest(&MyApp_DstAddr,//目标地址
      
                    &MyApp_epDesc,//端点描述符
      
                    12,//MyApp_CLUSTERID,//端点镞
      
                    (byte)osal_strlen( theMessageData ) + 1,//多少个字节
      
                    (byte *)&theMessageData,//发送数组的首地址
      
                    &MyApp_TransID,//发送计数每发送一次加一
      
                    AF_DISCV_ROUTE,
      
                    AF_DEFAULT_RADIUS ) ;
      

afNetworkLatencyReq_t

typedef enum
{
  noLatencyReqs,
  fastBeacons,
  slowBeacons
} afNetworkLatencyReq_t;

用于控制用于控制Zigbee设备发送Beacon消息的速率。它定义了三个枚举值:

  • noLatencyReqs 表示该设备没有进行网络延迟请求。
  • fastBeacons 表示该设备发送Beacon消息的速率较快,即高速Beacons。
  • slowBeacons 表示该设备发送Beacon消息的速率为标准速率,即普通Beacons。

这个枚举类型在Z-Stack协议栈中的某些源文件中出现过,主要用于控制Beacon消息的发送速率,从而影响Zigbee网络的性能和功耗。例如,在af.c文件中,该枚举类型用于控制Beacon消息的传输速率和延迟请求的状态等。


  • Beacon,信标。通信术语,例

一般无线网卡都是做所谓的被动式扫描(passive scanning),也叫背景扫描。

开启OS下的无线网络管理程序或是XP内建管理程序,无线网络卡其实都在从ISM 频道一直轮番扫描。

等待扫到无线基地台(如AP)的Beacon 才会显示这区域有哪些SSID。而基地台的Beacon传送频繁frame 会比较占用无线频宽资源。

cID

ID

len

要发送的数据的长度

*buf

指向发送数据缓冲的指针

*transID

事务序列号指针。如果消息缓存发送,这个函数将增加这个数字

options

  • AF_ACK_REQUEST 0x10 要求APS应答,这是应用层的应答,只在直接发送(单播)时使用。
  • AF_DISCV_ROUTE 0x20 总要包含这个选项
  • AF_SKIP_ROUTING 0x80 设置这个选项将导致设备跳过路由而直接发送消息。终点设备将不向其父亲发送消息。在直接发送(单播)和广播消息时很好用。

radius

最大的跳数,用默认值AF_DEFAULT_RADIUS

  • 含义

    在Zigbee网络中,AF_DataRequest()是一个函数,用于向目标节点发送一个Zigbee数据的帧。 radius是一个参数,它指定了数据帧的传输范围,既可以通过设置数据传输的距离,也可以指定跳数(hops)。
    具体来说,radius的作用是控制Zigbee数据帧从源节点向目标节点传输的距离或跳数。设备通过最大跳数(MaxHops)来限制数据帧的跳数,这样可以防止数据帧无限制地转发,避免网络资源的浪费和性能下降。将radius设置为0表示数据帧只能由源节点直接发送到目标节点。将radius设置为255则表示数据帧可以进行无限次转发,直到到达目标节点或达到最大跳数。
    需要注意的是,radius参数会影响网络传输的性能和延迟,因此需要根据实际应用场景中的需求进行设置。如果将radius参数设置得太小,可能会导致数据丢失或无法到达目标设备;如果将radius参数设置得太大,可能会影响网络性能和消耗网络资源。

  • 什么是“跳数”
    在Zigbee网络中,跳数(Hops)是指一个数据包从源设备传输到目标设备所涉及的路由器和重复器(中间设备)的数量。每经过一个中间设备,数据包的跳数加一。Zigbee设备使用跳数来限制数据包的转发次数,以避免网络资源浪费和性能下降,同时保障网络中数据包的传输质量。跳数越多,代表数据包需要经过更多设备才能到达目标设备,其延迟也会相应增加。
    在Zigbee网络中,每个设备都有一个最大跳数(Max Hops)的参数,它表示设备可以转发的数据包所允许的最大跳数。当数据包的跳数达到设备的最大跳数时,设备就不再转发该数据包,并将其丢弃。这样可以避免数据包在网络中反复转发,避免对网络的负载和性能造成影响,同时也可以避免数据包在网络中无限制地传递,降低网络的安全性。
    需要注意的是,并不是所有的Zigbee设备都允许转发数据包,例如终端设备(End-Device)只能连接一个Parent路由器,不能进行转发。而具有路由功能的设备(Router)和重复器(Repeater)则可以充当一跳或多跳的中间设备,帮助数据包传输到目标设备。

返回值

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

参考文档

https://blog.csdn.net/nt_yjj/article/details/45339237

posted @ 2023-05-07 15:14  云林天涯  阅读(551)  评论(0编辑  收藏  举报