feat: task manager endpoint, updated documentation
This commit is contained in:
444
README.md
444
README.md
@@ -16,420 +16,136 @@ SPORE is a cluster engine for ESP8266 microcontrollers that provides automatic n
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
- **ESP-01** (1MB Flash)
|
||||
- **ESP-01S** (1MB Flash)
|
||||
- **ESP-01 / ESP-01S** (1MB Flash)
|
||||
- **Wemos D1** (4MB Flash)
|
||||
- Other ESP8266 boards with 1MB+ flash
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
The system architecture consists of several key components working together:
|
||||
SPORE uses a modular architecture with automatic node discovery, health monitoring, and distributed task management.
|
||||
|
||||
**Core Components:**
|
||||
- **Network Manager**: WiFi connection handling and hostname configuration
|
||||
- **Cluster Manager**: Node discovery, member list management, and health monitoring
|
||||
- **API Server**: HTTP API server with dynamic endpoint registration
|
||||
- **Task Scheduler**: Cooperative multitasking system for background operations
|
||||
- **Node Context**: Central context providing event system and shared resources
|
||||
|
||||
### Auto Discovery Protocol
|
||||
**Key Features:**
|
||||
- **Auto Discovery**: UDP-based node detection on port 4210
|
||||
- **Health Monitoring**: Continuous status checking via HTTP API
|
||||
- **Task Scheduling**: Background tasks at configurable intervals
|
||||
- **Event System**: Local and cluster-wide event publishing/subscription
|
||||
|
||||
The cluster uses a UDP-based discovery protocol for automatic node detection:
|
||||
|
||||
1. **Discovery Broadcast**: Nodes periodically send UDP packets on port 4210
|
||||
2. **Response Handling**: Nodes respond with their hostname and IP address
|
||||
3. **Member Management**: Discovered nodes are automatically added to the cluster
|
||||
4. **Health Monitoring**: Continuous status checking via HTTP API calls
|
||||
|
||||
### Task Scheduling
|
||||
|
||||
The system runs several background tasks at different intervals:
|
||||
|
||||
- **Discovery Tasks**: Send/listen for discovery packets (1s/100ms)
|
||||
- **Status Updates**: Monitor cluster member health (1s)
|
||||
- **Heartbeat**: Maintain cluster connectivity (2s)
|
||||
- **Member Info**: Update detailed node information (10s)
|
||||
- **Debug Output**: Print cluster status (5s)
|
||||
📖 **Detailed Architecture:** See [`docs/Architecture.md`](./docs/Architecture.md) for comprehensive system design and implementation details.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Node Management
|
||||
The system provides a comprehensive RESTful API for monitoring and controlling the embedded device.
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/node/status` | GET | Get system resources and API endpoints |
|
||||
| `/api/node/update` | POST | Upload and install firmware update |
|
||||
| `/api/node/restart` | POST | Restart the node |
|
||||
**Core Endpoints:**
|
||||
- **`/api/node/status`** - System resources and API endpoint registry
|
||||
- **`/api/cluster/members`** - Cluster membership and health status
|
||||
- **`/api/node/update`** - OTA firmware updates
|
||||
- **`/api/node/restart`** - System restart
|
||||
- **`/api/tasks/status`** - Task management and monitoring
|
||||
- **`/api/tasks/control`** - Task control operations
|
||||
|
||||
### Cluster Management
|
||||
**Response Format:** All endpoints return JSON with standardized error handling and HTTP status codes.
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/cluster/members` | GET | Get cluster membership and status |
|
||||
|
||||
### Node Status Response
|
||||
|
||||
```json
|
||||
{
|
||||
"freeHeap": 12345,
|
||||
"chipId": 12345678,
|
||||
"sdkVersion": "2.2.2-dev(38a443e)",
|
||||
"cpuFreqMHz": 80,
|
||||
"flashChipSize": 1048576,
|
||||
"api": [
|
||||
{
|
||||
"uri": "/api/node/status",
|
||||
"method": "GET"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Cluster Members Response
|
||||
|
||||
```json
|
||||
{
|
||||
"members": [
|
||||
{
|
||||
"hostname": "esp_123456",
|
||||
"ip": "192.168.1.100",
|
||||
"lastSeen": 1234567890,
|
||||
"latency": 5,
|
||||
"status": "active",
|
||||
"resources": {
|
||||
"freeHeap": 12345,
|
||||
"chipId": 12345678,
|
||||
"sdkVersion": "2.2.2-dev(38a443e)",
|
||||
"cpuFreqMHz": 80,
|
||||
"flashChipSize": 1048576
|
||||
},
|
||||
"api": [
|
||||
{
|
||||
"uri": "/api/node/status",
|
||||
"method": "GET"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
📖 **Complete API Reference:** See [`docs/API.md`](./docs/API.md) for detailed endpoint documentation, examples, and integration guides.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Setup
|
||||
|
||||
Create a `.env` file in your project root:
|
||||
|
||||
```bash
|
||||
# API node IP for cluster management
|
||||
export API_NODE=192.168.1.100
|
||||
```
|
||||
|
||||
### PlatformIO Configuration
|
||||
|
||||
The project uses PlatformIO with the following configuration:
|
||||
The project uses PlatformIO with Arduino framework and supports multiple ESP8266 boards.
|
||||
|
||||
**Key Settings:**
|
||||
- **Framework**: Arduino
|
||||
- **Board**: ESP-01 with 1MB flash
|
||||
- **Board**: ESP-01 with 1MB flash (default)
|
||||
- **Upload Speed**: 115200 baud
|
||||
- **Flash Mode**: DOUT (required for ESP-01S)
|
||||
|
||||
### Dependencies
|
||||
**Dependencies:**
|
||||
- ESPAsyncWebServer, ArduinoJson, TaskScheduler
|
||||
- ESP8266WiFi and HTTPClient libraries
|
||||
|
||||
The project requires the following libraries:
|
||||
- `esp32async/ESPAsyncWebServer@^3.8.0` - HTTP API server
|
||||
- `bblanchon/ArduinoJson@^7.4.2` - JSON processing
|
||||
- `arkhipenko/TaskScheduler@^3.8.5` - Cooperative multitasking
|
||||
**Environment Setup:** Create `.env` file for cluster configuration and API node settings.
|
||||
|
||||
📖 **Development Guide:** See [`docs/Development.md`](./docs/Development.md) for comprehensive build, deployment, and configuration instructions.
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- PlatformIO Core or PlatformIO IDE
|
||||
- ESP8266 development tools
|
||||
- `jq` for JSON processing in scripts
|
||||
|
||||
### Building
|
||||
|
||||
Build the firmware for specific chip:
|
||||
|
||||
**Quick Commands:**
|
||||
```bash
|
||||
# Build firmware
|
||||
./ctl.sh build target esp01_1m
|
||||
```
|
||||
|
||||
### Flashing
|
||||
|
||||
Flash firmware to a connected device:
|
||||
|
||||
```bash
|
||||
# Flash device
|
||||
./ctl.sh flash target esp01_1m
|
||||
```
|
||||
|
||||
### Over-The-Air Updates
|
||||
|
||||
Update a specific node:
|
||||
|
||||
```bash
|
||||
# OTA update
|
||||
./ctl.sh ota update 192.168.1.100 esp01_1m
|
||||
```
|
||||
|
||||
Update all nodes in the cluster:
|
||||
|
||||
```bash
|
||||
./ctl.sh ota all esp01_1m
|
||||
```
|
||||
|
||||
### Cluster Management
|
||||
|
||||
View cluster members:
|
||||
|
||||
```bash
|
||||
# Cluster management
|
||||
./ctl.sh cluster members
|
||||
```
|
||||
|
||||
**Prerequisites:** PlatformIO Core, ESP8266 tools, `jq` for JSON processing
|
||||
|
||||
📖 **Complete Development Guide:** See [`docs/Development.md`](./docs/Development.md) for detailed build, deployment, and troubleshooting instructions.
|
||||
|
||||
## API Reference
|
||||
|
||||
The SPORE system provides a comprehensive RESTful API for monitoring and controlling the embedded device. All endpoints return JSON responses and support standard HTTP status codes.
|
||||
|
||||
### Quick Reference
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/tasks/status` | GET | Get comprehensive task status |
|
||||
| `/api/tasks/control` | POST | Control individual tasks |
|
||||
| `/api/node/status` | GET | System resource information |
|
||||
| `/api/cluster/members` | GET | Cluster membership |
|
||||
| `/api/node/update` | POST | OTA firmware updates |
|
||||
| `/api/node/restart` | POST | System restart |
|
||||
|
||||
**Available Task Actions:** `enable`, `disable`, `start`, `stop`, `status`
|
||||
|
||||
📖 **Detailed API Documentation:** See [`docs/API.md`](./docs/API.md) for complete API reference, examples, and integration guides.
|
||||
|
||||
🔧 **OpenAPI Specification:** Machine-readable API spec available in [`api/`](./api/) folder for code generation and tooling integration.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Event System
|
||||
The system uses an event-driven architecture with automatic resource monitoring and WiFi fallback capabilities.
|
||||
|
||||
The `NodeContext` provides an event-driven architecture:
|
||||
**Key Systems:**
|
||||
- **Event System**: Local and cluster-wide event publishing/subscription
|
||||
- **Status Tracking**: Automatic node categorization (ACTIVE, INACTIVE, DEAD)
|
||||
- **Resource Monitoring**: Memory, CPU, flash, and API endpoint tracking
|
||||
- **WiFi Fallback**: Automatic access point creation if connection fails
|
||||
|
||||
```cpp
|
||||
// Subscribe to events
|
||||
ctx.on("node_discovered", [](void* data) {
|
||||
NodeInfo* node = static_cast<NodeInfo*>(data);
|
||||
// Handle new node discovery
|
||||
});
|
||||
|
||||
// Publish events
|
||||
ctx.fire("node_discovered", &newNode);
|
||||
```
|
||||
|
||||
### Node Status Tracking
|
||||
|
||||
Nodes are automatically categorized by their activity:
|
||||
|
||||
- **ACTIVE**: Responding within 10 seconds
|
||||
- **INACTIVE**: No response for 10-60 seconds
|
||||
- **DEAD**: No response for over 60 seconds
|
||||
|
||||
### Resource Monitoring
|
||||
|
||||
Each node tracks:
|
||||
- Free heap memory
|
||||
- Chip ID and SDK version
|
||||
- CPU frequency
|
||||
- Flash chip size
|
||||
- API endpoint registry
|
||||
|
||||
### WiFi Fallback
|
||||
|
||||
The system includes automatic WiFi fallback:
|
||||
1. Attempts to connect to configured WiFi network
|
||||
2. If connection fails, creates an access point
|
||||
3. Hostname is automatically generated from MAC address
|
||||
📖 **Architecture Details:** See [`docs/Architecture.md`](./docs/Architecture.md) for comprehensive system design and implementation information.
|
||||
|
||||
## 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.
|
||||
The SPORE system includes a comprehensive TaskManager for background task management with runtime control and monitoring.
|
||||
|
||||
### TaskManager Features
|
||||
**Key Features:**
|
||||
- **Easy Registration**: Simple API for adding tasks with configurable intervals
|
||||
- **Dynamic Control**: Enable/disable tasks at runtime without restart
|
||||
- **Status Monitoring**: Real-time task health and performance tracking
|
||||
- **Remote Management**: REST API for cluster-wide task control
|
||||
|
||||
- **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();
|
||||
```
|
||||
|
||||
#### Using std::bind with Member Functions
|
||||
|
||||
```cpp
|
||||
#include <functional>
|
||||
#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
|
||||
|
||||
```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
|
||||
|
||||
#### 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);
|
||||
```
|
||||
|
||||
### 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);
|
||||
```
|
||||
📖 **Complete Task Management Guide:** See [`docs/TaskManagement.md`](./docs/TaskManagement.md) for detailed usage examples, best practices, and advanced features.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
- WiFi credentials are hardcoded in `Config.cpp` (should be configurable)
|
||||
- Limited error handling for network failures
|
||||
- No persistent storage for configuration
|
||||
- Basic health monitoring without advanced metrics
|
||||
- Task monitoring and system health metrics
|
||||
- Task execution history and performance analytics not yet implemented
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -448,6 +164,16 @@ Enable serial monitoring to see cluster activity:
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
📖 **For detailed task management examples and workflows, see [`docs/API.md`](./docs/API.md).**
|
||||
|
||||
## Documentation
|
||||
|
||||
📚 **Comprehensive documentation is available in the [`docs/`](./docs/) folder:**
|
||||
|
||||
- **[API Reference](./docs/API.md)** - Complete API documentation with examples
|
||||
- **[TaskManager Guide](./docs/TaskManager.md)** - Background task management system
|
||||
- **[OpenAPI Spec](./api/)** - Machine-readable API specification
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
|
||||
Reference in New Issue
Block a user