|
粗略的看了下这个程序,发现这个程序有一个EP(终端),每个终端有两个簇(SERIALAPP_CLUSTERID1、SERIALAPP_CLUSTERID2),可以在以下代码中定义
// This list should be filled with Application specific Cluster IDs.
const cId_t SerialApp_ClusterList[SERIALAPP_MAX_CLUSTERS] =
{
SERIALAPP_CLUSTERID1,
SERIALAPP_CLUSTERID2
};
其中SERIALAPP_CLUSTERID1是负责数据的传输的,而SERIALAPP_CLUSTERID2则负责传输的反馈。在以下函数中可以看出
/*********************************************************************
* @fn SerialApp_ProcessMSGCmd
*
* @brief Data message processor callback. This function processes
* any incoming data - probably from other devices. Based
* on the cluster ID, perform the intended action.
*
* @param pkt - pointer to the incoming message packet
*
* @return TRUE if the 'pkt' parameter is being used and will be freed later,
* FALSE otherwise.
*/
void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
uint8 stat;
uint8 seqnb;
uint8 delay;
switch ( pkt->clusterId )
{
// A message with a serial data block to be transmitted on the serial port.
case SERIALAPP_CLUSTERID1: // 处理数据
// Store the address for sending and retrying.
osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t )); // 保存来信地址
seqnb = pkt->cmd.Data[0]; // 保存计数(来自发送端,来用检验)
// Keep message if not a repeat packet
if ( (seqnb > SerialApp_RxSeq) || // Normal, 是否是最新的数据
((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around,
{
#ifndef GEC_EP
// Transmit the data on the serial port.
if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
{
// Save for next incoming message
SerialApp_RxSeq = seqnb; // 保存计数
stat = OTA_SUCCESS;
}
else
{
stat = OTA_SER_BUSY;
}
#else // 添加部分代码,实现数据回传显示到串口,没办法串口只有一个
if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_RxAddr,
(endPointDesc_t *)&SerialApp_epDesc,
SERIALAPP_CLUSTERID1,
SerialApp_TxLen+1, SerialApp_TxBuf,
&SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
{
osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
}
#endif
}
else
{
stat = OTA_DUP_MSG;
}
// Select approproiate OTA flow-control delay.
delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY; // UART忙则延时16ms,否则延时1ms
// Build & send OTA response message.
SerialApp_RspBuf[0] = stat; // 接收状态
SerialApp_RspBuf[1] = seqnb; // 计数
SerialApp_RspBuf[2] = LO_UINT16( delay );
SerialApp_RspBuf[3] = HI_UINT16( delay );
osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT ); // 发送反馈信息
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT); // 停止反馈定时器
break;
// A response to a received serial data block.
case SERIALAPP_CLUSTERID2: // 处理反馈
if ((pkt->cmd.Data[1] == SerialApp_TxSeq) && // 反馈回来的是刚才发的
((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG))) // 成功或者过期
{
SerialApp_TxLen = 0; // 准备下一次发送
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT); // 无需重发,关闭定时器
}
else // 需要重发
{
// Re-start timeout according to delay sent from other device.
delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] ); // 延时发送
osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay ); //
}
break;
default:
break;
}
}
总结一下以上的代码,当SERIALAPP_CLUSTERID1收到数据的时候,将会检验这个数据包是否是新的,由于逻辑有点复杂,下面用伪代码描述
if (新数据包)
{
if (UART发送成功)
{
反馈成功信息;
}
else 否则反馈UART忙;
}
else 反馈此包过期;
同样,对于SERIALAPP_CLUSTERID2的信息处理也可以这样描述
if (刚才发送的包 && (成功 || 过期))
{
关闭定时器,注备下一次的发送,也就是说没有收到确认信息,不会进行下一次的发送
}
else
{
给我延时重发去
}
|
|