/** 此测试演示了三个简单任务通过StatusRequest对象的交互。
 *  任务T1每5秒运行一次并发出状态请求st完成的信号。
 *  任务T2和T3正在等待相同的请求(st)
 *  任务T3不续订其对状态请求st的兴趣，因此它只被调用一次（第一次迭代）
 *  任务T2在每次st完成时都被调用，因为它在T1的每次迭代中续订其对状态请求对象st的状态的兴趣
 */
 
#define _TASK_SLEEP_ON_IDLE_RUN  // 启用空闲时睡眠模式，当没有任务需要运行时节电
#define _TASK_STATUS_REQUEST  // 启用状态请求功能
#include <TaskScheduler.h>  // 包含TaskScheduler库

StatusRequest st;  // 创建状态请求对象

Scheduler ts;  // 创建调度器对象

// 回调方法原型声明
void Callback1();
void Disable1();
void Callback2();
void Callback3();
void PrepareStatus();

// 任务定义
Task t1(5000, TASK_ONCE, &Callback1, &ts, true, NULL, &Disable1);  // 任务1：5000毫秒运行一次，运行一次，启用状态，有禁用回调
Task t2(&Callback2, &ts);  // 任务2：使用默认参数，等待状态请求
Task t3(&Callback3, &ts);  // 任务3：使用默认参数，等待状态请求

/** T1回调函数
 *  T1每5秒发出st完成的信号
 */
void Callback1() {
  Serial.println("T1: Signaling completion of ST");  // 打印T1正在发出ST完成信号的信息
  st.signalComplete();  // 发出状态请求完成信号
}

/** T1禁用回调函数
 *  此回调续订状态请求并延迟重启T1在5秒后再次运行
 */
void Disable1() {
  PrepareStatus();  // 准备状态请求
  t1.restartDelayed();  // 延迟重启T1任务
}

/** T2回调函数
 *  当状态请求st完成时被调用
 */
void Callback2() {
  Serial.println("T2: Invoked due to completion of ST");  // 打印T2由于ST完成而被调用的信息
}


/** T3回调函数
 *  当状态请求st完成时被调用。
 *  这只运行一次，因为T3在第一次迭代后不会续订其对状态请求st的兴趣
 */
 void Callback3() {
  Serial.println("T3: Invoked due to completion of ST");  // 打印T3由于ST完成而被调用的信息
  
}

/** 为下一次迭代准备状态请求st
 *  
 */
void PrepareStatus() {
  st.setWaiting();         // 设置状态请求对象为等待状态
  t2.waitFor(&st);  // 请求任务2等待对象st
}


/** 主Arduino代码
 *  这里没有太多事情要做。只需初始化串口并设置初始状态请求
 */
void setup() {

  Serial.begin(115200);  // 初始化串口通信，波特率115200
  delay(1000);  // 延时1秒等待串口稳定
  Serial.println("TaskScheduler: Status Request Test 1. Simple Test.");  // 打印测试标题

  ts.startNow();  // 设置调度开始的时间点，从现在开始调度
  PrepareStatus();  // 准备状态请求
  t3.waitFor(&st);  // 请求任务3等待对象st

  t1.delay();  // 延迟启动任务1
}

void loop() {

  ts.execute();  // 执行调度器，运行所有已安排的任务

}