#include "head.h"
#include "bluetooth.h"

// #define BL_DEBUG                                // 调试打印
#define FREAM_SPLIT_LEN             (240)       // 分帧长度
#define FREAM_INTERVAL_TIME_MS      (65)        // 帧间隔ms，手册建议帧间隔60ms以上
#define BL_DISC_REBOOT_TIME_MS      (100)       // 连接断开复位蓝牙延时ms
#define BL_IDLE_REBOOT_TIME_MS      (120000)    // 蓝牙空闲状态自动复位延时ms

#define BL_ENABLE_RESEND_MODE       (1)         // 重发机制
#define BL_RESEND_TIMES             (3)         // 重发次数
#define BL_RECV_TIMEOUT_MS          (500)       // 接收超时时间
#define BL_TIMEOUT_RESEND_MS        (500)       // 超时重发时间

#define BLUETOOTH_DEFAULT_NAME      "OLE-DTUv5" // 蓝牙默认名称，获取ID失败时设置此蓝牙名称

/* 各指令详细描述请参考蓝牙手册,路径:Z:\研发中心\研发二部\共享\88_DTU5.0\02蓝牙模块 */
/* AT指令匹配列表 */
const struct at_cmd_index_match at_cmd_index_match[AT_CMD_MAX] = 
{
    //指令字符串  追加字符串 指令结束字符串  数据段结束字符串 指令结果结束字符串    指令匹配的枚举类型
    {"SCAN"		,	"="	,   "{\r\n"	,       "}\r\n" ,       NULL	    ,       AT_CMD_SACN     },
	{"CONN"		,	"="	,   "="	    ,       NULL	,       NULL	    ,       AT_CMD_CONN     },
	{"CHINFO"	,	""  ,   "{\r\n"	,       "}\r\n"	,       "OK\r\n"    ,       AT_CMD_CHINFO   },
	{"LESEND"	,	"=" ,   "\r\n"	,       NULL	,       "OK\r\n"	,       AT_CMD_LESEND   },	
	{"LEDISC"	,	"="	,   "="	    ,       "\r\n"  ,       NULL	    ,       AT_CMD_LEDISC   },	
	{"NAME"		,	"="	,   "="	    ,       "\r\n"  ,       "OK\r\n"	,       AT_CMD_NAME     },	
	{"MAC"		,	""	,   "="	    ,       "\r\n"	,       "OK\r\n"	,       AT_CMD_MAC      },
	{"REBOOT"	,	""	,   "\r\n"	,       NULL	,       "OK\r\n"	,       AT_CMD_REBOOT   },
    {"DATA"	    ,	""	,   "="	    ,       "\r\n"	,       NULL	    ,       AT_CMD_DATA     },
    {"GATTSTAT"	,	""	,   "="	    ,       "\r\n"	,       NULL	    ,       AT_CMD_STAT     },
};

/**
 * @brief   获取一个buf
 * @details 从缓存队列中返回一个buf
 * @param   _pt 结构体指针
 * @return  buf索引
 * @author  EWen
 * @date    2025-10-11
 * @remarks 增加发送队列缓存是考虑到多帧分帧放进缓存后自动发送，但目前报文组帧处理了可以一帧发完，暂时用不上
 */
static u8 _get_one_buf(bl_tbuf_t *pt)
{
	u8 head;
	
	head = pt->tb_head;
	pt->tb_head++;
    if(pt->tb_head >= BL_TBUF_NUM)
    {
        pt->tb_head = 0;
    }

	// 系统设计时，保证缓冲不会满，以下情况不应出现
	if(pt->tb_head==pt->tb_tail_ack || pt->tb_head==pt->tb_tail_send) 
	{
		rt_printf_time("bluetooth: _get_one_buf error:head=%d,send=%d,ack=%d.\r\n",pt->tb_head,pt->tb_tail_send,pt->tb_tail_ack);
	}

	return head;
}


/**
 * @brief   确认一条发送的报文
 * @details none
 * @param   _pt 结构体指针
 * @param   _cmd_type 接收到的报文类型
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks Tnone
 */ 
