Skip to content

CODE

Warning

The following code should be based on the code in the release code, which may have been updated.

sensing_command.h

/**
 * @file sensing_command.h
 * @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
 * @brief MQTT remote control command handler for sensing modules
 * @version 1.0
 * @date 2025-01-XX
 * @copyright Copyright (c) 2025
 *
 * @details
 * This module handles MQTT commands for controlling online and offline sensing.
 * Command format: SENSE,ONLINE or SENSE,OFFLINE with parameters
 *
 * Supported commands:
 * - 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 Process MQTT sensing command
 * @param command Command string (e.g., "SENSE,ONLINE,F=20,D=60")
 * @param command_len Length of command string
 * @return ESP_OK on success, error code on failure
 * @note This function parses and executes the command, then publishes response via MQTT
 */
esp_err_t sensing_command_process(const char *command, int command_len);

/**
 * @brief Initialize sensing command handler
 * @return ESP_OK on success, error code on failure
 * @note Must be called after MQTT is initialized
 */
esp_err_t sensing_command_init(void);

/**
 * @brief Set sensor handle for command handler
 * @param handle ADXL355 sensor handle
 * @return ESP_OK on success, error code on failure
 * @note Must be called before processing commands
 */
esp_err_t sensing_command_set_sensor_handle(adxl355_handle_t *handle);

#ifdef __cplusplus
}
#endif

sensing_command.c

The implementation includes:

Key Functions

  1. Command Processing
  2. sensing_command_process(): Main entry point for command processing
  3. command_processing_task(): FreeRTOS task that processes commands from queue
  4. handle_online_command(): Handles ONLINE sensing commands
  5. handle_offline_command(): Handles OFFLINE sensing commands

  6. Parameter Parsing

  7. parse_float_param(): Extracts float parameters from command string
  8. parse_int_param(): Extracts integer parameters from command string
  9. parse_time_param(): Parses TIME parameter in YYMMDDHHMMSS format

  10. Task Management

  11. offline_sensing_task_wrapper(): Wrapper task for offline sensing with delay support
  12. online_sensing_stop_task(): Task to auto-stop online sensing after duration

  13. Response Handling

  14. send_mqtt_response(): Publishes command response via MQTT

Command Queue Structure

#define COMMAND_QUEUE_SIZE 5
#define MAX_COMMAND_LENGTH 256

typedef struct
{
    char command[MAX_COMMAND_LENGTH];
    int command_len;
} command_queue_item_t;

Initialization Flow

esp_err_t sensing_command_init(void)
{
    // Create command queue
    s_command_queue = xQueueCreate(COMMAND_QUEUE_SIZE, sizeof(command_queue_item_t));

    // Create command processing task
    BaseType_t ret = xTaskCreate(
        command_processing_task,
        "cmd_processor",
        4096, // Stack size
        NULL,
        5, // Priority
        &s_command_task_handle);

    return ret == pdPASS ? ESP_OK : ESP_FAIL;
}

Command Processing Flow

  1. Command received via MQTT callback
  2. Command queued for processing
  3. Command processing task dequeues and validates
  4. Command parsed and routed to appropriate handler
  5. Response published via MQTT

Parameter Parsing Example

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;
}

Online Command Handler

static esp_err_t handle_online_command(const char *cmd)
{
    // Check for STOP command
    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;
    }

    // Check for STATUS command
    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;
    }

    // Parse F and D parameters
    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; // Default: continuous
    }

    // Validate and start online sensing
    // ... (implementation details)
}

Offline Command Handler

static esp_err_t handle_offline_command(const char *cmd)
{
    // Check for STOP command
    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;
        }
        // ... (error handling)
    }

    // Parse parameters (F, D, DL, TIME)
    // ... (implementation details)

    // Create task for offline sensing with delay support
    // ... (task creation)
}

Usage Example

// Initialize command handler
esp_err_t ret = sensing_command_init();
if (ret != ESP_OK)
{
    ESP_LOGE(TAG, "Failed to initialize command handler");
    return;
}

// Set sensor handle
ret = sensing_command_set_sensor_handle(&adxl355_handle);
if (ret != ESP_OK)
{
    ESP_LOGE(TAG, "Failed to set sensor handle");
    return;
}

// In MQTT message callback
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);
    }
}