1085 lines
30 KiB
C
1085 lines
30 KiB
C
#include "BLE.h"
|
||
#include "flash.h"
|
||
#include "usart.h"
|
||
#include <string.h>
|
||
#include <stdint.h>
|
||
|
||
|
||
#define BLE_DBG_EN 0 // 1=开启调试输出,0=关闭
|
||
|
||
|
||
#if (BLE_DBG_EN)
|
||
#define DEBUG(format, ...) printf("[BLE] " format, ##__VA_ARGS__)
|
||
#else
|
||
#define DEBUG(format, ...) // 关闭时,宏替换为空,不产生任何代码
|
||
#endif
|
||
|
||
|
||
BLE_STATE curr_state;
|
||
static size_t current_cmd_index = 0;
|
||
static uint32_t cmd_start_time;
|
||
static uint8_t current_try_count = 0;
|
||
static CmdExecutor_t init_executor;
|
||
static CmdExecutor_t first_connect_executor;
|
||
static CmdExecutor_t connect_executor;
|
||
static CmdExecutor_t trans_cfg_executor; // 用于 AT+TRANSPORT 的执行器
|
||
static CmdExecutor_t ready_executor;
|
||
static CmdExecutor_t set_executor;
|
||
static uint8_t recovery_level = 0; // 放在文件开头
|
||
static uint8_t FT_connect = 0; // 放在文件开头
|
||
static char host_mac[13];
|
||
char ble_rx_buffer[256]; // 定义接收缓冲区
|
||
volatile uint8_t ble_cmd_rec_done;
|
||
|
||
|
||
const char* ble_state_names[] = {
|
||
"BLE_INIT",
|
||
"BLE_FIRST_CONECT",
|
||
"BLE_CONNECTED",
|
||
"BLE_READY",
|
||
"BLE_CFG_TRANS",
|
||
"BLE_ERROR",
|
||
"BLE_SET",
|
||
"BLE_WAITTING"
|
||
};
|
||
|
||
const char* ble_sub_state_names[] = {
|
||
"BLE_SUB_STATE_IDLE",
|
||
"BLE_SUB_STATE_SEND_WAIT",
|
||
"BLE_SUB_STATE_PROCESS_RESP"
|
||
};
|
||
|
||
const BleAtCmd_t ble_init_sequence[] = {
|
||
{"AT\\r\\n", 100, 3, NULL, parse_general_resp},
|
||
{"AT+LADDR\\r\\n", 100, 3, NULL, parse_laddr_resp},
|
||
{NULL, 0, 0, NULL, NULL} // 结束标记
|
||
|
||
|
||
};
|
||
|
||
const BleAtCmd_t ble_first_connect_sequence[] = {
|
||
{"AT+UUID<%d>\\r\\n", 100, 3, prepare_uuid_cmd, parse_general_resp},
|
||
{"AT+RESET\\r\\n", 100, 3, NULL, parse_general_resp},
|
||
{"AT+NOTI%d\\r\\n",100, 3, prepare_noti_cmd, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL} // 结束标记
|
||
|
||
};
|
||
|
||
|
||
const BleAtCmd_t ble_connect_sequence[] = {
|
||
// {"AT+DIRADV\\r\\n", 100, 3, NULL, parse_diradv_cmd},
|
||
{"AT+DIRADV%d,%d,%s\\r\\n", 100, 3, prepare_diradv_cmd, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL} // 结束标记
|
||
|
||
};
|
||
|
||
|
||
|
||
|
||
const BleAtCmd_t ble_trans_cfg_sequence[] = {
|
||
{"AT+TRANSPORT%d\\r\\n", 100, 3, prepare_transport_cmd, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL} // 结束标记
|
||
|
||
};
|
||
|
||
|
||
//software reset
|
||
const BleAtCmd_t ble_reset_sequence[] = {
|
||
{"AT+RESET\r\n", 100, 3, NULL, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL}
|
||
};
|
||
|
||
// reset to default
|
||
const BleAtCmd_t ble_default_sequence[] = {
|
||
{"AT+DEFAULT\r\n", 100, 3, NULL, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL}
|
||
};
|
||
|
||
// total reset sequence
|
||
const BleAtCmd_t ble_full_set_sequence[] = {
|
||
{"AT+DISC\r\n", 100, 3, NULL, NULL},
|
||
{"AT+RESET\r\n", 100, 3, NULL, parse_general_resp},
|
||
{"AT+DEFAULT\r\n", 100, 3, NULL, parse_general_resp},
|
||
{NULL, 0, 0, NULL, NULL}
|
||
};
|
||
|
||
BleErrorInfo_t g_ble_error = {0};
|
||
|
||
BleGlobalConfig_t g_ble_config = {
|
||
// 连接参数
|
||
.mac_addr = "",
|
||
.addr_type = 0,
|
||
// 广播参数
|
||
.adv_param = 0, // 改为0
|
||
.adv_type = 0, // 改为0
|
||
.target_mac = "", // 初始化为空字符串
|
||
// 通信参数
|
||
.baud_rate = 9600, // 只有这个是你想保留的非零值
|
||
.tx_power = 0,
|
||
// UUID
|
||
.service_uuid = 0, // 显式写0(也可省略)
|
||
|
||
// NOTI选项
|
||
.Noption = 1, // 显式写0
|
||
|
||
// TRANS选项
|
||
.Toption = 1 // 显式写0
|
||
|
||
};
|
||
|
||
// 错误码表(根据你的模块手册填充)
|
||
BleErrorCodeInfo_t g_ble_error_table[] = {
|
||
{101, "参数长度错误", RECOVERY_TARGET_RESTART_SEQ}, // 参数错,重试没用
|
||
{102, "参数格式错误", RECOVERY_TARGET_RESTART_SEQ}, // 状态错,需检查流程
|
||
{103, "参数数据异常", RECOVERY_TARGET_RESTART_SEQ}, // 可重试
|
||
{104, "指令错误", RECOVERY_TARGET_SW_RESET_MODULE}, // 可重试
|
||
};
|
||
|
||
|
||
|
||
void BLE_Init(void)
|
||
{
|
||
curr_state = BLE_INIT;
|
||
ble_cmd_rec_done = 0;
|
||
|
||
|
||
}
|
||
|
||
|
||
BLE_STATE BLE_GetState(void)
|
||
{
|
||
|
||
return curr_state;
|
||
|
||
}
|
||
|
||
|
||
void BLE_StateMachine_Handler(void)
|
||
{
|
||
|
||
switch(curr_state)
|
||
{
|
||
case BLE_INIT :
|
||
{
|
||
if(init_executor.sequence == NULL)
|
||
{
|
||
init_executor.sequence = ble_init_sequence;
|
||
init_executor.cmd_index = 0;
|
||
init_executor.retry_cnt = 0;
|
||
init_executor.state = EXEC_STATE_IDLE;
|
||
}
|
||
ExecutorResult_t res = CmdExecutor_Process(&init_executor);
|
||
if(res == EXECUTOR_DONE)
|
||
{
|
||
|
||
// 尝试读取保存在本地的数据,如果没有则进入first connect
|
||
// 如果有则进入connected
|
||
if(Load_MAC_From_Flash(host_mac) == 0)
|
||
{
|
||
|
||
curr_state = BLE_CONNECTED;
|
||
|
||
}
|
||
else
|
||
{
|
||
curr_state = BLE_FIRST_CONECT;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
memset(&init_executor, 0, sizeof(init_executor));
|
||
|
||
}
|
||
else if(res == EXECUTOR_ERROR)
|
||
{
|
||
g_ble_error.cmd_index = init_executor.cmd_index;
|
||
g_ble_error.error_code =init_executor.error_code;
|
||
g_ble_error.main_state = curr_state;
|
||
g_ble_error.timestamp = HAL_GetTick();
|
||
g_ble_error.origin_state = BLE_INIT;
|
||
|
||
curr_state = BLE_ERROR;
|
||
memset(&init_executor, 0, sizeof(init_executor));
|
||
|
||
}
|
||
|
||
}
|
||
break;
|
||
|
||
|
||
case BLE_FIRST_CONECT :
|
||
{
|
||
|
||
// 惰性初始化
|
||
if (first_connect_executor.sequence == NULL)
|
||
{
|
||
first_connect_executor.sequence = ble_first_connect_sequence;
|
||
first_connect_executor.cmd_index = 0;
|
||
first_connect_executor.retry_cnt = 0;
|
||
first_connect_executor.state = EXEC_STATE_IDLE;
|
||
}
|
||
|
||
ExecutorResult_t res = CmdExecutor_Process(&first_connect_executor);
|
||
if(res == EXECUTOR_DONE)
|
||
{
|
||
FT_connect = 1;
|
||
curr_state = BLE_WAIT_CONNECT;
|
||
|
||
}
|
||
else if(res == EXECUTOR_ERROR)
|
||
{
|
||
g_ble_error.cmd_index = first_connect_executor.cmd_index;
|
||
g_ble_error.error_code =first_connect_executor.error_code;
|
||
g_ble_error.main_state = curr_state;
|
||
g_ble_error.timestamp = HAL_GetTick();
|
||
g_ble_error.origin_state = BLE_FIRST_CONECT;
|
||
|
||
curr_state = BLE_ERROR;
|
||
memset(&first_connect_executor, 0, sizeof(first_connect_executor));
|
||
|
||
|
||
}
|
||
|
||
|
||
}
|
||
break;
|
||
|
||
|
||
case BLE_CONNECTED :
|
||
{
|
||
if (connect_executor.sequence == NULL)
|
||
{
|
||
connect_executor.sequence = ble_connect_sequence;
|
||
connect_executor.cmd_index = 0;
|
||
connect_executor.retry_cnt = 0;
|
||
connect_executor.state = EXEC_STATE_IDLE;
|
||
}
|
||
|
||
ExecutorResult_t res = CmdExecutor_Process(&connect_executor);
|
||
if(res == EXECUTOR_DONE)
|
||
{
|
||
/*
|
||
保存参数到本地
|
||
*/
|
||
curr_state = BLE_WAIT_CONNECT;
|
||
|
||
}
|
||
else if(res == EXECUTOR_ERROR)
|
||
{
|
||
g_ble_error.cmd_index = connect_executor.cmd_index;
|
||
g_ble_error.error_code =connect_executor.error_code;
|
||
g_ble_error.main_state = curr_state;
|
||
g_ble_error.timestamp = HAL_GetTick();
|
||
g_ble_error.origin_state = BLE_CONNECTED;
|
||
|
||
curr_state = BLE_ERROR;
|
||
memset(&init_executor, 0, sizeof(connect_executor));
|
||
|
||
|
||
}
|
||
|
||
|
||
}
|
||
break;
|
||
case BLE_WAIT_CONNECT:
|
||
{
|
||
|
||
if(ble_cmd_rec_done == 1)
|
||
{
|
||
parse_master_addr_resp(ble_rx_buffer);
|
||
if(FT_connect)
|
||
{
|
||
//写入本地flash
|
||
Save_MAC_To_Flash(host_mac);
|
||
|
||
}
|
||
curr_state = BLE_CFG_TRANS;
|
||
// 并设置一个标志,让BLE_READY开始发送透传命令
|
||
ble_cmd_rec_done = 0;
|
||
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
break;
|
||
case BLE_CFG_TRANS:
|
||
{
|
||
// 惰性初始化
|
||
if (trans_cfg_executor.sequence == NULL)
|
||
{
|
||
trans_cfg_executor.sequence = ble_trans_cfg_sequence; // 该序列只包含 AT+TRANSPORT
|
||
trans_cfg_executor.cmd_index = 0;
|
||
trans_cfg_executor.retry_cnt = 0;
|
||
trans_cfg_executor.state = EXEC_STATE_IDLE;
|
||
}
|
||
|
||
ExecutorResult_t res = CmdExecutor_Process(&trans_cfg_executor);
|
||
if (res == EXECUTOR_DONE)
|
||
{
|
||
// 透传开启成功,进入 BLE_READY
|
||
curr_state = BLE_READY;
|
||
memset(&trans_cfg_executor, 0, sizeof(trans_cfg_executor)); // 清理,下次可能复用
|
||
}
|
||
else if (res == EXECUTOR_ERROR)
|
||
{
|
||
g_ble_error.cmd_index = trans_cfg_executor.cmd_index;
|
||
g_ble_error.error_code = trans_cfg_executor.error_code;
|
||
g_ble_error.main_state = curr_state;
|
||
g_ble_error.timestamp = HAL_GetTick();
|
||
g_ble_error.origin_state = BLE_CFG_TRANS;
|
||
curr_state = BLE_ERROR;
|
||
memset(&trans_cfg_executor, 0, sizeof(trans_cfg_executor));
|
||
}
|
||
// 若返回 BUSY,继续等待
|
||
break;
|
||
}
|
||
|
||
case BLE_READY :
|
||
{
|
||
static uint32_t last_transmit_time = 0;
|
||
uint32_t now = HAL_GetTick();
|
||
if (now - last_transmit_time >= 300) // 定义发送间隔
|
||
{
|
||
// 发送透传数据(例如从应用层获取)
|
||
uint8_t tx_data[] = "Hello BLE!\r\n";
|
||
HAL_UART_Transmit(&huart1, tx_data, sizeof(tx_data)-1, 100);
|
||
last_transmit_time = now;
|
||
}
|
||
// 接收数据已在回调中处理,无需额外操作
|
||
break;
|
||
|
||
}
|
||
break;
|
||
|
||
case BLE_ERROR :
|
||
{
|
||
const uint8_t MAX_RECOVERY_LEVEL = 3;
|
||
recovery_level++;
|
||
if (recovery_level > MAX_RECOVERY_LEVEL) {
|
||
DEBUG("恢复尝试已达上限(%d次),进入等待", MAX_RECOVERY_LEVEL);
|
||
curr_state = BLE_WAITTING;
|
||
break;
|
||
}
|
||
|
||
switch(g_ble_error.type)
|
||
{
|
||
case ERR_TYPE_NONE:
|
||
curr_state = g_ble_error.origin_state;
|
||
break;
|
||
|
||
case ERR_TYPE_PREPARE_FAILED:
|
||
{
|
||
g_ble_error.recovery_target = RECOVERY_TARGET_RECONFIG_UART;
|
||
//curr_state = BLE_WAITTING;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case ERR_TYPE_TIMEOUT_EXCEEDED:
|
||
|
||
g_ble_error.recovery_target = RECOVERY_TARGET_RESTART_SEQ;
|
||
|
||
//curr_state = BLE_SET;
|
||
//重新配置串口信息
|
||
break;
|
||
|
||
case ERR_TYPE_PARSE_FAILED:
|
||
|
||
// DEBUG("error message ,main state:%s, sub state:%s, cmd_index:%d, timestamp:%d",
|
||
// ble_state_names[g_ble_error.main_state], ble_sub_state_names[g_ble_error.sub_state], g_ble_error.cmd_index, g_ble_error.timestamp);
|
||
g_ble_error.recovery_target = RECOVERY_TARGET_RESTART_SEQ;
|
||
|
||
//重新配置串口信息
|
||
break;
|
||
|
||
case ERR_TYPE_MODULE_ERROR:
|
||
{
|
||
uint8_t table_size = sizeof(g_ble_error_table) / sizeof(g_ble_error_table[0]);
|
||
uint8_t i;
|
||
for(i = 0; i < table_size; i++)
|
||
{
|
||
if(g_ble_error.error_code == g_ble_error_table[i].code)
|
||
{
|
||
g_ble_error.recovery_target = g_ble_error_table[i].recovery_target;
|
||
DEBUG("error message ,main state:%s, sub state:%s, cmd_index:%d, timestamp:%d",
|
||
ble_state_names[g_ble_error.main_state], ble_sub_state_names[g_ble_error.sub_state], g_ble_error.cmd_index, g_ble_error.timestamp);
|
||
//curr_state = BLE_SET;
|
||
break;
|
||
}
|
||
}
|
||
if(i == table_size)
|
||
{
|
||
g_ble_error.recovery_target = RECOVERY_TARGET_RESTART_SEQ;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
|
||
}
|
||
|
||
|
||
default:
|
||
g_ble_error.recovery_target = RECOVERY_TARGET_PANIC;
|
||
|
||
break;
|
||
|
||
|
||
}
|
||
|
||
// 3. 执行恢复动作
|
||
switch(g_ble_error.recovery_target)
|
||
{
|
||
case RECOVERY_TARGET_RESTART_SEQ:
|
||
// 重启当前流程阶段:根据 origin_state 重置对应的执行器
|
||
switch(g_ble_error.origin_state)
|
||
{
|
||
case BLE_INIT:
|
||
memset(&init_executor, 0, sizeof(init_executor));
|
||
break;
|
||
case BLE_FIRST_CONECT:
|
||
memset(&first_connect_executor, 0, sizeof(first_connect_executor));
|
||
break;
|
||
case BLE_CONNECTED:
|
||
memset(&connect_executor, 0, sizeof(connect_executor));
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
// 返回原状态,重新开始执行序列
|
||
recovery_level = 0;
|
||
curr_state = g_ble_error.origin_state;
|
||
break;
|
||
|
||
case RECOVERY_TARGET_RECONFIG_UART:
|
||
// 重新配置 MCU 串口(调用你的串口初始化函数)
|
||
// 例如: MX_USART1_UART_Init();
|
||
// 然后重置对应执行器
|
||
switch(g_ble_error.origin_state)
|
||
{
|
||
case BLE_INIT:
|
||
memset(&init_executor, 0, sizeof(init_executor));
|
||
break;
|
||
case BLE_FIRST_CONECT:
|
||
memset(&first_connect_executor, 0, sizeof(first_connect_executor));
|
||
break;
|
||
case BLE_CONNECTED:
|
||
memset(&connect_executor, 0, sizeof(connect_executor));
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
recovery_level = 0;
|
||
curr_state = g_ble_error.origin_state;
|
||
break;
|
||
|
||
case RECOVERY_TARGET_SW_RESET_MODULE:
|
||
case RECOVERY_TARGET_FACTORY_RESET:
|
||
// 需要通过 AT 命令执行,进入 BLE_SET 状态
|
||
// 注意:origin_state 保持不变,BLE_SET 执行完后会返回它
|
||
curr_state = BLE_SET;
|
||
break;
|
||
|
||
case RECOVERY_TARGET_HARD_RESET_MODULE:
|
||
// 硬件复位模块:拉低复位引脚,延时,拉高
|
||
// 假设有 BLE_RST_PIN 控制
|
||
// HAL_GPIO_WritePin(BLE_RST_GPIO_Port, BLE_RST_Pin, GPIO_PIN_RESET);
|
||
// HAL_Delay(100);
|
||
// HAL_GPIO_WritePin(BLE_RST_GPIO_Port, BLE_RST_Pin, GPIO_PIN_SET);
|
||
// 复位后重置对应执行器
|
||
switch(g_ble_error.origin_state)
|
||
{
|
||
case BLE_INIT:
|
||
memset(&init_executor, 0, sizeof(init_executor));
|
||
break;
|
||
case BLE_FIRST_CONECT:
|
||
memset(&first_connect_executor, 0, sizeof(first_connect_executor));
|
||
break;
|
||
case BLE_CONNECTED:
|
||
memset(&connect_executor, 0, sizeof(connect_executor));
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
recovery_level = 0;
|
||
curr_state = g_ble_error.origin_state;
|
||
break;
|
||
|
||
case RECOVERY_TARGET_SOFT_RESET_MCU:
|
||
// 软件复位整个 MCU
|
||
//NVIC_SystemReset();
|
||
break;
|
||
|
||
case RECOVERY_TARGET_PANIC:
|
||
default:
|
||
// 无法恢复,进入等待状态
|
||
DEBUG("error message ,main state:%s, sub state:%s, cmd_index:%d, timestamp:%d",
|
||
ble_state_names[g_ble_error.main_state], ble_sub_state_names[g_ble_error.sub_state], g_ble_error.cmd_index, g_ble_error.timestamp);
|
||
curr_state = BLE_WAITTING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
}
|
||
|
||
|
||
|
||
case BLE_SET :
|
||
{
|
||
const BleAtCmd_t* target_seq = NULL;
|
||
switch(g_ble_error.recovery_target)
|
||
{
|
||
case RECOVERY_TARGET_SW_RESET_MODULE:
|
||
{
|
||
static const BleAtCmd_t sw_reset_sq[] = {
|
||
|
||
{"AT+RESET\r\n", 100, 3, NULL, NULL},
|
||
{NULL, 0, 0, NULL, NULL}
|
||
|
||
};
|
||
target_seq = sw_reset_sq;
|
||
|
||
}
|
||
break;
|
||
case RECOVERY_TARGET_FACTORY_RESET:
|
||
{ //回复出厂设置
|
||
{
|
||
static const BleAtCmd_t factory_reset_seq[] = {
|
||
{"AT+DEFAULT\r\n", 100, 3, NULL, NULL},
|
||
{NULL, 0, 0, NULL, NULL}
|
||
};
|
||
target_seq = factory_reset_seq;
|
||
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
//没有匹配目标则返回原状态
|
||
curr_state = g_ble_error.origin_state;
|
||
break;
|
||
|
||
}
|
||
if(target_seq != NULL)
|
||
{
|
||
// 如果 set_executor 尚未启动,则初始化
|
||
if(set_executor.sequence == NULL)
|
||
{
|
||
set_executor.sequence = target_seq;
|
||
set_executor.cmd_index = 0;
|
||
set_executor.retry_cnt = 0;
|
||
set_executor.state = EXEC_STATE_IDLE;
|
||
}
|
||
ExecutorResult_t res = CmdExecutor_Process(&set_executor);
|
||
if(res == EXECUTOR_DONE)
|
||
{
|
||
// 恢复命令执行成功,将恢复级别清零,返回原状态
|
||
// 注意:恢复级别 recovery_level 是在 BLE_ERROR 中定义的静态变量,这里无法直接访问。
|
||
// 解决方案:可以在 BLE_ERROR 中定义一个全局或外部变量,或者通过某种方式传递。
|
||
// 简单起见,我们可以在 BLE_ERROR 中重置 recovery_level,但这里无法做到。
|
||
// 一个常见的做法是在 BLE_ERROR 中判断恢复成功与否,但由于这里返回原状态,我们可以在返回前设置一个标志,让 BLE_ERROR 下次进入时重置级别。
|
||
// 但考虑到恢复级别只在 BLE_ERROR 中管理,我们可以这样处理:当 BLE_SET 成功返回原状态后,原状态会继续执行,如果再次出错会重新进入 BLE_ERROR,此时 recovery_level 仍然存在,但这是合理的(因为已经成功过,应该重置级别?)
|
||
// 实际上,一次恢复成功意味着系统已经正常,应该重置级别。所以我们需要在 BLE_SET 成功时通知 BLE_ERROR 重置级别。
|
||
// 由于 recovery_level 是 BLE_ERROR 内部的静态变量,无法直接从外部修改。我们可以将 recovery_level 定义为全局变量,或者通过函数接口。
|
||
// 这里为了简单,我们假设 recovery_level 是全局变量(例如在文件顶部定义),并在 BLE_SET 成功时清零。
|
||
// 请根据实际情况调整。下面假设有一个全局变量 uint8_t g_recovery_level; 并在 BLE_ERROR 中改为使用它。
|
||
// 如果没有,你可以将 recovery_level 定义在文件作用域(static),然后在 BLE_SET 中包含一个 extern 声明。
|
||
// 这里我们暂时注释掉,你需要根据你的设计实现。
|
||
recovery_level = 0;
|
||
|
||
memset(&set_executor, 0, sizeof(set_executor));
|
||
curr_state = g_ble_error.origin_state;
|
||
}
|
||
else if(res == EXECUTOR_ERROR)
|
||
{
|
||
// 恢复命令也失败,将 set_executor 中的错误信息复制到 g_ble_error(保留 origin_state)
|
||
g_ble_error.type = set_executor.error_type;
|
||
g_ble_error.error_code = set_executor.error_code;
|
||
g_ble_error.cmd_index = set_executor.error_cmd_index;
|
||
g_ble_error.timestamp = HAL_GetTick();
|
||
// 注意:不要覆盖 origin_state
|
||
memset(&set_executor, 0, sizeof(set_executor));
|
||
// 再次进入 BLE_ERROR,恢复级别将在那里递增
|
||
curr_state = BLE_ERROR;
|
||
}
|
||
// 若返回 BUSY,则继续等待,不做状态切换
|
||
}
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
case BLE_WAITTING:
|
||
{
|
||
static uint32_t last_time = 0;
|
||
uint32_t time = HAL_GetTick();
|
||
uint32_t rest = time - last_time;
|
||
if(rest >= 500)
|
||
{
|
||
//输出警报
|
||
last_time = time;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
break;
|
||
default:
|
||
|
||
break;
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
ExecutorResult_t CmdExecutor_Process(CmdExecutor_t* ex) //发送流程执行器
|
||
{
|
||
switch(ex->state)
|
||
{
|
||
|
||
case EXEC_STATE_IDLE:
|
||
{
|
||
ble_cmd_rec_done= 0;
|
||
if(ex->sequence[ex->cmd_index].cmd == NULL)
|
||
{
|
||
DEBUG("init success");
|
||
return EXECUTOR_DONE;
|
||
|
||
}
|
||
const BleAtCmd_t *current_cmd = &ex->sequence[ex->cmd_index];
|
||
char final_cmd[64];
|
||
int prepare_ok = 0; // 标记准备是否成功
|
||
|
||
if(current_cmd->prepare_cmd != NULL)
|
||
{
|
||
int prepare_result = current_cmd->prepare_cmd(current_cmd->cmd, final_cmd, sizeof(final_cmd));
|
||
if(prepare_result != 0)
|
||
{
|
||
DEBUG("命令准备失败,错误码: %d,跳过此命令", prepare_result);
|
||
ex->error_type = ERR_TYPE_PREPARE_FAILED;
|
||
ex->error_code = prepare_result;
|
||
ex->error_cmd_index = ex->cmd_index;
|
||
ex->state = EXEC_STATE_ERROR;
|
||
return EXECUTOR_ERROR;
|
||
|
||
}
|
||
else
|
||
{
|
||
prepare_ok = 1;
|
||
|
||
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
strncpy(final_cmd, current_cmd->cmd, sizeof(final_cmd));
|
||
final_cmd[sizeof(final_cmd) - 1] = '\0';
|
||
prepare_ok = 1;
|
||
|
||
}
|
||
if(prepare_ok == 1)
|
||
{
|
||
//发送命令 待添加实际代码
|
||
|
||
ex->start_tick = HAL_GetTick();
|
||
ex->state = EXEC_STATE_SEND_WAIT;
|
||
ble_cmd_rec_done = 0;
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
|
||
|
||
case EXEC_STATE_SEND_WAIT:
|
||
{
|
||
const BleAtCmd_t *current_cmd = &ex->sequence[ex->cmd_index];
|
||
uint16_t out_time = current_cmd->timeout_ms;
|
||
uint8_t try_max = current_cmd->retry_max;
|
||
if(ble_cmd_rec_done == 1)
|
||
{
|
||
|
||
ex->retry_cnt = 0;
|
||
ex->state = EXEC_STATE_PROCESS_RESP;
|
||
return EXECUTOR_BUSY;
|
||
|
||
|
||
}
|
||
|
||
uint32_t time = HAL_GetTick();
|
||
if((time - ex->start_tick) > out_time)
|
||
{
|
||
ex->retry_cnt++;
|
||
if(ex->retry_cnt <= try_max)
|
||
{
|
||
ex->state = EXEC_STATE_IDLE;
|
||
ble_cmd_rec_done = 0; // 建议清零,避免旧数据影响下一次
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
else
|
||
{
|
||
ex->error_type = ERR_TYPE_TIMEOUT_EXCEEDED;
|
||
ex->error_code = 0;
|
||
ex->error_cmd_index = ex->cmd_index;
|
||
ex->state = EXEC_STATE_ERROR;
|
||
return EXECUTOR_ERROR;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
return EXECUTOR_BUSY;
|
||
|
||
|
||
}
|
||
|
||
|
||
case EXEC_STATE_PROCESS_RESP:
|
||
{
|
||
//接受串口回传具体信息
|
||
//char process_data[] = 缓存区数据
|
||
const BleAtCmd_t *current_cmd = &ex->sequence[ex->cmd_index];
|
||
int result;
|
||
if ((current_cmd->parse_resp) != NULL)
|
||
{
|
||
result = current_cmd->parse_resp(ble_rx_buffer);
|
||
}
|
||
else
|
||
{
|
||
result = parse_general_resp(ble_rx_buffer);
|
||
|
||
|
||
}
|
||
if(result == 0) //解析正确
|
||
{
|
||
ex->cmd_index++;
|
||
ex->retry_cnt = 0;
|
||
ex->state = EXEC_STATE_IDLE;
|
||
ble_cmd_rec_done = 0;
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
else if(result > 0) //模块返回错误码
|
||
{
|
||
ex->retry_cnt++;
|
||
if(ex->retry_cnt <= current_cmd->retry_max)
|
||
{
|
||
ex->state = EXEC_STATE_IDLE;
|
||
ble_cmd_rec_done = 0;
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
else
|
||
{
|
||
ex->error_type = ERR_TYPE_MODULE_ERROR;
|
||
ex->error_code = result;
|
||
ex->error_cmd_index = ex->cmd_index;
|
||
ex->state = EXEC_STATE_ERROR;
|
||
return EXECUTOR_ERROR;
|
||
|
||
|
||
}
|
||
|
||
}
|
||
else //result<0
|
||
{
|
||
//解析失败的其他情况
|
||
ex->retry_cnt++;
|
||
if(ex->retry_cnt <= current_cmd->retry_max)
|
||
{
|
||
ex->state = EXEC_STATE_IDLE;
|
||
ble_cmd_rec_done = 0;
|
||
return EXECUTOR_BUSY;
|
||
|
||
}
|
||
else
|
||
{
|
||
ex->error_type = ERR_TYPE_PARSE_FAILED;
|
||
ex->error_code = result;
|
||
ex->error_cmd_index = ex->cmd_index;
|
||
ex->state = EXEC_STATE_ERROR;
|
||
return EXECUTOR_ERROR;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
uint8_t BLE_UART_RxCallback(uint8_t *data, uint16_t len)
|
||
{
|
||
// 防止缓冲区溢出,保留一个字节给结束符
|
||
uint16_t copy_len = (len < sizeof(ble_rx_buffer)) ? len : (sizeof(ble_rx_buffer) - 1);
|
||
memcpy(ble_rx_buffer, data, copy_len);
|
||
ble_rx_buffer[copy_len] = '\0'; // 添加字符串结束符,便于字符串函数使用
|
||
|
||
// 置位接收完成标志
|
||
ble_cmd_rec_done = 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int parse_general_resp(const char* resp)
|
||
{
|
||
if(resp == NULL)
|
||
{
|
||
return -1;
|
||
|
||
}
|
||
|
||
const char *ok_result = strstr(resp, "OK");
|
||
if(ok_result != NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
int err_code = 0;
|
||
int auth = sscanf(resp, "ERROR=<%d>", &err_code);
|
||
if(auth == 1)
|
||
{
|
||
uint8_t table_size = sizeof(g_ble_error_table)/sizeof(g_ble_error_table[0]);
|
||
|
||
for(uint8_t i = 0; i<table_size; i++)
|
||
{
|
||
|
||
if(err_code == g_ble_error_table[i].code)
|
||
{
|
||
DEBUG("%s", g_ble_error_table[i].desc);
|
||
return err_code;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
DEBUG("未知错误码:%d", err_code);
|
||
return err_code;
|
||
|
||
}
|
||
DEBUG("无法识别的响应: %s", resp);
|
||
return -1; // 添加默认返回值
|
||
|
||
|
||
}
|
||
|
||
|
||
int prepare_diradv_cmd(const char* cmd_template, char* cmd_buf, int buf_size)
|
||
{
|
||
if(cmd_buf == NULL || buf_size <= 0)
|
||
{
|
||
return -1;
|
||
|
||
}
|
||
|
||
uint8_t para = g_ble_config.adv_param; //取出序号
|
||
uint8_t type = g_ble_config.addr_type; //取出地址类型
|
||
char* mac = g_ble_config.target_mac; //取出mac地址
|
||
|
||
int needed_len = snprintf(cmd_buf, buf_size, cmd_template, para, type, mac);
|
||
if(needed_len < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
else if(needed_len >= buf_size)
|
||
{
|
||
return -2;
|
||
|
||
}
|
||
else
|
||
{
|
||
return -3;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
int parse_laddr_resp(const char* resp)
|
||
{
|
||
if (resp == NULL)
|
||
{
|
||
return -1; // 无效输入
|
||
}
|
||
|
||
char mac[13]; // 用于临时存储提取的MAC地址(12字符 + '\0')
|
||
// 使用sscanf提取等号后面的连续12个字符(自动跳过空白符)
|
||
if (sscanf(resp, "+LADDR=%12s", mac) == 1)
|
||
{
|
||
// 检查提取的字符串长度是否为12(防止意外截断)
|
||
if (strlen(mac) == 12)
|
||
{
|
||
// 将MAC地址复制到全局配置结构体中
|
||
strncpy(g_ble_config.mac_addr, mac, 12);
|
||
g_ble_config.mac_addr[12] = '\0'; // 确保字符串终止
|
||
return 0; // 解析成功
|
||
}
|
||
}
|
||
|
||
// 如果响应格式不匹配或长度不对,则解析失败
|
||
return -1;
|
||
}
|
||
|
||
|
||
uint8_t parse_master_addr_resp(const char* resp)
|
||
{
|
||
char *res = strstr(ble_rx_buffer, "0x");
|
||
if (res != NULL)
|
||
{
|
||
char *num_start = res + 2; // 跳过 "0x"
|
||
char mac_str[13]; // 12字符 + 结束符
|
||
int i = 0;
|
||
|
||
// 遍历直到遇到非十六进制字符或字符串结束
|
||
while (*num_start != '\0')
|
||
{
|
||
char c = *num_start;
|
||
// 判断是否十六进制字符
|
||
if ((c >= '0' && c <= '9') ||
|
||
(c >= 'A' && c <= 'F') ||
|
||
(c >= 'a' && c <= 'f'))
|
||
{
|
||
if (i < sizeof(mac_str) - 1)
|
||
{ // 防止缓冲区溢出
|
||
mac_str[i++] = c;
|
||
}
|
||
else
|
||
{
|
||
break; // 超出缓冲区,停止
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break; // 遇到非十六进制字符,停止
|
||
}
|
||
num_start++;
|
||
}
|
||
mac_str[i] = '\0'; // 添加字符串结束符
|
||
|
||
// 此时 mac_str 就是提取出的字符串
|
||
// 例如保存到全局变量
|
||
strncpy(host_mac, mac_str, 12);
|
||
host_mac[12] = '\0';
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
int prepare_uuid_cmd(const char* cmd_template, char* cmd_buf, int buf_size)
|
||
{
|
||
if (cmd_buf == NULL || buf_size <= 0)
|
||
{
|
||
return -1; // 参数错误
|
||
}
|
||
|
||
uint16_t uuid = g_ble_config.service_uuid; // 从全局配置中取出 UUID
|
||
|
||
int needed_len = snprintf(cmd_buf, buf_size, cmd_template, uuid);
|
||
if (needed_len < 0)
|
||
{
|
||
return -1; // 格式化错误
|
||
}
|
||
else if (needed_len >= buf_size)
|
||
{
|
||
return -2; // 缓冲区不足
|
||
}
|
||
else
|
||
{
|
||
return 0; // 成功
|
||
}
|
||
}
|
||
|
||
|
||
int prepare_noti_cmd(const char* cmd_template, char* cmd_buf, int buf_size)
|
||
{
|
||
if (cmd_buf == NULL || buf_size <= 0)
|
||
{
|
||
return -1; // 参数错误
|
||
}
|
||
|
||
uint8_t noti_opt = g_ble_config.Noption; // 从全局配置中取出通知选项(0或1)
|
||
|
||
int needed_len = snprintf(cmd_buf, buf_size, cmd_template, noti_opt);
|
||
if (needed_len < 0)
|
||
{
|
||
return -1; // 格式化错误
|
||
}
|
||
else if (needed_len >= buf_size)
|
||
{
|
||
return -2; // 缓冲区不足
|
||
}
|
||
else
|
||
{
|
||
return 0; // 成功
|
||
}
|
||
}
|
||
|
||
|
||
int prepare_transport_cmd(const char* cmd_template, char* cmd_buf, int buf_size)
|
||
{
|
||
if (cmd_buf == NULL || buf_size <= 0)
|
||
{
|
||
return -1; // 参数错误
|
||
}
|
||
|
||
uint8_t transport_opt = g_ble_config.Toption; // 从全局配置中取出透传选项
|
||
|
||
int needed_len = snprintf(cmd_buf, buf_size, cmd_template, transport_opt);
|
||
if (needed_len < 0)
|
||
{
|
||
return -1; // 格式化错误
|
||
}
|
||
else if (needed_len >= buf_size)
|
||
{
|
||
return -2; // 缓冲区不足
|
||
}
|
||
else
|
||
{
|
||
return 0; // 成功
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|