static void _ack_one_buf(bl_tbuf_t *pt, s8 _cmd_type)
{
    if(_cmd_type == AT_CMD_DATA)
    {
        //蓝牙模块主动发送的数据不需进行发送确认
        return;
    }

    if(_cmd_type == AT_CMD_STAT)
    {
        u8 send_cmd_index;
        send_cmd_index = (pt->tb_tail_ack+1) >= BL_TBUF_NUM ? 0 : (pt->tb_tail_ack+1);
        // 不是因终端主动发起的命令而收到AT_CMD_STAT类型数据不需确认
        if(pt->tb_cmd[send_cmd_index] != AT_CMD_CONN\
        || pt->tb_cmd[send_cmd_index] != AT_CMD_LEDISC)
        return;
    }

    pt->tb_tail_ack++;
    if(pt->tb_tail_ack >= BL_TBUF_NUM)
        pt->tb_tail_ack = 0;

    #ifdef BL_DEBUG
    rt_printf("ack tb_head=%d,tb_tail_send=%d,tb_tail_ack=%d\r\n", pt->tb_head, pt->tb_tail_send, pt->tb_tail_ack);
    #endif
}

/**
 * @brief   组帧
 * @details none
 * @param   _pt 结构体指针
 * @param   _pdat 数据指针
 * @param   _cmd 组帧类型
 * @param   _len 数据长度
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks 目前格式字符填充部分最长长度为数据发送格式填充18字节
 */
static int _frame_packing(BLUETOOTH_DEF *_pt,const u8 *_pdat, AT_CMD _cmd, u8 _len)
{
    u8 i = 0;
    u8 head = 0;
    u8 *pd = NULL;
    u8 ext_len = 0;
    u8 str_len = 0;

    // 目前格式字符填充部分最长长度为数据发送格式填充18字节
    // 组帧buf首字节为发送长度因此再 -1
    if(_len >= BL_TBUF_LEN - 18 - 1)
    {
        rt_printf("蓝牙->%s 组帧数据长度越限,in len=%d,max=%d\r\n", __func__, _len, BL_TBUF_LEN - 19);
        return -1;
    }
    
    // 匹配at命令
    for(i = 0; i < AT_CMD_MAX; i++)
    {
        if(at_cmd_index_match[i].cmd == _cmd)
            break;
    }

    if(i == AT_CMD_MAX)
    {
        rt_printf("bluetooth: %s error! can't find cmd %d\r\n", __func__, _cmd);
        return -2;
    }

    head = _get_one_buf(&_pt->tx_buf[0]);
    
    _pt->tx_buf[0].tb_cmd[head] =  _cmd;

    pd = &_pt->tx_buf[0].tb_data[head][1];

    // 固定头
    strcpy(pd,"AT+"); 
    pd += 3;
    ext_len += 3;

    // 根据_cmd 填充命令
    str_len = strlen(at_cmd_index_match[i].cmd_str);
    strncpy(pd,at_cmd_index_match[i].cmd_str,str_len);
    pd += str_len;
    ext_len += str_len;

    // 根据可选字符填充
    if(at_cmd_index_match[i].send_op_str)
    {
        str_len = strlen(at_cmd_index_match[i].send_op_str);
        strncpy(pd,at_cmd_index_match[i].send_op_str,str_len);
        pd += str_len;
        ext_len += str_len;
    }

    // 填充长度数据
    if(_cmd == AT_CMD_LESEND)
    {
        u8 tmp_len[6] = {0};

        *pd++ = '0';
        *pd++ = ',';
        ext_len += 2;

        sprintf(tmp_len,"%d", _len);
        str_len = strlen(tmp_len);
        strncpy(pd,tmp_len,str_len);
        pd+= str_len;
        ext_len +=str_len;

        *pd++ = ',';
        ext_len += 1;
    }

    // 填充发送数据
    if(_pdat)
    {
        memcpy(pd,_pdat,_len);
        pd += _len;
    }

    // 固定尾
    strcpy(pd,"\r\n");
    ext_len += 2;

    // 首字节为需发送报文长度
    _pt->tx_buf[0].tb_data[head][0] = _len+ext_len; 

#ifdef BL_DEBUG
    rt_printf_time("%s data:%d,ext:%d\r\n", __func__, _len, ext_len);
    for(i = 0; i < _len+ext_len; i++)
    {
        if(i!=0 && i%16==0) rt_printf("\r\n");
        rt_printf("%02x ",_pt->tx_buf[0].tb_data[head][i+1]);
    }
    rt_printf("\r\n");
#endif

    return 0;
}

