#include #include #include "Globals.h" #include "NodeContext.h" #include "NetworkManager.h" #include "ClusterManager.h" #include "ApiServer.h" #include "TaskManager.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 class RelayService { public: RelayService(NodeContext& ctx, TaskManager& taskMgr, int pin) : ctx(ctx), taskManager(taskMgr), relayPin(pin), relayOn(false) { pinMode(relayPin, OUTPUT); // Many relay modules are active LOW. Start in OFF state (relay de-energized). digitalWrite(relayPin, HIGH); registerTasks(); } void registerApi(ApiServer& api) { api.addEndpoint("/api/relay/status", HTTP_GET, [this](AsyncWebServerRequest* request) { JsonDocument doc; doc["pin"] = relayPin; doc["state"] = relayOn ? "on" : "off"; doc["uptime"] = millis(); String json; serializeJson(doc, json); request->send(200, "application/json", json); }); api.addEndpoint("/api/relay/set", HTTP_POST, [this](AsyncWebServerRequest* request) { String state = request->hasParam("state", true) ? request->getParam("state", true)->value() : ""; bool ok = false; if (state.equalsIgnoreCase("on")) { turnOn(); ok = true; } else if (state.equalsIgnoreCase("off")) { turnOff(); ok = true; } else if (state.equalsIgnoreCase("toggle")) { toggle(); ok = true; } JsonDocument resp; resp["success"] = ok; resp["state"] = relayOn ? "on" : "off"; if (!ok) { resp["message"] = "Invalid state. Use: on, off, or toggle"; } String json; serializeJson(resp, json); request->send(ok ? 200 : 400, "application/json", json); }, std::vector{ ApiServer::ParamSpec{ String("state"), true, String("body"), String("string") } }); } void turnOn() { relayOn = true; // Active LOW relay digitalWrite(relayPin, LOW); Serial.println("[RelayService] Relay ON"); } void turnOff() { relayOn = false; digitalWrite(relayPin, HIGH); Serial.println("[RelayService] Relay OFF"); } void toggle() { if (relayOn) { turnOff(); } else { turnOn(); } } private: void registerTasks() { taskManager.registerTask("relay_status_print", 5000, [this]() { Serial.printf("[RelayService] Status - pin: %d, state: %s\n", relayPin, relayOn ? "ON" : "OFF"); }); } NodeContext& ctx; TaskManager& taskManager; int relayPin; bool relayOn; }; NodeContext ctx; NetworkManager network(ctx); TaskManager taskManager(ctx); ClusterManager cluster(ctx, taskManager); ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port); RelayService relayService(ctx, taskManager, RELAY_PIN); void setup() { // Setup WiFi first network.setupWiFi(); // Initialize and start all tasks taskManager.initialize(); // Start the API server and expose relay endpoints apiServer.begin(); relayService.registerApi(apiServer); // Print initial task status taskManager.printTaskStatus(); } void loop() { taskManager.execute(); yield(); }