feat: 添加时区设置功能,默认时区改为 CST-8
Some checks failed
Build / idf-build (push) Has been cancelled
Build & Release / build (push) Has been cancelled

- 新增 set_timezone LLM 工具,支持通过对话设置时区
- 新增 set_timezone / timezone_show CLI 命令
- 默认时区从 PST 改为 CST-8(中国标准时间 UTC+8)
- 支持 POSIX 格式和 18 个城市名映射(Asia/Shanghai 等)
- 时区通过 NVS 持久化存储(system_config namespace)
- config_show 中显示当前时区配置
- 更新 changelog.md 和 taolun.md 文档
This commit is contained in:
2026-04-01 00:50:41 +08:00
parent eedc6757d8
commit 7dc4122778
24 changed files with 645 additions and 52 deletions

View File

@@ -17,6 +17,8 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <time.h>
#include <dirent.h>
#include "esp_log.h"
#include "esp_console.h"
@@ -654,6 +656,11 @@ static int cmd_config_show(int argc, char **argv)
print_config_u16("Proxy Port", MIMI_NVS_PROXY, MIMI_NVS_KEY_PROXY_PORT, MIMI_SECRET_PROXY_PORT);
print_config("Search Key", MIMI_NVS_SEARCH, MIMI_NVS_KEY_API_KEY, MIMI_SECRET_SEARCH_KEY, true);
print_config("Tavily Key", MIMI_NVS_SEARCH, MIMI_NVS_KEY_TAVILY_KEY, MIMI_SECRET_TAVILY_KEY, true);
/* System configs */
printf(" --- System configs ---\n");
print_config("Timezone", "system_config", MIMI_NVS_KEY_TIMEZONE, MIMI_TIMEZONE, false);
printf("=============================\n");
return 0;
}
@@ -676,6 +683,87 @@ static int cmd_config_reset(int argc, char **argv)
return 0;
}
/* --- set_timezone command --- */
static struct {
struct arg_str *tz;
struct arg_end *end;
} timezone_args;
static int cmd_set_timezone(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **)&timezone_args);
if (nerrors != 0) {
arg_print_errors(stderr, timezone_args.end, argv[0]);
return 1;
}
const char *tz_str = timezone_args.tz->sval[0];
nvs_handle_t nvs;
esp_err_t err = nvs_open("system_config", NVS_READWRITE, &nvs);
if (err != ESP_OK) {
printf("Failed to open NVS: %s\n", esp_err_to_name(err));
return 1;
}
err = nvs_set_str(nvs, MIMI_NVS_KEY_TIMEZONE, tz_str);
if (err != ESP_OK) {
printf("Failed to save timezone: %s\n", esp_err_to_name(err));
nvs_close(nvs);
return 1;
}
err = nvs_commit(nvs);
nvs_close(nvs);
if (err != ESP_OK) {
printf("Failed to commit NVS: %s\n", esp_err_to_name(err));
return 1;
}
setenv("TZ", tz_str, 1);
tzset();
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);
char time_str[64];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z", &tm_now);
printf("Timezone set to '%s'. Current time: %s. Restart to apply permanently.\n", tz_str, time_str);
return 0;
}
/* --- timezone_show command --- */
static int cmd_timezone_show(int argc, char **argv)
{
(void)argc;
(void)argv;
char nvs_val[64] = {0};
const char *source = "build";
const char *display = MIMI_TIMEZONE;
nvs_handle_t nvs;
if (nvs_open("system_config", NVS_READONLY, &nvs) == ESP_OK) {
size_t len = sizeof(nvs_val);
if (nvs_get_str(nvs, MIMI_NVS_KEY_TIMEZONE, nvs_val, &len) == ESP_OK && nvs_val[0]) {
source = "NVS";
display = nvs_val;
}
nvs_close(nvs);
}
printf("Current timezone: %s [%s]\n", display, source);
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);
char time_str[64];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z (%A)", &tm_now);
printf("Local time: %s\n", time_str);
return 0;
}
/* --- heartbeat_trigger command --- */
static int cmd_heartbeat_trigger(int argc, char **argv)
{
@@ -736,13 +824,22 @@ typedef struct {
size_t output_size;
esp_err_t err;
SemaphoreHandle_t done;
bool timed_out;
} web_search_task_ctx_t;
static void web_search_task(void *arg)
{
web_search_task_ctx_t *task_ctx = (web_search_task_ctx_t *)arg;
task_ctx->err = tool_web_search_execute(task_ctx->input_json, task_ctx->output, task_ctx->output_size);
xSemaphoreGive(task_ctx->done);
if (!task_ctx->timed_out) {
xSemaphoreGive(task_ctx->done);
} else {
/* Main thread timed out and freed ctx, so we must clean up ourselves */
free((void *)task_ctx->input_json);
free(task_ctx->output);
vSemaphoreDelete(task_ctx->done);
free(task_ctx);
}
vTaskDelete(NULL);
}
@@ -838,10 +935,8 @@ static int cmd_web_search(int argc, char **argv)
if (xSemaphoreTake(ctx->done, pdMS_TO_TICKS(45000)) != pdTRUE) {
printf("web_search status: timeout\n");
vSemaphoreDelete(ctx->done);
free(input_copy);
free(ctx);
free(output);
ctx->timed_out = true;
/* Task will clean up ctx, input_copy, output, and done on its own */
return 1;
}
esp_err_t err = ctx->err;
@@ -1163,6 +1258,25 @@ esp_err_t serial_cli_init(void)
};
esp_console_cmd_register(&config_reset_cmd);
/* set_timezone */
timezone_args.tz = arg_str1(NULL, NULL, "<timezone>", "Timezone (e.g. CST-8, Asia/Shanghai)");
timezone_args.end = arg_end(1);
esp_console_cmd_t set_timezone_cmd = {
.command = "set_timezone",
.help = "Set system timezone (e.g. set_timezone CST-8)",
.func = &cmd_set_timezone,
.argtable = &timezone_args,
};
esp_console_cmd_register(&set_timezone_cmd);
/* timezone_show */
esp_console_cmd_t timezone_show_cmd = {
.command = "timezone_show",
.help = "Show current timezone and local time",
.func = &cmd_timezone_show,
};
esp_console_cmd_register(&timezone_show_cmd);
/* heartbeat_trigger */
esp_console_cmd_t heartbeat_cmd = {
.command = "heartbeat_trigger",