/**
 * @brief   设置蓝牙名称
 * @details none
 * @param   _pt 结构体指针
 * @param   _pdat 名称字符串指针
 * @param   _len 名称长度
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static int _name_set(BLUETOOTH_DEF *pt, const u8 *_pdat, u8 _len)
{
   return _frame_packing(pt,_pdat,AT_CMD_NAME,_len);
}

/**
 * @brief   蓝牙模块软重启
 * @details none
 * @param   _pt 结构体指针
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static int _reboot(BLUETOOTH_DEF *pt)
{
    return _frame_packing(pt,NULL,AT_CMD_REBOOT,0);
}

/**
 * @brief   断开蓝牙连接
 * @details none
 * @param   _pt 结构体指针
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks 已连接状态才起作用，否则蓝牙模块不回复
 */
static int _ledisc(BLUETOOTH_DEF *pt)
{
    const u8 para = '0'; // 固定为 "0"

    if(!pt->lnk_sta){
        // 非连接状态下发送断开连接命令，蓝牙模块不会回复报文
        rt_printf("非连接状态下不能进行断开连接操作!\r\n");
        return -1;
    }

    return _frame_packing(pt,&para,AT_CMD_LEDISC,1);
}

/**
 * @brief   接收数据复位
 * @details none
 * @param   _pt 结构体指针
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static void _recv_rst(BLUETOOTH_DEF *pt,u8 num)
{
    if(num == 10)
    {
        rt_printf_time("接收帧错误,超时未能接收到帧结束符号!!!\r\n");
    }
	if(pt->cTypeCounter)
	{
		rt_printf_time("bluetooth_recv_rst:state=%d,counter=%d,num=%d\r\n",pt->cTypeCounter,pt->cRecvCnt,num);
	}
	
	pt->cTypeCounter=0;
	pt->cRecvLenth=0;
	pt->cRecvCnt=0;

    pt->us0_recv = 0;
}

/**
 * @brief   蓝牙接收数据解析
 * @details 判断是否接收到完整一帧
 * @param   _pt 结构体指针
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static int _recv_parse(BLUETOOTH_DEF *pt, u8 c)
{
    u8 i = 0;
    u8 match_count = 0;

    switch(pt->cTypeCounter)
    {
        case 0:
            if (c == '+') //固定起始符号
            {
                pt->cmd_type = -1;
                pt->cTypeCounter++;
                pt->us0_recv = bsp_ustimer_get_origin();
                memset(pt->cmd_recvbuf,'\0',sizeof(pt->cmd_recvbuf));
            }
            else
            {
                _recv_rst(pt,1);
            }
            break;
        case 1:
            pt->cmd_recvbuf[pt->cRecvCnt++] = c;

            if(pt->cRecvCnt >= CMD_RECVBUF_LEN)
            {
                _recv_rst(pt,2);
                rt_printf_time("接收指令错误，指令长度溢出!!!\r\n");
                break; 
            }

            // 最短命令匹配字符MAC
            if(pt->cRecvCnt < 3)
            {
                break;
            }

            // 命令未匹配
            if(pt->cmd_type == -1)
            {
                for(i = 0; i < AT_CMD_MAX; i++)
                {
                    // 匹配命令
                    if(strstr(at_cmd_index_match[i].cmd_str,pt->cmd_recvbuf) != NULL)
                    {
                        match_count++;
                        pt->cmd_type = at_cmd_index_match[i].cmd;
                        break;
                    }
                }

                // 3个字符都未能匹配一条，不支持命令，重新接收
                if(match_count == 0)
                {
                    rt_printf("蓝牙接收->不支持的指令:%s\r\n",pt->cmd_recvbuf);
                    pt->cmd_type = -1;
                    _recv_rst(pt,3);
                    break;
                }
                else if(match_count > 1)
                {
                    // 多条匹配继续接收匹配
                    pt->cmd_type = -1;  
                }
            }
            else
            {
                if(strstr(pt->cmd_recvbuf,at_cmd_index_match[pt->cmd_type].cmd_end_str) != NULL)
                {
                    #ifdef BL_DEBUG
                    pt->cmd_recvbuf[pt->cRecvCnt - 1] = '\0';
                    rt_printf("recv cmd:%s\r\n",pt->cmd_recvbuf);
                    #endif
                    // 命令结束,转入下一流程
                    pt->cRecvCnt = 0;
                    pt->cTypeCounter++;
                    memset(pt->recvbuf,0,sizeof(pt->recvbuf));

                    _ack_one_buf(&pt->tx_buf[0], pt->cmd_type);
                    
                }
            }
            break;
        case 2:
            if(at_cmd_index_match[pt->cmd_type].data_end_str)
            {
                // 此帧包含数据
                pt->recvbuf[pt->cRecvCnt++] = c;
                if(pt->cRecvCnt >= BLUETOOTH_BUF_LEN)
                {
                    _recv_rst(pt,4);
                    rt_printf("蓝牙接收->数据长度溢出!!!\r\n");
                    break; 
                }

                if(c == '\n')
                {
                    if(strstr(&pt->recvbuf[pt->cRecvCnt - strlen(at_cmd_index_match[pt->cmd_type].data_end_str)],at_cmd_index_match[pt->cmd_type].data_end_str) != NULL)
                    {
                        #ifdef BL_DEBUG
                        int i = 0;
                        rt_printf("recv data:\r\n");
                        for(i = 0; i <= pt->cRecvCnt-1; i++)
                        {
                            if(i%16 == 0 && i != 0) rt_printf("\r\n"); 
                            rt_printf("%02x ", pt->recvbuf[i]);  
                        }
                        rt_printf("\r\n");
                        #endif

                        if(at_cmd_index_match[pt->cmd_type].sta_end_str)
                        {
                            pt->cRecvCnt = 0;
                            pt->cTypeCounter++;
                        }
                        else
                        {
                            pt->bData = true;
                            pt->cTypeCounter = 0;
                             _recv_rst(pt,5); 
                        }
                    }
                }
            }
            else if(at_cmd_index_match[pt->cmd_type].sta_end_str)
            {
                // 结果判断
                pt->cTypeCounter++;
                pt->cmd_recvbuf[pt->cRecvCnt++] = c;
            }
            else
            {
                _recv_rst(pt,6);
                rt_printf("%s %d unknowd operation!\r\n", __func__, __LINE__);  
            }
            break;
        case 3:
            // 结果
            pt->cmd_recvbuf[pt->cRecvCnt++] = c;
            if(c == '\n')
            {
                #ifdef BL_DEBUG
                rt_printf("recv statue:%s",  pt->cmd_recvbuf);
                #endif

                if(strstr(pt->cmd_recvbuf,"OK\r\n") != NULL)
                {
                    pt->cmd_sta = true;
                    if(at_cmd_index_match[pt->cmd_type].data_end_str)
                    {
                        pt->bData = true;
                    }
                }
                else
                {
                    rt_printf("蓝牙->执行%s->%s失败!!\r\n", at_cmd_index_match[pt->cmd_type].cmd_str, pt->cmd_recvbuf); 
                }

                pt->cTypeCounter = 0;
                _recv_rst(pt,7);
            }
            break;

        default:
            _recv_rst(pt,8);
            break;
    }

    return 0;
}

/**
 * @brief   接收应用
 * @details 从fifo提取数据去解析
 * @param   _pt 结构体指针
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static void _recv_app(BLUETOOTH_DEF *pt) 
{
	u8 c;
	// 接收数据
	while(pt->bData == false)
	{
		if(rt_fifo_get(&pt->recv_fifo,&c,1) == 0)
		{
			if(pt->b_recv_reset)
			{
				_recv_rst(pt,10);
				pt->b_recv_reset = 0;
			}
		
			break;
		}

        _recv_parse(pt,c);
 	}
}

/**
 * @brief   蓝牙接收数据解析
 * @details 数据接收判断时已将"+DATA="去除
 * @param   _pt 结构体指针
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks 数据内容格式：+DATA=para1,para2,para3; para1：固定值0，para2：接收的数据长度，para3：接收的数据内容
 */
