/**
 * TaskScheduler OnEnable和OnDisable方法测试，以及使用包装任务实现超时功能的示例
 *
 * 	一个包装任务每10秒运行一次并启动测试用例
 * 	另一个任务运行一次持续5秒，作为LED闪烁的超时控制 - 5秒
 * 	最后，一个专门控制LED的任务周期性运行直到被停止，使LED以0.5到1秒的间隔闪烁。
 *
 */

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

#ifndef LED_BUILTIN
#define LED_BUILTIN 13    // 为你的开发板定义适当的引脚
#endif

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

// 回调方法原型声明
void WrapperCallback();
bool BlinkOnEnable();
void BlinkOnDisable();
void LEDOn();
void LEDOff();

// 任务定义
Task tWrapper(10000L, TASK_FOREVER, &WrapperCallback, &ts, true);  // 包装任务：每10000毫秒运行一次，无限期运行，创建时启用
Task tBlink(5000, TASK_ONCE, NULL, &ts, false, &BlinkOnEnable, &BlinkOnDisable);  // 闪烁超时任务：运行5000毫秒一次，禁用状态，有使能和禁用回调
Task tLED(0, TASK_FOREVER, NULL, &ts, false, NULL, &LEDOff);  // LED控制任务：初始间隔0毫秒，无限期运行，禁用状态，有禁用回调

void WrapperCallback() {
	tBlink.restartDelayed(); // LED闪烁被启动
							 //每30秒运行一次，持续5秒
}


// 当被启用时，tBlink将定义参数
// 并启用LED闪烁任务，该任务实际控制
// 硬件（本例中为LED）
bool BlinkOnEnable() {
	tLED.setInterval( 200 + random(801) );  // 设置LED闪烁间隔为200-1000毫秒随机值
	tLED.setCallback( &LEDOn);  // 设置LED开启回调函数
	tLED.enable();  // 启用LED控制任务

	return true; // 任务应该被启用
}

// tBlink实际上不需要回调函数
// 因为它只等待5秒进行第一次
// 也是唯一一次迭代。一旦迭代
// 发生，tBlink被调度器禁用，
// 从而执行下面的OnDisable方法。

void BlinkOnDisable() {
	tLED.disable();  // 禁用LED控制任务
}

void LEDOn () {
	digitalWrite(LED_BUILTIN , HIGH);  // 点亮LED
	tLED.setCallback( &LEDOff);  // 设置下次回调为LED关闭函数
}

void LEDOff () {
	digitalWrite(LED_BUILTIN , LOW);  // 熄灭LED
	tLED.setCallback( &LEDOn);  // 设置下次回调为LED开启函数
}

// 注意LEDOff方法作为OnDisable方法
// 确保当tBlink任务完成时
// （或提前禁用）LED被关闭

void setup() {
// 将设置代码放在这里，运行一次：
  pinMode(LED_BUILTIN , OUTPUT);  // 设置LED引脚为输出模式
}

void loop() {
// 将主代码放在这里，循环运行：
	ts.execute();  // 执行调度器，运行所有已安排的任务
}