跳转到内容

cap_scheduler — 定时调度

源码:cap_scheduler.c · 头文件:cap_scheduler.h

cap_scheduler 是 ESP-Claw 的时间触发中心。它负责在指定的时间点生成事件并推送到 claw_event_router。调度器本身不执行具体的业务逻辑(如发消息或调工具),而是通过发布事件来触发后续的自动化规则。

这种「调度与执行分离」的设计,使得定时任务可以复用 Event Router 的所有动作能力(run_agent、call_cap、run_script 等)。

每个调度项定义了「什么时候」发布「什么样的事件」。主要字段包括:

  • id: 唯一标识。
  • kind: 调度类型,支持 once(一次性)、interval(间隔)、cron(标准 5 段式 Cron 表达式)。
  • enabled: 是否启用。
  • event_type: 发布事件的类型(对应路由规则的 match.event_type)。
  • event_key: 事件键(对应路由规则的 match.event_key)。
  • payload_json: 附带的 JSON 数据。

调度器管理两份数据:

  1. 定义文件 (schedules.json):存储所有的调度项配置。
  2. 状态文件(由 schedules_path + ".state" 自动推导,例如 schedules.json.state):存储运行时的动态信息,如 last_fire_ms(上次触发时间)、run_count(运行次数)等。这保证了设备重启后能正确找回进度,不会丢失或重复触发任务。

每次 scheduler_reload(以及启动时加载)后,调度器会将条目按默认值规则补齐 schedules.json 中的缺失字段。

工具 ID功能输入参数
scheduler_list列出所有调度项及其运行状态(无)
scheduler_get查询单个调度项详情id
scheduler_add新增一个调度项schedule_json (字符串)
scheduler_update更新一个已存在的调度项schedule_json (字符串)
scheduler_remove删除一个调度项id
scheduler_enable启用指定调度项id
scheduler_disable禁用指定调度项id
scheduler_pause暂停指定调度项id
scheduler_resume恢复指定调度项id
scheduler_trigger_now立即触发一次调度(不影响后续计划)id
scheduler_reload从磁盘重新加载配置(无)

其中:

  • schedule_json (字符串) 指 {"schedule_json":"<JSON 字符串>"},其中 schedule_json 是字符串(需转义),不是嵌套的对象。
  • id{"id":"..."}

典型的 schedules.json 条目:

{
  "id": "morning_reminder",
  "kind": "cron",
  "cron_expr": "0 7 * * *",
  "enabled": true,
  "event_type": "schedule",
  "event_key": "reminder",
  "text": "早上好!又是充满活力的一天,记得喝水喵。"
}

router_rules.json 中添加对应规则,将该调度事件发送到 IM:

{
  "id": "handle_morning_reminder",
  "match": {
    "event_type": "schedule",
    "event_key": "reminder"
  },
  "actions": [
    {
      "type": "send_message",
      "input": {
        "channel": "telegram",
        "chat_id": "YOUR_CHAT_ID",
        "message": "{{event.text}}"
      }
    }
  ]
}

cap_scheduler 依赖系统时间的准确性。

  • 对于 crononce 任务,必须在 SNTP 同步成功后才会触发。
  • 对于 interval 任务,若没有配置 start_atend_at,则不依赖外部时间,上电即开始计时。
  • cron 的匹配基于设备当前本地时间(localtime_r)。

basic_demo 在首次 SNTP 同步成功(had_valid_time == false)后,会调用 cap_scheduler_handle_time_sync() 对调度器进行时间校准(rebase):设备上电后可能基于不准确的时钟提前开始计时,首次获得有效系统时间后,调度器会修正各任务的参考时间点,避免重复触发或遗漏触发。

在应用层初始化:

ESP_RETURN_ON_ERROR(cap_scheduler_init(&(cap_scheduler_config_t) {
    .schedules_path = "/fatfs/scheduler/schedules.json",
    .tick_ms = 1000,              // 检查频率(ms)
    .max_items = 32,              // 最大调度项数
    .task_stack_size = 6144,      // 调度任务栈大小
    .task_priority = 5,           // 调度任务优先级
    .task_core = tskNO_AFFINITY,  // 核心亲和性
    .publish_event = claw_event_router_publish, // 绑定发布接口
    .persist_after_fire = true,   // 触发后持久化运行时状态
}), TAG, "Failed to init scheduler");

// cap_scheduler_start() 在 claw_event_router_start() 之后调用
cap_scheduler_start();