代码¶
Warning
以下代码应基于发布代码中的代码,可能已更新。
sensing_command.h¶
/**
* @file sensing_command.h
* @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
* @brief MQTT远程控制命令处理器,用于传感模块
* @version 1.0
* @date 2025-01-XX
* @copyright Copyright (c) 2025
*
* @details
* 该模块处理用于控制在线和离线传感的MQTT命令。
* 命令格式:SENSE,ONLINE 或 SENSE,OFFLINE,带参数
*
* 支持的命令:
* - SENSE,ONLINE,F=频率,D=持续时间
* - SENSE,ONLINE,STOP
* - SENSE,ONLINE,STATUS
* - SENSE,OFFLINE,F=频率,D=采样时长
* - SENSE,OFFLINE,F=频率,D=采样时长,DL=延迟秒
* - SENSE,OFFLINE,F=频率,D=采样时长,TIME=YYMMDDHHMMSS
* - SENSE,OFFLINE,STOP
* - SENSE,OFFLINE,STATUS
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "node_acc_adxl355.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* ============================================================================
* FUNCTION DECLARATIONS
* ============================================================================ */
/**
* @brief 处理MQTT传感命令
* @param command 命令字符串(例如:"SENSE,ONLINE,F=20,D=60")
* @param command_len 命令字符串长度
* @return 成功返回ESP_OK,失败返回错误码
* @note 此函数解析并执行命令,然后通过MQTT发布响应
*/
esp_err_t sensing_command_process(const char *command, int command_len);
/**
* @brief 初始化传感命令处理器
* @return 成功返回ESP_OK,失败返回错误码
* @note 必须在MQTT初始化后调用
*/
esp_err_t sensing_command_init(void);
/**
* @brief 为命令处理器设置传感器句柄
* @param handle ADXL355传感器句柄
* @return 成功返回ESP_OK,失败返回错误码
* @note 必须在处理命令之前调用
*/
esp_err_t sensing_command_set_sensor_handle(adxl355_handle_t *handle);
#ifdef __cplusplus
}
#endif
sensing_command.c¶
实现包括:
关键函数¶
- 命令处理
sensing_command_process(): 命令处理的主入口点command_processing_task(): 从队列处理命令的FreeRTOS任务handle_online_command(): 处理在线传感命令-
handle_offline_command(): 处理离线传感命令 -
参数解析
parse_float_param(): 从命令字符串中提取浮点参数parse_int_param(): 从命令字符串中提取整数参数-
parse_time_param(): 解析YYMMDDHHMMSS格式的TIME参数 -
任务管理
offline_sensing_task_wrapper(): 支持延迟的离线传感包装任务-
online_sensing_stop_task(): 在持续时间后自动停止在线传感的任务 -
响应处理
send_mqtt_response(): 通过MQTT发布命令响应
命令队列结构¶
#define COMMAND_QUEUE_SIZE 5
#define MAX_COMMAND_LENGTH 256
typedef struct
{
char command[MAX_COMMAND_LENGTH];
int command_len;
} command_queue_item_t;
初始化流程¶
esp_err_t sensing_command_init(void)
{
// 创建命令队列
s_command_queue = xQueueCreate(COMMAND_QUEUE_SIZE, sizeof(command_queue_item_t));
// 创建命令处理任务
BaseType_t ret = xTaskCreate(
command_processing_task,
"cmd_processor",
4096, // 栈大小
NULL,
5, // 优先级
&s_command_task_handle);
return ret == pdPASS ? ESP_OK : ESP_FAIL;
}
命令处理流程¶
- 通过MQTT回调接收命令
- 命令排队等待处理
- 命令处理任务出队并验证
- 命令解析并路由到相应的处理器
- 通过MQTT发布响应
参数解析示例¶
static esp_err_t parse_float_param(const char *str, const char *prefix, float *value)
{
char search_str[32];
snprintf(search_str, sizeof(search_str), "%s=", prefix);
const char *pos = strstr(str, search_str);
if (pos == NULL)
{
return ESP_ERR_NOT_FOUND;
}
pos += strlen(search_str);
const char *end = strchr(pos, ',');
if (end == NULL)
{
end = pos + strlen(pos);
}
char value_str[64];
size_t len = end - pos;
if (len >= sizeof(value_str))
{
len = sizeof(value_str) - 1;
}
strncpy(value_str, pos, len);
value_str[len] = '\0';
char *parse_end;
*value = strtof(value_str, &parse_end);
if (parse_end == value_str || *parse_end != '\0')
{
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
在线命令处理器¶
static esp_err_t handle_online_command(const char *cmd)
{
// 检查STOP命令
if (strstr(cmd, "STOP") != NULL)
{
esp_err_t ret = online_sensing_stop();
send_mqtt_response(ret == ESP_OK ?
"SENSE,OK,ONLINE,STOPPED" :
"SENSE,ERROR,ONLINE,STOP_FAILED");
return ret;
}
// 检查STATUS命令
if (strstr(cmd, "STATUS") != NULL)
{
bool is_running = false;
online_sensing_is_running(&is_running);
online_sensing_config_t config;
online_sensing_get_config(&config);
char resp[128];
snprintf(resp, sizeof(resp), "SENSE,STATUS,ONLINE,RUNNING=%s,F=%.2f",
is_running ? "YES" : "NO", config.sampling_frequency_hz);
send_mqtt_response(resp);
return ESP_OK;
}
// 解析F和D参数
float freq = 0.0f;
float duration = 0.0f;
if (parse_float_param(cmd, "F", &freq) != ESP_OK)
{
send_mqtt_response("SENSE,ERROR,ONLINE,INVALID_FREQ");
return ESP_ERR_INVALID_ARG;
}
if (parse_float_param(cmd, "D", &duration) != ESP_OK)
{
duration = 0.0f; // 默认:持续运行
}
// 验证并启动在线传感
// ... (实现细节)
}
离线命令处理器¶
static esp_err_t handle_offline_command(const char *cmd)
{
// 检查STOP命令
if (strstr(cmd, "STOP") != NULL)
{
bool is_running = false;
offline_sensing_is_running(&is_running);
if (is_running)
{
esp_err_t ret = offline_sensing_stop();
send_mqtt_response(ret == ESP_OK ?
"SENSE,OK,OFFLINE,STOPPED" :
"SENSE,ERROR,OFFLINE,STOP_FAILED");
return ret;
}
// ... (错误处理)
}
// 解析参数(F, D, DL, TIME)
// ... (实现细节)
// 创建支持延迟的离线传感任务
// ... (任务创建)
}
使用示例¶
// 初始化命令处理器
esp_err_t ret = sensing_command_init();
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "初始化命令处理器失败");
return;
}
// 设置传感器句柄
ret = sensing_command_set_sensor_handle(&adxl355_handle);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "设置传感器句柄失败");
return;
}
// 在MQTT消息回调中
void mqtt_message_callback(esp_mqtt_event_handle_t event)
{
if (strncmp(event->data, "SENSE,", 6) == 0)
{
sensing_command_process(event->data, event->data_len);
}
}