static int _data_parse(BLUETOOTH_DEF *pt)
{
    u16 i = 0;
    u8 *pd = NULL;
    char *endptr;
    u16 data_len = 0;
    u8 len_str[5] = {0};
    
    // 固定开头为 "0,"
    if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',') 
    {
        rt_printf("%s data format error!\r\n", __func__);
        return -1;
    }

    // 解析长度字符串
    pd = &pt->recvbuf[2];
    for(i = 0; i < 5; i++)
    {
       len_str[i] = *pd++;
       // 长度字符串以","结束，跳过","
       if(*pd == ',') 
       {
            pd++;
            break;
       }
    }

    if(i == 5)
    {
        rt_printf("%s lenth error!\r\n", __func__);
        return -2;
    }
    else
    {
        data_len = strtol(len_str,&endptr,10);
        if(*endptr != '\0')
        {
            rt_printf("%s lenth strtol failed!\r\n", __func__);
            return -3;
        }
        #ifdef BL_DEBUG
        rt_printf("%s data_len:%d\r\n", __func__, data_len);
        #endif
    }

    for(i = 0; i < data_len; i++)
    {
        u8 j;
        int ret;
        
        ret =  sec_recv(&pt->rx_buf,*pd++,pt->arrSendBuf,false);
        if(ret==SEC_FRAME_OK_APP) // 带规约的报文
        {
            rt_printf("未实现的蓝牙通讯帧处理->SEC_FRAME_OK_APP\r\n");
        }
        else if(ret==SEC_FRAME_OK_EXT) //纯安全扩展报文 发送
        {
            u16 remaining_length = 0;

            // 前两个字节为加密返回报文的长度
            remaining_length = ((pt->arrSendBuf[0]<<8)+(pt->arrSendBuf[1]));
            #ifdef BL_DEBUG
            rt_printf("esam data len->%d\r\n", remaining_length);
            #endif
            // 分帧
            // TODO 直接将报文分帧有较大几率证书管理工具会报错，此处已在加密报文处理中将每帧证书长度修改为220处理
            // 可以在一帧报文中将加密安全扩展报文发送，如确实需分帧的话要按照加密报文分帧处理再分帧，此处没有处理。。。
            if(remaining_length > FREAM_SPLIT_LEN)
            {
                for(j = 0;;j++)
                {
                    if(remaining_length <= FREAM_SPLIT_LEN)
                    {
                        _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,(u8)remaining_length);
                        break;
                    }
                    _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,FREAM_SPLIT_LEN);
                    remaining_length -= FREAM_SPLIT_LEN;
                }
            }
            else
            {
                _frame_packing(pt,pt->arrSendBuf+2,AT_CMD_LESEND,(u8)remaining_length);
            }
        }	  
    }

    return 0;
}

