- Restructure include/ and src/ directories with logical grouping - Move core components to spore/core/ (NodeContext, NetworkManager, TaskManager, ClusterManager, ApiServer) - Move services to spore/services/ (NodeService, NetworkService, ClusterService, TaskService) - Move types to spore/types/ (NodeInfo, ApiTypes, Config) - Move internal components to spore/internal/ (Globals) - Update all #include statements to use new namespace paths - Update platformio.ini build filters for all environments - Update all example files to use new include paths - Maintain backward compatibility for public API - Improve code organization, maintainability, and scalability This reorganization follows modern C++ project structure patterns and provides clear separation between public API, internal implementation, and utilities. All examples compile successfully with the new structure.
90 lines
2.5 KiB
C++
90 lines
2.5 KiB
C++
#include "RelayService.h"
|
|
#include "spore/core/ApiServer.h"
|
|
|
|
RelayService::RelayService(TaskManager& taskMgr, int pin)
|
|
: 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 RelayService::registerEndpoints(ApiServer& api) {
|
|
api.addEndpoint("/api/relay/status", HTTP_GET,
|
|
[this](AsyncWebServerRequest* request) { handleStatusRequest(request); },
|
|
std::vector<ParamSpec>{});
|
|
|
|
api.addEndpoint("/api/relay", HTTP_POST,
|
|
[this](AsyncWebServerRequest* request) { handleControlRequest(request); },
|
|
std::vector<ParamSpec>{
|
|
ParamSpec{String("state"), true, String("body"), String("string"),
|
|
{String("on"), String("off"), String("toggle")}}
|
|
});
|
|
}
|
|
|
|
void RelayService::handleStatusRequest(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);
|
|
}
|
|
|
|
void RelayService::handleControlRequest(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);
|
|
}
|
|
|
|
void RelayService::turnOn() {
|
|
relayOn = true;
|
|
// Active LOW relay
|
|
digitalWrite(relayPin, LOW);
|
|
Serial.println("[RelayService] Relay ON");
|
|
}
|
|
|
|
void RelayService::turnOff() {
|
|
relayOn = false;
|
|
digitalWrite(relayPin, HIGH);
|
|
Serial.println("[RelayService] Relay OFF");
|
|
}
|
|
|
|
void RelayService::toggle() {
|
|
if (relayOn) {
|
|
turnOff();
|
|
} else {
|
|
turnOn();
|
|
}
|
|
}
|
|
|
|
void RelayService::registerTasks() {
|
|
taskManager.registerTask("relay_status_print", 5000, [this]() {
|
|
Serial.printf("[RelayService] Status - pin: %d, state: %s\n",
|
|
relayPin, relayOn ? "ON" : "OFF");
|
|
});
|
|
}
|