fix cron/heartbeat e2e stability and build issues
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -45,5 +45,4 @@ nanobot/
|
|||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
references/
|
references/
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "memory/session_mgr.h"
|
#include "memory/session_mgr.h"
|
||||||
#include "proxy/http_proxy.h"
|
#include "proxy/http_proxy.h"
|
||||||
#include "tools/tool_web_search.h"
|
#include "tools/tool_web_search.h"
|
||||||
|
#include "tools/tool_registry.h"
|
||||||
|
#include "cron/cron_service.h"
|
||||||
#include "heartbeat/heartbeat.h"
|
#include "heartbeat/heartbeat.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -329,6 +331,42 @@ static int cmd_heartbeat_trigger(int argc, char **argv)
|
|||||||
return 0;
|
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 <name> [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 --- */
|
/* --- restart command --- */
|
||||||
static int cmd_restart(int argc, char **argv)
|
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);
|
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 <name> '{...json...}'",
|
||||||
|
.func = &cmd_tool_exec,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&tool_exec_cmd);
|
||||||
|
|
||||||
/* restart */
|
/* restart */
|
||||||
esp_console_cmd_t restart_cmd = {
|
esp_console_cmd_t restart_cmd = {
|
||||||
.command = "restart",
|
.command = "restart",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/timers.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_random.h"
|
#include "esp_random.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
@@ -18,7 +18,7 @@ static const char *TAG = "cron";
|
|||||||
|
|
||||||
static cron_job_t s_jobs[MAX_CRON_JOBS];
|
static cron_job_t s_jobs[MAX_CRON_JOBS];
|
||||||
static int s_job_count = 0;
|
static int s_job_count = 0;
|
||||||
static TimerHandle_t s_cron_timer = NULL;
|
static TaskHandle_t s_cron_task = NULL;
|
||||||
|
|
||||||
/* ── Persistence ──────────────────────────────────────────────── */
|
/* ── Persistence ──────────────────────────────────────────────── */
|
||||||
|
|
||||||
@@ -199,17 +199,11 @@ static esp_err_t cron_save_jobs(void)
|
|||||||
return ESP_OK;
|
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);
|
time_t now = time(NULL);
|
||||||
if (now < 1700000000) {
|
|
||||||
/* System time not set yet (before ~2023), skip */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool changed = false;
|
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 ───────────────────── */
|
/* ── Compute initial next_run for a new job ───────────────────── */
|
||||||
|
|
||||||
static void compute_initial_next_run(cron_job_t *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)
|
esp_err_t cron_service_start(void)
|
||||||
{
|
{
|
||||||
if (s_cron_timer) {
|
if (s_cron_task) {
|
||||||
ESP_LOGW(TAG, "Cron timer already running");
|
ESP_LOGW(TAG, "Cron task already running");
|
||||||
return ESP_OK;
|
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",
|
"cron",
|
||||||
pdMS_TO_TICKS(MIMI_CRON_CHECK_INTERVAL_MS),
|
4096,
|
||||||
pdTRUE, /* auto-reload */
|
|
||||||
NULL,
|
NULL,
|
||||||
cron_timer_callback
|
4,
|
||||||
|
&s_cron_task
|
||||||
);
|
);
|
||||||
|
if (ok != pdPASS || !s_cron_task) {
|
||||||
if (!s_cron_timer) {
|
ESP_LOGE(TAG, "Failed to create cron task");
|
||||||
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");
|
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,10 +337,9 @@ esp_err_t cron_service_start(void)
|
|||||||
|
|
||||||
void cron_service_stop(void)
|
void cron_service_stop(void)
|
||||||
{
|
{
|
||||||
if (s_cron_timer) {
|
if (s_cron_task) {
|
||||||
xTimerStop(s_cron_timer, pdMS_TO_TICKS(1000));
|
vTaskDelete(s_cron_task);
|
||||||
xTimerDelete(s_cron_timer, pdMS_TO_TICKS(1000));
|
s_cron_task = NULL;
|
||||||
s_cron_timer = NULL;
|
|
||||||
ESP_LOGI(TAG, "Cron service stopped");
|
ESP_LOGI(TAG, "Cron service stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,13 @@
|
|||||||
|
|
||||||
static const char *TAG = "llm";
|
static const char *TAG = "llm";
|
||||||
|
|
||||||
static char s_api_key[128] = {0};
|
#define LLM_API_KEY_MAX_LEN 256
|
||||||
static char s_model[64] = MIMI_LLM_DEFAULT_MODEL;
|
#define LLM_MODEL_MAX_LEN 64
|
||||||
static char s_provider[16] = MIMI_LLM_PROVIDER_DEFAULT;
|
#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)
|
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 overrides take highest priority (set via CLI) */
|
||||||
nvs_handle_t nvs;
|
nvs_handle_t nvs;
|
||||||
if (nvs_open(MIMI_NVS_LLM, NVS_READONLY, &nvs) == ESP_OK) {
|
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);
|
size_t len = sizeof(tmp);
|
||||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_API_KEY, tmp, &len) == ESP_OK && tmp[0]) {
|
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);
|
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));
|
char model_tmp[LLM_MODEL_MAX_LEN] = {0};
|
||||||
if (nvs_get_str(nvs, MIMI_NVS_KEY_PROVIDER, tmp, &len) == ESP_OK && tmp[0]) {
|
len = sizeof(model_tmp);
|
||||||
safe_copy(s_provider, sizeof(s_provider), 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);
|
nvs_close(nvs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,17 +170,20 @@ esp_err_t tool_cron_remove_execute(const char *input_json, char *output, size_t
|
|||||||
return ESP_ERR_INVALID_ARG;
|
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);
|
cJSON_Delete(root);
|
||||||
|
|
||||||
if (err == ESP_OK) {
|
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) {
|
} 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 {
|
} else {
|
||||||
snprintf(output, output_size, "Error: failed to remove job (%s)", esp_err_to_name(err));
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user