/**
 * @brief   蓝牙连接状态解析
 * @details none
 * @param   _pt 结构体指针
 * @return  0：成功 其它：失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks 数据格式0,0 1 2
 */
static int _status_parse(BLUETOOTH_DEF *pt)
{
    // 固定开头为 "0,"
    if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',') 
    {
        rt_printf("%s data format error!\r\n", __func__);
        return -1;
    }

    if(pt->recvbuf[2] == '1')
    {
        // 连接断开
        pt->lnk_sta = false;
        rt_printf("蓝牙连接断开!\r\n");
        pt->us0_disc_reboot = bsp_ustimer_get_origin();
    }
    else if(pt->recvbuf[2] == '2')
    {
        // 正在连接
        rt_printf("蓝牙连接中...\r\n");
    }
    else if(pt->recvbuf[2] == '3')
    {
        // 已连接
        pt->lnk_sta = true;
        rt_printf("蓝牙已连接!\r\n");
    }
    else
    {
        // 未知的连接状态
        rt_printf_time("蓝牙连接状态解析错误,未知的状态%d%d%d!\r\n",pt->recvbuf[0],pt->recvbuf[1],pt->recvbuf[2]);
        return -2;
    }

    return 0;
}

/**
 * @brief   蓝牙名称设置解析
 * @details 解析名称设置结果
 * @param   _pt 结构体指针
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
static void _name_set_parse(BLUETOOTH_DEF *pt)
{
    rt_printf("设置蓝牙名称:%s%s\r\n", pt->recvbuf, pt->cmd_sta ? "成功!" : "失败!");
}

/**
 * @brief   蓝牙数据初始化
 * @details none
 * @param   _pt 结构体指针
 * @param   chnl 通道
 * @return  0: 成功 其它: 失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
int bluetooth_init(BLUETOOTH_DEF *pt, u8 chnl)
{
    u8 name_buf[30] = {0};
    RMT_FIXED_TABLE tfixedset;

    memset(pt,0,sizeof(BLUETOOTH_DEF));
    memset(&tfixedset,0,sizeof(tfixedset));
    tfixedset.num = RMT_FIXED_SET_NUM;
    tfixedset.set[0].type = FIXED_SET_ID;
    iec_get_fixedset_csv(&tfixedset);

    // 初始化接收buf结构
    pt->chnl = chnl;
	pt->rx_buf.chn = pt->chnl;
	pt->rx_buf.buf = pt->esambuf;
    rt_fifo_init(&pt->recv_fifo,pt->recv_fifo_buf,BLUETOOTH_BUF_LEN);
    
    if(tfixedset.set[0].len == 24)
    {
        /* ID 标准定义24位 */
        rt_printf("设置蓝牙名称:%s\r\n", tfixedset.set[0].str);
        memcpy(name_buf,tfixedset.set[0].str,tfixedset.set[0].len);
    }
    else
    {
        strcpy(name_buf,BLUETOOTH_DEFAULT_NAME);
        rt_printf("蓝牙: 未能从fixset.csv中获取到正确ID,使用默认名称:%s.\r\n", BLUETOOTH_DEFAULT_NAME);
    }

    _name_set(pt,name_buf,strlen(name_buf));
    _reboot(pt);

    return 0;
}

