pressure_sensor_system/Software/master/PressureSensorBoardMaster/BSP/BLE.c

802 lines
21 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "BLE.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
char ble_rx_buffer[256];
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 set_executor;
static uint8_t recovery_level = 0; // 放在文件开头
const char* ble_state_names[] = {
"BLE_INIT",
"BLE_FIRST_CONECT",
"BLE_CONNECTED",
"BLE_READY",
"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"
};
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
*/
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 :
{
ExecutorResult_t res = CmdExecutor_Process(&first_connect_executor);
if(res == EXECUTOR_DONE)
{
/*
保存参数到本地
*/
curr_state = BLE_CONNECTED;
}
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_FIRST_CONECT;
curr_state = BLE_ERROR;
memset(&init_executor, 0, sizeof(first_connect_executor));
}
}
break;
case BLE_CONNECTED :
{
ExecutorResult_t res = CmdExecutor_Process(&connect_executor);
if(res == EXECUTOR_DONE)
{
/*
保存参数到本地
*/
curr_state = BLE_READY;
}
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_CONNECTED;
curr_state = BLE_ERROR;
memset(&init_executor, 0, sizeof(connect_executor));
}
}
break;
case BLE_READY :
{
/*
在已经开启透传的情况下周期性发送消息,一般情况不进行跳转其他状态
如果超时则返回连接状态多次出问题则进error
*/
}
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", "OK", 100, 3, NULL, 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", "OK", 100, 3, NULL, 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;
}
break;
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;
}
break;
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(void)
{
}
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_diradv_cmd(const char* cmd_template, char* cmd_buf, int buf_size)
{
}