From a085b3b8ee7288123e04c67e9e728c1b17abfb53 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Thu, 28 Aug 2025 09:18:11 +0200 Subject: [PATCH] feat: create examples and corresponding build config --- {src => examples/base}/main.cpp | 0 examples/relay/README.md | 83 ++++++++++++ examples/relay/main.cpp | 128 ++++++++++++++++++ .../{ => tasks}/task_management_example.cpp | 0 platformio.ini | 26 +++- 5 files changed, 236 insertions(+), 1 deletion(-) rename {src => examples/base}/main.cpp (100%) create mode 100644 examples/relay/README.md create mode 100644 examples/relay/main.cpp rename examples/{ => tasks}/task_management_example.cpp (100%) diff --git a/src/main.cpp b/examples/base/main.cpp similarity index 100% rename from src/main.cpp rename to examples/base/main.cpp diff --git a/examples/relay/README.md b/examples/relay/README.md new file mode 100644 index 0000000..16351ca --- /dev/null +++ b/examples/relay/README.md @@ -0,0 +1,83 @@ +# 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. + +- Default relay pin: `GPIO0` (ESP-01). Override with `-DRELAY_PIN=`. +- WiFi and API port are configured in `src/Config.cpp`. + +## Build & Upload + +- ESP‑01S: +```bash +pio run -e esp01_1m_relay -t upload +``` +- D1 Mini: +```bash +pio run -e d1_mini_relay -t upload +``` + +Monitor serial logs: +```bash +pio device monitor -b 115200 +``` + +Assume the device IP is 192.168.1.50 below (replace with your device's IP shown in serial output). + +## Relay API + +- Get relay status +```bash +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 +``` + +- Turn relay OFF +```bash +curl -X POST http://192.168.1.50/api/relay/set -d state=off +``` + +- Toggle relay +```bash +curl -X POST http://192.168.1.50/api/relay/set -d state=toggle +``` + +Notes: +- Requests use `application/x-www-form-urlencoded` by default when using `curl -d`. + +## Task Management (optional) +The example registers a periodic task `relay_status_print` that logs the current relay state. + +- Fetch all task statuses +```bash +curl http://192.168.1.50/api/tasks/status +``` + +- Query a specific task status +```bash +curl -X POST http://192.168.1.50/api/tasks/control \ + -d task=relay_status_print -d action=status +``` + +- Enable / Disable the task +```bash +curl -X POST http://192.168.1.50/api/tasks/control \ + -d task=relay_status_print -d action=enable + +curl -X POST http://192.168.1.50/api/tasks/control \ + -d task=relay_status_print -d action=disable +``` + +## General System Endpoints (optional) +- Node status +```bash +curl http://192.168.1.50/api/node/status +``` + +- Restart device +```bash +curl -X POST http://192.168.1.50/api/node/restart +``` \ No newline at end of file diff --git a/examples/relay/main.cpp b/examples/relay/main.cpp new file mode 100644 index 0000000..675477c --- /dev/null +++ b/examples/relay/main.cpp @@ -0,0 +1,128 @@ +#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); + }); + } + + 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 = nullptr; + +void setup() { + // Setup WiFi first + network.setupWiFi(); + + // Create RelayService (registers its tasks) + relayService = new RelayService(ctx, taskManager, RELAY_PIN); + + // 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(); +} diff --git a/examples/task_management_example.cpp b/examples/tasks/task_management_example.cpp similarity index 100% rename from examples/task_management_example.cpp rename to examples/tasks/task_management_example.cpp diff --git a/platformio.ini b/platformio.ini index 7b9a24f..aba648c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,6 +10,7 @@ [platformio] default_envs = esp01_1m +src_dir = . [common] monitor_speed = 115200 @@ -28,6 +29,10 @@ board_build.partitions = partitions_ota_1M.csv board_build.flash_mode = dout ; ESP‑01S uses DOUT on 1 Mbit flash board_build.flash_size = 1M lib_deps = ${common.lib_deps} +build_src_filter = + + + + + + [env:d1_mini] platform = platformio/espressif8266@^4.2.1 @@ -37,4 +42,23 @@ upload_speed = 115200 monitor_speed = 115200 board_build.flash_mode = dio ; D1 Mini uses DIO on 4 Mbit flash board_build.flash_size = 4M -lib_deps = ${common.lib_deps} \ No newline at end of file +lib_deps = ${common.lib_deps} +build_src_filter = + + + + + + + +[env:esp01_1m_relay] +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} +build_src_filter = + + + + + +