Merge pull request 'feat: implement Spore framework class as main orchestration layer' (#3) from feature/spore into main

Reviewed-on: #3
This commit is contained in:
2025-09-14 12:24:24 +02:00
40 changed files with 438 additions and 252 deletions

View File

@@ -41,6 +41,7 @@ SPORE is a cluster engine for ESP8266 microcontrollers that provides automatic n
SPORE uses a modular architecture with automatic node discovery, health monitoring, and distributed task management.
**Core Components:**
- **Spore Framework**: Main framework class that orchestrates all 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
@@ -58,6 +59,50 @@ SPORE uses a modular architecture with automatic node discovery, health monitori
📖 **Detailed Architecture:** See [`docs/Architecture.md`](./docs/Architecture.md) for comprehensive system design and implementation details.
## Quick Start
The Spore framework provides a simple, unified interface for all core functionality:
```cpp
#include <Arduino.h>
#include "Spore.h"
// Create Spore instance with custom labels
Spore spore({
{"app", "my_app"},
{"role", "controller"}
});
void setup() {
spore.setup();
spore.begin();
}
void loop() {
spore.loop();
}
```
**Adding Custom Services:**
```cpp
void setup() {
spore.setup();
// Create and register custom services
RelayService* relayService = new RelayService(spore.getTaskManager(), 2);
spore.addService(relayService);
// Or using smart pointers
auto sensorService = std::make_shared<SensorService>();
spore.addService(sensorService);
// Start the API server and complete initialization
spore.begin();
}
```
**Examples:** See [`examples/base/`](./examples/base/) for basic usage and [`examples/relay/`](./examples/relay/) for custom service integration.
## API Reference
The system provides a comprehensive RESTful API for monitoring and controlling the embedded device. All endpoints return JSON responses and support standard HTTP status codes.

View File

@@ -1,56 +1,21 @@
#include <Arduino.h>
#include <functional>
#include "Globals.h"
#include "NodeContext.h"
#include "NetworkManager.h"
#include "ClusterManager.h"
#include "ApiServer.h"
#include "TaskManager.h"
#include "spore/Spore.h"
// Services
#include "services/NodeService.h"
#include "services/NetworkService.h"
#include "services/ClusterService.h"
#include "services/TaskService.h"
using namespace std;
NodeContext ctx({
// Create Spore instance with custom labels
Spore spore({
{"app", "base"},
{"role", "demo"}
});
NetworkManager network(ctx);
TaskManager taskManager(ctx);
ClusterManager cluster(ctx, taskManager);
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
// Create services
NodeService nodeService(ctx, apiServer);
NetworkService networkService(network);
ClusterService clusterService(ctx);
TaskService taskService(taskManager);
void setup() {
Serial.begin(115200);
// Setup WiFi first
network.setupWiFi();
// Initialize and start all tasks
taskManager.initialize();
// Initialize the Spore framework
spore.setup();
// Register services and start API server
apiServer.addService(nodeService);
apiServer.addService(networkService);
apiServer.addService(clusterService);
apiServer.addService(taskService);
apiServer.begin();
// Print initial task status
taskManager.printTaskStatus();
// Start the API server and complete initialization
spore.begin();
}
void loop() {
taskManager.execute();
yield();
// Run the Spore framework loop
spore.loop();
}

View File

@@ -1,5 +1,5 @@
#include "NeoPatternService.h"
#include "ApiServer.h"
#include "spore/core/ApiServer.h"
NeoPatternService::NeoPatternService(TaskManager& taskMgr, uint16_t numPixels, uint8_t pin, uint8_t type)
: taskManager(taskMgr),

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "TaskManager.h"
#include "spore/Service.h"
#include "spore/core/TaskManager.h"
#include "NeoPattern.cpp"
#include <map>
#include <vector>

View File

@@ -1,17 +1,5 @@
#include <Arduino.h>
#include <functional>
#include "Globals.h"
#include "NodeContext.h"
#include "NetworkManager.h"
#include "ClusterManager.h"
#include "ApiServer.h"
#include "TaskManager.h"
// Services
#include "services/NodeService.h"
#include "services/NetworkService.h"
#include "services/ClusterService.h"
#include "services/TaskService.h"
#include "spore/Spore.h"
#include "NeoPatternService.h"
#ifndef LED_STRIP_PIN
@@ -26,46 +14,32 @@
#define LED_STRIP_TYPE (NEO_GRB + NEO_KHZ800)
#endif
NodeContext ctx({
// Create Spore instance with custom labels
Spore spore({
{"app", "neopattern"},
{"device", "light"},
{"pixels", String(LED_STRIP_LENGTH)},
{"pin", String(LED_STRIP_PIN)}
});
NetworkManager network(ctx);
TaskManager taskManager(ctx);
ClusterManager cluster(ctx, taskManager);
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
// Create services
NodeService nodeService(ctx, apiServer);
NetworkService networkService(network);
ClusterService clusterService(ctx);
TaskService taskService(taskManager);
NeoPatternService neoPatternService(taskManager, LED_STRIP_LENGTH, LED_STRIP_PIN, LED_STRIP_TYPE);
// Create custom service
NeoPatternService* neoPatternService = nullptr;
void setup() {
Serial.begin(115200);
// Setup WiFi first
network.setupWiFi();
// Initialize and start all tasks
taskManager.initialize();
// Register services and start API server
apiServer.addService(nodeService);
apiServer.addService(networkService);
apiServer.addService(clusterService);
apiServer.addService(taskService);
apiServer.addService(neoPatternService);
apiServer.begin();
// Print initial task status
taskManager.printTaskStatus();
// Initialize the Spore framework
spore.setup();
// Create and add custom service
neoPatternService = new NeoPatternService(spore.getTaskManager(), LED_STRIP_LENGTH, LED_STRIP_PIN, LED_STRIP_TYPE);
spore.addService(neoPatternService);
// Start the API server and complete initialization
spore.begin();
Serial.println("[Main] NeoPattern service registered and ready!");
}
void loop() {
taskManager.execute();
yield();
// Run the Spore framework loop
spore.loop();
}

View File

@@ -1,5 +1,5 @@
#include "NeoPixelService.h"
#include "ApiServer.h"
#include "spore/core/ApiServer.h"
// Wheel helper: map 0-255 to RGB rainbow
static uint32_t colorWheel(Adafruit_NeoPixel& strip, uint8_t pos) {

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "TaskManager.h"
#include "spore/Service.h"
#include "spore/core/TaskManager.h"
#include <Adafruit_NeoPixel.h>
#include <map>
#include <vector>

View File

@@ -1,17 +1,5 @@
#include <Arduino.h>
#include <functional>
#include "Globals.h"
#include "NodeContext.h"
#include "NetworkManager.h"
#include "ClusterManager.h"
#include "ApiServer.h"
#include "TaskManager.h"
// Services
#include "services/NodeService.h"
#include "services/NetworkService.h"
#include "services/ClusterService.h"
#include "services/TaskService.h"
#include "spore/Spore.h"
#include "NeoPixelService.h"
#ifndef NEOPIXEL_PIN
@@ -26,46 +14,32 @@
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800)
#endif
NodeContext ctx({
// Create Spore instance with custom labels
Spore spore({
{"app", "neopixel"},
{"device", "light"},
{"pixels", String(NEOPIXEL_COUNT)},
{"pin", String(NEOPIXEL_PIN)}
});
NetworkManager network(ctx);
TaskManager taskManager(ctx);
ClusterManager cluster(ctx, taskManager);
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
// Create services
NodeService nodeService(ctx, apiServer);
NetworkService networkService(network);
ClusterService clusterService(ctx);
TaskService taskService(taskManager);
NeoPixelService neoPixelService(taskManager, NEOPIXEL_COUNT, NEOPIXEL_PIN, NEOPIXEL_TYPE);
// Create custom service
NeoPixelService* neoPixelService = nullptr;
void setup() {
Serial.begin(115200);
// Setup WiFi first
network.setupWiFi();
// Initialize and start all tasks
taskManager.initialize();
// Register services and start API server
apiServer.addService(nodeService);
apiServer.addService(networkService);
apiServer.addService(clusterService);
apiServer.addService(taskService);
apiServer.addService(neoPixelService);
apiServer.begin();
// Print initial task status
taskManager.printTaskStatus();
// Initialize the Spore framework
spore.setup();
// Create and add custom service
neoPixelService = new NeoPixelService(spore.getTaskManager(), NEOPIXEL_COUNT, NEOPIXEL_PIN, NEOPIXEL_TYPE);
spore.addService(neoPixelService);
// Start the API server and complete initialization
spore.begin();
Serial.println("[Main] NeoPixel service registered and ready!");
}
void loop() {
taskManager.execute();
yield();
// Run the Spore framework loop
spore.loop();
}

View File

@@ -1,10 +1,48 @@
# Relay Service Example
A minimal example that uses the framework's `NodeContext`, `NetworkManager`, `TaskManager`, and `ApiServer` to control a relay via REST and log status periodically as a task.
A minimal example that demonstrates the Spore framework with a custom RelayService. The Spore framework automatically handles all core functionality (WiFi, clustering, API server, task management) while allowing easy registration of custom services.
- Default relay pin: `GPIO0` (ESP-01). Override with `-DRELAY_PIN=<pin>`.
- WiFi and API port are configured in `src/Config.cpp`.
## Spore Framework Usage
This example demonstrates the simplified Spore framework approach:
```cpp
#include <Arduino.h>
#include "Spore.h"
#include "RelayService.h"
Spore spore({
{"app", "relay"},
{"device", "actuator"},
{"pin", String(RELAY_PIN)}
});
RelayService* relayService = nullptr;
void setup() {
spore.setup();
relayService = new RelayService(spore.getTaskManager(), RELAY_PIN);
spore.addService(relayService);
spore.begin();
}
void loop() {
spore.loop();
}
```
The Spore framework automatically provides:
- WiFi connectivity management
- Cluster discovery and management
- REST API server with core endpoints
- Task scheduling and execution
- Node status monitoring
## Build & Upload
- ESP01S:
@@ -32,17 +70,17 @@ curl http://192.168.1.50/api/relay/status
- Turn relay ON
```bash
curl -X POST http://192.168.1.50/api/relay/set -d state=on
curl -X POST http://192.168.1.50/api/relay -d state=on
```
- Turn relay OFF
```bash
curl -X POST http://192.168.1.50/api/relay/set -d state=off
curl -X POST http://192.168.1.50/api/relay -d state=off
```
- Toggle relay
```bash
curl -X POST http://192.168.1.50/api/relay/set -d state=toggle
curl -X POST http://192.168.1.50/api/relay -d state=toggle
```
Notes:

View File

@@ -1,5 +1,5 @@
#include "RelayService.h"
#include "ApiServer.h"
#include "spore/core/ApiServer.h"
RelayService::RelayService(TaskManager& taskMgr, int pin)
: taskManager(taskMgr), relayPin(pin), relayOn(false) {

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "TaskManager.h"
#include "spore/Service.h"
#include "spore/core/TaskManager.h"
#include <ArduinoJson.h>
class RelayService : public Service {

View File

@@ -1,65 +1,37 @@
#include <Arduino.h>
#include <functional>
#include "Globals.h"
#include "NodeContext.h"
#include "NetworkManager.h"
#include "ClusterManager.h"
#include "ApiServer.h"
#include "TaskManager.h"
// Services
#include "services/NodeService.h"
#include "services/NetworkService.h"
#include "services/ClusterService.h"
#include "services/TaskService.h"
#include "spore/Spore.h"
#include "RelayService.h"
using namespace std;
// Choose a default relay pin. For ESP-01 this is GPIO0. Adjust as needed for your board.
#ifndef RELAY_PIN
#define RELAY_PIN 0
#endif
NodeContext ctx({
// Create Spore instance with custom labels
Spore spore({
{"app", "relay"},
{"device", "actuator"},
{"pin", String(RELAY_PIN)}
});
NetworkManager network(ctx);
TaskManager taskManager(ctx);
ClusterManager cluster(ctx, taskManager);
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
// Create services
NodeService nodeService(ctx, apiServer);
NetworkService networkService(network);
ClusterService clusterService(ctx);
TaskService taskService(taskManager);
RelayService relayService(taskManager, RELAY_PIN);
// Create custom service
RelayService* relayService = nullptr;
void setup() {
Serial.begin(115200);
// Setup WiFi first
network.setupWiFi();
// Initialize and start all tasks
taskManager.initialize();
// Register services and start API server
apiServer.addService(nodeService);
apiServer.addService(networkService);
apiServer.addService(clusterService);
apiServer.addService(taskService);
apiServer.addService(relayService);
apiServer.begin();
// Print initial task status
taskManager.printTaskStatus();
// Initialize the Spore framework
spore.setup();
// Create and add custom service
relayService = new RelayService(spore.getTaskManager(), RELAY_PIN);
spore.addService(relayService);
// Start the API server and complete initialization
spore.begin();
Serial.println("[Main] Relay service registered and ready!");
}
void loop() {
taskManager.execute();
yield();
// Run the Spore framework loop
spore.loop();
}

View File

@@ -1,5 +1,5 @@
#pragma once
#include "ApiServer.h"
#include "spore/core/ApiServer.h"
class Service {
public:

51
include/spore/Spore.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <vector>
#include <memory>
#include <initializer_list>
#include <utility>
#include "core/NodeContext.h"
#include "core/NetworkManager.h"
#include "core/ClusterManager.h"
#include "core/ApiServer.h"
#include "core/TaskManager.h"
#include "Service.h"
class Spore {
public:
Spore();
Spore(std::initializer_list<std::pair<String, String>> initialLabels);
~Spore();
// Core lifecycle methods
void setup();
void begin();
void loop();
// Service management
void addService(std::shared_ptr<Service> service);
void addService(Service* service);
// Access to core components
NodeContext& getContext() { return ctx; }
NetworkManager& getNetwork() { return network; }
TaskManager& getTaskManager() { return taskManager; }
ClusterManager& getCluster() { return cluster; }
ApiServer& getApiServer() { return apiServer; }
private:
void initializeCore();
void registerCoreServices();
void startApiServer();
NodeContext ctx;
NetworkManager network;
TaskManager taskManager;
ClusterManager cluster;
ApiServer apiServer;
std::vector<std::shared_ptr<Service>> services;
bool initialized;
bool apiServerStarted;
};

View File

@@ -7,10 +7,10 @@
#include <vector>
#include <tuple>
#include "NodeContext.h"
#include "NodeInfo.h"
#include "TaskManager.h"
#include "ApiTypes.h"
#include "spore/core/NodeContext.h"
#include "spore/types/NodeInfo.h"
#include "spore/core/TaskManager.h"
#include "spore/types/ApiTypes.h"
class Service; // Forward declaration

View File

@@ -1,8 +1,7 @@
#pragma once
#include "Globals.h"
#include "NodeContext.h"
#include "NodeInfo.h"
#include "TaskManager.h"
#include "spore/core/NodeContext.h"
#include "spore/types/NodeInfo.h"
#include "spore/core/TaskManager.h"
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

View File

@@ -1,5 +1,5 @@
#pragma once
#include "NodeContext.h"
#include "spore/core/NodeContext.h"
#include <ESP8266WiFi.h>
#include <vector>

View File

@@ -2,12 +2,12 @@
#include <WiFiUdp.h>
#include <map>
#include "NodeInfo.h"
#include "spore/types/NodeInfo.h"
#include <functional>
#include <string>
#include <initializer_list>
#include "Config.h"
#include "ApiTypes.h"
#include "spore/types/Config.h"
#include "spore/types/ApiTypes.h"
class NodeContext {
public:

View File

@@ -4,7 +4,7 @@
#include <functional>
#include <string>
#include <map>
#include "NodeContext.h"
#include "spore/core/NodeContext.h"
#include <ArduinoJson.h>
// Define our own callback type to avoid conflict with TaskScheduler

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "NodeContext.h"
#include "spore/Service.h"
#include "spore/core/NodeContext.h"
#include <ArduinoJson.h>
class ClusterService : public Service {

View File

@@ -1,7 +1,7 @@
#pragma once
#include "services/Service.h"
#include "NetworkManager.h"
#include "NodeContext.h"
#include "spore/Service.h"
#include "spore/core/NetworkManager.h"
#include "spore/core/NodeContext.h"
class NetworkService : public Service {
public:

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "NodeContext.h"
#include "spore/Service.h"
#include "spore/core/NodeContext.h"
#include <ArduinoJson.h>
#include <Updater.h>

View File

@@ -1,6 +1,6 @@
#pragma once
#include "services/Service.h"
#include "TaskManager.h"
#include "spore/Service.h"
#include "spore/core/TaskManager.h"
#include <ArduinoJson.h>
class TaskService : public Service {

View File

@@ -1,5 +1,4 @@
#pragma once
#include "Globals.h"
#include <IPAddress.h>
#include <vector>
#include <tuple>

View File

@@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
default_envs = esp01_1m
;default_envs = esp01_1m
src_dir = .
[common]
@@ -30,9 +30,11 @@ board_build.flash_size = 1M
lib_deps = ${common.lib_deps}
build_src_filter =
+<examples/base/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:d1_mini]
platform = platformio/espressif8266@^4.2.1
@@ -45,9 +47,11 @@ board_build.flash_size = 4M
lib_deps = ${common.lib_deps}
build_src_filter =
+<examples/base/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:esp01_1m_relay]
platform = platformio/espressif8266@^4.2.1
@@ -61,9 +65,11 @@ board_build.flash_size = 1M
lib_deps = ${common.lib_deps}
build_src_filter =
+<examples/relay/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:esp01_1m_neopixel]
platform = platformio/espressif8266@^4.2.1
@@ -78,9 +84,11 @@ lib_deps = ${common.lib_deps}
adafruit/Adafruit NeoPixel@^1.15.1
build_src_filter =
+<examples/neopixel/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:d1_mini_neopixel]
platform = platformio/espressif8266@^4.2.1
@@ -94,9 +102,11 @@ lib_deps = ${common.lib_deps}
adafruit/Adafruit NeoPixel@^1.15.1
build_src_filter =
+<examples/neopixel/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:esp01_1m_neopattern]
platform = platformio/espressif8266@^4.2.1
@@ -112,9 +122,11 @@ lib_deps = ${common.lib_deps}
build_flags = -DLED_STRIP_PIN=2
build_src_filter =
+<examples/neopattern/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>
[env:d1_mini_neopattern]
platform = platformio/espressif8266@^4.2.1
@@ -128,6 +140,8 @@ lib_deps = ${common.lib_deps}
adafruit/Adafruit NeoPixel@^1.15.1
build_src_filter =
+<examples/neopattern/*.cpp>
+<src/*.c>
+<src/*.cpp>
+<src/services/*.cpp>
+<src/spore/*.cpp>
+<src/spore/core/*.cpp>
+<src/spore/services/*.cpp>
+<src/spore/types/*.cpp>
+<src/internal/*.cpp>

153
src/spore/Spore.cpp Normal file
View File

@@ -0,0 +1,153 @@
#include "spore/Spore.h"
#include "spore/services/NodeService.h"
#include "spore/services/NetworkService.h"
#include "spore/services/ClusterService.h"
#include "spore/services/TaskService.h"
#include <Arduino.h>
Spore::Spore() : ctx(), network(ctx), taskManager(ctx), cluster(ctx, taskManager),
apiServer(ctx, taskManager, ctx.config.api_server_port),
initialized(false), apiServerStarted(false) {
}
Spore::Spore(std::initializer_list<std::pair<String, String>> initialLabels)
: ctx(initialLabels), network(ctx), taskManager(ctx), cluster(ctx, taskManager),
apiServer(ctx, taskManager, ctx.config.api_server_port),
initialized(false), apiServerStarted(false) {
}
Spore::~Spore() {
// Services will be automatically cleaned up by shared_ptr
}
void Spore::setup() {
if (initialized) {
Serial.println("[Spore] Already initialized, skipping setup");
return;
}
Serial.begin(115200);
Serial.println("[Spore] Starting Spore framework...");
// Initialize core components
initializeCore();
// Register core services
registerCoreServices();
initialized = true;
Serial.println("[Spore] Framework setup complete - call begin() to start API server");
}
void Spore::begin() {
if (!initialized) {
Serial.println("[Spore] Framework not initialized, call setup() first");
return;
}
if (apiServerStarted) {
Serial.println("[Spore] API server already started");
return;
}
Serial.println("[Spore] Starting API server...");
// Start API server
startApiServer();
// Print initial task status
taskManager.printTaskStatus();
Serial.println("[Spore] Framework ready!");
}
void Spore::loop() {
if (!initialized) {
Serial.println("[Spore] Framework not initialized, call setup() first");
return;
}
taskManager.execute();
yield();
}
void Spore::addService(std::shared_ptr<Service> service) {
if (!service) {
Serial.println("[Spore] Warning: Attempted to add null service");
return;
}
services.push_back(service);
if (apiServerStarted) {
// If API server is already started, register the service immediately
apiServer.addService(*service);
Serial.printf("[Spore] Added service '%s' to running API server\n", service->getName());
} else {
Serial.printf("[Spore] Registered service '%s' (will be added to API server when begin() is called)\n", service->getName());
}
}
void Spore::addService(Service* service) {
if (!service) {
Serial.println("[Spore] Warning: Attempted to add null service");
return;
}
// Wrap raw pointer in shared_ptr with no-op deleter to avoid double-delete
addService(std::shared_ptr<Service>(service, [](Service*){}));
}
void Spore::initializeCore() {
Serial.println("[Spore] Initializing core components...");
// Setup WiFi first
network.setupWiFi();
// Initialize task manager
taskManager.initialize();
Serial.println("[Spore] Core components initialized");
}
void Spore::registerCoreServices() {
Serial.println("[Spore] Registering core services...");
// Create core services
auto nodeService = std::make_shared<NodeService>(ctx, apiServer);
auto networkService = std::make_shared<NetworkService>(network);
auto clusterService = std::make_shared<ClusterService>(ctx);
auto taskService = std::make_shared<TaskService>(taskManager);
// Add to services list
services.push_back(nodeService);
services.push_back(networkService);
services.push_back(clusterService);
services.push_back(taskService);
Serial.println("[Spore] Core services registered");
}
void Spore::startApiServer() {
if (apiServerStarted) {
Serial.println("[Spore] API server already started");
return;
}
Serial.println("[Spore] Starting API server...");
// Register all services with API server
for (auto& service : services) {
if (service) {
apiServer.addService(*service);
Serial.printf("[Spore] Added service '%s' to API server\n", service->getName());
}
}
// Start the API server
apiServer.begin();
apiServerStarted = true;
Serial.println("[Spore] API server started");
}

View File

@@ -1,5 +1,5 @@
#include "ApiServer.h"
#include "services/Service.h"
#include "spore/core/ApiServer.h"
#include "spore/Service.h"
#include <algorithm>
const char* ApiServer::methodToStr(int method) {

View File

@@ -1,4 +1,5 @@
#include "ClusterManager.h"
#include "spore/core/ClusterManager.h"
#include "spore/internal/Globals.h"
ClusterManager::ClusterManager(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx), taskManager(taskMgr) {
// Register callback for node_discovered event

View File

@@ -1,4 +1,4 @@
#include "NetworkManager.h"
#include "spore/core/NetworkManager.h"
// SSID and password are now configured via Config class

View File

@@ -1,4 +1,4 @@
#include "NodeContext.h"
#include "spore/core/NodeContext.h"
NodeContext::NodeContext() {
udp = new WiFiUDP();

View File

@@ -1,4 +1,4 @@
#include "TaskManager.h"
#include "spore/core/TaskManager.h"
#include <Arduino.h>
TaskManager::TaskManager(NodeContext& ctx) : ctx(ctx) {}

View File

@@ -1,5 +1,5 @@
#include "services/ClusterService.h"
#include "ApiServer.h"
#include "spore/services/ClusterService.h"
#include "spore/core/ApiServer.h"
ClusterService::ClusterService(NodeContext& ctx) : ctx(ctx) {}

View File

@@ -1,4 +1,4 @@
#include "services/NetworkService.h"
#include "spore/services/NetworkService.h"
#include <ArduinoJson.h>
NetworkService::NetworkService(NetworkManager& networkManager)

View File

@@ -1,5 +1,5 @@
#include "services/NodeService.h"
#include "ApiServer.h"
#include "spore/services/NodeService.h"
#include "spore/core/ApiServer.h"
NodeService::NodeService(NodeContext& ctx, ApiServer& apiServer) : ctx(ctx), apiServer(apiServer) {}

View File

@@ -1,5 +1,5 @@
#include "services/TaskService.h"
#include "ApiServer.h"
#include "spore/services/TaskService.h"
#include "spore/core/ApiServer.h"
#include <algorithm>
TaskService::TaskService(TaskManager& taskManager) : taskManager(taskManager) {}

View File

@@ -1,4 +1,4 @@
#include "Config.h"
#include "spore/types/Config.h"
Config::Config() {
// WiFi Configuration

View File

@@ -1,4 +1,5 @@
#include "NodeInfo.h"
#include "spore/types/NodeInfo.h"
#include "spore/internal/Globals.h"
const char* statusToStr(NodeInfo::Status status) {
switch (status) {