3.3 数据发送API简介
一句话理解
AF 层所有发送数据的工作,最终都汇到一个函数:AF_DataRequest()。点对点、广播、组播,不过是它的三种"填法"。
核心 API:AF_DataRequest()
打开配套工程,在 Profile 文件夹下找到 AF.h,可以看到 AF 层的数据发送 API——AF_DataRequest():
/*
* @param dstAddr 目标设备地址(网络地址 + 端点号)
* @param srcEP 发送设备的简单描述符
* @param cID Cluster ID(后续章节详细讲解)
* @param len 待发送数据的长度
* @param buf 待发送的数据
* @param transID 传输 ID,给每一次发送的数据包编号
* @param options 附加选项,给这次发送添加说明
* @param radius 最大路由跳转级数
*/
afStatus_t AF_DataRequest(
afAddrType_t *dstAddr,
endPointDesc_t *srcEP,
uint16 cID,
uint16 len,
uint8 *buf,
uint8 *transID,
uint8 options,
uint8 radius );参数速记
AF_DataRequest( 发给谁, 用哪个名片, 什么业务, 多长, 什么内容, 编号, 选项, 跳数 )
协议栈里的 SampleSwitch 例程,基于这个 API 封装出了三种通信 API:点对点 / 广播 / 组播。下面逐个看。
① 点对点通信 API
在 zcl_samplesw.c 中可以找到点对点通信 API:
/*
* @param destNwkAddr 目标设备的网络地址
* @param cid Cluster ID
* @param len 数据长度
* @param data 数据内容
*/
static void zclSampleSw_AF_P2P(
uint16 destNwkAddr,
uint16 cid,
uint8 len,
uint8 *data)
{
afAddrType_t dstAddr; // 寻址信息配置
static uint8 transferId = 0; // 传输 ID,是数据包的标识符
/* Destination */
dstAddr.addrMode = afAddr16Bit; // 16 位网络地址 → 点对点方式
dstAddr.addr.shortAddr = destNwkAddr; // 目标设备的网络地址
dstAddr.endPoint = SAMPLESW_ENDPOINT; // 目标设备的端点号
transferId++;
AF_DataRequest(&dstAddr,
&sampleSw_TestEp, // 已经创建好的简单描述符
cid,
len,
data,
&transferId,
AF_DISCV_ROUTE, // 路由扫描,建立通信路径(保持例程默认即可)
AF_DEFAULT_RADIUS); // 最大路由跳转级数
}用到的两个关键类型
afAddrType_t:寻址信息结构体,用于配置"发给谁":
typedef struct
{
union
{
uint16 shortAddr; // 16 位短地址(网络地址)
ZLongAddr_t extAddr; // 64 位扩展地址
} addr;
afAddrMode_t addrMode; // 地址模式:点对点 / 广播 / 组播
uint8 endpoint; // 目标端点号
uint16 panId; // 用于 INTER_PAN 特性
} afAddrType_t;afAddrMode_t:地址模式枚举,说明用哪种通信方式:
typedef enum
{
afAddrNotPresent = AddrNotPresent, // 地址不存在(间接寻址)
afAddr16Bit = Addr16Bit, // 16 位网络地址 → 点对点
afAddr64Bit = Addr64Bit, // 64 位扩展地址
afAddrGroup = AddrGroup, // 组地址 → 组播
afAddrBroadcast = AddrBroadcast // 广播地址 → 广播
} afAddrMode_t;观察
点对点 API 最后一步还是调用 AF_DataRequest() 发送数据。你也可以基于 AF_DataRequest() 写自己的通信 API,不必非用例程自带的这个。
② 广播通信 API
在 zcl_samplesw.c 中可以找到广播通信 API:
/*
* @param cid Cluster ID
* @param len 待发送数据的长度
* @param data 待发送数据的内容
*/
static void zclSampleSw_AF_Broadcast(
uint16 cid,
uint8 len,
uint8 *data)
{
afAddrType_t dstAddr;
static uint8 transferId = 0;
/* Destination */
dstAddr.addrMode = afAddrBroadcast; // 使用广播模式
dstAddr.addr.shortAddr = 0xFFFF; // 广播地址
dstAddr.endPoint = SAMPLESW_ENDPOINT; // 目标设备的端点号
/* Transfer id */
transferId++;
/* Send */
AF_DataRequest(&dstAddr,
&sampleSw_TestEp,
cid,
len,
data,
&transferId,
AF_TX_OPTIONS_NONE,
AF_DEFAULT_RADIUS);
}它和点对点 API 结构几乎一样,区别就在:地址模式设为 afAddrBroadcast,目标地址填广播地址 0xFFFF。
ZigBee 的广播地址一共有 3 个:
③ 组播通信 API
组播可以只给指定的一组设备发数据。在 zcl_samplesw.c 中可以找到组播通信 API:
/*
* @param groupId 组 ID
* @param cid Cluster ID
* @param len 待发送数据的长度
* @param data 待发送数据的内容
*/
static void zclSampleSw_AF_Groupcast(
uint16 groupId,
uint16 cid,
uint8 len,
uint8 *data)
{
afAddrType_t dstAddr;
static uint8 transferId = 0;
/* Destination */
dstAddr.addrMode = afAddrGroup; // 使用组播通信模式
dstAddr.addr.shortAddr = groupId; // 组 ID
dstAddr.endPoint = SAMPLESW_ENDPOINT; // 组中设备的端点号
/* Transfer id */
transferId++;
/* Send */
AF_DataRequest(&dstAddr,
&sampleSw_TestEp,
cid,
len,
data,
&transferId,
AF_TX_OPTIONS_NONE,
AF_DEFAULT_RADIUS);
}组播的关键就是:地址模式设为 afAddrGroup,目标地址填组 ID(groupId)。后续章节会以实验的方式讲解如何让设备加入指定组。
三种通信方式对比
目标 = 设备网络地址
例:zclSampleSw_AF_P2P
目标 = 0xFFFF 等广播地址
例:zclSampleSw_AF_Broadcast
目标 = 组 ID
例:zclSampleSw_AF_Groupcast
小结
三种 API 长得像、结构同——都是把"地址模式 + 目标地址"填好,然后调用 AF_DataRequest()。理解这一个函数,三种通信方式就都掌握了。
内容来源:紫甲 IoT《ZigBee 3.0 开发指南》第四部分·3.3 数据发送API简介,原站链接
本章自测
一、单项选择题(每题 4 分,共 40 分)
AF 层所有发送数据的工作,最终都汇到的一个核心函数是(A.
zcl_SendCommand()B.AF_DataRequest()C.afRegister()D.bdb_StartCommissioning()) 答案:B在
AF_DataRequest()的参数中,radius参数的含义是(A. 待发送数据的长度 B. 传输 ID C. 最大路由跳转级数 D. 附加选项) 答案:C实现点对点通信时,
dstAddr.addrMode应设置为(A. afAddrBroadcast B. afAddrGroup C. afAddr16Bit D. afAddrNotPresent) 答案:C广播通信时,目标地址
dstAddr.addr.shortAddr应填写(A. 0x0000 B. 0xFFFF C. 0x0EF1 D. 组 ID) 答案:B组播通信的关键配置是(A. addrMode 设为 afAddrGroup,目标地址填组 ID(groupId) B. addrMode 设为 afAddrBroadcast C. addrMode 设为 afAddr16Bit D. 目标地址填 0xFFFF) 答案:A
ZigBee 的广播地址
0xFFFD的含义是(A. 广播给网络中所有设备 B. 只广播给网络中打开收听功能的设备 C. 只广播给协调器和路由设备 D. 广播给 ZDO) 答案:BZigBee 的广播地址
0xFFFC的含义是(A. 广播给网络中所有设备 B. 只广播给网络中打开收听功能的设备 C. 只广播给网络中的协调器和路由设备 D. 广播给终端设备) 答案:C在
afAddrMode_t枚举中,表示"组地址 → 组播"的是(A. afAddr16Bit B. afAddr64Bit C. afAddrGroup D. afAddrBroadcast) 答案:CafAddrType_t结构体中的addr是一个 union,其成员不包括(A. shortAddr(16 位短地址) B. extAddr(64 位扩展地址) C. endpoint(目标端点号)) 答案:C(endpoint 是结构体的独立成员,不是 addr union 的成员)关于三种通信 API(点对点 / 广播 / 组播),下列说法正确的是(A. 三者内部实现完全不同的发送机制 B. 结构几乎相同,都是把"地址模式 + 目标地址"填好后调用
AF_DataRequest()C. 广播不需要调用AF_DataRequest()D. 组播只能由协调器发起) 答案:B
二、问答题(每题 20 分,共 60 分)
- 题干:写出
AF_DataRequest()的各主要参数含义(可用书中的速记口诀)。 参考答案要点:
- dstAddr:目标设备地址(网络地址 + 端点号);srcEP:发送设备的简单描述符。
- cID:Cluster ID;len:待发送数据长度;buf:待发送数据内容。
- transID:传输 ID,给每次发送的数据包编号;options:附加选项;radius:最大路由跳转级数。
- 速记口诀:发给谁、用哪个名片、什么业务、多长、什么内容、编号、选项、跳数。
- 题干:点对点、广播、组播三种方式在配置
afAddrType_t时有何区别?请分别写出 addrMode 与目标地址的填法。 参考答案要点:
- 点对点:addrMode = afAddr16Bit,目标 shortAddr = 目标设备网络地址。
- 广播:addrMode = afAddrBroadcast,目标 shortAddr = 0xFFFF 等广播地址。
- 组播:addrMode = afAddrGroup,目标 shortAddr = 组 ID(groupId)。
- 三者都还需指定 dstAddr.endPoint(目标端点号),最后统一调用
AF_DataRequest()。
- 题干:ZigBee 的广播地址共有哪几个?各自的接收范围是什么? 参考答案要点:
- 0xFFFF:广播给该网络中的所有设备。
- 0xFFFD:只广播给网络中打开收听功能的设备。
- 0xFFFC:只广播给网络中的协调器和路由设备。