feat: task manager
This commit is contained in:
94
README.md
94
README.md
@@ -228,6 +228,100 @@ The system includes automatic WiFi fallback:
|
|||||||
2. If connection fails, creates an access point
|
2. If connection fails, creates an access point
|
||||||
3. Hostname is automatically generated from MAC address
|
3. Hostname is automatically generated from MAC address
|
||||||
|
|
||||||
|
## Task Management
|
||||||
|
|
||||||
|
The SPORE system includes a comprehensive TaskManager that provides a clean interface for managing system tasks. This makes it easy to add, configure, and control background tasks without cluttering the main application code.
|
||||||
|
|
||||||
|
### TaskManager Features
|
||||||
|
|
||||||
|
- **Easy Task Registration**: Simple API for adding new tasks with configurable intervals
|
||||||
|
- **Dynamic Control**: Enable/disable tasks at runtime
|
||||||
|
- **Interval Management**: Change task execution frequency on the fly
|
||||||
|
- **Status Monitoring**: View task status and configuration
|
||||||
|
- **Automatic Lifecycle**: Tasks are automatically managed and executed
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "TaskManager.h"
|
||||||
|
|
||||||
|
// Create task manager
|
||||||
|
TaskManager taskManager(ctx);
|
||||||
|
|
||||||
|
// Register tasks
|
||||||
|
taskManager.registerTask("heartbeat", 2000, heartbeatFunction);
|
||||||
|
taskManager.registerTask("maintenance", 30000, maintenanceFunction);
|
||||||
|
|
||||||
|
// Initialize and start all tasks
|
||||||
|
taskManager.initialize();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Task Control API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Enable/disable tasks
|
||||||
|
taskManager.enableTask("heartbeat");
|
||||||
|
taskManager.disableTask("maintenance");
|
||||||
|
|
||||||
|
// Change intervals
|
||||||
|
taskManager.setTaskInterval("heartbeat", 5000); // 5 seconds
|
||||||
|
|
||||||
|
// Check status
|
||||||
|
bool isRunning = taskManager.isTaskEnabled("heartbeat");
|
||||||
|
unsigned long interval = taskManager.getTaskInterval("heartbeat");
|
||||||
|
|
||||||
|
// Print all task statuses
|
||||||
|
taskManager.printTaskStatus();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Remote Task Management
|
||||||
|
|
||||||
|
The TaskManager integrates with the API server to provide remote task control:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get task status
|
||||||
|
curl http://192.168.1.100/api/tasks/status
|
||||||
|
|
||||||
|
# Control tasks
|
||||||
|
curl -X POST http://192.168.1.100/api/tasks/control \
|
||||||
|
-d "task=heartbeat&action=disable"
|
||||||
|
|
||||||
|
# Available actions: enable, disable, start, stop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding Custom Tasks
|
||||||
|
|
||||||
|
To add custom tasks to your SPORE system:
|
||||||
|
|
||||||
|
1. **Define your task function**:
|
||||||
|
```cpp
|
||||||
|
void myCustomTask() {
|
||||||
|
// Your task logic here
|
||||||
|
Serial.println("Custom task executed");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Register with TaskManager**:
|
||||||
|
```cpp
|
||||||
|
taskManager.registerTask("my_task", 10000, myCustomTask);
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **The TaskManager handles the rest** - automatic execution, lifecycle management, and monitoring.
|
||||||
|
|
||||||
|
### Task Configuration Options
|
||||||
|
|
||||||
|
When registering tasks, you can specify:
|
||||||
|
|
||||||
|
- **Name**: Unique identifier for the task
|
||||||
|
- **Interval**: Execution frequency in milliseconds
|
||||||
|
- **Enabled**: Whether the task starts enabled (default: true)
|
||||||
|
- **AutoStart**: Whether to start automatically (default: true)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
taskManager.registerTask("delayed_task", 5000, taskFunction, true, false);
|
||||||
|
// Creates a task that's enabled but won't auto-start
|
||||||
|
```
|
||||||
|
|
||||||
## Current Limitations
|
## Current Limitations
|
||||||
|
|
||||||
- WiFi credentials are hardcoded in `Config.cpp` (should be configurable)
|
- WiFi credentials are hardcoded in `Config.cpp` (should be configurable)
|
||||||
|
|||||||
68
examples/task_management_example.cpp
Normal file
68
examples/task_management_example.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Task Management Example
|
||||||
|
*
|
||||||
|
* This example demonstrates how to use the TaskManager to add custom tasks
|
||||||
|
* to the SPORE system. The TaskManager provides a clean interface for
|
||||||
|
* registering, controlling, and monitoring system tasks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "TaskManager.h"
|
||||||
|
#include "NodeContext.h"
|
||||||
|
|
||||||
|
// Example custom task functions
|
||||||
|
void customTask1() {
|
||||||
|
Serial.println("[CustomTask1] Executing custom task 1");
|
||||||
|
// Add your custom logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
void customTask2() {
|
||||||
|
Serial.println("[CustomTask2] Executing custom task 2");
|
||||||
|
// Add your custom logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
void periodicMaintenance() {
|
||||||
|
Serial.println("[Maintenance] Running periodic maintenance");
|
||||||
|
// Add maintenance logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Task Management Example");
|
||||||
|
|
||||||
|
// Create context and task manager
|
||||||
|
NodeContext ctx;
|
||||||
|
TaskManager taskManager(ctx);
|
||||||
|
|
||||||
|
// Register custom tasks with different intervals
|
||||||
|
taskManager.registerTask("custom_task_1", 5000, customTask1); // Every 5 seconds
|
||||||
|
taskManager.registerTask("custom_task_2", 10000, customTask2); // Every 10 seconds
|
||||||
|
taskManager.registerTask("maintenance", 30000, periodicMaintenance); // Every 30 seconds
|
||||||
|
|
||||||
|
// Initialize and start all tasks
|
||||||
|
taskManager.initialize();
|
||||||
|
|
||||||
|
// Print initial task status
|
||||||
|
taskManager.printTaskStatus();
|
||||||
|
|
||||||
|
// Example: Disable a task temporarily
|
||||||
|
taskManager.disableTask("custom_task_2");
|
||||||
|
Serial.println("Disabled custom_task_2");
|
||||||
|
|
||||||
|
// Example: Change task interval
|
||||||
|
taskManager.setTaskInterval("custom_task_1", 2000); // Change to 2 seconds
|
||||||
|
Serial.println("Changed custom_task_1 interval to 2 seconds");
|
||||||
|
|
||||||
|
// Re-enable the disabled task
|
||||||
|
taskManager.enableTask("custom_task_2");
|
||||||
|
Serial.println("Re-enabled custom_task_2");
|
||||||
|
|
||||||
|
// Print updated status
|
||||||
|
taskManager.printTaskStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// The TaskManager handles all task execution
|
||||||
|
// No need to call individual task functions
|
||||||
|
yield();
|
||||||
|
}
|
||||||
63
include/TaskManager.h
Normal file
63
include/TaskManager.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include "NodeContext.h"
|
||||||
|
|
||||||
|
// Forward declarations to avoid multiple definition errors
|
||||||
|
class Task;
|
||||||
|
class Scheduler;
|
||||||
|
|
||||||
|
// Define the callback type that TaskScheduler expects
|
||||||
|
using TaskCallback = void (*)();
|
||||||
|
|
||||||
|
struct TaskDefinition {
|
||||||
|
std::string name;
|
||||||
|
unsigned long interval;
|
||||||
|
TaskCallback callback;
|
||||||
|
bool enabled;
|
||||||
|
bool autoStart;
|
||||||
|
|
||||||
|
TaskDefinition(const std::string& n, unsigned long intv, TaskCallback cb, bool en = true, bool autoS = true)
|
||||||
|
: name(n), interval(intv), callback(cb), enabled(en), autoStart(autoS) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TaskManager {
|
||||||
|
public:
|
||||||
|
TaskManager(NodeContext& ctx);
|
||||||
|
~TaskManager();
|
||||||
|
|
||||||
|
// Task registration methods
|
||||||
|
void registerTask(const std::string& name, unsigned long interval, TaskCallback callback, bool enabled = true, bool autoStart = true);
|
||||||
|
void registerTask(const TaskDefinition& taskDef);
|
||||||
|
|
||||||
|
// Task control methods
|
||||||
|
void enableTask(const std::string& name);
|
||||||
|
void disableTask(const std::string& name);
|
||||||
|
void setTaskInterval(const std::string& name, unsigned long interval);
|
||||||
|
void startTask(const std::string& name);
|
||||||
|
void stopTask(const std::string& name);
|
||||||
|
|
||||||
|
// Task status methods
|
||||||
|
bool isTaskEnabled(const std::string& name) const;
|
||||||
|
bool isTaskRunning(const std::string& name) const;
|
||||||
|
unsigned long getTaskInterval(const std::string& name) const;
|
||||||
|
|
||||||
|
// Management methods
|
||||||
|
void initialize();
|
||||||
|
void enableAllTasks();
|
||||||
|
void disableAllTasks();
|
||||||
|
void printTaskStatus() const;
|
||||||
|
|
||||||
|
// Task execution
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeContext& ctx;
|
||||||
|
std::vector<Task*> tasks;
|
||||||
|
std::vector<TaskDefinition> taskDefinitions;
|
||||||
|
|
||||||
|
Task* findTask(const std::string& name) const;
|
||||||
|
void createTask(const TaskDefinition& taskDef);
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "ApiServer.h"
|
#include "ApiServer.h"
|
||||||
|
|
||||||
ApiServer::ApiServer(NodeContext& ctx, uint16_t port) : server(port), ctx(ctx) {}
|
ApiServer::ApiServer(NodeContext& ctx, TaskManager& taskMgr, uint16_t port) : server(port), ctx(ctx), taskManager(taskMgr) {}
|
||||||
|
|
||||||
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler) {
|
void ApiServer::addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler) {
|
||||||
serviceRegistry.push_back(std::make_tuple(uri, method));
|
serviceRegistry.push_back(std::make_tuple(uri, method));
|
||||||
@@ -37,6 +37,13 @@ void ApiServer::begin() {
|
|||||||
);
|
);
|
||||||
addEndpoint("/api/node/restart", HTTP_POST,
|
addEndpoint("/api/node/restart", HTTP_POST,
|
||||||
std::bind(&ApiServer::onRestartRequest, this, std::placeholders::_1));
|
std::bind(&ApiServer::onRestartRequest, this, std::placeholders::_1));
|
||||||
|
|
||||||
|
// Task management endpoints
|
||||||
|
addEndpoint("/api/tasks/status", HTTP_GET,
|
||||||
|
std::bind(&ApiServer::onTaskStatusRequest, this, std::placeholders::_1));
|
||||||
|
addEndpoint("/api/tasks/control", HTTP_POST,
|
||||||
|
std::bind(&ApiServer::onTaskControlRequest, this, std::placeholders::_1));
|
||||||
|
|
||||||
server.begin();
|
server.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,3 +181,70 @@ void ApiServer::onRestartRequest(AsyncWebServerRequest *request) {
|
|||||||
ESP.restart();
|
ESP.restart();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiServer::onTaskStatusRequest(AsyncWebServerRequest *request) {
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonArray tasksArr = doc["tasks"].to<JsonArray>();
|
||||||
|
|
||||||
|
// This would need to be implemented in TaskManager to expose task status
|
||||||
|
// For now, we'll return a basic response
|
||||||
|
JsonObject taskObj = tasksArr.add<JsonObject>();
|
||||||
|
taskObj["message"] = "Task status endpoint - implementation pending";
|
||||||
|
taskObj["note"] = "Task status will be available in future versions";
|
||||||
|
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
request->send(200, "application/json", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiServer::onTaskControlRequest(AsyncWebServerRequest *request) {
|
||||||
|
// Parse the request body for task control commands
|
||||||
|
if (request->hasParam("task", true) && request->hasParam("action", true)) {
|
||||||
|
String taskName = request->getParam("task", true)->value();
|
||||||
|
String action = request->getParam("action", true)->value();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
String message = "";
|
||||||
|
|
||||||
|
if (action == "enable") {
|
||||||
|
taskManager.enableTask(taskName.c_str());
|
||||||
|
success = true;
|
||||||
|
message = "Task enabled";
|
||||||
|
} else if (action == "disable") {
|
||||||
|
taskManager.disableTask(taskName.c_str());
|
||||||
|
success = true;
|
||||||
|
message = "Task disabled";
|
||||||
|
} else if (action == "start") {
|
||||||
|
taskManager.startTask(taskName.c_str());
|
||||||
|
success = true;
|
||||||
|
message = "Task started";
|
||||||
|
} else if (action == "stop") {
|
||||||
|
taskManager.stopTask(taskName.c_str());
|
||||||
|
success = true;
|
||||||
|
message = "Task stopped";
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
message = "Invalid action. Use: enable, disable, start, or stop";
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["success"] = success;
|
||||||
|
doc["message"] = message;
|
||||||
|
doc["task"] = taskName;
|
||||||
|
doc["action"] = action;
|
||||||
|
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
request->send(success ? 200 : 400, "application/json", json);
|
||||||
|
} else {
|
||||||
|
// Missing parameters
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["success"] = false;
|
||||||
|
doc["message"] = "Missing parameters. Required: task, action";
|
||||||
|
doc["example"] = "{\"task\": \"discovery_send\", \"action\": \"disable\"}";
|
||||||
|
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
request->send(400, "application/json", json);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,13 +9,14 @@
|
|||||||
|
|
||||||
#include "NodeContext.h"
|
#include "NodeContext.h"
|
||||||
#include "NodeInfo.h"
|
#include "NodeInfo.h"
|
||||||
|
#include "TaskManager.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
class ApiServer {
|
class ApiServer {
|
||||||
public:
|
public:
|
||||||
ApiServer(NodeContext& ctx, uint16_t port = 80);
|
ApiServer(NodeContext& ctx, TaskManager& taskMgr, uint16_t port = 80);
|
||||||
void begin();
|
void begin();
|
||||||
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler);
|
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler);
|
||||||
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
|
void addEndpoint(const String& uri, int method, std::function<void(AsyncWebServerRequest*)> requestHandler,
|
||||||
@@ -23,6 +24,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
AsyncWebServer server;
|
AsyncWebServer server;
|
||||||
NodeContext& ctx;
|
NodeContext& ctx;
|
||||||
|
TaskManager& taskManager;
|
||||||
std::vector<std::tuple<String, int>> serviceRegistry;
|
std::vector<std::tuple<String, int>> serviceRegistry;
|
||||||
void onClusterMembersRequest(AsyncWebServerRequest *request);
|
void onClusterMembersRequest(AsyncWebServerRequest *request);
|
||||||
void methodToStr(const std::tuple<String, int> &endpoint, ArduinoJson::V742PB22::JsonObject &apiObj);
|
void methodToStr(const std::tuple<String, int> &endpoint, ArduinoJson::V742PB22::JsonObject &apiObj);
|
||||||
@@ -30,4 +32,8 @@ private:
|
|||||||
void onFirmwareUpdateRequest(AsyncWebServerRequest *request);
|
void onFirmwareUpdateRequest(AsyncWebServerRequest *request);
|
||||||
void onFirmwareUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
void onFirmwareUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
||||||
void onRestartRequest(AsyncWebServerRequest *request);
|
void onRestartRequest(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
// Task management endpoints
|
||||||
|
void onTaskStatusRequest(AsyncWebServerRequest *request);
|
||||||
|
void onTaskControlRequest(AsyncWebServerRequest *request);
|
||||||
};
|
};
|
||||||
|
|||||||
162
src/TaskManager.cpp
Normal file
162
src/TaskManager.cpp
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
#include "TaskManager.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <TaskScheduler.h>
|
||||||
|
|
||||||
|
TaskManager::TaskManager(NodeContext& ctx) : ctx(ctx) {}
|
||||||
|
|
||||||
|
TaskManager::~TaskManager() {
|
||||||
|
// Clean up tasks
|
||||||
|
for (auto task : tasks) {
|
||||||
|
delete task;
|
||||||
|
}
|
||||||
|
tasks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::registerTask(const std::string& name, unsigned long interval, TaskCallback callback, bool enabled, bool autoStart) {
|
||||||
|
TaskDefinition taskDef(name, interval, callback, enabled, autoStart);
|
||||||
|
registerTask(taskDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::registerTask(const TaskDefinition& taskDef) {
|
||||||
|
taskDefinitions.push_back(taskDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::initialize() {
|
||||||
|
// Initialize the scheduler
|
||||||
|
ctx.scheduler->init();
|
||||||
|
|
||||||
|
// Create all registered tasks
|
||||||
|
for (const auto& taskDef : taskDefinitions) {
|
||||||
|
createTask(taskDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable tasks that should auto-start
|
||||||
|
for (const auto& taskDef : taskDefinitions) {
|
||||||
|
if (taskDef.autoStart && taskDef.enabled) {
|
||||||
|
enableTask(taskDef.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::createTask(const TaskDefinition& taskDef) {
|
||||||
|
// Create new task
|
||||||
|
Task* task = new Task(0, TASK_FOREVER, taskDef.callback);
|
||||||
|
task->setInterval(taskDef.interval);
|
||||||
|
|
||||||
|
// Add to scheduler
|
||||||
|
ctx.scheduler->addTask(*task);
|
||||||
|
|
||||||
|
// Store task pointer
|
||||||
|
tasks.push_back(task);
|
||||||
|
|
||||||
|
Serial.printf("[TaskManager] Created task: %s (interval: %lu ms)\n",
|
||||||
|
taskDef.name.c_str(), taskDef.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::enableTask(const std::string& name) {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
if (task) {
|
||||||
|
task->enable();
|
||||||
|
Serial.printf("[TaskManager] Enabled task: %s\n", name.c_str());
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TaskManager] Warning: Task not found: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::disableTask(const std::string& name) {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
if (task) {
|
||||||
|
task->disable();
|
||||||
|
Serial.printf("[TaskManager] Disabled task: %s\n", name.c_str());
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TaskManager] Warning: Task not found: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::setTaskInterval(const std::string& name, unsigned long interval) {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
if (task) {
|
||||||
|
task->setInterval(interval);
|
||||||
|
Serial.printf("[TaskManager] Set interval for task %s: %lu ms\n", name.c_str(), interval);
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TaskManager] Warning: Task not found: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::startTask(const std::string& name) {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
if (task) {
|
||||||
|
task->enable();
|
||||||
|
Serial.printf("[TaskManager] Started task: %s\n", name.c_str());
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TaskManager] Warning: Task not found: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::stopTask(const std::string& name) {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
if (task) {
|
||||||
|
task->disable();
|
||||||
|
Serial.printf("[TaskManager] Stopped task: %s\n", name.c_str());
|
||||||
|
} else {
|
||||||
|
Serial.printf("[TaskManager] Warning: Task not found: %s\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskManager::isTaskEnabled(const std::string& name) const {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
return task ? task->isEnabled() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskManager::isTaskRunning(const std::string& name) const {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
return task ? task->isEnabled() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long TaskManager::getTaskInterval(const std::string& name) const {
|
||||||
|
Task* task = findTask(name);
|
||||||
|
return task ? task->getInterval() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::enableAllTasks() {
|
||||||
|
for (auto task : tasks) {
|
||||||
|
task->enable();
|
||||||
|
}
|
||||||
|
Serial.println("[TaskManager] Enabled all tasks");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::disableAllTasks() {
|
||||||
|
for (auto task : tasks) {
|
||||||
|
task->disable();
|
||||||
|
}
|
||||||
|
Serial.println("[TaskManager] Disabled all tasks");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::printTaskStatus() const {
|
||||||
|
Serial.println("\n[TaskManager] Task Status:");
|
||||||
|
Serial.println("==========================");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < tasks.size() && i < taskDefinitions.size(); ++i) {
|
||||||
|
const auto& taskDef = taskDefinitions[i];
|
||||||
|
const auto& task = tasks[i];
|
||||||
|
|
||||||
|
Serial.printf(" %s: %s (interval: %lu ms)\n",
|
||||||
|
taskDef.name.c_str(),
|
||||||
|
task->isEnabled() ? "ENABLED" : "DISABLED",
|
||||||
|
task->getInterval());
|
||||||
|
}
|
||||||
|
Serial.println("==========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskManager::execute() {
|
||||||
|
ctx.scheduler->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* TaskManager::findTask(const std::string& name) const {
|
||||||
|
for (size_t i = 0; i < tasks.size() && i < taskDefinitions.size(); ++i) {
|
||||||
|
if (taskDefinitions[i].name == name) {
|
||||||
|
return tasks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* https://github.com/arkhipenko/TaskScheduler/tree/master/examples/Scheduler_example16_Multitab
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <TaskScheduler.h>
|
|
||||||
54
src/main.cpp
54
src/main.cpp
@@ -4,47 +4,45 @@
|
|||||||
#include "NetworkManager.h"
|
#include "NetworkManager.h"
|
||||||
#include "ClusterManager.h"
|
#include "ClusterManager.h"
|
||||||
#include "ApiServer.h"
|
#include "ApiServer.h"
|
||||||
|
#include "TaskManager.h"
|
||||||
|
|
||||||
NodeContext ctx;
|
NodeContext ctx;
|
||||||
NetworkManager network(ctx);
|
NetworkManager network(ctx);
|
||||||
ClusterManager cluster(ctx);
|
ClusterManager cluster(ctx);
|
||||||
ApiServer apiServer(ctx, ctx.config.api_server_port);
|
TaskManager taskManager(ctx);
|
||||||
|
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
|
||||||
|
|
||||||
Task tSendDiscovery(0, TASK_FOREVER, [](){ cluster.sendDiscovery(); });
|
// Task callback wrapper functions
|
||||||
Task tListenForDiscovery(0, TASK_FOREVER, [](){ cluster.listenForDiscovery(); });
|
void discoverySendTask() { cluster.sendDiscovery(); }
|
||||||
Task tUpdateStatus(0, TASK_FOREVER, [](){ cluster.updateAllNodeStatuses(); cluster.removeDeadNodes(); });
|
void discoveryListenTask() { cluster.listenForDiscovery(); }
|
||||||
Task tPrintMemberList(0, TASK_FOREVER, [](){ cluster.printMemberList(); });
|
void statusUpdateTask() { cluster.updateAllNodeStatuses(); cluster.removeDeadNodes(); }
|
||||||
Task tHeartbeat(0, TASK_FOREVER, [](){ cluster.heartbeatTaskCallback(); });
|
void printMembersTask() { cluster.printMemberList(); }
|
||||||
Task tUpdateAllMembersInfo(0, TASK_FOREVER, [](){ cluster.updateAllMembersInfoTaskCallback(); });
|
void heartbeatTask() { cluster.heartbeatTaskCallback(); }
|
||||||
|
void updateMembersInfoTask() { cluster.updateAllMembersInfoTaskCallback(); }
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
// Setup WiFi first
|
||||||
network.setupWiFi();
|
network.setupWiFi();
|
||||||
ctx.scheduler->init();
|
|
||||||
|
|
||||||
// Set task intervals from config
|
// Register all system tasks
|
||||||
tSendDiscovery.setInterval(ctx.config.discovery_interval_ms);
|
taskManager.registerTask("discovery_send", ctx.config.discovery_interval_ms, discoverySendTask);
|
||||||
tListenForDiscovery.setInterval(ctx.config.discovery_interval_ms / 10); // Listen more frequently
|
taskManager.registerTask("discovery_listen", ctx.config.discovery_interval_ms / 10, discoveryListenTask);
|
||||||
tUpdateStatus.setInterval(ctx.config.status_update_interval_ms);
|
taskManager.registerTask("status_update", ctx.config.status_update_interval_ms, statusUpdateTask);
|
||||||
tPrintMemberList.setInterval(ctx.config.print_interval_ms);
|
taskManager.registerTask("print_members", ctx.config.print_interval_ms, printMembersTask);
|
||||||
tHeartbeat.setInterval(ctx.config.heartbeat_interval_ms);
|
taskManager.registerTask("heartbeat", ctx.config.heartbeat_interval_ms, heartbeatTask);
|
||||||
tUpdateAllMembersInfo.setInterval(ctx.config.member_info_update_interval_ms);
|
taskManager.registerTask("update_members_info", ctx.config.member_info_update_interval_ms, updateMembersInfoTask);
|
||||||
|
|
||||||
ctx.scheduler->addTask(tSendDiscovery);
|
// Initialize and start all tasks
|
||||||
ctx.scheduler->addTask(tListenForDiscovery);
|
taskManager.initialize();
|
||||||
ctx.scheduler->addTask(tUpdateStatus);
|
|
||||||
ctx.scheduler->addTask(tPrintMemberList);
|
// Start the API server
|
||||||
ctx.scheduler->addTask(tHeartbeat);
|
|
||||||
ctx.scheduler->addTask(tUpdateAllMembersInfo);
|
|
||||||
tSendDiscovery.enable();
|
|
||||||
tListenForDiscovery.enable();
|
|
||||||
tUpdateStatus.enable();
|
|
||||||
tPrintMemberList.enable();
|
|
||||||
tHeartbeat.enable();
|
|
||||||
tUpdateAllMembersInfo.enable();
|
|
||||||
apiServer.begin();
|
apiServer.begin();
|
||||||
|
|
||||||
|
// Print initial task status
|
||||||
|
taskManager.printTaskStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
ctx.scheduler->execute();
|
taskManager.execute();
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user