AF_DataRequest()
2018-01-09 10:50
423 查看
/*********************************************************************
* @fn AF_DataRequest
*
* @brief Common
functionality for invoking APSDE_DataReq() for both
* SendMulti
and MSG-Send.
*
* input parameters
*
* @param *dstAddr
- Full ZB destination address: Nwk Addr + End Point. //网络地址??
*
@param *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
* @param cID
- A valid cluster ID as specified by the Profile.
* @param len
- Number of bytes of data pointed to by next param.
* @param *buf
- A pointer to the data bytes to send.
* @param *transID
- A pointer to a byte which can be modified and which will
* be
used as the transaction sequence number of the msg.
* @param options
- Valid bit mask of Tx options.
* @param radius
- Normally set to AF_DEFAULT_RADIUS.
*
* output parameters
*
* @param *transID
- Incremented by one if the return value is success.
*
* @return afStatus_t
- See previous definition of afStatus_... types.
*/
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;
}
//对AddrNotPresent检查是否未开启绑定功能
#if !defined( REFLECTOR )
if ( dstAddr->addrMode == afAddrNotPresent )
{
return afStatus_INVALID_PARAMETER;
}
#endif
// Check if route is available before sending data
//对AddrNotPresent检查是否未开启绑定功能
if ( options & AF_LIMIT_CONCENTRATOR )
{
if ( dstAddr->addrMode != afAddr16Bit ) //仅对单播 进行检查
{
return ( afStatus_INVALID_PARAMETER );
}
// First, make sure the destination is not its self, then check for an existing route.
//确认其目的地址 不是 本节点地址且 检查链路
if ( (dstAddr->addr.shortAddr != NLME_GetShortAddr())
&& (RTG_CheckRtStatus( dstAddr->addr.shortAddr,
RT_ACTIVE, (MTO_ROUTE | NO_ROUTE_CACHE) ) != RTG_SUCCESS) )
{
// A valid route to a concentrator wasn't found
return ( afStatus_NO_ROUTE );
}
}
// 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;
//规范ID选择
req.profileID = ZDO_PROFILE_ID;
// 如果源端点有回调函数,调用回调函数修改规范ID
if ( (pfnDescCB = afGetDescCB( srcEP )) )
{
uint16 *pID = (uint16 *)(pfnDescCB(
AF_DESCRIPTOR_PROFILE_ID,
srcEP->endPoint ));
if ( pID )
{
req.profileID = *pID;
osal_mem_free( pID );
}
}
//如果端点有简单描述符,覆盖掉默认规范ID
else if ( srcEP->simpleDesc )
{
req.profileID = srcEP->simpleDesc->AppProfId;
}
//检查txOption
//AF_ACK_REQUEST 0x10 要求APS应答,仅在单播时使用(会多出一个APS层的应答数据帧)。
//AF_DISCV_ROUTE 0x20 总要包含这个选项
//AF_SKIP_ROUTING 0x80 设置这个选项将导致设备跳过路由而直接发送消息。终点设备将不向其父亲发送消息。在单播和广播消息时很好用(测试情况需要在通讯范围内的两个节点才能完成直接通讯)。
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;
}
if ( options & AF_PREPROCESS )
{
req.txOptions |= APS_TX_OPTIONS_PREPROCESS;
}
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
{
//基于输入参数的最大可发送字节数,根据长度选择发送方式
//uint8 afDataReqMTU( afDataReqMTU_t* fields )返回能发送的最大字节数
//fields -要发送的消息类型参数
if (len > afDataReqMTU( &mtu ) )
{
if (apsfSendFragmented)
{
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.
*/
/*对于点对点通讯且目的地址是其本身,则不需要将数据写入NWK层的数据缓冲区,即不需要触发无线而引起MACCB_DATA_CONFIRM_CMD回调。
在该处产生响应的 AF_DATA_CONFIRM_CMD 消息命令,且不会产生附带的消息。
*/
if ( (req.dstAddr.addrMode == Addr16Bit) &&
(req.dstAddr.addr.shortAddr == NLME_GetShortAddr())
)
{
afDataConfirm( srcEP->endPoint, *transID, stat
);
}
//如果应用层发送成功 时间戳 自加1
if ( stat == afStatus_SUCCESS )
{
(*transID)++;
}
return (afStatus_t)stat;
}
参考链接:http://blog.sina.com.cn/s/blog_70b26edc0100mgu7.html
http://www.feibit.com/forum.php?mod=viewthread&tid=3598
* @fn AF_DataRequest
*
* @brief Common
functionality for invoking APSDE_DataReq() for both
* SendMulti
and MSG-Send.
*
* input parameters
*
* @param *dstAddr
- Full ZB destination address: Nwk Addr + End Point. //网络地址??
*
@param *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
* @param cID
- A valid cluster ID as specified by the Profile.
* @param len
- Number of bytes of data pointed to by next param.
* @param *buf
- A pointer to the data bytes to send.
* @param *transID
- A pointer to a byte which can be modified and which will
* be
used as the transaction sequence number of the msg.
* @param options
- Valid bit mask of Tx options.
* @param radius
- Normally set to AF_DEFAULT_RADIUS.
*
* output parameters
*
* @param *transID
- Incremented by one if the return value is success.
*
* @return afStatus_t
- See previous definition of afStatus_... types.
*/
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;
}
//对AddrNotPresent检查是否未开启绑定功能
#if !defined( REFLECTOR )
if ( dstAddr->addrMode == afAddrNotPresent )
{
return afStatus_INVALID_PARAMETER;
}
#endif
// Check if route is available before sending data
//对AddrNotPresent检查是否未开启绑定功能
if ( options & AF_LIMIT_CONCENTRATOR )
{
if ( dstAddr->addrMode != afAddr16Bit ) //仅对单播 进行检查
{
return ( afStatus_INVALID_PARAMETER );
}
// First, make sure the destination is not its self, then check for an existing route.
//确认其目的地址 不是 本节点地址且 检查链路
if ( (dstAddr->addr.shortAddr != NLME_GetShortAddr())
&& (RTG_CheckRtStatus( dstAddr->addr.shortAddr,
RT_ACTIVE, (MTO_ROUTE | NO_ROUTE_CACHE) ) != RTG_SUCCESS) )
{
// A valid route to a concentrator wasn't found
return ( afStatus_NO_ROUTE );
}
}
// 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;
//规范ID选择
req.profileID = ZDO_PROFILE_ID;
// 如果源端点有回调函数,调用回调函数修改规范ID
if ( (pfnDescCB = afGetDescCB( srcEP )) )
{
uint16 *pID = (uint16 *)(pfnDescCB(
AF_DESCRIPTOR_PROFILE_ID,
srcEP->endPoint ));
if ( pID )
{
req.profileID = *pID;
osal_mem_free( pID );
}
}
//如果端点有简单描述符,覆盖掉默认规范ID
else if ( srcEP->simpleDesc )
{
req.profileID = srcEP->simpleDesc->AppProfId;
}
//检查txOption
//AF_ACK_REQUEST 0x10 要求APS应答,仅在单播时使用(会多出一个APS层的应答数据帧)。
//AF_DISCV_ROUTE 0x20 总要包含这个选项
//AF_SKIP_ROUTING 0x80 设置这个选项将导致设备跳过路由而直接发送消息。终点设备将不向其父亲发送消息。在单播和广播消息时很好用(测试情况需要在通讯范围内的两个节点才能完成直接通讯)。
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;
}
if ( options & AF_PREPROCESS )
{
req.txOptions |= APS_TX_OPTIONS_PREPROCESS;
}
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
{
//基于输入参数的最大可发送字节数,根据长度选择发送方式
//uint8 afDataReqMTU( afDataReqMTU_t* fields )返回能发送的最大字节数
//fields -要发送的消息类型参数
if (len > afDataReqMTU( &mtu ) )
{
if (apsfSendFragmented)
{
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.
*/
/*对于点对点通讯且目的地址是其本身,则不需要将数据写入NWK层的数据缓冲区,即不需要触发无线而引起MACCB_DATA_CONFIRM_CMD回调。
在该处产生响应的 AF_DATA_CONFIRM_CMD 消息命令,且不会产生附带的消息。
*/
if ( (req.dstAddr.addrMode == Addr16Bit) &&
(req.dstAddr.addr.shortAddr == NLME_GetShortAddr())
)
{
afDataConfirm( srcEP->endPoint, *transID, stat
);
}
//如果应用层发送成功 时间戳 自加1
if ( stat == afStatus_SUCCESS )
{
(*transID)++;
}
return (afStatus_t)stat;
}
参考链接:http://blog.sina.com.cn/s/blog_70b26edc0100mgu7.html
http://www.feibit.com/forum.php?mod=viewthread&tid=3598
相关文章推荐
- AF_DataRequest ()函数说明
- (六) 发送函数AF_DataRequest zigbee数据发送和接受
- AF_DataRequest()函数说明
- Zigbee协议栈发送函数AF_DataRequest说明
- Z-STACK-1.4.3发送函数AF_DataRequest ()详解
- Zigbee协议栈发送函数AF_DataRequest说明
- zigbee__AF_DataRequest函数详解
- 【Z-Stack发送函数AF_DataRequest】
- Z-Stack协议学习笔记1--发送函数AF_DataRequest
- zigbee 数据发送AF_Data_Request和数据接收afIncomingMSGPacket_t结构体
- AF_DataRequest zigbee单播、组播、广播
- AF_DataRequest详解
- AF_DataRequest详解
- AF_DataRequest详解
- Transmitting Network Data Using Volley 之Sending a Simple Request
- Vue-resource中post请求将data数据以request payload转换为form data的形式
- Transmitting Network Data Using Volley -Implementing a Custom Request
- AFDownloadRequestOperation
- 什么时候该用ASIHTTPRequest,什么时候该用ASIFormDataRequest
- django - request.raw_post_data 与 request.body