/**
 * @brief   蓝牙数据接收
 * @details 将数据存入fifo中
 * @param   _pt 结构体指针
 * @param   _byte 数据
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
void bluetooth_recv(BLUETOOTH_DEF *pt, u8 _byte)
{
    rt_fifo_put(&pt->recv_fifo,&_byte,1);
}

/**
 * @brief   发送检查
 * @details none
 * @param   _pt 结构体指针
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks 帧间隔延时精度受扫描间隔影响，实际测试到1000ms间隔发送也没什么问题
 */
static void _send_polling(BLUETOOTH_DEF *_pt)
{
	u8 *buf;
    u16 i = 0;
    u16 len = 0;
    u8 *pd,tb_send;
	bl_tbuf_t *pbuf;	

    pbuf = &_pt->tx_buf[0];
#if BL_ENABLE_RESEND_MODE
    // 上一帧未收到回复
    if(pbuf->tb_tail_send != pbuf->tb_tail_ack)
    {
        // 未超时不发下一帧
        if(bsp_ustimer_get_duration(_pt->us0_cfmtimeout) < USTIMER_MS*BL_TIMEOUT_RESEND_MS)
        {
            // tb_tail_send != tb_tail_ack,说明已进行过报文发送即更新过_pt->us0_cfmtimeout
            // 所以此处直接判断延时是否超时也没有问题
            return;
        }
        else
        {
            // 重发次数到达不再重发
            if(_pt->resend_cnt >= BL_RESEND_TIMES)
            {
                _pt->resend_cnt = 0;
                memset(_pt->tx_buf,0,sizeof(_pt->tx_buf));
                return;
            }

            // 超时重发
            pbuf->tb_tail_send--; // 发送尾索引回上一帧的位置进行重发
            _pt->resend_cnt++;
            rt_printf_time("超时重发上一帧,重发次数=%d,tb_head=%d,tb_tail_send=%d,len=%d\r\n", _pt->resend_cnt, pbuf->tb_head, pbuf->tb_tail_send, pbuf->tb_data[pbuf->tb_tail_send][0]);
            for(i = 0; i < pbuf->tb_data[pbuf->tb_tail_send][0]; i++)
            {
                if(i!=0 && i%16==0) rt_printf("\r\n");
                rt_printf("%02x ",pbuf->tb_data[pbuf->tb_tail_send][i+1]);
            }
            rt_printf("\r\n");

        }
    }
#endif
	// 如果串口忙或者帧间隔时间未到，不能发送数据
	if(g_tRsComm[_pt->chnl].bextsend || bsp_ustimer_get_duration(_pt->us0_sendpiece) < USTIMER_MS*FREAM_INTERVAL_TIME_MS)
	{
		return;
	}

    if(pbuf->tb_head == pbuf->tb_tail_send)  
    {
        return;
    }
	
    // 更新发送尾指针,保留老指针备用。
    tb_send = pbuf->tb_tail_send;
    pbuf->tb_tail_send++;
    if(pbuf->tb_tail_send >= BL_TBUF_NUM)
    {
       pbuf->tb_tail_send = 0; 
    }
    #ifdef BL_DEBUG
    rt_printf("send tb_head=%dtb_tail_send=%dtb_tail_ack=%d\r\n", pbuf->tb_head, pbuf->tb_tail_send, pbuf->tb_tail_ack);
    #endif
    //将数据复制到真正发送的buf
    len = pbuf->tb_data[tb_send][0];
    pd = g_tRsComm[_pt->chnl].extsendbuf;
    memcpy(pd,&pbuf->tb_data[tb_send][1],len); 
    g_tRsComm[_pt->chnl].extsendcnt=0;
    g_tRsComm[_pt->chnl].extsendlen=len;
    g_tRsComm[_pt->chnl].bextsend=true;
    #ifdef BL_DEBUG
    {
        rt_printf_time("bluetooth send data:%d\r\n",len);
        for(i = 0; i <len; i++)
        {
            if(i!=0 && i%16==0) rt_printf("\r\n");
            rt_printf("%02x ",g_tRsComm[_pt->chnl].extsendbuf[i]);
            
        }
        rt_printf("\r\n");
    }
    #endif

    _pt->us0_cfmtimeout=_pt->us0_sendpiece=bsp_ustimer_get_origin();
}

