diff --git a/include/config.h b/include/config.h index 2a612a2..e2e2e65 100644 --- a/include/config.h +++ b/include/config.h @@ -1,5 +1,6 @@ #pragma once #include +#include inline constexpr uint8_t ledPinR = 16; inline constexpr uint8_t ledPinG = 17; @@ -7,5 +8,8 @@ inline constexpr uint8_t ledPinB = 18; inline constexpr uint8_t ledPinCW = 19; inline constexpr uint8_t ledPinWW = 21; +inline constexpr std::string_view hostName = "smart-rgb-dev"; +inline constexpr std::string_view friendlyName = "Smart RGB Dev"; +inline constexpr uint32_t maxNumberOfStates = 10; -inline constexpr uint32_t maxNumberOfStates = 10; \ No newline at end of file +inline constexpr std::string_view mqttBroker = "10.238.75.81"; \ No newline at end of file diff --git a/lib/network/network.cpp b/lib/network/network.cpp index a32d5be..1daab44 100644 --- a/lib/network/network.cpp +++ b/lib/network/network.cpp @@ -5,14 +5,14 @@ WIFIMANAGER Network::WifiManager; AsyncWebServer Network::webServer(80); -Network::Network(std::string hostname, std::string apSsid) : hostname(hostname), apSsid(apSsid) { +Network::Network(std::string_view hostname, std::string_view apSsid) : hostname(hostname), apSsid(apSsid) { setHostname(hostname); - WifiManager.startBackgroundTask(apSsid.c_str(), ""); + WifiManager.startBackgroundTask(apSsid.data(), ""); WifiManager.fallbackToSoftAp(true); WifiManager.attachWebServer(&webServer); WifiManager.attachUI(); webServer.on("/", HTTP_GET, [this](AsyncWebServerRequest *request) { - request->send(200, "text/html", this->defaultHomepage.c_str()); + request->send(200, "text/html", this->defaultHomepage.data()); }); webServer.begin(); } @@ -25,14 +25,14 @@ std::string Network::getHostname() const { return WiFi.getHostname(); } -bool Network::setHostname(const std::string &hostname) { - return WiFi.setHostname(hostname.c_str()); +bool Network::setHostname(const std::string_view &hostname) { + return WiFi.setHostname(hostname.data()); } void Network::registerMDNS() { - if (!MDNS.begin(hostname.c_str())) { + if (!MDNS.begin(hostname.data())) { Serial.println("Error setting up MDNS responder!"); } else { - Serial.printf("mDNS responder started with hostname: %s\n", hostname.c_str()); + Serial.printf("mDNS responder started with hostname: %s\n", hostname.data()); } } \ No newline at end of file diff --git a/lib/network/network.h b/lib/network/network.h index cf226e9..d8cc002 100644 --- a/lib/network/network.h +++ b/lib/network/network.h @@ -1,12 +1,13 @@ #include +#include #include "wifimanager.h" class Network { public: - Network(std::string hostname, std::string apSsid = "Smart RGB"); + Network(std::string_view hostname, std::string_view apSsid = "Smart RGB"); bool isConnected() const; std::string getHostname() const; - bool setHostname(const std::string &hostname); + bool setHostname(const std::string_view &hostname); void registerMDNS(); private: static WIFIMANAGER WifiManager; @@ -25,6 +26,6 @@ private:

