#include "timer_manager.h" #include #include #include #include const char* TimerManager::TAG = "TimerManager"; TimerManager::TimerManager() : is_running_(false) { ESP_LOGI(TAG, "TimerManager initialized"); } TimerManager::~TimerManager() { StopManager(); ESP_LOGI(TAG, "TimerManager destroyed"); } std::string TimerManager::CreateCountdownTimer(const std::string& name, uint32_t duration_ms, const std::string& description) { std::lock_guard lock(tasks_mutex_); TimerTask task; task.id = GenerateTaskId(); task.name = name; task.type = TimerType::COUNTDOWN; task.status = TimerStatus::PENDING; task.duration_ms = duration_ms; task.description = description; task.created_time = time(nullptr); tasks_[task.id] = task; ESP_LOGI(TAG, "Created countdown timer: %s (ID: %s, Duration: %u ms)", name.c_str(), task.id.c_str(), duration_ms); return task.id; } std::string TimerManager::CreateDelayedMcpTask(const std::string& name, uint32_t delay_ms, const std::string& mcp_tool_name, const std::string& mcp_tool_args, const std::string& description) { std::lock_guard lock(tasks_mutex_); TimerTask task; task.id = GenerateTaskId(); task.name = name; task.type = TimerType::DELAYED_EXEC; task.status = TimerStatus::PENDING; task.duration_ms = delay_ms; task.mcp_tool_name = mcp_tool_name; task.mcp_tool_args = mcp_tool_args; task.description = description; task.created_time = time(nullptr); tasks_[task.id] = task; ESP_LOGI(TAG, "Created delayed MCP task: %s (ID: %s, Delay: %u ms, Tool: %s)", name.c_str(), task.id.c_str(), delay_ms, mcp_tool_name.c_str()); return task.id; } std::string TimerManager::CreatePeriodicTask(const std::string& name, uint32_t interval_ms, int repeat_count, const std::string& mcp_tool_name, const std::string& mcp_tool_args, const std::string& description) { std::lock_guard lock(tasks_mutex_); TimerTask task; task.id = GenerateTaskId(); task.name = name; task.type = TimerType::PERIODIC; task.status = TimerStatus::PENDING; task.interval_ms = interval_ms; task.repeat_count = repeat_count; task.current_repeat = 0; task.mcp_tool_name = mcp_tool_name; task.mcp_tool_args = mcp_tool_args; task.description = description; task.created_time = time(nullptr); tasks_[task.id] = task; ESP_LOGI(TAG, "Created periodic task: %s (ID: %s, Interval: %u ms, Repeat: %d)", name.c_str(), task.id.c_str(), interval_ms, repeat_count); return task.id; } std::string TimerManager::CreateScheduledTask(const std::string& name, time_t scheduled_time, const std::string& mcp_tool_name, const std::string& mcp_tool_args, const std::string& description) { std::lock_guard lock(tasks_mutex_); TimerTask task; task.id = GenerateTaskId(); task.name = name; task.type = TimerType::SCHEDULED; task.status = TimerStatus::PENDING; task.scheduled_time = scheduled_time; task.mcp_tool_name = mcp_tool_name; task.mcp_tool_args = mcp_tool_args; task.description = description; task.created_time = time(nullptr); tasks_[task.id] = task; ESP_LOGI(TAG, "Created scheduled task: %s (ID: %s, Time: %ld)", name.c_str(), task.id.c_str(), scheduled_time); return task.id; } bool TimerManager::StartTask(const std::string& task_id) { std::lock_guard lock(tasks_mutex_); auto it = tasks_.find(task_id); if (it == tasks_.end()) { ESP_LOGE(TAG, "Task not found: %s", task_id.c_str()); return false; } TimerTask& task = it->second; if (task.status != TimerStatus::PENDING) { ESP_LOGW(TAG, "Task %s is not in pending status", task_id.c_str()); return false; } // 创建FreeRTOS定时器 TimerHandle_t timer_handle = xTimerCreate( task.name.c_str(), pdMS_TO_TICKS(task.duration_ms), (task.type == TimerType::PERIODIC) ? pdTRUE : pdFALSE, (void*)task_id.c_str(), TimerCallback ); if (timer_handle == nullptr) { ESP_LOGE(TAG, "Failed to create timer for task: %s", task_id.c_str()); return false; } timers_[task_id] = timer_handle; task.status = TimerStatus::RUNNING; task.start_time = time(nullptr); if (xTimerStart(timer_handle, 0) != pdPASS) { ESP_LOGE(TAG, "Failed to start timer for task: %s", task_id.c_str()); xTimerDelete(timer_handle, 0); timers_.erase(task_id); task.status = TimerStatus::FAILED; return false; } ESP_LOGI(TAG, "Started task: %s", task_id.c_str()); return true; } bool TimerManager::StopTask(const std::string& task_id) { std::lock_guard lock(tasks_mutex_); auto it = tasks_.find(task_id); if (it == tasks_.end()) { ESP_LOGE(TAG, "Task not found: %s", task_id.c_str()); return false; } TimerTask& task = it->second; if (task.status != TimerStatus::RUNNING) { ESP_LOGW(TAG, "Task %s is not running", task_id.c_str()); return false; } auto timer_it = timers_.find(task_id); if (timer_it != timers_.end()) { xTimerStop(timer_it->second, 0); xTimerDelete(timer_it->second, 0); timers_.erase(timer_it); } task.status = TimerStatus::CANCELLED; task.end_time = time(nullptr); ESP_LOGI(TAG, "Stopped task: %s", task_id.c_str()); return true; } bool TimerManager::CancelTask(const std::string& task_id) { return StopTask(task_id); } bool TimerManager::DeleteTask(const std::string& task_id) { std::lock_guard lock(tasks_mutex_); // 先停止任务 StopTask(task_id); auto it = tasks_.find(task_id); if (it == tasks_.end()) { ESP_LOGE(TAG, "Task not found: %s", task_id.c_str()); return false; } tasks_.erase(it); ESP_LOGI(TAG, "Deleted task: %s", task_id.c_str()); return true; } TimerTask* TimerManager::GetTask(const std::string& task_id) { std::lock_guard lock(tasks_mutex_); auto it = tasks_.find(task_id); if (it == tasks_.end()) { return nullptr; } return &it->second; } std::vector TimerManager::GetAllTasks() { std::lock_guard lock(tasks_mutex_); std::vector result; for (const auto& pair : tasks_) { result.push_back(pair.second); } return result; } std::vector TimerManager::GetTasksByStatus(TimerStatus status) { std::lock_guard lock(tasks_mutex_); std::vector result; for (const auto& pair : tasks_) { if (pair.second.status == status) { result.push_back(pair.second); } } return result; } std::vector TimerManager::GetRunningTasks() { return GetTasksByStatus(TimerStatus::RUNNING); } std::vector TimerManager::GetUpcomingTasks(int minutes) { std::lock_guard lock(tasks_mutex_); std::vector result; time_t now = time(nullptr); time_t future_time = now + (minutes * 60); for (const auto& pair : tasks_) { const TimerTask& task = pair.second; if (task.status == TimerStatus::PENDING && task.scheduled_time >= now && task.scheduled_time <= future_time) { result.push_back(task); } } return result; } int TimerManager::GetTaskCount() { std::lock_guard lock(tasks_mutex_); return tasks_.size(); } int TimerManager::GetTaskCountByStatus(TimerStatus status) { std::lock_guard lock(tasks_mutex_); int count = 0; for (const auto& pair : tasks_) { if (pair.second.status == status) { count++; } } return count; } int TimerManager::GetTaskCountByType(TimerType type) { std::lock_guard lock(tasks_mutex_); int count = 0; for (const auto& pair : tasks_) { if (pair.second.type == type) { count++; } } return count; } void TimerManager::StartManager() { if (is_running_) { ESP_LOGW(TAG, "TimerManager is already running"); return; } is_running_ = true; worker_thread_ = std::thread(&TimerManager::TaskWorker, this); ESP_LOGI(TAG, "TimerManager started"); } void TimerManager::StopManager() { if (!is_running_) { return; } is_running_ = false; if (worker_thread_.joinable()) { worker_thread_.join(); } // 停止所有定时器 std::lock_guard lock(tasks_mutex_); for (auto& pair : timers_) { xTimerStop(pair.second, 0); xTimerDelete(pair.second, 0); } timers_.clear(); ESP_LOGI(TAG, "TimerManager stopped"); } bool TimerManager::IsRunning() { return is_running_; } void TimerManager::SetTaskCompletedCallback(std::function callback) { task_completed_callback_ = callback; } void TimerManager::SetTaskFailedCallback(std::function callback) { task_failed_callback_ = callback; } bool TimerManager::SaveToStorage() { // TODO: 实现数据持久化到NVS或SPIFFS ESP_LOGW(TAG, "SaveToStorage not implemented yet"); return true; } bool TimerManager::LoadFromStorage() { // TODO: 实现从NVS或SPIFFS加载数据 ESP_LOGW(TAG, "LoadFromStorage not implemented yet"); return true; } std::string TimerManager::ExportToJson() { std::lock_guard lock(tasks_mutex_); std::stringstream json; json << "{\"tasks\":["; bool first = true; for (const auto& pair : tasks_) { if (!first) json << ","; first = false; const TimerTask& task = pair.second; json << "{" << "\"id\":\"" << task.id << "\"," << "\"name\":\"" << task.name << "\"," << "\"description\":\"" << task.description << "\"," << "\"duration_ms\":" << task.duration_ms << "," << "\"interval_ms\":" << task.interval_ms << "," << "\"repeat_count\":" << task.repeat_count << "," << "\"current_repeat\":" << task.current_repeat << "," << "\"created_time\":" << task.created_time << "," << "\"start_time\":" << task.start_time << "," << "\"end_time\":" << task.end_time << "," << "\"scheduled_time\":" << task.scheduled_time << "," << "\"mcp_tool_name\":\"" << task.mcp_tool_name << "\"," << "\"mcp_tool_args\":\"" << task.mcp_tool_args << "\"," << "\"user_data\":\"" << task.user_data << "\","; std::string status_str; switch (task.status) { case TimerStatus::PENDING: status_str = "pending"; break; case TimerStatus::RUNNING: status_str = "running"; break; case TimerStatus::COMPLETED: status_str = "completed"; break; case TimerStatus::CANCELLED: status_str = "cancelled"; break; case TimerStatus::FAILED: status_str = "failed"; break; } json << "\"status\":\"" << status_str << "\","; std::string type_str; switch (task.type) { case TimerType::COUNTDOWN: type_str = "countdown"; break; case TimerType::DELAYED_EXEC: type_str = "delayed_exec"; break; case TimerType::PERIODIC: type_str = "periodic"; break; case TimerType::SCHEDULED: type_str = "scheduled"; break; } json << "\"type\":\"" << type_str << "\""; json << "}"; } json << "]}"; return json.str(); } std::string TimerManager::GenerateTaskId() { static int counter = 0; return "task_" + std::to_string(++counter) + "_" + std::to_string(time(nullptr)); } void TimerManager::TaskWorker() { ESP_LOGI(TAG, "Task worker thread started"); while (is_running_) { vTaskDelay(pdMS_TO_TICKS(1000)); // 检查定时任务 std::lock_guard lock(tasks_mutex_); time_t now = time(nullptr); for (auto& pair : tasks_) { TimerTask& task = pair.second; if (task.status == TimerStatus::PENDING && task.type == TimerType::SCHEDULED && now >= task.scheduled_time) { ESP_LOGI(TAG, "Executing scheduled task: %s", task.id.c_str()); ExecuteTask(task); } } } ESP_LOGI(TAG, "Task worker thread stopped"); } void TimerManager::ExecuteTask(TimerTask& task) { task.status = TimerStatus::RUNNING; task.start_time = time(nullptr); bool success = true; std::string error_msg; try { if (!task.mcp_tool_name.empty()) { success = ExecuteMcpTool(task.mcp_tool_name, task.mcp_tool_args); if (!success) { error_msg = "MCP tool execution failed"; } } } catch (const std::exception& e) { success = false; error_msg = e.what(); } catch (...) { success = false; error_msg = "Unknown error occurred"; } task.end_time = time(nullptr); if (success) { if (task.type == TimerType::PERIODIC) { task.current_repeat++; if (task.repeat_count == -1 || task.current_repeat < task.repeat_count) { // 继续下一次重复 task.status = TimerStatus::PENDING; ESP_LOGI(TAG, "Periodic task %s completed repeat %d/%d", task.id.c_str(), task.current_repeat, task.repeat_count); } else { // 所有重复完成 task.status = TimerStatus::COMPLETED; ESP_LOGI(TAG, "Periodic task %s completed all repeats", task.id.c_str()); NotifyTaskCompleted(task); } } else { task.status = TimerStatus::COMPLETED; ESP_LOGI(TAG, "Task %s completed successfully", task.id.c_str()); NotifyTaskCompleted(task); } } else { task.status = TimerStatus::FAILED; ESP_LOGE(TAG, "Task %s failed: %s", task.id.c_str(), error_msg.c_str()); NotifyTaskFailed(task, error_msg); } } bool TimerManager::ExecuteMcpTool(const std::string& tool_name, const std::string& args) { // TODO: 实现MCP工具执行 ESP_LOGW(TAG, "ExecuteMcpTool not implemented yet: %s with args: %s", tool_name.c_str(), args.c_str()); return true; } void TimerManager::UpdateTaskStatus(TimerTask& task, TimerStatus status) { task.status = status; if (status == TimerStatus::RUNNING) { task.start_time = time(nullptr); } else if (status == TimerStatus::COMPLETED || status == TimerStatus::FAILED) { task.end_time = time(nullptr); } } void TimerManager::NotifyTaskCompleted(const TimerTask& task) { if (task_completed_callback_) { task_completed_callback_(task); } } void TimerManager::NotifyTaskFailed(const TimerTask& task, const std::string& error) { if (task_failed_callback_) { task_failed_callback_(task, error); } } void TimerManager::TimerCallback(TimerHandle_t timer_handle) { const char* task_id = (const char*)pvTimerGetTimerID(timer_handle); ESP_LOGI(TAG, "Timer callback triggered for task: %s", task_id); // 获取任务管理器实例 TimerManager& manager = TimerManager::GetInstance(); std::lock_guard lock(manager.tasks_mutex_); auto it = manager.tasks_.find(task_id); if (it != manager.tasks_.end()) { TimerTask& task = it->second; if (task.type == TimerType::COUNTDOWN) { // 倒计时完成 task.status = TimerStatus::COMPLETED; task.end_time = time(nullptr); ESP_LOGI(TAG, "Countdown timer %s completed", task_id); manager.NotifyTaskCompleted(task); } else if (task.type == TimerType::DELAYED_EXEC) { // 延时执行MCP工具 manager.ExecuteTask(task); } } // 删除一次性定时器 if (xTimerIsTimerActive(timer_handle) == pdFALSE) { xTimerDelete(timer_handle, 0); manager.timers_.erase(task_id); } }