/**
 * @brief   蓝牙应用巡检
 * @details none
 * @param   _pt 结构体指针
 * @return  0：成功 其它：失败
 * @author  EWen
 * @date    2025-10-11
 * @remarks none
 */
int bluetooth_app(BLUETOOTH_DEF *pt)
{
    _recv_app(pt);

    if(pt->bData)
    {
        switch (pt->cmd_type)
        {
        case AT_CMD_DATA:
            _data_parse(pt);
            break;
        case AT_CMD_STAT:
            _status_parse(pt);
            break;
        case AT_CMD_NAME:
            _name_set_parse(pt);
            break;
        default:
            rt_printf("%s 未支持的指令类型->%d\r\n", __func__, pt->cmd_type);
            break;
        }
        pt->bData = false;
    }

    _send_polling(pt);

    return 0;
}

/**
 * @brief   蓝牙定时器
 * @details 处理一些定时任务
 * @param   _pt 结构体指针
 * @return  none
 * @author  EWen
 * @date    2025-10-11
 * @remarks 延时精度受扫描间隔影响，但实际在此处理的操作实时性要求不高，因此没有关系
 */
void bluetooth_timer(BLUETOOTH_DEF *pt)
{
    if(pt->us0_disc_reboot)
    {
        if(bsp_ustimer_get_duration(pt->us0_disc_reboot) >= BL_DISC_REBOOT_TIME_MS*USTIMER_MS)
        {
            _reboot(pt);
            pt->us0_disc_reboot = 0;
        }
    }

    if(pt->lnk_sta)
    {
        pt->us0_idle_reboot = 0;
    }
    else
    {
        if(pt->us0_idle_reboot == 0)
        {
            pt->us0_idle_reboot = bsp_ustimer_get_origin();
        }
        else
        {
            if(bsp_ustimer_get_duration(pt->us0_idle_reboot) >= BL_IDLE_REBOOT_TIME_MS*USTIMER_MS)
            {
                _reboot(pt);
                pt->us0_idle_reboot = 0;
            }
        }
    }

    if(pt->us0_recv)
    {
        if(bsp_ustimer_get_duration(pt->us0_recv) >= BL_RECV_TIMEOUT_MS*USTIMER_MS)
        {
            pt->us0_recv = 0;
            pt->b_recv_reset = true;
        }
    }

}