feat: add NeoPixel example
This commit is contained in:
363
examples/neopixel/main.cpp
Normal file
363
examples/neopixel/main.cpp
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "NodeContext.h"
|
||||||
|
#include "NetworkManager.h"
|
||||||
|
#include "ClusterManager.h"
|
||||||
|
#include "ApiServer.h"
|
||||||
|
#include "TaskManager.h"
|
||||||
|
|
||||||
|
#ifndef NEOPIXEL_PIN
|
||||||
|
#define NEOPIXEL_PIN 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NEOPIXEL_COUNT
|
||||||
|
#define NEOPIXEL_COUNT 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NEOPIXEL_TYPE
|
||||||
|
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Wheel helper: map 0-255 to RGB rainbow
|
||||||
|
static uint32_t colorWheel(Adafruit_NeoPixel &strip, uint8_t pos) {
|
||||||
|
pos = 255 - pos;
|
||||||
|
if (pos < 85) {
|
||||||
|
return strip.Color(255 - pos * 3, 0, pos * 3);
|
||||||
|
}
|
||||||
|
if (pos < 170) {
|
||||||
|
pos -= 85;
|
||||||
|
return strip.Color(0, pos * 3, 255 - pos * 3);
|
||||||
|
}
|
||||||
|
pos -= 170;
|
||||||
|
return strip.Color(pos * 3, 255 - pos * 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
class NeoPixelService {
|
||||||
|
public:
|
||||||
|
enum class Pattern {
|
||||||
|
Off,
|
||||||
|
ColorWipe,
|
||||||
|
Rainbow,
|
||||||
|
RainbowCycle,
|
||||||
|
TheaterChase,
|
||||||
|
TheaterChaseRainbow
|
||||||
|
};
|
||||||
|
|
||||||
|
NeoPixelService(NodeContext &ctx, TaskManager &taskMgr,
|
||||||
|
uint16_t numPixels,
|
||||||
|
uint8_t pin,
|
||||||
|
neoPixelType type)
|
||||||
|
: ctx(ctx), taskManager(taskMgr),
|
||||||
|
strip(numPixels, pin, type),
|
||||||
|
currentPattern(Pattern::Off),
|
||||||
|
updateIntervalMs(20),
|
||||||
|
lastUpdateMs(0),
|
||||||
|
wipeIndex(0),
|
||||||
|
wipeColor(strip.Color(255, 0, 0)),
|
||||||
|
rainbowJ(0),
|
||||||
|
cycleJ(0),
|
||||||
|
chaseJ(0),
|
||||||
|
chaseQ(0),
|
||||||
|
chasePhaseOn(true),
|
||||||
|
chaseColor(strip.Color(127, 127, 127)),
|
||||||
|
brightness(50) {
|
||||||
|
strip.begin();
|
||||||
|
strip.setBrightness(brightness);
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
registerPatterns();
|
||||||
|
registerTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerApi(ApiServer &api) {
|
||||||
|
api.addEndpoint("/api/neopixel/status", HTTP_GET, [this](AsyncWebServerRequest *request) {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["pin"] = NEOPIXEL_PIN;
|
||||||
|
doc["count"] = strip.numPixels();
|
||||||
|
doc["interval_ms"] = updateIntervalMs;
|
||||||
|
doc["brightness"] = brightness;
|
||||||
|
doc["pattern"] = currentPatternName();
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
request->send(200, "application/json", json);
|
||||||
|
});
|
||||||
|
|
||||||
|
api.addEndpoint("/api/neopixel/patterns", HTTP_GET, [this](AsyncWebServerRequest *request) {
|
||||||
|
JsonDocument doc;
|
||||||
|
JsonArray arr = doc.to<JsonArray>();
|
||||||
|
for (auto &kv : patternUpdaters) arr.add(kv.first);
|
||||||
|
String json;
|
||||||
|
serializeJson(doc, json);
|
||||||
|
request->send(200, "application/json", json);
|
||||||
|
});
|
||||||
|
|
||||||
|
api.addEndpoint("/api/neopixel", HTTP_POST,
|
||||||
|
[this](AsyncWebServerRequest *request) {
|
||||||
|
String pattern = request->hasParam("pattern", true) ? request->getParam("pattern", true)->value() : "";
|
||||||
|
if (pattern.length()) {
|
||||||
|
setPatternByName(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("interval_ms", true)) {
|
||||||
|
updateIntervalMs = request->getParam("interval_ms", true)->value().toInt();
|
||||||
|
if (updateIntervalMs < 1) updateIntervalMs = 1;
|
||||||
|
taskManager.setTaskInterval("neopixel_update", updateIntervalMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("brightness", true)) {
|
||||||
|
int b = request->getParam("brightness", true)->value().toInt();
|
||||||
|
if (b < 0) b = 0; if (b > 255) b = 255;
|
||||||
|
setBrightness((uint8_t)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional RGB for color_wipe and theater_chase
|
||||||
|
if (request->hasParam("r", true) || request->hasParam("g", true) || request->hasParam("b", true)) {
|
||||||
|
int r = request->hasParam("r", true) ? request->getParam("r", true)->value().toInt() : 0;
|
||||||
|
int g = request->hasParam("g", true) ? request->getParam("g", true)->value().toInt() : 0;
|
||||||
|
int b = request->hasParam("b", true) ? request->getParam("b", true)->value().toInt() : 0;
|
||||||
|
wipeColor = strip.Color(r, g, b);
|
||||||
|
chaseColor = strip.Color(r / 2, g / 2, b / 2); // dimmer for chase
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonDocument resp;
|
||||||
|
resp["ok"] = true;
|
||||||
|
resp["pattern"] = currentPatternName();
|
||||||
|
resp["interval_ms"] = updateIntervalMs;
|
||||||
|
resp["brightness"] = brightness;
|
||||||
|
String json;
|
||||||
|
serializeJson(resp, json);
|
||||||
|
request->send(200, "application/json", json);
|
||||||
|
},
|
||||||
|
std::vector<ApiServer::ParamSpec>{
|
||||||
|
ApiServer::ParamSpec{ String("pattern"), false, String("body"), String("string"), patternNamesVector() },
|
||||||
|
ApiServer::ParamSpec{ String("interval_ms"), false, String("body"), String("number"), {} },
|
||||||
|
ApiServer::ParamSpec{ String("brightness"), false, String("body"), String("number"), {} },
|
||||||
|
ApiServer::ParamSpec{ String("r"), false, String("body"), String("number"), {} },
|
||||||
|
ApiServer::ParamSpec{ String("g"), false, String("body"), String("number"), {} },
|
||||||
|
ApiServer::ParamSpec{ String("b"), false, String("body"), String("number"), {} },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPatternByName(const String &name) {
|
||||||
|
auto it = patternUpdaters.find(name);
|
||||||
|
if (it != patternUpdaters.end()) {
|
||||||
|
// Map name to enum for status and reset state
|
||||||
|
currentPattern = nameToPattern(name);
|
||||||
|
resetStateForPattern(currentPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBrightness(uint8_t b) {
|
||||||
|
brightness = b;
|
||||||
|
strip.setBrightness(brightness);
|
||||||
|
strip.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void registerTasks() {
|
||||||
|
taskManager.registerTask("neopixel_update", updateIntervalMs, [this]() { update(); });
|
||||||
|
taskManager.registerTask("neopixel_status_print", 10000, [this]() {
|
||||||
|
Serial.printf("[NeoPixel] pattern=%s interval=%lu ms brightness=%u\n",
|
||||||
|
currentPatternName().c_str(), updateIntervalMs, brightness);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerPatterns() {
|
||||||
|
patternUpdaters["off"] = [this]() { updateOff(); };
|
||||||
|
patternUpdaters["color_wipe"] = [this]() { updateColorWipe(); };
|
||||||
|
patternUpdaters["rainbow"] = [this]() { updateRainbow(); };
|
||||||
|
patternUpdaters["rainbow_cycle"] = [this]() { updateRainbowCycle(); };
|
||||||
|
patternUpdaters["theater_chase"] = [this]() { updateTheaterChase(); };
|
||||||
|
patternUpdaters["theater_chase_rainbow"] = [this]() { updateTheaterChaseRainbow(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<String> patternNamesVector() const {
|
||||||
|
std::vector<String> v;
|
||||||
|
v.reserve(patternUpdaters.size());
|
||||||
|
for (const auto &kv : patternUpdaters) v.push_back(kv.first);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
String currentPatternName() const {
|
||||||
|
switch (currentPattern) {
|
||||||
|
case Pattern::Off: return String("off");
|
||||||
|
case Pattern::ColorWipe: return String("color_wipe");
|
||||||
|
case Pattern::Rainbow: return String("rainbow");
|
||||||
|
case Pattern::RainbowCycle: return String("rainbow_cycle");
|
||||||
|
case Pattern::TheaterChase: return String("theater_chase");
|
||||||
|
case Pattern::TheaterChaseRainbow: return String("theater_chase_rainbow");
|
||||||
|
}
|
||||||
|
return String("off");
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern nameToPattern(const String &name) const {
|
||||||
|
if (name.equalsIgnoreCase("color_wipe")) return Pattern::ColorWipe;
|
||||||
|
if (name.equalsIgnoreCase("rainbow")) return Pattern::Rainbow;
|
||||||
|
if (name.equalsIgnoreCase("rainbow_cycle")) return Pattern::RainbowCycle;
|
||||||
|
if (name.equalsIgnoreCase("theater_chase")) return Pattern::TheaterChase;
|
||||||
|
if (name.equalsIgnoreCase("theater_chase_rainbow")) return Pattern::TheaterChaseRainbow;
|
||||||
|
return Pattern::Off;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetStateForPattern(Pattern p) {
|
||||||
|
// Clear strip by default when changing pattern
|
||||||
|
strip.clear();
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
// Reset indexes/state variables
|
||||||
|
wipeIndex = 0;
|
||||||
|
rainbowJ = 0;
|
||||||
|
cycleJ = 0;
|
||||||
|
chaseJ = 0;
|
||||||
|
chaseQ = 0;
|
||||||
|
chasePhaseOn = true;
|
||||||
|
lastUpdateMs = 0; // force immediate update on next tick
|
||||||
|
|
||||||
|
currentPattern = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
if (now - lastUpdateMs < updateIntervalMs) return;
|
||||||
|
lastUpdateMs = now;
|
||||||
|
|
||||||
|
const String name = currentPatternName();
|
||||||
|
auto it = patternUpdaters.find(name);
|
||||||
|
if (it != patternUpdaters.end()) {
|
||||||
|
it->second();
|
||||||
|
} else {
|
||||||
|
updateOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern updaters (non-blocking; advance a small step each call)
|
||||||
|
void updateOff() {
|
||||||
|
// Ensure off state
|
||||||
|
strip.clear();
|
||||||
|
strip.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateColorWipe() {
|
||||||
|
if (wipeIndex < strip.numPixels()) {
|
||||||
|
strip.setPixelColor(wipeIndex, wipeColor);
|
||||||
|
++wipeIndex;
|
||||||
|
strip.show();
|
||||||
|
} else {
|
||||||
|
// Restart
|
||||||
|
strip.clear();
|
||||||
|
wipeIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRainbow() {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i++) {
|
||||||
|
strip.setPixelColor(i, colorWheel(strip, (i + rainbowJ) & 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
rainbowJ = (rainbowJ + 1) & 0xFF; // 0..255
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRainbowCycle() {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i++) {
|
||||||
|
uint8_t pos = ((i * 256 / strip.numPixels()) + cycleJ) & 0xFF;
|
||||||
|
strip.setPixelColor(i, colorWheel(strip, pos));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
cycleJ = (cycleJ + 1) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTheaterChase() {
|
||||||
|
// Phase toggles on/off for the current q offset
|
||||||
|
if (chasePhaseOn) {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i += 3) {
|
||||||
|
uint16_t idx = i + chaseQ;
|
||||||
|
if (idx < strip.numPixels()) strip.setPixelColor(idx, chaseColor);
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
chasePhaseOn = false;
|
||||||
|
} else {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i += 3) {
|
||||||
|
uint16_t idx = i + chaseQ;
|
||||||
|
if (idx < strip.numPixels()) strip.setPixelColor(idx, 0);
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
chasePhaseOn = true;
|
||||||
|
chaseQ = (chaseQ + 1) % 3; // move the crawl
|
||||||
|
chaseJ = (chaseJ + 1) % 10; // cycle count kept for status if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTheaterChaseRainbow() {
|
||||||
|
if (chasePhaseOn) {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i += 3) {
|
||||||
|
uint16_t idx = i + chaseQ;
|
||||||
|
if (idx < strip.numPixels()) strip.setPixelColor(idx, colorWheel(strip, (idx + chaseJ) % 255));
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
chasePhaseOn = false;
|
||||||
|
} else {
|
||||||
|
for (uint16_t i = 0; i < strip.numPixels(); i += 3) {
|
||||||
|
uint16_t idx = i + chaseQ;
|
||||||
|
if (idx < strip.numPixels()) strip.setPixelColor(idx, 0);
|
||||||
|
}
|
||||||
|
strip.show();
|
||||||
|
chasePhaseOn = true;
|
||||||
|
chaseQ = (chaseQ + 1) % 3;
|
||||||
|
chaseJ = (chaseJ + 1) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeContext &ctx;
|
||||||
|
TaskManager &taskManager;
|
||||||
|
Adafruit_NeoPixel strip;
|
||||||
|
|
||||||
|
std::map<String, std::function<void()>> patternUpdaters;
|
||||||
|
|
||||||
|
Pattern currentPattern;
|
||||||
|
unsigned long updateIntervalMs;
|
||||||
|
unsigned long lastUpdateMs;
|
||||||
|
|
||||||
|
// State for patterns
|
||||||
|
uint16_t wipeIndex;
|
||||||
|
uint32_t wipeColor;
|
||||||
|
|
||||||
|
uint8_t rainbowJ;
|
||||||
|
uint8_t cycleJ;
|
||||||
|
|
||||||
|
int chaseJ;
|
||||||
|
int chaseQ;
|
||||||
|
bool chasePhaseOn;
|
||||||
|
uint32_t chaseColor;
|
||||||
|
|
||||||
|
uint8_t brightness;
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeContext ctx;
|
||||||
|
NetworkManager network(ctx);
|
||||||
|
TaskManager taskManager(ctx);
|
||||||
|
ClusterManager cluster(ctx, taskManager);
|
||||||
|
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
|
||||||
|
NeoPixelService neoService(ctx, taskManager, NEOPIXEL_COUNT, NEOPIXEL_PIN, NEOPIXEL_TYPE);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
network.setupWiFi();
|
||||||
|
|
||||||
|
taskManager.initialize();
|
||||||
|
|
||||||
|
apiServer.begin();
|
||||||
|
neoService.registerApi(apiServer);
|
||||||
|
|
||||||
|
taskManager.printTaskStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
taskManager.execute();
|
||||||
|
yield();
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
request->send(200, "application/json", json);
|
request->send(200, "application/json", json);
|
||||||
});
|
});
|
||||||
|
|
||||||
api.addEndpoint("/api/relay/set", HTTP_POST, [this](AsyncWebServerRequest* request) {
|
api.addEndpoint("/api/relay", HTTP_POST, [this](AsyncWebServerRequest* request) {
|
||||||
String state = request->hasParam("state", true) ? request->getParam("state", true)->value() : "";
|
String state = request->hasParam("state", true) ? request->getParam("state", true)->value() : "";
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (state.equalsIgnoreCase("on")) {
|
if (state.equalsIgnoreCase("on")) {
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
/*
|
|
||||||
* Task Management Example with std::bind and Class-Based Registration
|
|
||||||
*
|
|
||||||
* This example demonstrates how to use the TaskManager with std::bind
|
|
||||||
* and how classes can register their own tasks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <functional>
|
|
||||||
#include "TaskManager.h"
|
|
||||||
#include "NodeContext.h"
|
|
||||||
|
|
||||||
// Example service class that registers its own tasks
|
|
||||||
class SensorService {
|
|
||||||
public:
|
|
||||||
SensorService(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx), taskManager(taskMgr) {
|
|
||||||
// Register all sensor-related tasks in constructor
|
|
||||||
registerTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void readTemperature() {
|
|
||||||
Serial.println("[SensorService] Reading temperature");
|
|
||||||
// Simulate temperature reading
|
|
||||||
temperature = random(20, 30);
|
|
||||||
Serial.printf("[SensorService] Temperature: %d°C\n", temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void readHumidity() {
|
|
||||||
Serial.println("[SensorService] Reading humidity");
|
|
||||||
// Simulate humidity reading
|
|
||||||
humidity = random(40, 80);
|
|
||||||
Serial.printf("[SensorService] Humidity: %d%%\n", humidity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void calibrateSensors() {
|
|
||||||
Serial.println("[SensorService] Calibrating sensors");
|
|
||||||
// Simulate calibration
|
|
||||||
calibrationOffset = random(-2, 3);
|
|
||||||
Serial.printf("[SensorService] Calibration offset: %d\n", calibrationOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printStatus() {
|
|
||||||
Serial.printf("[SensorService] Status - Temp: %d°C, Humidity: %d%%, Offset: %d\n",
|
|
||||||
temperature, humidity, calibrationOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void registerTasks() {
|
|
||||||
// Register all sensor tasks using std::bind
|
|
||||||
taskManager.registerTask("temp_read", 2000,
|
|
||||||
std::bind(&SensorService::readTemperature, this));
|
|
||||||
taskManager.registerTask("humidity_read", 3000,
|
|
||||||
std::bind(&SensorService::readHumidity, this));
|
|
||||||
taskManager.registerTask("calibrate", 10000,
|
|
||||||
std::bind(&SensorService::calibrateSensors, this));
|
|
||||||
taskManager.registerTask("status_print", 5000,
|
|
||||||
std::bind(&SensorService::printStatus, this));
|
|
||||||
|
|
||||||
Serial.println("[SensorService] Registered all sensor tasks");
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeContext& ctx;
|
|
||||||
TaskManager& taskManager;
|
|
||||||
int temperature = 25;
|
|
||||||
int humidity = 60;
|
|
||||||
int calibrationOffset = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Example network service class
|
|
||||||
class NetworkService {
|
|
||||||
public:
|
|
||||||
NetworkService(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx), taskManager(taskMgr) {
|
|
||||||
registerTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkConnection() {
|
|
||||||
Serial.println("[NetworkService] Checking WiFi connection");
|
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
|
||||||
Serial.printf("[NetworkService] Connected to %s\n", WiFi.SSID().c_str());
|
|
||||||
} else {
|
|
||||||
Serial.println("[NetworkService] WiFi disconnected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendHeartbeat() {
|
|
||||||
Serial.println("[NetworkService] Sending heartbeat");
|
|
||||||
// Simulate heartbeat
|
|
||||||
heartbeatCount++;
|
|
||||||
Serial.printf("[NetworkService] Heartbeat #%d sent\n", heartbeatCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void registerTasks() {
|
|
||||||
taskManager.registerTask("connection_check", 5000,
|
|
||||||
std::bind(&NetworkService::checkConnection, this));
|
|
||||||
taskManager.registerTask("heartbeat", 8000,
|
|
||||||
std::bind(&NetworkService::sendHeartbeat, this));
|
|
||||||
|
|
||||||
Serial.println("[NetworkService] Registered all network tasks");
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeContext& ctx;
|
|
||||||
TaskManager& taskManager;
|
|
||||||
int heartbeatCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Example custom task functions (legacy style - still supported)
|
|
||||||
void customTask1() {
|
|
||||||
Serial.println("[CustomTask1] Executing custom task 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
void customTask2() {
|
|
||||||
Serial.println("[CustomTask2] Executing custom task 2");
|
|
||||||
}
|
|
||||||
|
|
||||||
void periodicMaintenance() {
|
|
||||||
Serial.println("[Maintenance] Running periodic maintenance");
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200);
|
|
||||||
Serial.println("Task Management Example with Class-Based Registration");
|
|
||||||
|
|
||||||
// Create context and task manager
|
|
||||||
NodeContext ctx;
|
|
||||||
TaskManager taskManager(ctx);
|
|
||||||
|
|
||||||
// Create service instances - they will register their own tasks
|
|
||||||
SensorService sensors(ctx, taskManager);
|
|
||||||
NetworkService network(ctx, taskManager);
|
|
||||||
|
|
||||||
// Register additional custom tasks (legacy style)
|
|
||||||
taskManager.registerTask("custom_task_1", 12000, customTask1);
|
|
||||||
taskManager.registerTask("custom_task_2", 15000, customTask2);
|
|
||||||
taskManager.registerTask("maintenance", 30000, periodicMaintenance);
|
|
||||||
|
|
||||||
// Register a lambda function directly
|
|
||||||
taskManager.registerTask("lambda_function", 6000, []() {
|
|
||||||
Serial.println("[Lambda] Lambda function called");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize and start all tasks
|
|
||||||
taskManager.initialize();
|
|
||||||
|
|
||||||
// Print initial task status
|
|
||||||
taskManager.printTaskStatus();
|
|
||||||
|
|
||||||
Serial.println("\n=== Task Registration Examples ===");
|
|
||||||
Serial.println("1. SensorService: Registers its own tasks in constructor");
|
|
||||||
Serial.println("2. NetworkService: Registers its own tasks in constructor");
|
|
||||||
Serial.println("3. Custom tasks: Legacy function registration");
|
|
||||||
Serial.println("4. Lambda function: Direct lambda registration");
|
|
||||||
Serial.println("=====================================\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// The TaskManager handles all task execution
|
|
||||||
// No need to call individual task functions
|
|
||||||
yield();
|
|
||||||
}
|
|
||||||
@@ -61,3 +61,34 @@ build_src_filter =
|
|||||||
+<examples/relay/*.cpp>
|
+<examples/relay/*.cpp>
|
||||||
+<src/*.c>
|
+<src/*.c>
|
||||||
+<src/*.cpp>
|
+<src/*.cpp>
|
||||||
|
|
||||||
|
[env:esp01_1m_neopixel]
|
||||||
|
platform = platformio/espressif8266@^4.2.1
|
||||||
|
board = esp01_1m
|
||||||
|
framework = arduino
|
||||||
|
upload_speed = 115200
|
||||||
|
monitor_speed = 115200
|
||||||
|
board_build.partitions = partitions_ota_1M.csv
|
||||||
|
board_build.flash_mode = dout
|
||||||
|
board_build.flash_size = 1M
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.1
|
||||||
|
build_src_filter =
|
||||||
|
+<examples/neopixel/*.cpp>
|
||||||
|
+<src/*.c>
|
||||||
|
+<src/*.cpp>
|
||||||
|
|
||||||
|
[env:d1_mini_neopixel]
|
||||||
|
platform = platformio/espressif8266@^4.2.1
|
||||||
|
board = d1_mini
|
||||||
|
framework = arduino
|
||||||
|
upload_speed = 115200
|
||||||
|
monitor_speed = 115200
|
||||||
|
board_build.flash_mode = dio
|
||||||
|
board_build.flash_size = 4M
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.1
|
||||||
|
build_src_filter =
|
||||||
|
+<examples/neopixel/*.cpp>
|
||||||
|
+<src/*.c>
|
||||||
|
+<src/*.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user