From c120a6fe45738da4dde2b5d9a4f92915a167ecbc Mon Sep 17 00:00:00 2001 From: Bo Date: Mon, 16 Feb 2026 23:00:00 +0800 Subject: [PATCH] fix cron/heartbeat e2e stability and build issues --- .gitignore | 3 +-- main/cli/serial_cli.c | 54 ++++++++++++++++++++++++++++++++++++++++ main/cron/cron_service.c | 54 +++++++++++++++++++--------------------- main/llm/llm_proxy.c | 31 ++++++++++++++--------- main/tools/tool_cron.c | 11 +++++--- main/tools/tool_files.c | 1 + 6 files changed, 108 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index cae43d8..63f5ed0 100644 --- a/.gitignore +++ b/.gitignore @@ -45,5 +45,4 @@ nanobot/ # OS .DS_Store Thumbs.db - -references/ \ No newline at end of file +references/ diff --git a/main/cli/serial_cli.c b/main/cli/serial_cli.c index 2ae63cc..88e0eab 100644 --- a/main/cli/serial_cli.c +++ b/main/cli/serial_cli.c @@ -7,6 +7,8 @@ #include "memory/session_mgr.h" #include "proxy/http_proxy.h" #include "tools/tool_web_search.h" +#include "tools/tool_registry.h" +#include "cron/cron_service.h" #include "heartbeat/heartbeat.h" #include @@ -329,6 +331,42 @@ static int cmd_heartbeat_trigger(int argc, char **argv) return 0; } +/* --- cron_start command --- */ +static int cmd_cron_start(int argc, char **argv) +{ + esp_err_t err = cron_service_start(); + if (err == ESP_OK) { + printf("Cron service started.\n"); + return 0; + } + + printf("Failed to start cron service: %s\n", esp_err_to_name(err)); + return 1; +} + +static int cmd_tool_exec(int argc, char **argv) +{ + if (argc < 2) { + printf("Usage: tool_exec [json]\n"); + return 1; + } + + const char *tool_name = argv[1]; + const char *input_json = (argc >= 3) ? argv[2] : "{}"; + + char *output = calloc(1, 4096); + if (!output) { + printf("Out of memory.\n"); + return 1; + } + + esp_err_t err = tool_registry_execute(tool_name, input_json, output, 4096); + printf("tool_exec status: %s\n", esp_err_to_name(err)); + printf("%s\n", output[0] ? output : "(empty)"); + free(output); + return (err == ESP_OK) ? 0 : 1; +} + /* --- restart command --- */ static int cmd_restart(int argc, char **argv) { @@ -526,6 +564,22 @@ esp_err_t serial_cli_init(void) }; esp_console_cmd_register(&heartbeat_cmd); + /* cron_start */ + esp_console_cmd_t cron_start_cmd = { + .command = "cron_start", + .help = "Start cron scheduler timer now", + .func = &cmd_cron_start, + }; + esp_console_cmd_register(&cron_start_cmd); + + /* tool_exec */ + esp_console_cmd_t tool_exec_cmd = { + .command = "tool_exec", + .help = "Execute a registered tool: tool_exec '{...json...}'", + .func = &cmd_tool_exec, + }; + esp_console_cmd_register(&tool_exec_cmd); + /* restart */ esp_console_cmd_t restart_cmd = { .command = "restart", diff --git a/main/cron/cron_service.c b/main/cron/cron_service.c index 6dcab84..58b237f 100644 --- a/main/cron/cron_service.c +++ b/main/cron/cron_service.c @@ -7,7 +7,7 @@ #include #include #include "freertos/FreeRTOS.h" -#include "freertos/timers.h" +#include "freertos/task.h" #include "esp_log.h" #include "esp_random.h" #include "cJSON.h" @@ -18,7 +18,7 @@ static const char *TAG = "cron"; static cron_job_t s_jobs[MAX_CRON_JOBS]; static int s_job_count = 0; -static TimerHandle_t s_cron_timer = NULL; +static TaskHandle_t s_cron_task = NULL; /* ── Persistence ──────────────────────────────────────────────── */ @@ -199,17 +199,11 @@ static esp_err_t cron_save_jobs(void) return ESP_OK; } -/* ── Timer callback ───────────────────────────────────────────── */ +/* ── Due-job processing ───────────────────────────────────────── */ -static void cron_timer_callback(TimerHandle_t xTimer) +static void cron_process_due_jobs(void) { - (void)xTimer; - time_t now = time(NULL); - if (now < 1700000000) { - /* System time not set yet (before ~2023), skip */ - return; - } bool changed = false; @@ -267,6 +261,16 @@ static void cron_timer_callback(TimerHandle_t xTimer) } } +static void cron_task_main(void *arg) +{ + (void)arg; + + while (1) { + vTaskDelay(pdMS_TO_TICKS(MIMI_CRON_CHECK_INTERVAL_MS)); + cron_process_due_jobs(); + } +} + /* ── Compute initial next_run for a new job ───────────────────── */ static void compute_initial_next_run(cron_job_t *job) @@ -295,8 +299,8 @@ esp_err_t cron_service_init(void) esp_err_t cron_service_start(void) { - if (s_cron_timer) { - ESP_LOGW(TAG, "Cron timer already running"); + if (s_cron_task) { + ESP_LOGW(TAG, "Cron task already running"); return ESP_OK; } @@ -313,21 +317,16 @@ esp_err_t cron_service_start(void) } } - s_cron_timer = xTimerCreate( + BaseType_t ok = xTaskCreate( + cron_task_main, "cron", - pdMS_TO_TICKS(MIMI_CRON_CHECK_INTERVAL_MS), - pdTRUE, /* auto-reload */ + 4096, NULL, - cron_timer_callback + 4, + &s_cron_task ); - - if (!s_cron_timer) { - ESP_LOGE(TAG, "Failed to create cron timer"); - return ESP_FAIL; - } - - if (xTimerStart(s_cron_timer, pdMS_TO_TICKS(1000)) != pdPASS) { - ESP_LOGE(TAG, "Failed to start cron timer"); + if (ok != pdPASS || !s_cron_task) { + ESP_LOGE(TAG, "Failed to create cron task"); return ESP_FAIL; } @@ -338,10 +337,9 @@ esp_err_t cron_service_start(void) void cron_service_stop(void) { - if (s_cron_timer) { - xTimerStop(s_cron_timer, pdMS_TO_TICKS(1000)); - xTimerDelete(s_cron_timer, pdMS_TO_TICKS(1000)); - s_cron_timer = NULL; + if (s_cron_task) { + vTaskDelete(s_cron_task); + s_cron_task = NULL; ESP_LOGI(TAG, "Cron service stopped"); } } diff --git a/main/llm/llm_proxy.c b/main/llm/llm_proxy.c index 2835cd4..11fd3ca 100644 --- a/main/llm/llm_proxy.c +++ b/main/llm/llm_proxy.c @@ -13,9 +13,13 @@ static const char *TAG = "llm"; -static char s_api_key[128] = {0}; -static char s_model[64] = MIMI_LLM_DEFAULT_MODEL; -static char s_provider[16] = MIMI_LLM_PROVIDER_DEFAULT; +#define LLM_API_KEY_MAX_LEN 256 +#define LLM_MODEL_MAX_LEN 64 +#define LLM_PROVIDER_MAX_LEN 16 + +static char s_api_key[LLM_API_KEY_MAX_LEN] = {0}; +static char s_model[LLM_MODEL_MAX_LEN] = MIMI_LLM_DEFAULT_MODEL; +static char s_provider[LLM_PROVIDER_MAX_LEN] = MIMI_LLM_PROVIDER_DEFAULT; static void safe_copy(char *dst, size_t dst_size, const char *src) { @@ -118,20 +122,23 @@ esp_err_t llm_proxy_init(void) /* NVS overrides take highest priority (set via CLI) */ nvs_handle_t nvs; if (nvs_open(MIMI_NVS_LLM, NVS_READONLY, &nvs) == ESP_OK) { - char tmp[128] = {0}; + char tmp[LLM_API_KEY_MAX_LEN] = {0}; size_t len = sizeof(tmp); if (nvs_get_str(nvs, MIMI_NVS_KEY_API_KEY, tmp, &len) == ESP_OK && tmp[0]) { safe_copy(s_api_key, sizeof(s_api_key), tmp); } - len = sizeof(tmp); - memset(tmp, 0, sizeof(tmp)); - if (nvs_get_str(nvs, MIMI_NVS_KEY_MODEL, tmp, &len) == ESP_OK && tmp[0]) { - safe_copy(s_model, sizeof(s_model), tmp); } - len = sizeof(tmp); - memset(tmp, 0, sizeof(tmp)); - if (nvs_get_str(nvs, MIMI_NVS_KEY_PROVIDER, tmp, &len) == ESP_OK && tmp[0]) { - safe_copy(s_provider, sizeof(s_provider), tmp); + + char model_tmp[LLM_MODEL_MAX_LEN] = {0}; + len = sizeof(model_tmp); + if (nvs_get_str(nvs, MIMI_NVS_KEY_MODEL, model_tmp, &len) == ESP_OK && model_tmp[0]) { + safe_copy(s_model, sizeof(s_model), model_tmp); + } + + char provider_tmp[LLM_PROVIDER_MAX_LEN] = {0}; + len = sizeof(provider_tmp); + if (nvs_get_str(nvs, MIMI_NVS_KEY_PROVIDER, provider_tmp, &len) == ESP_OK && provider_tmp[0]) { + safe_copy(s_provider, sizeof(s_provider), provider_tmp); } nvs_close(nvs); } diff --git a/main/tools/tool_cron.c b/main/tools/tool_cron.c index dfb0a6d..b8b8e25 100644 --- a/main/tools/tool_cron.c +++ b/main/tools/tool_cron.c @@ -170,17 +170,20 @@ esp_err_t tool_cron_remove_execute(const char *input_json, char *output, size_t return ESP_ERR_INVALID_ARG; } - esp_err_t err = cron_remove_job(job_id); + char job_id_copy[16] = {0}; + strncpy(job_id_copy, job_id, sizeof(job_id_copy) - 1); + + esp_err_t err = cron_remove_job(job_id_copy); cJSON_Delete(root); if (err == ESP_OK) { - snprintf(output, output_size, "OK: Removed cron job %s", job_id); + snprintf(output, output_size, "OK: Removed cron job %s", job_id_copy); } else if (err == ESP_ERR_NOT_FOUND) { - snprintf(output, output_size, "Error: job '%s' not found", job_id); + snprintf(output, output_size, "Error: job '%s' not found", job_id_copy); } else { snprintf(output, output_size, "Error: failed to remove job (%s)", esp_err_to_name(err)); } - ESP_LOGI(TAG, "cron_remove: %s -> %s", job_id, esp_err_to_name(err)); + ESP_LOGI(TAG, "cron_remove: %s -> %s", job_id_copy, esp_err_to_name(err)); return err; } diff --git a/main/tools/tool_files.c b/main/tools/tool_files.c index 7bf16cc..358f060 100644 --- a/main/tools/tool_files.c +++ b/main/tools/tool_files.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "esp_log.h"