# ESP-IDF 定时任务(Cron)组件 > English version: [README.md](./README.md) ## 组件特性 本组件是 ESP-IDF 框架的类 Cron 任务调度工具,采用类 Cron 语法结合 ESP-IDF 框架的 `esp_timer.h` 实现高精度任务调度,更贴合嵌入式场景需求。 ## 使用指南 我们精心设计了极简的接口体系,包含任务创建、销毁、调度器启停等核心功能。标准工作流程为:先定义至少一个任务,再启动调度器,后续可根据需求动态管理任务。特别设计了智能休眠机制:当无待调度任务时,调度器会自动进入低功耗模式,避免无谓的 CPU 资源消耗。 **重要提示**:组件基于 esp_timer 实现定时,无需手动管理系统时间,但需确保在创建任务前已完成必要的定时器初始化配置,以保证调度精度。 ### 代码结构 ```tree esp-cron/ ├── esp_cron.c # 核心调度逻辑与 API 实现 ├── include/ │ ├── esp_cron.h # 公共头文件,暴露 API │ └── cron.h # 内部头文件,调度器实现 ├── library/ │ ├── ccronexpr/ # cron 表达式解析器(开源组件) │ └── jobs/ # 任务链表管理模块 └── examples/ # 示例代码 ``` ## 快速使用指南 ### 头文件引入 ```c #include "esp_cron.h" ``` ### 1. 创建定时任务 ```c cron_job *cron_job_create(const char *schedule, cron_job_callback callback, void *data) ``` - `schedule` 支持秒级精度的类 Cron 表达式,格式说明: ```txt ┌────────────── 秒(0 - 59) | ┌───────────── 分(0 - 59) | │ ┌───────────── 时(0 - 23) | │ │ ┌───────────── 日(1 - 31) | │ │ │ ┌───────────── 月(1 - 12) | │ │ │ │ ┌───────────── 周(0 - 6,周日为 0;部分系统中 7 也表示周日) | │ │ │ │ │ * * * * * * ``` - `callback` 为任务回调函数指针,参数为当前任务句柄,定义如下: ```c typedef void (*cron_job_callback)(cron_job *); ``` 回调函数设计为轻量级接口,无需自行处理任务调度逻辑,框架会自动管理执行周期。 - `data` 为用户自定义数据指针,可存储任意类型数据,随任务句柄传递至回调函数。 ### 任务销毁 如需停止已创建的任务,直接调用销毁函数: ```c int cron_job_destroy(cron_job *job); ``` ### 启动调度器 当至少存在一个可调度任务时,调用启动函数: ```c int cron_start(); ``` ### 停止调度器 调用以下函数关闭调度器: ```c int cron_stop(); ``` ### 批量清空任务 ```c int cron_job_clear_all(); ``` ### 应用示例 以下是完整的使用示例,展示了从任务创建到调度的全流程: ```c /* 初始化 ESP-Timer 环境(非组件必需步骤,依项目需求调整) */ esp_timer_init(); /* 创建两个定时任务 */ cron_job *jobs[2]; jobs[0] = cron_job_create("* * * * * *", on_timer_trigger, (void *)0); jobs[1] = cron_job_create("*/5 * * * * *", on_timer_trigger, (void *)10000); /* 启动调度器 */ cron_start(); /* 模拟主程序运行(实际项目中可替换为业务逻辑) */ vTaskDelay(pdMS_TO_TICKS(60000)); // 运行 60 秒后停止 /* 资源释放 */ cron_stop(); cron_job_clear_all(); ``` 回调函数示例: ```c void on_timer_trigger(cron_job *job) { /* 处理定时任务逻辑 */ uint32_t task_id = (uint32_t)job->data; printf("Task %u triggered at %lu\n", task_id, esp_timer_get_time() / 1000); } ``` ## 核心 API 列表 ### 任务管理 | 函数名 | 描述 | |---------------------------|-------------------------------| | `cron_job* cron_job_create(const char* schedule, cron_job_callback callback, void* data);` | 创建并注册定时任务 | | `int cron_job_destroy(cron_job* job);` | 销毁指定任务 | | `int cron_job_clear_all();` | 清空所有任务 | ### 调度控制 | 函数名 | 描述 | |-------------------|-----------------------| | `int cron_start();` | 启动任务调度器 | | `int cron_stop();` | 停止任务调度器 | ### 任务调度操作 | 函数名 | 描述 | |-------------------------|-------------------------------| | `int cron_job_schedule(cron_job* job);` | 手动调度指定任务 | | `int cron_job_unschedule(cron_job* job);` | 取消指定任务的调度 | | `void cron_schedule_task(void* args);` | 特殊调度(如仅运行一次) | ### 状态查询 | 函数名 | 描述 | |---------------------------------|-------------------------------| | `int cron_job_load_expression(cron_job* job, const char* schedule);` | 动态加载 cron 表达式 | | `int cron_job_has_loaded(cron_job* job);` | 检查任务是否已加载表达式式 | | `time_t cron_job_seconds_until_next_execution();` | 获取下次执行剩余秒数 | ## 时间同步与精度优化 ### 本地时区设置 若项目需求涉及基于系统时区的时间显示或跨区域协同,可通过以下方式配置本地时区: 1. **时区环境变量配置** ```c setenv("TZ", "CST-8", 1); // 北京时间(东八区) tzset(); // 应用时区设置 ``` 该配置会影响 `localtime` 等函数的输出,但 **不影响定时任务的调度精度**——任务调度始终基于硬件定时器的绝对时间,与系统时区无关。 2. **SNTP 时间同步(可选)** 如需在任务中使用标准时间(如日志时间戳),可通过 SNTP 同步系统时间: ```c void init_system_time(void) { sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, "pool.ntp.org"); // 推荐使用国内服务器如 "cn.ntp.org" sntp_init(); // 等待同步(最多 10 次重试) int retry = 0; const int max_retry = 10; while (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED && retry < max_retry) { vTaskDelay(pdMS_TO_TICKS(1000)); retry++; } time_t now = 0; time(&now); // 获取同步后的系统时间 printf("System time synced: %s", ctime(&now)); } ``` **注意**:SNTP 同步仅用于系统时间显示,本组件的任务调度不依赖 `time.h` 的系统时间,而是直接基于 `esp_timer` 的硬件计时,确保调度精度不受网络同步延迟影响。 ### 定时精度优化指南 1. **硬件定时器配置** ```c /* 启用高精度定时器模式(ESP32 专用) */ esp_timer_create_args_t timer_args = { .callback = NULL, .arg = NULL, .flags = ESP_TIMER_FLAG_HIGH_PRECISION, // 关键配置,启用 APB 时钟源 }; esp_timer_init(&timer_args); ``` 2. **调度器参数调整** ```c /* 配置最小调度间隔(默认 1ms,可根据功耗需求调整) */ #define MIN_SCHEDULE_INTERVAL_US 100000 // 100ms 间隔,降低轻休眠功耗 cron_start(); // 启动后自动应用配置 ``` 3. **低功耗场景适配** ```c /* 结合定时器唤醒实现低功耗调度 */ esp_sleep_enable_timer_wakeup(5000000); // 5 秒唤醒一次 esp_light_sleep_start(); ``` 此时调度器会在唤醒周期内检查任务触发条件,兼顾精度与功耗。 ### 为何任务调度无需依赖时区? 本组件采用 **硬件定时器直接计时** 的调度机制,具有以下优势: 1. **精度隔离**:定时触发基于 ESP32 内部定时器,不受系统时间、时区配置的影响,误差可控制在微秒级 2. **无网络依赖**:无需 SNTP 同步即可实现稳定调度,适合无网络连接的嵌入式场景 3. **功耗优化**:定时器可在 CPU 休眠时独立工作,避免传统系统时间方案的持续唤醒需求 **时区配置的实际作用**:仅影响通过 `localtime` 等函数获取的时间显示格式,与任务调度逻辑完全解耦。 ## 特别鸣谢 - [esp_cron](https://github.com/DavidMora/esp_cron) 项目及作者 David Mora Rodriguez - [ccronexpr](https://github.com/staticlibs/ccronexpr) 表达式解析器 ## 许可证 本项目遵循 [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)。
idf.py add-dependency "bubao/esp_cron^0.0.5"