/** 此测试模拟每10秒查询3个传感器一次，每个传感器可能有不同的响应延迟
 *    （例如超声波传感器），并在所有三个传感器都报告其值时打印三个值中的最小值。
 *    还设置了1秒的总超时时间。
 *    如果发生超时而不是获取到值，则需要打印错误消息。
 */


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

#ifdef ARDUINO_ARCH_STM32F1
#define A0	3  // STM32F1架构下定义A0为3
#endif

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

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

// 回调方法原型声明
void CycleCallback();
void MeasureCallback(); 
bool MeasureEnable();
void MeasureDisable();
void CalcCallback();
void S1Callback(); bool S1Enable();
void S2Callback(); bool S2Enable();
void S3Callback(); bool S3Enable();

// 任务定义
Task tCycle(10000, TASK_FOREVER, &CycleCallback, &ts, true);  // 循环任务：每10000毫秒运行一次，无限期运行，启用状态
Task tMeasure(1000, TASK_ONCE, &MeasureCallback, &ts, false, &MeasureEnable, &MeasureDisable);  // 测量任务：1000毫秒运行一次，运行一次，禁用状态，有使能和禁用回调
Task tCalculate(&CalcCallback, &ts);  // 计算任务：使用默认参数，等待状态请求
Task tSensor1(0, TASK_ONCE, &S1Callback, &ts, false, &S1Enable);  // 传感器1任务：初始间隔0毫秒，运行一次，禁用状态，有使能回调
Task tSensor2(0, TASK_ONCE, &S2Callback, &ts, false, &S2Enable);  // 传感器2任务：初始间隔0毫秒，运行一次，禁用状态，有使能回调
Task tSensor3(0, TASK_ONCE, &S3Callback, &ts, false, &S3Enable);  // 传感器3任务：初始间隔0毫秒，运行一次，禁用状态，有使能回调


long distance, d1, d2, d3;  // 距离变量和三个传感器数据变量

void CycleCallback() {
  Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");  // 打印循环回调信息

  tMeasure.restartDelayed();  // 重启测量任务
}



bool MeasureEnable() {
  Serial.println("MeasureEnable: Activating sensors");  // 打印测量使能信息

  distance = 0;  // 重置距离变量
  measure.setWaiting(3); // 设置状态请求等待3个信号
  tCalculate.waitFor(&measure);  // 请求计算任务等待测量状态

  tSensor1.restartDelayed();  // 重启传感器1任务
  tSensor2.restartDelayed();  // 重启传感器2任务
  tSensor3.restartDelayed();  // 重启传感器3任务

  return true;  // 返回true使任务启用
}

void MeasureCallback() {
  Serial.println("MeasureCallback: Invoked by calculate task or one second later");  // 打印测量回调信息

  if (measure.pending()) {  // 如果状态请求仍在等待
    tCalculate.disable();  // 禁用计算任务
    measure.signalComplete(-1);  // 发出错误信号
    Serial.println("MeasureCallback: Timeout!");  // 打印超时信息
  }
  else {  // 如果状态请求已完成
    Serial.print("MeasureCallback: Min distance=");Serial.println(distance);  // 打印最小距离
  }
}

void MeasureDisable() {
  Serial.println("MeasureDisable: Cleaning up");  // 打印测量禁用信息
  
  tSensor1.disable();  // 禁用传感器1任务
  tSensor2.disable();  // 禁用传感器2任务
  tSensor3.disable();  // 禁用传感器3任务
}


void CalcCallback() {
  Serial.println("CalcCallback: calculating");  // 打印计算回调信息
  distance = -1;  // 重置距离变量
  if ( measure.getStatus() >= 0) {  // 只有在状态请求成功结束时才计算
    distance = d1 < d2 ? d1 : d2;  // 计算d1和d2中的较小值
    distance = d3 < distance ? d3 : distance;  // 计算d3和之前结果中的较小值
    tMeasure.forceNextIteration();  // 强制测量任务进入下一次迭代
  }
}


/** 传感器1的模拟代码
 *  ----------------------------
 */
bool S1Enable() {
  Serial.print("S1Enable: Triggering sensor1. Delay=");  // 打印传感器1使能信息

  tSensor1.setInterval( random(1200) );  // 模拟传感器延迟，可能超过1秒并导致超时
  d1 = 0;  // 重置传感器1数据
  
  Serial.println( tSensor1.getInterval() );  // 打印设置的延迟时间
  return true;  // 返回true使任务启用
}

void S1Callback() {
  Serial.print("S1Callback: Emulating measurement. d1=");  // 打印传感器1回调信息
  d1 = random(501); // 从0到500"厘米"中选择一个值模拟测量
  measure.signal();  // 向状态请求发送信号
  
  Serial.println(d1);  // 打印传感器1测量值
}


/** 传感器2的模拟代码
 *  ----------------------------
 */
bool S2Enable() {
  Serial.print("S2Enable: Triggering sensor2. Delay=");  // 打印传感器2使能信息

  tSensor2.setInterval( random(1200) );  // 模拟传感器延迟，可能超过1秒并导致超时
  d2 = 0;  // 重置传感器2数据

  Serial.println( tSensor2.getInterval() );  // 打印设置的延迟时间
  return true;  // 返回true使任务启用
}

void S2Callback() {
  Serial.print("S2Callback: Emulating measurement. d2=");  // 打印传感器2回调信息
  d2 = random(501); // 从0到500"厘米"中选择一个值模拟测量
  measure.signal();  // 向状态请求发送信号

  Serial.println(d2);  // 打印传感器2测量值
}


/** 传感器3的模拟代码
 *  ----------------------------
 */
bool S3Enable() {
  Serial.print("S3Enable: Triggering sensor3. Delay=");  // 打印传感器3使能信息

  tSensor3.setInterval( random(1200) );  // 模拟传感器延迟，可能超过1秒并导致超时
  d3 = 0;  // 重置传感器3数据

  Serial.println( tSensor3.getInterval() );  // 打印设置的延迟时间
  return true;  // 返回true使任务启用
}

void S3Callback() {
  Serial.print("S3Callback: Emulating measurement. d3=");  // 打印传感器3回调信息
  d3 = random(501); // 从0到500"厘米"中选择一个值模拟测量
  measure.signal();  // 向状态请求发送信号
  
  Serial.println(d3);  // 打印传感器3测量值
}


/** 主Arduino代码
 *  -------------------
 */
void setup() {
  Serial.begin(115200);  // 初始化串口通信，波特率115200
  delay(1000);  // 延时1秒等待串口稳定

  Serial.println(F("Scheduler Example 5: Status Request"));  // 打印测试标题
  Serial.println();

  ts.startNow();  // 设置调度开始的时间点，从现在开始调度
}

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