首页 > 其他分享 >AF_DataRequest函数 解读

AF_DataRequest函数 解读

时间:2023-05-07 15:22:27浏览次数:41  
标签:req AF 跳数 addrMode 解读 DataRequest dstAddr afStatus

目录

作用

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;

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消息的传输速率和延迟请求的状态等。

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
以及部分内容从chatgpt获取

标签:req,AF,跳数,addrMode,解读,DataRequest,dstAddr,afStatus
From: https://www.cnblogs.com/dongxinya/p/17379369.html

相关文章

  • Mac-Kafka安装
    Mac-Kafka安装安装kafkabrewinstallkafka设置单机版本,修改监听端口vim/usr/local/etc/kafka/server.properties//修改listeners=PLAINTEXT://localhost:9092启动服务brewservicesstartzookeeperbrewservicesstartkafkaBroker配置常用配置zookeeper.conn......
  • Kafka生产者
    Kafka生产者下面是生产者使用kafka的API发送消息的过程可以从上面看出,如果发送成功则会返回元数据,否者抛出异常!创建Kafka生产者属性介绍bootstrap.servers:指定broker的地址清单,没有必要填写所有的地址,生产者会根据已有地址找到所有broker地址。key.serializer:序列化方式,比......
  • Kafka消费者
    Kafka消费者消费者和消费者群组Kafka消费者从属于消费者群组。一个群组里的消费者订阅的是同一个主题,每个消费者接收一部分分区的消息。若分区的数量大于等于消费者的数量,则消费者会消费一个或多个分区的数据。若分区的数量小于消费者的数量就会出现闲置消费者。上面为1个组......
  • 论文解读(ID-MixGCL)《ID-MixGCL: Identity Mixup for Graph Contrastive Learning》
    论文信息论文标题:ID-MixGCL:IdentityMixupforGraphContrastiveLearning论文作者:GehangZhang.....论文来源:2023aRxiv论文地址:download 论文代码:download视屏讲解:click介绍    ......
  • 【笔记】跟吴恩达和IsaFulford学提示词工程(初级开发者入门课程)
    标签:#Prompt#LLM创建时间:2023-04-2817:05:45链接:课程(含JupyterNotebook),中文版讲师:AndrewNg,IsaFulford阅读提示这是一篇入门的教程,入门的意思是指大部分内容,可能你都已经知道了,但是知道不等于掌握,Prompt是一门实践经验主义科学,LLM是个黑盒,你只要不断去“实践”才能......
  • SAM:SegMent Anything万物分割论文解读
    SAM:SegMentAnything作者:elfin  资料来源:SAM论文论文:https://ai.facebook.com/research/publications/segment-anything/代码:https://github.com/facebookresearch/segment-anythingDatasets:https://segment-anything.com/dataset/index.htmlSAM目录:目......
  • 数据湖Iceberg-FlinkSQL-kafka类型表数据无法成功写入(6)
    数据湖Iceberg-简介(1)数据湖Iceberg-存储结构(2)数据湖Iceberg-Hive集成Iceberg(3)数据湖Iceberg-SparkSQL集成(4)数据湖Iceberg-FlinkSQL集成(5)数据湖Iceberg-FlinkSQL-kafka类型表数据无法成功写入(6)数据湖Iceberg-FlinkDataFrame集成(7)数据湖Iceberg-FlinkSQL-kafka类型表......
  • GB/T28181-2022相对2016版“基于TCP协议的视音频媒体传输要求“规范解读和技术实现
    ​规范解读GB/T28181-2022和GB/T28181-2016规范,有这么一条“更改了附录D基于TCP协议的视音频媒体传输要求(见附录D,2016年版的附录L)。”。本文主要是针对GB/T28181-2022里面提到的“基于TCP协议的视音频媒体传输要求”做相应的接口适配,在此之前,我们先回顾下规范里面针对......
  • Crypto|[AFCTF2018]可怜的RSA
    public.key-----BEGINPUBLICKEY-----MIIBJDANBgkqhkiG9w0BAQEFAAOCAREAMIIBDAKCAQMlsYv184kJfRcjeGa7Uc/43pIkU3SevEA7CZXJfA44bUbBYcrf93xphg2uR5HCFM+Eh6qqnybpIKl3g0kGA4rvtcMIJ9/PP8npdpVE+U4Hzf4IcgOaOmJiEWZ4smH7LWudMlOekqFTs2dWKbqzlC59NeMPfu9avxxQ15fQzIjhvc......
  • Grafana 系列-统一展示-1-开篇
    系列文章Grafana系列文章Grafana简介Grafana是GrafanaLabs的第一款也是最重要的产品。它的定位是可视化,用于监控展示和可观察性.是当前最为完善、流行的云原生、公有云和企业监控可视化平台。Dashboardanything.Observeeverything无论你的数据存储在哪里,都可......