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

Z-Stack协议学习笔记1--发送函数AF_DataRequest

2015-01-14 13:28 330 查看
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设备有两种类型的地址。一种是64位IEEE地址(物理),即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 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.

*/

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;

}

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