ESP32 WiFi Manager (c) 2022-2025 by Martin Verges

)html"; - std::string hostname; - std::string apSsid; // SSID for the fallback AP + std::string_view hostname; + std::string_view apSsid; // SSID for the fallback AP }; \ No newline at end of file diff --git a/lib/ota/ota.cpp b/lib/ota/ota.cpp index ad2b093..4f73ac3 100644 --- a/lib/ota/ota.cpp +++ b/lib/ota/ota.cpp @@ -1,8 +1,8 @@ #include #include "ota.h" -OTAHandler::OTAHandler(std::string hostname) { - ArduinoOTA.setHostname(hostname.c_str()); +OTAHandler::OTAHandler(std::string_view hostname) { + ArduinoOTA.setHostname(hostname.data()); ArduinoOTA.onStart([]() { Serial.println("OTA Start"); }); diff --git a/lib/ota/ota.h b/lib/ota/ota.h index 9ba41e2..5e8bc9b 100644 --- a/lib/ota/ota.h +++ b/lib/ota/ota.h @@ -1,9 +1,9 @@ #pragma once -#include +#include class OTAHandler { public: - OTAHandler(std::string hostname); + OTAHandler(std::string_view hostname); void poll(); }; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 889e17b..5149aaa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,4 +28,4 @@ lib_deps = [env:esp32dev-ota] upload_protocol = espota -upload_port = smart-rgb.local +upload_port = smart-rgb-dev.local diff --git a/src/appcontext.hpp b/src/appcontext.hpp index 00fde83..16f3945 100644 --- a/src/appcontext.hpp +++ b/src/appcontext.hpp @@ -19,6 +19,6 @@ struct AppContext { Network *network = nullptr; Light *light = nullptr; Mqtt *mqtt = nullptr; - OTAHandler *ota = nullptr; + OTAHandler *otaHandler = nullptr; Scheduler *scheduler = nullptr; }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 39deec4..df83bc0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,15 +11,16 @@ #include "TaskScheduler.h" #include "wifimanager.h" -Network* network = nullptr; -OTAHandler* otaHandler = nullptr; -Mqtt* mqttClient = nullptr; -Light *light = nullptr; +// Network* network = nullptr; +// OTAHandler* otaHandler = nullptr; +// Mqtt* mqttClient = nullptr; +// Light *light = nullptr; -Task *updateTask = nullptr; -Task *mqttTickTask = nullptr; -Task *mqttCheckConnectionTask = nullptr; +// Task *updateTask = nullptr; +// Task *mqttTickTask = nullptr; +// Task *mqttCheckConnectionTask = nullptr; +Task *appStateMachineUpdateTask = nullptr; Pin *pinR = new Pin(ledPinR, true, true, 5000, 0); Pin *pinG = new Pin(ledPinG, true, true, 5000, 1); @@ -29,6 +30,9 @@ Pin *pinWW = new Pin(ledPinWW, true, true, 5000, 4); AppContext *appContext = new AppContext(); StartState *startState = new StartState(appContext); +NetworkInitializeState *networkInitializeState = new NetworkInitializeState(appContext); +RunningState *runningState = new RunningState(appContext); + StateMachine *stateMachine = nullptr; @@ -38,8 +42,9 @@ void initializeScheduler(); void setup() { // put your setup code here, to run once: - // Serial.begin(115200); - // Serial.println("Starting Smart RGB ESP32..."); + Serial.begin(115200); + Serial.println("Starting Smart RGB ESP32..."); + initializeScheduler(); stateMachine = new StateMachine(); appContext->pinR = pinR; appContext->pinG = pinG; @@ -47,14 +52,15 @@ void setup() { appContext->pinCW = pinCW; appContext->pinWW = pinWW; stateMachine->addStateRaw(startState); + stateMachine->addStateRaw(networkInitializeState); + stateMachine->addTransition(StateId::StartState, EventId::PinInitialized, StateId::NetworkInitializeState); + stateMachine->addStateRaw(runningState); + stateMachine->addTransition(StateId::NetworkInitializeState, EventId::WifiConnected, StateId::RunningState); stateMachine->setInitialState(StateId::StartState); - network = new Network("smart-rgb"); - otaHandler = new OTAHandler("smart-rgb-ota"); - network->registerMDNS(); - Mqtt::connect("10.238.75.81", 1883, "smart_rgb_client", "mqtt", "mqtt"); - delay(1000); // Wait for MQTT connection to stabilize - light = new Light(pinR, pinG, pinB, pinCW, pinWW, mqttClient, "smart_rgb_light"); - initializeScheduler(); + + // Mqtt::connect("10.238.75.81", 1883, "smart_rgb_client", "mqtt", "mqtt"); + // delay(1000); // Wait for MQTT connection to stabilize + // light = new Light(pinR, pinG, pinB, pinCW, pinWW, mqttClient, "smart_rgb_light"); } void loop() { @@ -64,14 +70,15 @@ void loop() { void initializeScheduler() { scheduler = new Scheduler(); - updateTask = new Task(TASK_SECOND, TASK_FOREVER, []() { - otaHandler->poll(); // Poll for OTA updates - - }, scheduler, true, nullptr, nullptr); - mqttTickTask = new Task(TASK_MILLISECOND * 100, TASK_FOREVER, []() { - Mqtt::poll(); // Poll MQTT client for messages - }, scheduler, true, nullptr, nullptr); - mqttCheckConnectionTask = new Task(TASK_SECOND * 30, TASK_FOREVER, []() { - Mqtt::checkConnection(); // Check MQTT connection status + appStateMachineUpdateTask = new Task(TASK_MILLISECOND, TASK_FOREVER, []() { + if (stateMachine) { + stateMachine->update(); + } }, scheduler, true, nullptr, nullptr); + // mqttTickTask = new Task(TASK_MILLISECOND * 100, TASK_FOREVER, []() { + // Mqtt::poll(); // Poll MQTT client for messages + // }, scheduler, true, nullptr, nullptr); + // mqttCheckConnectionTask = new Task(TASK_SECOND * 30, TASK_FOREVER, []() { + // Mqtt::checkConnection(); // Check MQTT connection status + // }, scheduler, true, nullptr, nullptr); } \ No newline at end of file diff --git a/src/states.hpp b/src/states.hpp index 94be70b..830a0da 100644 --- a/src/states.hpp +++ b/src/states.hpp @@ -1,11 +1,21 @@ +#include #include "appcontext.hpp" +#include "config.h" +#include "mqtt.h" #include "pin.h" #include "statemachine.hpp" enum class StateId { StartState, - NetworkInitializeState + NetworkInitializeState, + RunningState +}; + +enum class EventId +{ + PinInitialized, + WifiConnected }; class StartState : public State @@ -21,6 +31,7 @@ public: appContext->pinCW->setLedLevel(0); appContext->pinWW->setLedLevel(0); } + stateMachine.postEvent(EventId::PinInitialized); } void onExit(StateMachineBase &stateMachine) override { @@ -36,14 +47,68 @@ private: class NetworkInitializeState : public State { public: - NetworkInitializeState() : State("NetworkInitializeState", StateId::NetworkInitializeState) {} + NetworkInitializeState(AppContext *appContext) : State("NetworkInitializeState", StateId::NetworkInitializeState), appContext(appContext) {} void onEnter(StateMachineBase &stateMachine) override { + if (appContext) { + appContext->network = new Network(hostName, friendlyName); + } + } + + void onExit(StateMachineBase &stateMachine) override { + if (appContext && appContext->network) { + appContext->network->registerMDNS(); + appContext->otaHandler = new OTAHandler(hostName); + } + Mqtt::connect(mqttBroker.data(), 1883, "smart_rgb_dev", "mqtt", "mqtt"); + } + + void onUpdate(StateMachineBase &stateMachine) override { + if (appContext && appContext->network && appContext->network->isConnected()) { + stateMachine.postEvent(EventId::WifiConnected); + } + } + +private: + AppContext *appContext = nullptr; +}; + +class RunningState : public State +{ +public: + RunningState(AppContext *appContext) : State("RunningState", StateId::RunningState), appContext(appContext) {} + void onEnter(StateMachineBase &stateMachine) override { + lastOtaPollMs = millis(); + lastMqttPollMs = millis(); + lastMqttCheckConnectionPollSecond = millis() / 1000; } void onExit(StateMachineBase &stateMachine) override { } void onUpdate(StateMachineBase &stateMachine) override { + if ((millis() - lastOtaPollMs) >= otaPollInterval) { + lastOtaPollMs = millis(); + if (appContext && appContext->otaHandler) { + appContext->otaHandler->poll(); + } + } + if ((millis() - lastMqttPollMs) >= mqttPollInterval) { + lastMqttPollMs = millis(); + Mqtt::poll(); + } + if ((millis() - lastMqttCheckConnectionPollSecond) >= mqttCheckConnectionPollIntervalSecond * 1000) { + lastMqttCheckConnectionPollSecond = millis() / 1000; + Mqtt::checkConnection(); + } } + +private: + AppContext *appContext = nullptr; + uint32_t lastOtaPollMs = 0; + static constexpr uint32_t otaPollInterval = 1000; // Poll every second + uint32_t lastMqttPollMs = 0; + static constexpr uint32_t mqttPollInterval = 100; // Poll every 100 milliseconds + uint32_t lastMqttCheckConnectionPollSecond = 0; + static constexpr uint32_t mqttCheckConnectionPollIntervalSecond = 30; // Poll every 30 seconds };