645 lines
13 KiB
C
645 lines
13 KiB
C
#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;
|
||
|
||
|
||
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 :
|
||
|
||
switch(g_ble_error.type)
|
||
{
|
||
case ERR_TYPE_NONE:
|
||
break;
|
||
|
||
case ERR_TYPE_PREPARE_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);
|
||
curr_state = BLE_WAITTING;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case ERR_TYPE_TIMEOUT_EXCEEDED:
|
||
{
|
||
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;
|
||
|
||
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);
|
||
curr_state = BLE_SET;
|
||
//重新配置串口信息
|
||
|
||
|
||
}
|
||
|
||
|
||
break;
|
||
|
||
case ERR_TYPE_MODULE_ERROR:
|
||
{
|
||
for(uint8_t i = 0; i < 4; i++)
|
||
{
|
||
if(g_ble_error.error_code == g_ble_error_table[i].code)
|
||
{
|
||
g_ble_error.
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
break;
|
||
|
||
|
||
case BLE_SET :
|
||
{
|
||
if() //重新配置串口信息
|
||
{
|
||
|
||
|
||
|
||
|
||
}
|
||
else if() //重新启动设备
|
||
{
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
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)
|
||
{
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|