#define _TASK_SLEEP_ON_IDLE_RUN  // 启用空闲时睡眠模式，当没有任务需要运行时节电
#include <TaskScheduler.h>  // 包含TaskScheduler库

Scheduler runner;  // 创建调度器对象
// 回调方法原型声明
void t1Callback();
void t2Callback();
void t3Callback(); 

// 任务定义
Task t4();  // 空任务定义（未使用）
Task t1(2000, 10, &t1Callback, &runner, true);  // 任务1：每2000毫秒运行一次，运行10次，创建时添加到调度器链
Task t2(3000, TASK_FOREVER, &t2Callback, &runner, true);  // 任务2：每3000毫秒运行一次，无限期运行，创建时添加到调度器链
Task t3(5000, TASK_FOREVER, &t3Callback);  // 任务3：每5000毫秒运行一次，无限期运行

// 测试说明
// 初始时只有任务1和任务2被启用
// 任务1每2秒运行一次，运行10次后停止
// 任务2每3秒运行一次，无限期运行
// 任务1在第一次运行时启用任务3
// 任务3每5秒运行一次
// loop()函数每1秒运行一次（默认的调度器延时，如果没有更短的任务间隔被检测到）
// 任务1在最后一次迭代时禁用任务3，并将任务2的运行间隔改为每1/2秒
// 因为任务2的间隔比调度器默认的滴答时间短，现在loop()每1/2秒执行一次
// 最终只有任务2每1/2秒运行
//
// 注意：t1和t2受到setup()方法中delay()函数的影响，会立即被调度两次以"追赶"millis()时间。





void t1Callback() {
    Serial.print("t1: ");  // 打印任务1标识
    Serial.println(millis());  // 打印当前时间戳
    
    if (t1.isFirstIteration()) {
      runner.addTask(t3);  // 将任务3添加到调度器
      t3.enable();  // 启用任务3
      Serial.println("t1: enabled t3 and added to the chain");  // 打印任务3已启用并添加到链表的确认信息
    }
    
    if (t1.isLastIteration()) {
      t3.disable();  // 禁用任务3
      runner.deleteTask(t3);  // 从调度器中删除任务3
      t2.setInterval(500);  // 将任务2的运行间隔改为500毫秒（每0.5秒）
      Serial.println("t1: disable t3 and delete it from the chain. t2 interval set to 500");  // 打印任务3已禁用删除，任务2间隔已修改的确认信息
    }
}

void t2Callback() {
    Serial.print("t2: ");  // 打印任务2标识
    Serial.println(millis());  // 打印当前时间戳
  
}

void t3Callback() {
    Serial.print("t3: ");  // 打印任务3标识
    Serial.println(millis());  // 打印当前时间戳
  
}

void setup () {
  Serial.begin(115200);  // 初始化串口通信，波特率115200
  delay(5000);  // 延时5秒，让用户有时间打开串口监视器
  Serial.println("Scheduler TEST");  // 打印测试标题
  
  runner.startNow();  // 设置调度开始的时间点，从现在开始调度
}


void loop () {
  
  runner.execute();  // 执行调度器，运行所有已安排的任务
  
//  Serial.println("Loop ticks at: ");  // 取消注释可打印循环执行时间
//  Serial.println(millis());  // 取消注释可打印当前时间戳
}