#include "timer_manager.h" TimerManager::TimerManager() { timerCount = 0; timeManager = nullptr; lastStateSave = 0; } void TimerManager::begin(TimeManager* tm) { timeManager = tm; // 初始化EEPROM EEPROM.begin(EEPROM_SIZE); // 初始化所有可用引脚为输出模式 for (int i = 0; i < AVAILABLE_PINS_COUNT; i++) { pinMode(AVAILABLE_PINS[i], OUTPUT); digitalWrite(AVAILABLE_PINS[i], LOW); // 为PWM引脚设置频率 analogWriteFreq(PWM_FREQUENCY); analogWriteResolution(PWM_RESOLUTION); } loadTimers(); Serial.println("Timer Manager 初始化完成,已加载 " + String(timerCount) + " 个定时器"); // 输出恢复的状态信息 int activeCount = 0; for (int i = 0; i < timerCount; i++) { if (timers[i].isActive) { activeCount++; } } if (activeCount > 0) { Serial.println("已恢复 " + String(activeCount) + " 个活跃定时器状态"); } } void TimerManager::update() { if (!timeManager) return; unsigned long currentTime = millis(); int currentHour = timeManager->getCurrentHour(); int currentMinute = timeManager->getCurrentMinute(); unsigned long currentDay = timeManager->getCurrentDay(); bool stateChanged = false; for (int i = 0; i < timerCount; i++) { if (!timers[i].enabled) continue; // 检查是否到达触发时间 bool shouldTrigger = false; if (!timers[i].isActive && timers[i].hour == currentHour && timers[i].minute == currentMinute) { if (timers[i].repeatDaily) { // 每天重复:检查今天是否已经触发过 if (timers[i].lastTriggerDay != currentDay) { shouldTrigger = true; timers[i].lastTriggerDay = currentDay; } } else { // 单次触发 shouldTrigger = true; } } if (shouldTrigger) { timers[i].isActive = true; timers[i].startTime = currentTime; // 保存真实时间戳(如果可用) if (timeManager->isTimeValid()) { timers[i].realStartTime = timeManager->getEpochTime(); } else { timers[i].realStartTime = 0; } setPin(timers[i].pin, HIGH, timers[i].isPWM ? timers[i].pwmValue : 0); String modeStr = timers[i].isPWM ? " PWM(" + String(timers[i].pwmValue) + ")" : ""; Serial.println("定时器 " + String(i) + " 激活,引脚 " + String(timers[i].pin) + " 开启" + modeStr + (timers[i].repeatDaily ? " (每天重复)" : " (单次)")); stateChanged = true; // 如果是单次定时器,触发后自动禁用 if (!timers[i].repeatDaily) { timers[i].enabled = false; saveTimers(); // 立即保存配置更改 } } // 检查是否需要关闭 if (timers[i].isActive && currentTime - timers[i].startTime >= (unsigned long)(timers[i].duration * 1000.0)) { timers[i].isActive = false; timers[i].realStartTime = 0; // 清理真实时间戳 setPin(timers[i].pin, LOW, 0); Serial.println("定时器 " + String(i) + " 完成,引脚 " + String(timers[i].pin) + " 关闭"); stateChanged = true; } } // 定期保存状态,或者有状态变化时立即保存 if (stateChanged || (currentTime - lastStateSave >= STATE_SAVE_INTERVAL)) { saveTimerStates(); lastStateSave = currentTime; } } bool TimerManager::addTimer(int pin, int hour, int minute, float duration, bool repeatDaily, bool isPWM, int pwmValue) { if (timerCount >= MAX_TIMERS) { return false; } // 验证引脚是否可用 bool pinValid = false; for (int i = 0; i < AVAILABLE_PINS_COUNT; i++) { if (AVAILABLE_PINS[i] == pin) { pinValid = true; break; } } if (!pinValid) return false; // 验证时间 if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || duration <= 0.0) { return false; } // 验证PWM值 if (isPWM && (pwmValue < 0 || pwmValue > PWM_MAX_VALUE)) { return false; } timers[timerCount].enabled = true; timers[timerCount].pin = pin; timers[timerCount].hour = hour; timers[timerCount].minute = minute; timers[timerCount].duration = duration; timers[timerCount].repeatDaily = repeatDaily; timers[timerCount].isActive = false; timers[timerCount].startTime = 0; timers[timerCount].lastTriggerDay = 0; // 初始化为0 timers[timerCount].isPWM = isPWM; timers[timerCount].pwmValue = isPWM ? pwmValue : 0; timers[timerCount].realStartTime = 0; // 初始化真实时间戳 timerCount++; saveTimers(); String modeStr = isPWM ? " PWM模式, 值=" + String(pwmValue) : " 数字模式"; Serial.println("添加定时器:引脚 " + String(pin) + ", 时间 " + String(hour) + ":" + String(minute) + ", 持续 " + String(duration) + "秒" + modeStr + (repeatDaily ? " (每天重复)" : " (单次)")); return true; } bool TimerManager::removeTimer(int index) { if (index < 0 || index >= timerCount) { return false; } // 如果定时器正在运行,先关闭引脚 if (timers[index].isActive) { setPin(timers[index].pin, LOW, 0); } // 移动数组元素 for (int i = index; i < timerCount - 1; i++) { timers[i] = timers[i + 1]; } timerCount--; saveTimers(); Serial.println("删除定时器 " + String(index)); return true; } bool TimerManager::updateTimer(int index, int pin, int hour, int minute, float duration, bool enabled, bool repeatDaily, bool isPWM, int pwmValue) { if (index < 0 || index >= timerCount) { return false; } // 验证引脚 bool pinValid = false; for (int i = 0; i < AVAILABLE_PINS_COUNT; i++) { if (AVAILABLE_PINS[i] == pin) { pinValid = true; break; } } if (!pinValid) return false; // 验证时间 if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || duration <= 0.0) { return false; } // 验证PWM值 if (isPWM && (pwmValue < 0 || pwmValue > PWM_MAX_VALUE)) { return false; } // 如果定时器正在运行且引脚发生变化,先关闭旧引脚 if (timers[index].isActive && timers[index].pin != pin) { setPin(timers[index].pin, LOW, 0); timers[index].isActive = false; } timers[index].enabled = enabled; timers[index].pin = pin; timers[index].hour = hour; timers[index].minute = minute; timers[index].duration = duration; timers[index].repeatDaily = repeatDaily; timers[index].isPWM = isPWM; timers[index].pwmValue = isPWM ? pwmValue : 0; // 如果修改了重复设置,重置触发状态 timers[index].lastTriggerDay = 0; saveTimers(); Serial.println("更新定时器 " + String(index)); return true; } String TimerManager::getTimersJSON() { JsonDocument doc; JsonArray array = doc.to(); for (int i = 0; i < timerCount; i++) { JsonObject timer = array.add(); timer["index"] = i; timer["enabled"] = timers[i].enabled; timer["pin"] = timers[i].pin; timer["hour"] = timers[i].hour; timer["minute"] = timers[i].minute; timer["duration"] = timers[i].duration; timer["repeatDaily"] = timers[i].repeatDaily; timer["isActive"] = timers[i].isActive; timer["isPWM"] = timers[i].isPWM; timer["pwmValue"] = timers[i].pwmValue; } String result; serializeJson(doc, result); return result; } String TimerManager::getAvailablePinsJSON() { JsonDocument doc; JsonArray array = doc.to(); for (int i = 0; i < AVAILABLE_PINS_COUNT; i++) { JsonObject pin = array.add(); pin["pin"] = AVAILABLE_PINS[i]; pin["state"] = digitalRead(AVAILABLE_PINS[i]); // 检查是否被定时器占用 bool inUse = false; for (int j = 0; j < timerCount; j++) { if (timers[j].pin == AVAILABLE_PINS[i] && timers[j].isActive) { inUse = true; break; } } pin["inUse"] = inUse; } String result; serializeJson(doc, result); return result; } void TimerManager::executeManualControl(int pin, float duration, bool isPWM, int pwmValue) { // 验证引脚 bool pinValid = false; for (int i = 0; i < AVAILABLE_PINS_COUNT; i++) { if (AVAILABLE_PINS[i] == pin) { pinValid = true; break; } } if (!pinValid) return; // 验证PWM值 if (isPWM && (pwmValue < 0 || pwmValue > PWM_MAX_VALUE)) { return; } if (duration > 0.0) { // 开启引脚指定时间 setPin(pin, HIGH, isPWM ? pwmValue : 0); String modeStr = isPWM ? " PWM模式, 值=" + String(pwmValue) : " 数字模式"; Serial.println("手动控制:引脚 " + String(pin) + " 开启 " + String(duration) + " 秒" + modeStr); // 这里应该使用定时器来关闭,简化处理 delay((unsigned long)(duration * 1000.0)); setPin(pin, LOW, 0); Serial.println("手动控制:引脚 " + String(pin) + " 关闭"); } else { // 切换状态 bool currentState = digitalRead(pin); if (isPWM) { // PWM模式切换 if (currentState) { setPin(pin, LOW, 0); Serial.println("手动控制:引脚 " + String(pin) + " PWM关闭"); } else { setPin(pin, HIGH, pwmValue); Serial.println("手动控制:引脚 " + String(pin) + " PWM开启, 值=" + String(pwmValue)); } } else { // 数字模式切换 setPin(pin, !currentState, 0); Serial.println("手动控制:引脚 " + String(pin) + " 数字切换到 " + String(!currentState)); } } } void TimerManager::saveTimers() { int addr = TIMER_CONFIG_ADDR; // 保存定时器数量 EEPROM.write(addr++, timerCount); // 保存每个定时器 for (int i = 0; i < timerCount; i++) { EEPROM.write(addr++, timers[i].enabled ? 1 : 0); EEPROM.write(addr++, timers[i].pin); EEPROM.write(addr++, timers[i].hour); EEPROM.write(addr++, timers[i].minute); // 保存float类型的duration(4字节) union { float f; uint8_t bytes[4]; } durationConverter; durationConverter.f = timers[i].duration; EEPROM.write(addr++, durationConverter.bytes[0]); EEPROM.write(addr++, durationConverter.bytes[1]); EEPROM.write(addr++, durationConverter.bytes[2]); EEPROM.write(addr++, durationConverter.bytes[3]); EEPROM.write(addr++, timers[i].repeatDaily ? 1 : 0); EEPROM.write(addr++, timers[i].isPWM ? 1 : 0); EEPROM.write(addr++, (timers[i].pwmValue >> 8) & 0xFF); EEPROM.write(addr++, timers[i].pwmValue & 0xFF); // 保存运行时状态 EEPROM.write(addr++, timers[i].isActive ? 1 : 0); // 保存开始时间(4字节) unsigned long startTime = timers[i].startTime; EEPROM.write(addr++, (startTime >> 24) & 0xFF); EEPROM.write(addr++, (startTime >> 16) & 0xFF); EEPROM.write(addr++, (startTime >> 8) & 0xFF); EEPROM.write(addr++, startTime & 0xFF); // 保存上次触发天数(4字节) unsigned long lastTriggerDay = timers[i].lastTriggerDay; EEPROM.write(addr++, (lastTriggerDay >> 24) & 0xFF); EEPROM.write(addr++, (lastTriggerDay >> 16) & 0xFF); EEPROM.write(addr++, (lastTriggerDay >> 8) & 0xFF); EEPROM.write(addr++, lastTriggerDay & 0xFF); // 保存真实开始时间(4字节) unsigned long realStartTime = timers[i].realStartTime; EEPROM.write(addr++, (realStartTime >> 24) & 0xFF); EEPROM.write(addr++, (realStartTime >> 16) & 0xFF); EEPROM.write(addr++, (realStartTime >> 8) & 0xFF); EEPROM.write(addr++, realStartTime & 0xFF); } EEPROM.commit(); } void TimerManager::loadTimers() { int addr = TIMER_CONFIG_ADDR; // 读取定时器数量 timerCount = EEPROM.read(addr++); if (timerCount > MAX_TIMERS) timerCount = 0; // 读取每个定时器 for (int i = 0; i < timerCount; i++) { timers[i].enabled = EEPROM.read(addr++) == 1; timers[i].pin = EEPROM.read(addr++); timers[i].hour = EEPROM.read(addr++); timers[i].minute = EEPROM.read(addr++); // 读取float类型的duration(4字节) union { float f; uint8_t bytes[4]; } durationConverter; durationConverter.bytes[0] = EEPROM.read(addr++); durationConverter.bytes[1] = EEPROM.read(addr++); durationConverter.bytes[2] = EEPROM.read(addr++); durationConverter.bytes[3] = EEPROM.read(addr++); timers[i].duration = durationConverter.f; timers[i].repeatDaily = EEPROM.read(addr++) == 1; // 检查是否有PWM数据(向后兼容) if (addr < EEPROM_SIZE - 20) { // 更新了字节数计算:duration现在是4字节而不是2字节 timers[i].isPWM = EEPROM.read(addr++) == 1; int pwmHigh = EEPROM.read(addr++); int pwmLow = EEPROM.read(addr++); timers[i].pwmValue = (pwmHigh << 8) | pwmLow; // 读取运行时状态 timers[i].isActive = EEPROM.read(addr++) == 1; // 读取开始时间(4字节) unsigned long startTime = 0; startTime |= ((unsigned long)EEPROM.read(addr++)) << 24; startTime |= ((unsigned long)EEPROM.read(addr++)) << 16; startTime |= ((unsigned long)EEPROM.read(addr++)) << 8; startTime |= (unsigned long)EEPROM.read(addr++); timers[i].startTime = startTime; // 读取上次触发天数(4字节) unsigned long lastTriggerDay = 0; lastTriggerDay |= ((unsigned long)EEPROM.read(addr++)) << 24; lastTriggerDay |= ((unsigned long)EEPROM.read(addr++)) << 16; lastTriggerDay |= ((unsigned long)EEPROM.read(addr++)) << 8; lastTriggerDay |= (unsigned long)EEPROM.read(addr++); timers[i].lastTriggerDay = lastTriggerDay; // 读取真实开始时间(4字节) unsigned long realStartTime = 0; realStartTime |= ((unsigned long)EEPROM.read(addr++)) << 24; realStartTime |= ((unsigned long)EEPROM.read(addr++)) << 16; realStartTime |= ((unsigned long)EEPROM.read(addr++)) << 8; realStartTime |= (unsigned long)EEPROM.read(addr++); timers[i].realStartTime = realStartTime; } else { // 旧数据没有PWM和运行时状态信息,设为默认值 timers[i].isPWM = false; timers[i].pwmValue = 0; timers[i].isActive = false; timers[i].startTime = 0; timers[i].lastTriggerDay = 0; timers[i].realStartTime = 0; } // 恢复活跃定时器的引脚状态 if (timers[i].isActive) { // 使用真实时间检查定时器是否应该仍然活跃 if (timeManager && timeManager->isTimeValid() && timers[i].realStartTime > 0) { // 需要添加获取当前时间戳的方法到TimeManager // 暂时使用millis()逻辑,但添加更好的时间处理 unsigned long currentTime = millis(); // 重置开始时间为当前时间减去已经运行的时间 // 这样可以在重启后继续正确计时 if (timers[i].startTime > currentTime) { // millis() 已重置,重新计算开始时间 timers[i].startTime = currentTime; Serial.println("重启后调整定时器 " + String(i) + " 开始时间"); } unsigned long elapsedTime = currentTime - timers[i].startTime; // 检查定时器是否已经超时 if (elapsedTime >= (unsigned long)(timers[i].duration * 1000.0)) { // 定时器已经超时,关闭它 timers[i].isActive = false; timers[i].realStartTime = 0; setPin(timers[i].pin, LOW, 0); Serial.println("重启后发现定时器 " + String(i) + " 已超时,关闭引脚 " + String(timers[i].pin)); } else { // 定时器仍然有效,恢复引脚状态 setPin(timers[i].pin, HIGH, timers[i].isPWM ? timers[i].pwmValue : 0); String modeStr = timers[i].isPWM ? " PWM(" + String(timers[i].pwmValue) + ")" : ""; unsigned long remainingTime = (unsigned long)(timers[i].duration * 1000.0) - elapsedTime; Serial.println("恢复定时器 " + String(i) + " 状态,引脚 " + String(timers[i].pin) + " 开启" + modeStr + ",剩余时间: " + String(remainingTime / 1000) + "秒"); } } else { // 没有有效的时间或者是旧格式数据,保守处理 unsigned long currentTime = millis(); timers[i].startTime = currentTime; setPin(timers[i].pin, HIGH, timers[i].isPWM ? timers[i].pwmValue : 0); String modeStr = timers[i].isPWM ? " PWM(" + String(timers[i].pwmValue) + ")" : ""; Serial.println("恢复定时器 " + String(i) + " 状态,引脚 " + String(timers[i].pin) + " 开启" + modeStr + "(重启后重新计时)"); } } } } bool TimerManager::hasValidTime() { return timeManager && timeManager->isTimeValid(); } void TimerManager::saveTimerStates() { // 只保存运行时状态,不保存完整配置 // 这样可以减少EEPROM写入次数,延长寿命 int addr = TIMER_CONFIG_ADDR + 1; // 跳过定时器数量 for (int i = 0; i < timerCount; i++) { // 跳过基本配置部分 (12字节: enabled(1) + pin(1) + hour(1) + minute(1) + duration(4) + repeatDaily(1) + isPWM(1) + pwmValue(2)) addr += 12; // 更新运行时状态部分 (13字节) EEPROM.write(addr++, timers[i].isActive ? 1 : 0); // 更新开始时间(4字节) unsigned long startTime = timers[i].startTime; EEPROM.write(addr++, (startTime >> 24) & 0xFF); EEPROM.write(addr++, (startTime >> 16) & 0xFF); EEPROM.write(addr++, (startTime >> 8) & 0xFF); EEPROM.write(addr++, startTime & 0xFF); // 更新上次触发天数(4字节) unsigned long lastTriggerDay = timers[i].lastTriggerDay; EEPROM.write(addr++, (lastTriggerDay >> 24) & 0xFF); EEPROM.write(addr++, (lastTriggerDay >> 16) & 0xFF); EEPROM.write(addr++, (lastTriggerDay >> 8) & 0xFF); EEPROM.write(addr++, lastTriggerDay & 0xFF); // 更新真实开始时间(4字节) unsigned long realStartTime = timers[i].realStartTime; EEPROM.write(addr++, (realStartTime >> 24) & 0xFF); EEPROM.write(addr++, (realStartTime >> 16) & 0xFF); EEPROM.write(addr++, (realStartTime >> 8) & 0xFF); EEPROM.write(addr++, realStartTime & 0xFF); } EEPROM.commit(); } void TimerManager::clearAllTimers() { // 关闭所有激活的引脚 for (int i = 0; i < timerCount; i++) { if (timers[i].isActive) { setPin(timers[i].pin, LOW, 0); } } timerCount = 0; saveTimers(); Serial.println("所有定时器已清除"); } int TimerManager::getTimerCount() { return timerCount; } TimerConfig TimerManager::getTimer(int index) { if (index >= 0 && index < timerCount) { return timers[index]; } TimerConfig empty = {false, 0, 0, 0, 0.0, false, false, 0, 0UL, false, 0, 0UL}; return empty; } void TimerManager::setPin(int pin, bool state, int pwmValue) { if (pwmValue > 0 && state) { // PWM 模式 analogWrite(pin, pwmValue); } else { // 数字模式 digitalWrite(pin, state ? HIGH : LOW); } }