# Task Management System 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. ## Overview The TaskManager system provides: - **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 Registration Methods ### Using std::bind with Member Functions (Recommended) ```cpp #include #include "TaskManager.h" class MyService { public: void sendHeartbeat() { Serial.println("Service heartbeat"); } void performMaintenance() { Serial.println("Running maintenance"); } }; MyService service; TaskManager taskManager(ctx); // Register member functions using std::bind taskManager.registerTask("heartbeat", 2000, std::bind(&MyService::sendHeartbeat, &service)); taskManager.registerTask("maintenance", 30000, std::bind(&MyService::performMaintenance, &service)); // Initialize and start all tasks taskManager.initialize(); ``` ### Using Lambda Functions ```cpp // Register lambda functions directly taskManager.registerTask("counter", 1000, []() { static int count = 0; Serial.printf("Count: %d\n", ++count); }); // Lambda with capture int threshold = 100; taskManager.registerTask("monitor", 5000, [&threshold]() { if (ESP.getFreeHeap() < threshold) { Serial.println("Low memory warning!"); } }); ``` ### Complex Task Registration ```cpp class NetworkManager { public: void checkConnection() { /* ... */ } void sendData(String data) { /* ... */ } }; NetworkManager network; // Multiple operations in one task taskManager.registerTask("network_ops", 3000, std::bind([](NetworkManager* net) { net->checkConnection(); net->sendData("status_update"); }, &network)); ``` ## Task Control API ### Basic Operations ```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(); ``` ### Task Lifecycle Management ```cpp // Start/stop tasks taskManager.startTask("heartbeat"); taskManager.stopTask("discovery"); // Bulk operations taskManager.enableAllTasks(); taskManager.disableAllTasks(); ``` ## Task Configuration Options When registering tasks, you can specify: - **Name**: Unique identifier for the task - **Interval**: Execution frequency in milliseconds - **Callback**: Function, bound method, or lambda to execute - **Enabled**: Whether the task starts enabled (default: true) - **AutoStart**: Whether to start automatically (default: true) ```cpp // Traditional function taskManager.registerTask("delayed_task", 5000, taskFunction, true, false); // Member function with std::bind taskManager.registerTask("service_task", 3000, std::bind(&Service::method, &instance), true, false); // Lambda function taskManager.registerTask("lambda_task", 2000, []() { Serial.println("Lambda!"); }, true, false); ``` ## Adding Custom Tasks ### Method 1: Using std::bind (Recommended) 1. **Create your service class**: ```cpp class SensorService { public: void readTemperature() { // Read sensor logic Serial.println("Reading temperature"); } void calibrateSensors() { // Calibration logic Serial.println("Calibrating sensors"); } }; ``` 2. **Register with TaskManager**: ```cpp SensorService sensors; taskManager.registerTask("temp_read", 1000, std::bind(&SensorService::readTemperature, &sensors)); taskManager.registerTask("calibrate", 60000, std::bind(&SensorService::calibrateSensors, &sensors)); ``` ### Method 2: Traditional Functions 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); ``` ## Enhanced TaskManager Capabilities ### Task Status Monitoring - **Real-time Status**: Check enabled/disabled state and running status - **Performance Metrics**: Monitor execution intervals and timing - **System Integration**: View task status alongside system resources - **Bulk Operations**: Get status of all tasks at once ### Task Control Features - **Runtime Control**: Enable/disable tasks without restart - **Dynamic Intervals**: Change task execution frequency on-the-fly - **Individual Status**: Get detailed information about specific tasks - **Health Monitoring**: Track task health and system resources ## Remote Task Management The TaskManager integrates with the API server to provide comprehensive remote task control and monitoring. ### Task Status Overview Get a complete overview of all tasks and system status: ```bash # Get comprehensive task status curl http://192.168.1.100/api/tasks/status ``` **Response includes:** - **Summary**: Total task count and active task count - **Task Details**: Individual status for each task (name, interval, enabled, running, auto-start) - **System Info**: Free heap memory and uptime **Example Response:** ```json { "summary": { "totalTasks": 6, "activeTasks": 5 }, "tasks": [ { "name": "discovery_send", "interval": 1000, "enabled": true, "running": true, "autoStart": true }, { "name": "heartbeat", "interval": 2000, "enabled": true, "running": true, "autoStart": true } ], "system": { "freeHeap": 48748, "uptime": 12345 } } ``` ### Individual Task Control Control individual tasks with various actions: ```bash # Control tasks curl -X POST http://192.168.1.100/api/tasks/control \ -d "task=heartbeat&action=disable" # Get detailed status for a specific task curl -X POST http://192.168.1.100/api/tasks/control \ -d "task=discovery_send&action=status" ``` **Available Actions:** - `enable` - Enable a task - `disable` - Disable a task - `start` - Start a task - `stop` - Stop a task - `status` - Get detailed status for a specific task **Task Status Response:** ```json { "success": true, "message": "Task status retrieved", "task": "discovery_send", "action": "status", "taskDetails": { "name": "discovery_send", "enabled": true, "running": true, "interval": 1000, "system": { "freeHeap": 48748, "uptime": 12345 } } } ``` ## Performance Considerations - `std::bind` creates a callable object that may have a small overhead compared to direct function pointers - For high-frequency tasks, consider the performance impact - The overhead is typically negligible for most embedded applications - The TaskManager stores bound functions efficiently in a registry ## Best Practices 1. **Use std::bind for member functions**: Cleaner than wrapper functions 2. **Group related tasks**: Register multiple related operations in a single task 3. **Monitor task health**: Use the status API to monitor task performance 4. **Plan intervals carefully**: Balance responsiveness with system resources 5. **Use descriptive names**: Make task names clear and meaningful ## Migration from Wrapper Functions ### Before (with wrapper functions): ```cpp void discoverySendTask() { cluster.sendDiscovery(); } void discoveryListenTask() { cluster.listenForDiscovery(); } taskManager.registerTask("discovery_send", interval, discoverySendTask); taskManager.registerTask("discovery_listen", interval, discoveryListenTask); ``` ### After (with std::bind): ```cpp taskManager.registerTask("discovery_send", interval, std::bind(&ClusterManager::sendDiscovery, &cluster)); taskManager.registerTask("discovery_listen", interval, std::bind(&ClusterManager::listenForDiscovery, &cluster)); ``` ## Compatibility - The new `std::bind` support is fully backward compatible - Existing code using function pointers will continue to work - You can mix both approaches in the same project - All existing TaskManager methods remain unchanged - New status monitoring methods are additive and don't break existing functionality ## Related Documentation - **[TaskManager API Reference](./TaskManager.md)** - Detailed API documentation - **[API Reference](./API.md)** - REST API for remote task management - **[OpenAPI Specification](../api/)** - Machine-readable API specification