diff --git a/EasyNetworkManager.code-workspace b/EasyNetworkManager.code-workspace index 52e43ac..a8b45ea 100644 --- a/EasyNetworkManager.code-workspace +++ b/EasyNetworkManager.code-workspace @@ -121,7 +121,8 @@ "xstring": "cpp", "xtr1common": "cpp", "xtree": "cpp", - "xutility": "cpp" + "xutility": "cpp", + "variant": "cpp" } } } diff --git a/NetworkManager/examples/captivePortal.cpp b/NetworkManager/examples/captivePortal.cpp index d2ffce5..0dce730 100644 --- a/NetworkManager/examples/captivePortal.cpp +++ b/NetworkManager/examples/captivePortal.cpp @@ -1,82 +1,55 @@ #include - -// Note: Here is a list of all the library header files - required ones are -// marked -// with an asterisk (*) - -//! This is a Captive Portal Example. Please see the customHTML.cpp for an -//! example of how to implement custom HTML files to use instead of the default -//! wifimanager. - -//! Optional header files #include // (*) used for captive portal -#include -#include -#include // various network utilities -// (unique_ptr) to create unique objects -// #include -// #include -// #include // used for extending enums with new -// values -// #include // used with smart pointers (unique_ptr) -// to create unique objects -// #include // various helper functions - -//! Required header files -#include // (*) - -// Note: The Project Config Manager is used to store and retrieve the -// configuration -// data ? The config manager constructor takes two (optional) parameters: ? 1. -// The name of the project (used to create the config file name) ? 2. The -// hostname for your device on the network(used for mDNS, OTA, etc.) -ConfigHandler configHandler("easynetwork", MDNS_HOSTNAME); - -// Note: The WiFi Handler is used to manage the WiFi connection -// Note: The WiFi Handler constructor takes four parameters: -// Note: 1. A pointer to the config manager -// Note: 2. A pointer to the WiFi State Manager -// Note: 3. The SSID of the WiFi network to connect to -// Note: 4. The password of the WiFi network to connect to -WiFiHandler network(configHandler.config, WIFI_SSID, WIFI_PASSWORD, 1); +#include +//! Only needed for BLOCKING OTA. AsyncOTA is recommended and builtin +// #include + +/** + * @brief Setup the EasyNetworkManager Instance + * @note The EasyNetworkManager constructor takes 12 parameters: + * @param config_name The name of the project (used to create the config + * file name) + * @param hostname The hostname for your device on the network(used for + * mDNS, OTA, etc.) + * @param ssid The SSID of the WiFi network to connect to + * @param password The password of the WiFi network to connect to + * @param channel The channel of the WiFi network to connect to + * @param service_name The name of the service + * @param service_instance_name The instance name of the service + * @param service_protocol The protocol of the service + * @param service_description The description of the service + * @param service_port The port of the service + * @param enable_mdns Enable mDNS + * @param enable_adhoc Enable Adhoc + */ +EasyNetworkManager networkManager("easynetwork", MDNS_HOSTNAME, WIFI_SSID, + WIFI_PASSWORD, 1, "_easynetwork", "test", + "_tcp", "_api_port", "80", true, false); DNSServer dnsServer; -// Note: The API Server is used to create a web server that can be used to send -// commands to the device ? The API Server constructor takes five parameters: -// Note: 1. The port number to use for the web server -// Note: 2. A pointer to the config manager -// Note: 3. The root path for the API -// Note: 4. The path for the WiFi Manager html page -// Note: 5. The root path for the user commands for the API -// Note: This file example will create a web server on port 80, with the root -// path: -// http://easynetwork.local/api/mycommands/command/helloWorld -// http://easynetwork.local/api/mycommands/command/blink -// http://easynetwork.local/api/mycommands/command/params?Axes1=1&Axes2=2 - -AsyncServer_t async_server(80, configHandler.config, "/api", "/wifimanager", - "/mycommands"); - -APIServer server(configHandler.config, async_server); +/** + * @brief Setup the AsyncServer Instance + * @note The AsyncServer constructor takes 5 parameters: + * @param port The port to listen on + * @param config The config manager + * @param api_path The path to the API + * @param wifi_manager_path The path to the WiFi Manager + * @param command_path The path to the command handler + */ +AsyncServer_t async_server(80, networkManager.configHandler->config, "/api", + "/wifimanager", "/mycommands"); + +/** + * @brief Setup the API Server Instance + * @note The API Server constructor takes 2 parameters: + * @param config The config manager + * @param server The AsyncServer instance + */ +APIServer api(networkManager.configHandler->config, async_server); // Note: Not required if you are going to use the AsyncOTA feature -OTA ota(configHandler.config); - -// Note: The mDNS Manager is used to create a mDNS service for the device -// Note: The mDNS Manager constructor takes seven parameters: -// Note: 1. A pointer to the mDNS State Manager -// Note: 2. A pointer to the config manager -// Note: 3. The service name -// Note: 4. The service instance name -// Note: 5. The service protocol -// Note: 6. The service description -// Note: 7. The service port - -//! service name and service protocol have to be -//! lowercase and begin with an underscore -MDNSHandler mDNS(configHandler.config, "_easynetwork", "test", "_tcp", - "_api_port", "80"); +// OTA ota(networkManager.configHandler->config); class CustomConfig : public CustomConfigInterface { void save() override { @@ -158,21 +131,15 @@ void setupServer() { // add command handlers to the API server // you can add as many as you want - you can also add methods. log_d("[SETUP]: Starting API Server"); - - // Enabled the captive portal handler - server.setupCaptivePortal(true); - - // Create a custom REST API for our application - server.addAPICommand("blink", blink); - server.addAPICommand("helloWorld", printHelloWorld); - server.addAPICommand("params", grabParams); - server.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { + api.setupCaptivePortal(true); + api.addAPICommand("blink", blink); + api.addAPICommand("helloWorld", printHelloWorld); + api.addAPICommand("params", grabParams); + api.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { Temp t; t.grabParams(request); }); - - // start the server - server.begin(); + api.begin(); log_d("[SETUP]: API Server Started"); } @@ -181,31 +148,43 @@ void setup() { pinMode(4, OUTPUT); Serial.println("\nHello, EasyNetworkManager!"); - configHandler.config.attach(configHandler); //* Optionally register a custom config - this will be saved and loaded - configHandler.config.registerUserConfig(&customConfig); - configHandler.config.attach(network); - configHandler.config.attach( - mDNS); // attach the config manager to the mdns object - this will - // update the config when mdns hostname changes - - configHandler.begin(); // load the config from flash - - //* Begin the network manager - network.begin(); // setup wifi connection - - //* Begin the dns server for the captive portal - //* Port, domain name - wildcard to capture all + networkManager.configHandler->config.registerUserConfig(&customConfig); + networkManager.begin(); dnsServer.start(53, "*", WiFi.softAPIP()); - mDNS.begin(); // start mDNS service (optional) - - setupServer(); // setup the API server - - ota.begin(); + /** + * @brief This Function is used to handle the state changes of the WiFi + */ + updateWrapper( + networkManager.configHandler->config.getState( + networkManager.wifiHandler->getName()), + [](WiFiState_e state) { + switch (state) { + //! intentional fallthrough case + case WiFiState_e::WiFiState_ADHOC: + case WiFiState_e::WiFiState_Connected: { + setupServer(); + break; + } + case WiFiState_e::WiFiState_Disconnected: { + break; + } + case WiFiState_e::WiFiState_Disconnecting: { + break; + } + case WiFiState_e::WiFiState_Connecting: { + break; + } + case WiFiState_e::WiFiState_Error: { + break; + } + } + }); + // ota.begin(); } void loop() { dnsServer.processNextRequest(); - ota.handleOTAUpdate(); + // ota.handleOTAUpdate(); } diff --git a/NetworkManager/examples/customHTML.cpp b/NetworkManager/examples/customHTML.cpp index e649aa9..cda5451 100644 --- a/NetworkManager/examples/customHTML.cpp +++ b/NetworkManager/examples/customHTML.cpp @@ -1,75 +1,52 @@ #include - -// Note: Here is a list of all the library header files - required ones are -// marked -// with an asterisk (*) - -//! Optional header files -#include -#include -#include // various network utilities -// (unique_ptr) to create unique objects -// #include -// #include -// #include // used for extending enums with new -// values -// #include // used with smart pointers (unique_ptr) -// to create unique objects -// #include // various helper functions - -//! Required header files -#include // (*) -#include "api/server.hpp" - -// Note: The Project Config Manager is used to store and retrieve the -// configuration -// data ? The config manager constructor takes two (optional) parameters: ? 1. -// The name of the project (used to create the config file name) ? 2. The -// hostname for your device on the network(used for mDNS, OTA, etc.) -ConfigHandler configHandler("easynetwork", MDNS_HOSTNAME); - -// Note: The WiFi Handler is used to manage the WiFi connection -// Note: The WiFi Handler constructor takes four parameters: -// Note: 1. A pointer to the config manager -// Note: 2. A pointer to the WiFi State Manager -// Note: 3. The SSID of the WiFi network to connect to -// Note: 4. The password of the WiFi network to connect to -WiFiHandler network(configHandler.config, WIFI_SSID, WIFI_PASSWORD, 1); - -// Note: The API Server is used to create a web server that can be used to send -// commands to the device ? The API Server constructor takes five parameters: -// Note: 1. The port number to use for the web server -// Note: 2. A pointer to the config manager -// Note: 3. The root path for the API -// Note: 4. The path for the WiFi Manager html page -// Note: 5. The root path for the user commands for the API -// Note: This file example will create a web server on port 80, with the root -// path: -// http://easynetwork.local/api/mycommands/command/helloWorld -// http://easynetwork.local/api/mycommands/command/blink -// http://easynetwork.local/api/mycommands/command/params?Axes1=1&Axes2=2 -AsyncServer_t async_server(80, configHandler.config, "/api", "/wifimanager", - "/mycommands"); - -APIServer server(configHandler.config, async_server); +#include +//! Only needed for BLOCKING OTA. AsyncOTA is recommended and builtin +// #include + +/** + * @brief Setup the EasyNetworkManager Instance + * @note The EasyNetworkManager constructor takes 12 parameters: + * @param config_name The name of the project (used to create the config + * file name) + * @param hostname The hostname for your device on the network(used for + * mDNS, OTA, etc.) + * @param ssid The SSID of the WiFi network to connect to + * @param password The password of the WiFi network to connect to + * @param channel The channel of the WiFi network to connect to + * @param service_name The name of the service + * @param service_instance_name The instance name of the service + * @param service_protocol The protocol of the service + * @param service_description The description of the service + * @param service_port The port of the service + * @param enable_mdns Enable mDNS + * @param enable_adhoc Enable Adhoc + */ +EasyNetworkManager networkManager("easynetwork", MDNS_HOSTNAME, WIFI_SSID, + WIFI_PASSWORD, 1, "_easynetwork", "test", + "_tcp", "_api_port", "80", true, false); + +/** + * @brief Setup the AsyncServer Instance + * @note The AsyncServer constructor takes 5 parameters: + * @param port The port to listen on + * @param config The config manager + * @param api_path The path to the API + * @param wifi_manager_path The path to the WiFi Manager + * @param command_path The path to the command handler + */ +AsyncServer_t async_server(80, networkManager.configHandler->config, "/api", + "/wifimanager", "/mycommands"); + +/** + * @brief Setup the API Server Instance + * @note The API Server constructor takes 2 parameters: + * @param config The config manager + * @param server The AsyncServer instance + */ +APIServer api(networkManager.configHandler->config, async_server); // Note: Not required if you are going to use the AsyncOTA feature -OTA ota(configHandler.config); - -// Note: The mDNS Manager is used to create a mDNS service for the device -// Note: The mDNS Manager constructor takes seven parameters: -// Note: 1. A pointer to the mDNS State Manager -// Note: 2. A pointer to the config manager -// Note: 3. The service name -// Note: 4. The service instance name -// Note: 5. The service protocol -// Note: 6. The service description -// Note: 7. The service port - -//! service name and service protocol have to be -//! lowercase and begin with an underscore -MDNSHandler mDNS(configHandler.config, "_easynetwork", "test", "_tcp", - "_api_port", "80"); +// OTA ota(networkManager.configHandler->config); class CustomConfig : public CustomConfigInterface { void save() override { @@ -157,14 +134,14 @@ void setupServer() { async_server.custom_html_files.emplace_back("/goodbye", "/goodbye.html", "POST"); - server.addAPICommand("blink", blink); - server.addAPICommand("helloWorld", printHelloWorld); - server.addAPICommand("params", grabParams); - server.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { + api.addAPICommand("blink", blink); + api.addAPICommand("helloWorld", printHelloWorld); + api.addAPICommand("params", grabParams); + api.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { Temp t; t.grabParams(request); }); - server.begin(); + api.begin(); log_d("[SETUP]: API Server Started"); } @@ -173,46 +150,41 @@ void setup() { pinMode(4, OUTPUT); Serial.println("\nHello, EasyNetworkManager!"); - configHandler.config.attach(configHandler); //* Optionally register a custom config - this will be saved and loaded - configHandler.config.registerUserConfig(&customConfig); - configHandler.config.attach(network); - configHandler.config.attach( - mDNS); // attach the config manager to the mdns object - this will - // update the config when mdns hostname changes - - configHandler.begin(); // load the config from flash - network.begin(); // setup wifi connection - mDNS.begin(); // start mDNS service (optional) - - // handle the WiFi connection state changes - switch (wifiStateManager.getCurrentState()) { - case WiFiState_e::WiFiState_Disconnected: { - break; - } - case WiFiState_e::WiFiState_Disconnecting: { - break; - } - case WiFiState_e::WiFiState_ADHOC: { - // only start the API server if we have AP connection - setupServer(); - break; - } - case WiFiState_e::WiFiState_Connected: { - // only start the API server if we have wifi connection - setupServer(); - break; - } - case WiFiState_e::WiFiState_Connecting: { - break; - } - case WiFiState_e::WiFiState_Error: { - break; - } - } - ota.begin(); + networkManager.configHandler->config.registerUserConfig(&customConfig); + networkManager.begin(); + + /** + * @brief This Function is used to handle the state changes of the WiFi + */ + updateWrapper( + networkManager.configHandler->config.getState( + networkManager.wifiHandler->getName()), + [](WiFiState_e state) { + switch (state) { + //! intentional fallthrough case + case WiFiState_e::WiFiState_ADHOC: + case WiFiState_e::WiFiState_Connected: { + setupServer(); + break; + } + case WiFiState_e::WiFiState_Disconnected: { + break; + } + case WiFiState_e::WiFiState_Disconnecting: { + break; + } + case WiFiState_e::WiFiState_Connecting: { + break; + } + case WiFiState_e::WiFiState_Error: { + break; + } + } + }); + // ota.begin(); } void loop() { - ota.handleOTAUpdate(); + // ota.handleOTAUpdate(); } diff --git a/NetworkManager/examples/main.cpp b/NetworkManager/examples/main.cpp index 8e82396..d8ef430 100644 --- a/NetworkManager/examples/main.cpp +++ b/NetworkManager/examples/main.cpp @@ -1,74 +1,52 @@ #include - -// Note: Here is a list of all the library header files - required ones are -// marked -// with an asterisk (*) - -//! Optional header files -#include -#include -#include // various network utilities -// (unique_ptr) to create unique objects -// #include -// #include -// #include // used for extending enums with new -// values -// #include // used with smart pointers (unique_ptr) -// to create unique objects -// #include // various helper functions - -//! Required header files -#include // (*) - -// Note: The Project Config Manager is used to store and retrieve the -// configuration -// data ? The config manager constructor takes two (optional) parameters: ? 1. -// The name of the project (used to create the config file name) ? 2. The -// hostname for your device on the network(used for mDNS, OTA, etc.) -ConfigHandler configHandler("easynetwork", MDNS_HOSTNAME); - -// Note: The WiFi Handler is used to manage the WiFi connection -// Note: The WiFi Handler constructor takes four parameters: -// Note: 1. A pointer to the config manager -// Note: 2. A pointer to the WiFi State Manager -// Note: 3. The SSID of the WiFi network to connect to -// Note: 4. The password of the WiFi network to connect to -WiFiHandler network(configHandler.config, WIFI_SSID, WIFI_PASSWORD, 1); - -// Note: The API Server is used to create a web server that can be used to send -// commands to the device ? The API Server constructor takes five parameters: -// Note: 1. The port number to use for the web server -// Note: 2. A pointer to the config manager -// Note: 3. The root path for the API -// Note: 4. The path for the WiFi Manager html page -// Note: 5. The root path for the user commands for the API -// Note: This file example will create a web server on port 80, with the root -// path: -// http://easynetwork.local/api/mycommands/command/helloWorld -// http://easynetwork.local/api/mycommands/command/blink -// http://easynetwork.local/api/mycommands/command/params?Axes1=1&Axes2=2 -AsyncServer_t async_server(80, configHandler.config, "/api", "/wifimanager", - "/mycommands"); - -APIServer server(configHandler.config, async_server); +#include +//! Only needed for BLOCKING OTA. AsyncOTA is recommended and builtin +// #include + +/** + * @brief Setup the EasyNetworkManager Instance + * @note The EasyNetworkManager constructor takes 12 parameters: + * @param config_name The name of the project (used to create the config + * file name) + * @param hostname The hostname for your device on the network(used for + * mDNS, OTA, etc.) + * @param ssid The SSID of the WiFi network to connect to + * @param password The password of the WiFi network to connect to + * @param channel The channel of the WiFi network to connect to + * @param service_name The name of the service + * @param service_instance_name The instance name of the service + * @param service_protocol The protocol of the service + * @param service_description The description of the service + * @param service_port The port of the service + * @param enable_mdns Enable mDNS + * @param enable_adhoc Enable Adhoc + */ +EasyNetworkManager networkManager("easynetwork", MDNS_HOSTNAME, WIFI_SSID, + WIFI_PASSWORD, 1, "_easynetwork", "test", + "_tcp", "_api_port", "80", true, false); + +/** + * @brief Setup the AsyncServer Instance + * @note The AsyncServer constructor takes 5 parameters: + * @param port The port to listen on + * @param config The config manager + * @param api_path The path to the API + * @param wifi_manager_path The path to the WiFi Manager + * @param command_path The path to the command handler + */ +AsyncServer_t async_server(80, networkManager.configHandler->config, "/api", + "/wifimanager", "/mycommands"); + +/** + * @brief Setup the API Server Instance + * @note The API Server constructor takes 2 parameters: + * @param config The config manager + * @param server The AsyncServer instance + */ +APIServer api(networkManager.configHandler->config, async_server); // Note: Not required if you are going to use the AsyncOTA feature -OTA ota(configHandler.config); - -// Note: The mDNS Manager is used to create a mDNS service for the device -// Note: The mDNS Manager constructor takes seven parameters: -// Note: 1. A pointer to the mDNS State Manager -// Note: 2. A pointer to the config manager -// Note: 3. The service name -// Note: 4. The service instance name -// Note: 5. The service protocol -// Note: 6. The service description -// Note: 7. The service port - -//! service name and service protocol have to be -//! lowercase and begin with an underscore -MDNSHandler mDNS(configHandler.config, "_easynetwork", "test", "_tcp", - "_api_port", "80"); +// OTA ota(networkManager.configHandler->config); class CustomConfig : public CustomConfigInterface { void save() override { @@ -150,14 +128,14 @@ void setupServer() { // add command handlers to the API server // you can add as many as you want - you can also add methods. log_d("[SETUP]: Starting API Server"); - server.addAPICommand("blink", blink); - server.addAPICommand("helloWorld", printHelloWorld); - server.addAPICommand("params", grabParams); - server.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { + api.addAPICommand("blink", blink); + api.addAPICommand("helloWorld", printHelloWorld); + api.addAPICommand("params", grabParams); + api.addAPICommand("paramsClass", [&](AsyncWebServerRequest* request) { Temp t; t.grabParams(request); }); - server.begin(); + api.begin(); log_d("[SETUP]: API Server Started"); } @@ -166,46 +144,41 @@ void setup() { pinMode(4, OUTPUT); Serial.println("\nHello, EasyNetworkManager!"); - configHandler.config.attach(configHandler); //* Optionally register a custom config - this will be saved and loaded - configHandler.config.registerUserConfig(&customConfig); - configHandler.config.attach(network); - configHandler.config.attach( - mDNS); // attach the config manager to the mdns object - this will - // update the config when mdns hostname changes - - configHandler.begin(); // load the config from flash - network.begin(); // setup wifi connection - mDNS.begin(); // start mDNS service (optional) - - // handle the WiFi connection state changes - switch (wifiStateManager.getCurrentState()) { - case WiFiState_e::WiFiState_Disconnected: { - break; - } - case WiFiState_e::WiFiState_Disconnecting: { - break; - } - case WiFiState_e::WiFiState_ADHOC: { - // only start the API server if we have AP connection - setupServer(); - break; - } - case WiFiState_e::WiFiState_Connected: { - // only start the API server if we have wifi connection - setupServer(); - break; - } - case WiFiState_e::WiFiState_Connecting: { - break; - } - case WiFiState_e::WiFiState_Error: { - break; - } - } - ota.begin(); + networkManager.configHandler->config.registerUserConfig(&customConfig); + networkManager.begin(); + + /** + * @brief This Function is used to handle the state changes of the WiFi + */ + updateWrapper( + networkManager.configHandler->config.getState( + networkManager.wifiHandler->getName()), + [](WiFiState_e state) { + switch (state) { + //! intentional fallthrough case + case WiFiState_e::WiFiState_ADHOC: + case WiFiState_e::WiFiState_Connected: { + setupServer(); + break; + } + case WiFiState_e::WiFiState_Disconnected: { + break; + } + case WiFiState_e::WiFiState_Disconnecting: { + break; + } + case WiFiState_e::WiFiState_Connecting: { + break; + } + case WiFiState_e::WiFiState_Error: { + break; + } + } + }); + // ota.begin(); } void loop() { - ota.handleOTAUpdate(); + // ota.handleOTAUpdate(); } diff --git a/NetworkManager/include/EasyNetworkManager.hpp b/NetworkManager/include/EasyNetworkManager.hpp index 650169c..c89fd16 100644 --- a/NetworkManager/include/EasyNetworkManager.hpp +++ b/NetworkManager/include/EasyNetworkManager.hpp @@ -1,14 +1,64 @@ -#ifndef EASY_NETWORK_MANAGER_HPP -#define EASY_NETWORK_MANAGER_HPP +#pragma once //! Required header files -#include //! (*) -#include //! (*) -#include //! (*) +#include //! (*) +#include //! (*) +#include //! (*) + +#include #if ENABLE_ETHERNET # include //! (*) #else # include //! (*) #endif -#endif // EASY_NETWORK_MANAGER_HPP \ No newline at end of file + +class EasyNetworkManager { + public: + EasyNetworkManager(const std::string& config_name, + const std::string& hostname, const std::string& ssid, + const std::string& password, int channel, + const std::string& service_name, + const std::string& service_instance_name, + const std::string& service_protocol, + const std::string& service_description, + const std::string& service_port, + bool enable_mdns = false, bool enable_adhoc = false); + virtual ~EasyNetworkManager(); + + void begin(); + + /** + * @brief + * @note The Project Config Manager is used to store and retrieve the + * configuration + * @param config_name The name of the project (used to create the config + * file name) + * @param hostname The hostname for your device on the network(used for + * mDNS, OTA, etc.) + */ + std::shared_ptr configHandler; + + /** + * @brief The WiFi Handler is used to manage the WiFi connection + * @note The WiFi Handler constructor takes four parameters: + * @param configHandler A pointer to the config manager + * @param wifi_ssid The SSID of the WiFi network to connect to + * @param wifi_password The password of the WiFi network to connect to + * @param wifi_channel The channel of the WiFi network to connect to + */ + std::shared_ptr wifiHandler; + + /** + * @brief The mDNS Manager is used to create a mDNS service for the device + * @note Service name and service protocol have to be lowercase and begin + * with an underscore + * @param configHandler A reference to the config manager + * @param service_name The name of the service + * @param service_instance_name The instance name of the service + * @param service_protocol The protocol of the service + * @param service_description The description of the service + * @param service_port The port of the service + */ + std::shared_ptr mdnsHandler = nullptr; +}; \ No newline at end of file diff --git a/NetworkManager/include/api/rest_api_handler.hpp b/NetworkManager/include/api/rest_api_handler.hpp index 68e5e0c..23fffd1 100644 --- a/NetworkManager/include/api/rest_api_handler.hpp +++ b/NetworkManager/include/api/rest_api_handler.hpp @@ -11,8 +11,9 @@ class APIServer : public BaseAPI { void handleUserCommands(AsyncWebServerRequest* request); public: - APIServer(ProjectConfig& configManager, AsyncServer_t& async_server, - AsyncOTA* async_ota = nullptr); + APIServer(ProjectConfig& configManager, + AsyncServer_t& async_server, + AsyncOTA* async_ota = nullptr); virtual ~APIServer(); void begin(); void setupServer(); @@ -39,7 +40,7 @@ class CaptiveRequestHandler : public AsyncWebHandler { virtual ~CaptiveRequestHandler(); bool canHandle(AsyncWebServerRequest* request); - + //* use SPIFFS or built in HTML wifimanager void handleRequest(AsyncWebServerRequest* request); }; diff --git a/NetworkManager/include/data/config/config_handler.hpp b/NetworkManager/include/data/config/config_handler.hpp index a691616..fcecd73 100644 --- a/NetworkManager/include/data/config/config_handler.hpp +++ b/NetworkManager/include/data/config/config_handler.hpp @@ -1,15 +1,17 @@ #pragma once -#include "data/config/project_config.hpp" -#include "data/statemanager/state_manager.hpp" -#include "utilities/observer.hpp" +#include +#include +#include -class ConfigHandler : public IObserver { +class ConfigHandler : public IObserver { public: ConfigHandler(const std::string& configName = std::string(), const std::string& mdnsName = std::string()); virtual ~ConfigHandler(); virtual void begin(); - virtual void update(const Event_e &event) override; - virtual std::string getName() override; + virtual void update(const StateVariant& event) override; + std::string getName() const override { + return "ConfigHandler"; + } ProjectConfig config; }; \ No newline at end of file diff --git a/NetworkManager/include/data/config/project_config.hpp b/NetworkManager/include/data/config/project_config.hpp index f80f4a8..42b06bb 100644 --- a/NetworkManager/include/data/config/project_config.hpp +++ b/NetworkManager/include/data/config/project_config.hpp @@ -1,16 +1,15 @@ #pragma once -#ifndef PROJECT_CONFIG_HPP -# define PROJECT_CONFIG_HPP -# include -# include +#include +#include -# include -# include -# include +#include +#include +#include -# include "utilities/helpers.hpp" -# include "utilities/network_utilities.hpp" -# include "utilities/observer.hpp" +#include +#include +#include +#include namespace Project_Config { struct DeviceConfig_t { @@ -79,7 +78,7 @@ class CustomConfigInterface { virtual void save() = 0; }; -class ProjectConfig : public Preferences, public ISubject { +class ProjectConfig : public StateManager, public Preferences { private: virtual void initConfig(); Project_Config::ProjectConfig_t config; @@ -124,5 +123,3 @@ class ProjectConfig : public Preferences, public ISubject { bool reboot; }; - -#endif // PROJECT_CONFIG_HPP diff --git a/NetworkManager/include/data/statemanager/state_manager.hpp b/NetworkManager/include/data/statemanager/state_manager.hpp deleted file mode 100644 index eb7fe51..0000000 --- a/NetworkManager/include/data/statemanager/state_manager.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef STATEMANAGER_HPP -#define STATEMANAGER_HPP - -/* - * StateManager - * All Project States are managed here - */ -namespace ProgramStates { -struct DeviceStates { - enum State_e { Starting, Started, Stopping, Stopped, Error }; - - enum Event_e { - configLoaded, - configSaved, - deviceConfigUpdated, - mdnsConfigUpdated, - networksConfigUpdated, - apConfigUpdated, - wifiTxPowerUpdated, - deviceDataJsonUpdated, - }; - - enum WiFiState_e { - WiFiState_None, - WiFiState_Idle, - WiFiState_Connecting, - WiFiState_Connected, - WiFiState_Disconnected, - WiFiState_Disconnecting, - WiFiState_ADHOC, - WiFiState_Error - }; - - enum WebServerState_e { - WebServerState_None, - WebServerState_Starting, - WebServerState_Started, - WebServerState_Stopping, - WebServerState_Stopped, - WebServerState_Error - }; - - enum MDNSState_e { - MDNSState_None, - MDNSState_Starting, - MDNSState_Started, - MDNSState_Stopping, - MDNSState_Stopped, - MDNSState_Error - }; -}; -}; // namespace ProgramStates - -/* - * EventManager - * All Project Events are managed here - */ -template -class StateManager { - public: - StateManager() {} - - virtual ~StateManager() { - this->_current_state = static_cast(0); - } - - /* - * @brief Sets the state of the stateManager - * @param T state - the state to be set - */ - void setState(T state) { - _current_state = state; - } - - /* - * Get States - * Returns the current state of the device - */ - T getCurrentState() { - return _current_state; - } - - protected: - T _current_state; -}; - -typedef ProgramStates::DeviceStates::State_e State_e; -typedef ProgramStates::DeviceStates::Event_e Event_e; -typedef ProgramStates::DeviceStates::WiFiState_e WiFiState_e; -typedef ProgramStates::DeviceStates::WebServerState_e WebServerState_e; -typedef ProgramStates::DeviceStates::MDNSState_e MDNSState_e; - -extern StateManager eventManager; -extern StateManager stateManager; -extern StateManager wifiStateManager; -extern StateManager webServerStateManager; -extern StateManager mdnsStateManager; - -#endif // STATEMANAGER_HPP \ No newline at end of file diff --git a/NetworkManager/include/network/mdns/mdns_manager.hpp b/NetworkManager/include/network/mdns/mdns_manager.hpp index cfa44f6..eb20ac7 100644 --- a/NetworkManager/include/network/mdns/mdns_manager.hpp +++ b/NetworkManager/include/network/mdns/mdns_manager.hpp @@ -1,12 +1,9 @@ -#ifndef MDNS_HANDLER_HPP -#define MDNS_HANDLER_HPP +#pragma once #include +#include +#include -#include "data/config/project_config.hpp" -#include "data/statemanager/state_manager.hpp" -#include "utilities/observer.hpp" - -class MDNSHandler : public IObserver { +class MDNSHandler : public IObserver { private: ProjectConfig& configManager; std::string service_name; @@ -20,8 +17,9 @@ class MDNSHandler : public IObserver { const std::string& service_text, const std::string& proto, const std::string& key, const std::string& value); bool begin(); - void update(const Event_e& event) override; - std::string getName() override; + /* Overrides */ + void update(const StateVariant& event) override; + std::string getName() const override { + return this->service_name; + } }; - -#endif // MDNS_HANDLER_HPP diff --git a/NetworkManager/include/network/wifihandler/wifi_handler.hpp b/NetworkManager/include/network/wifihandler/wifi_handler.hpp index 1dc497a..e3baa42 100644 --- a/NetworkManager/include/network/wifihandler/wifi_handler.hpp +++ b/NetworkManager/include/network/wifihandler/wifi_handler.hpp @@ -1,30 +1,28 @@ #pragma once -#ifndef WIFIHANDLER_HPP -# define WIFIHANDLER_HPP -# include -# include -# include -# if defined(ARDUINO_SAMD_MKRWIFI1010) || \ - defined(ARDUINO_SAMD_NANO_33_IOT) || \ - defined(ARDUINO_AVR_UNO_WIFI_REV2) -# include -# elif defined(ARDUINO_SAMD_MKR1000) -# include -# elif defined(ARDUINO_ARCH_ESP8266) -# include -# elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || \ - defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_GIGA) -# ifdef USE_ETHERNET -# include "ethernet/ethernetHandler.hpp" -# else -# include -# endif +#include +#include +#include +#include +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) +# include +#elif defined(ARDUINO_SAMD_MKR1000) +# include +#elif defined(ARDUINO_ARCH_ESP8266) +# include +#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || \ + defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_GIGA) +# ifdef USE_ETHERNET +# include "ethernet/ethernetHandler.hpp" +# else +# include # endif -# include "data/config/project_config.hpp" -# include "data/statemanager/state_manager.hpp" -# include "utilities/helpers.hpp" +#endif +#include +#include +#include -class WiFiHandler : public IObserver { +class WiFiHandler : public IObserver { public: WiFiHandler(ProjectConfig& configManager, const std::string& ssid, const std::string& password, uint8_t channel); @@ -36,6 +34,10 @@ class WiFiHandler : public IObserver { ProjectConfig& configManager; Project_Config::WiFiTxPower_t& txpower; + std::string getName() const override { + return "WiFiHandler"; + } + private: void setUpADHOC(); void adhoc(const std::string& ssid, uint8_t channel, @@ -43,8 +45,8 @@ class WiFiHandler : public IObserver { bool iniSTA(const std::string& ssid, const std::string& password, uint8_t channel, wifi_power_t power); - void update(const Event_e& event) override; - std::string getName() override; + /* Overrides */ + void update(const StateVariant& event) override; std::string ssid; std::string password; @@ -52,4 +54,3 @@ class WiFiHandler : public IObserver { uint8_t power; bool _enable_adhoc; }; -#endif // WIFIHANDLER_HPP diff --git a/NetworkManager/include/utilities/api_utilities.hpp b/NetworkManager/include/utilities/api_utilities.hpp index 1cc652f..a014b66 100644 --- a/NetworkManager/include/utilities/api_utilities.hpp +++ b/NetworkManager/include/utilities/api_utilities.hpp @@ -1,5 +1,4 @@ -#ifndef APIUTILITIES_HPP -#define APIUTILITIES_HPP +#pragma once #include @@ -68,5 +67,3 @@ class API_Utilities { static const char* MIMETYPE_ICO; static const char* MIMETYPE_JSON; }; - -#endif // APIUTILITIES_HPP \ No newline at end of file diff --git a/NetworkManager/include/utilities/helpers.hpp b/NetworkManager/include/utilities/helpers.hpp index a595c6e..3be2865 100644 --- a/NetworkManager/include/utilities/helpers.hpp +++ b/NetworkManager/include/utilities/helpers.hpp @@ -1,6 +1,4 @@ -#ifndef HELPERS_HPP -#define HELPERS_HPP -//#include +#pragma once #include #include @@ -59,5 +57,3 @@ std::string format_string(const std::string& format, Args... args) { buf.get() + size - 1); // We don't want the '\0' inside } } // namespace Helpers - -#endif // HELPERS_HPP \ No newline at end of file diff --git a/NetworkManager/include/utilities/network_utilities.hpp b/NetworkManager/include/utilities/network_utilities.hpp index b3d33d9..1da30fe 100644 --- a/NetworkManager/include/utilities/network_utilities.hpp +++ b/NetworkManager/include/utilities/network_utilities.hpp @@ -1,12 +1,7 @@ #pragma once -#ifndef UTILITIES_hpp -# define UTILITIES_hpp -# include - -# include - -# include -# include +#include +#include +#include namespace Network_Utilities { bool loopWifiScan(); @@ -15,5 +10,4 @@ void my_delay(volatile long delay_time); int getStrength(int points); std::string generateDeviceID(); void checkWiFiState(); -} // namespace Network_Utilities -#endif // !UTILITIES_hpp \ No newline at end of file +} // namespace Network_Utilities \ No newline at end of file diff --git a/NetworkManager/include/utilities/observer.hpp b/NetworkManager/include/utilities/observer.hpp index 0734883..6d3e6a8 100644 --- a/NetworkManager/include/utilities/observer.hpp +++ b/NetworkManager/include/utilities/observer.hpp @@ -1,56 +1,81 @@ -#ifndef OBSERVER_HPP -#define OBSERVER_HPP -#include +#pragma once +#include #include #include #include +#include template class IObserver { public: virtual void update(const EnumT& event) = 0; - virtual std::string getName() = 0; + virtual std::string getName() const = 0; }; +/** + * @brief + * @note The `key` parameter is used to determine which Events to notify on. + * @tparam EnumT + */ template class ISubject { private: - typedef IObserver& Observer_t; - typedef std::unordered_map Observers_t; + typedef std::shared_ptr > ObserverPtr_t; + typedef std::unordered_map ObserversByNameMap_t; + typedef std::unordered_map > + ObserverKeysMap_t; - Observers_t observers; + ObserverKeysMap_t observerKeys; + ObserversByNameMap_t observers; public: - virtual ~ISubject(){}; - void attach(Observer_t observer) { - this->observers.emplace(observer.getName(), observer); + virtual ~ISubject() { + detachAll(); } - void detach(Observer_t observer) { - this->observers.erase(observer.getName()); + void attach(const std::string& key, ObserverPtr_t observer) { + observers.emplace(observer->getName(), observer); + observerKeys[observer->getName()].push_back(key); + } + + void detach(const ObserverPtr_t& observer) { + const std::string& name = observer.getName(); + observerKeys.erase(name); + observers.erase(name); + } + + void detach(const std::string& observerName) { + observerKeys.erase(observerName); + observers.erase(observerName); } void detachAll() { - // Note: clear map - this->observers.clear(); + observerKeys.clear(); + observers.clear(); + } + + void notify(const std::string& key, EnumT event) { + for (const auto& [observerName, keys] : observerKeys) { + if (std::find(keys.begin(), keys.end(), key) != keys.end()) { + // access the observer from the map of vectors and notify it + observers[observerName]->update(event); + } + } } void notifyAll(EnumT event) { - for (auto observer = observers.begin(); observer != observers.end(); - ++observer) { - (*observer).second.update(event); + for (const auto& [observerName, keys] : observerKeys) { + //* Notify the observer if it's subscribed to the key + observers[observerName]->update(event); } } - void notify(EnumT event, const std::string& observerName) { - auto it_map = observers.find(observerName); - if (it_map != observers.end()) { - (*it_map).second.update(event); - return; + std::vector getObserverKeys( + const std::string& observerName) const { + if (auto it = observerKeys.find(observerName); + it != observerKeys.end()) { + return it->second; } - log_e("Invalid Map Index"); - return; + return {}; } - int id = 0; }; -#endif // OBSERVER_HPP \ No newline at end of file diff --git a/NetworkManager/include/utilities/state_manager.hpp b/NetworkManager/include/utilities/state_manager.hpp new file mode 100644 index 0000000..3c56869 --- /dev/null +++ b/NetworkManager/include/utilities/state_manager.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include "observer.hpp" + +/** + * @brief StateManager is a singleton class that manages all states in the + * program. + * @note It is a singleton because it is used by many classes. + */ +template +class StateManager : public ISubject { + public: + StateManager() = default; + virtual ~StateManager() override = default; + + void setState(const std::string& key, const StateVariant& state) { + states[key] = state; + this->notify(key, state); + } + + StateVariant getState(const std::string& key) const { + auto it = states.find(key); + if (it == states.end()) { + log_e("State not found for key: %s", key.c_str()); + return {}; + } + return it->second; + } + + private: + std::map states; +}; + +// Define a generic function that applies a switch-case logic to an enum +// variant. +template +void updateWrapper(const VariantType& _variant, Func&& _switchCaseFunc) { + std::visit( + [&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + _switchCaseFunc(arg); + } + }, + _variant); +} \ No newline at end of file diff --git a/NetworkManager/include/utilities/states.hpp b/NetworkManager/include/utilities/states.hpp new file mode 100644 index 0000000..55f6806 --- /dev/null +++ b/NetworkManager/include/utilities/states.hpp @@ -0,0 +1,61 @@ +#pragma once +#include +#include "state_manager.hpp" + +/* \ + * StateManager \ + * All Project States are managed here \ + */ +namespace ProgramStates { +enum State_e { Starting, Started, Stopping, Stopped, Error }; +enum Event_e { + configLoaded, + configSaved, + deviceConfigUpdated, + mdnsConfigUpdated, + networksConfigUpdated, + apConfigUpdated, + wifiTxPowerUpdated, + deviceDataJsonUpdated, +}; + +enum WiFiState_e { + WiFiState_None, + WiFiState_Idle, + WiFiState_Connecting, + WiFiState_Connected, + WiFiState_Disconnected, + WiFiState_Disconnecting, + WiFiState_ADHOC, + WiFiState_Error +}; + +enum WebServerState_e { + WebServerState_None, + WebServerState_Starting, + WebServerState_Started, + WebServerState_Stopping, + WebServerState_Stopped, + WebServerState_Error +}; + +enum MDNSState_e { + MDNSState_None, + MDNSState_Starting, + MDNSState_Started, + MDNSState_Stopping, + MDNSState_Stopped, + MDNSState_Error +}; +}; // namespace ProgramStates + +typedef ProgramStates::State_e State_e; +typedef ProgramStates::Event_e Event_e; +typedef ProgramStates::WiFiState_e WiFiState_e; +typedef ProgramStates::WebServerState_e WebServerState_e; +typedef ProgramStates::MDNSState_e MDNSState_e; + +//* Define a broad variant +using StateVariant = + std::variant; +// extern StateManager stateManager; \ No newline at end of file diff --git a/NetworkManager/ini/dev_config.ini b/NetworkManager/ini/dev_config.ini index f701795..74f7db5 100644 --- a/NetworkManager/ini/dev_config.ini +++ b/NetworkManager/ini/dev_config.ini @@ -5,13 +5,11 @@ description = "EasyNetworkManager" [env] platform = espressif32 framework = arduino -lib_deps = - https://github.com/me-no-dev/ESPAsyncWebServer.git - https://github.com/me-no-dev/AsyncTCP.git +lib_deps = + https://github.com/me-no-dev/ESPAsyncWebServer.git + https://github.com/me-no-dev/AsyncTCP.git monitor_speed = 115200 -#monitor_rts = 0 -#monitor_dtr = 0 monitor_filters = log2file time @@ -41,11 +39,9 @@ build_flags = '-DOTA_IP=${ota.otaserverip}' ; Set the OTA password -O2 ; optimize for speed - -DUSE_WEBMANAGER ; enable webmanager + -DUSE_WEBMANAGER ; enable webmanager -DASYNCWEBSERVER_REGEX ; enable regex in asyncwebserver - -DUSE_ASYNCOTA ; enable asyncota - - # Comment these out if you are not using psram - #-DBOARD_HAS_PSRAM ; enable psram - #-mfix-esp32-psram-cache-issue ; fix for psram - ; Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run faster \ No newline at end of file + -DUSE_ASYNCOTA ; enable asyncota + -DHTTP_PARSER_STRICT=0 ;to make less checks, but run faster + -std=gnu++17 +build_unflags = -std=gnu++11 diff --git a/NetworkManager/src/EasyNetworkManager.cpp b/NetworkManager/src/EasyNetworkManager.cpp new file mode 100644 index 0000000..8e0efef --- /dev/null +++ b/NetworkManager/src/EasyNetworkManager.cpp @@ -0,0 +1,36 @@ +#include + +EasyNetworkManager::EasyNetworkManager( + const std::string& config_name, const std::string& hostname, + const std::string& ssid, const std::string& password, int channel, + const std::string& service_name, const std::string& service_instance_name, + const std::string& service_protocol, const std::string& service_description, + const std::string& service_port, bool enable_mdns, bool enable_adhoc) + : configHandler(std::make_shared(std::move(config_name), + std::move(hostname))), + wifiHandler(std::make_shared(configHandler->config, + std::move(ssid), + std::move(password), channel)) { + if (enable_mdns) { + mdnsHandler = std::make_shared( + configHandler->config, std::move(service_name), + std::move(service_instance_name), std::move(service_protocol), + std::move(service_description), std::move(service_port)); + } +} + +EasyNetworkManager::~EasyNetworkManager() {} + +void EasyNetworkManager::begin() { + configHandler->config.attach("ConfigHandler", configHandler); + configHandler->config.attach("WiFiHandler", wifiHandler); + if (mdnsHandler != nullptr) + configHandler->config.attach("MDNSHandler", mdnsHandler); + configHandler->config.setState(wifiHandler->getName(), + WiFiState_e::WiFiState_Connecting); + configHandler->begin(); + wifiHandler->begin(); + + if (mdnsHandler != nullptr) + mdnsHandler->begin(); +} \ No newline at end of file diff --git a/NetworkManager/src/data/config/config_handler.cpp b/NetworkManager/src/data/config/config_handler.cpp index eee9d66..67763c5 100644 --- a/NetworkManager/src/data/config/config_handler.cpp +++ b/NetworkManager/src/data/config/config_handler.cpp @@ -10,16 +10,14 @@ void ConfigHandler::begin() { config.load(); } -void ConfigHandler::update(const Event_e& event) { - switch (event) { - case Event_e::configSaved: - this->begin(); - break; - default: - break; - } +void ConfigHandler::update(const StateVariant& event) { + updateWrapper(event, [this](Event_e _event) { + switch (_event) { + case Event_e::configSaved: + this->begin(); + break; + default: + break; + } + }); } - -std::string ConfigHandler::getName() { - return "ConfigHandler"; -} \ No newline at end of file diff --git a/NetworkManager/src/data/config/project_config.cpp b/NetworkManager/src/data/config/project_config.cpp index 8a55a31..c772f2a 100644 --- a/NetworkManager/src/data/config/project_config.cpp +++ b/NetworkManager/src/data/config/project_config.cpp @@ -7,6 +7,22 @@ ProjectConfig::ProjectConfig(const std::string& configName, _already_loaded(false) {} ProjectConfig::~ProjectConfig() { + this->detachAll(); +} + +/** + *@brief Initializes the structures with blank data to prevent empty memory + *sectors and nullptr errors. + *@brief This is to be called in setup() before loading the config. + */ +void ProjectConfig::initConfig() { + if (_configName.empty()) { + log_e("[Project Config]: Config name is null\n"); + _configName = "easynetwork"; + } + + bool success = begin(_configName.c_str()); + this->config.device = { "admin", "12345678", @@ -31,20 +47,6 @@ ProjectConfig::~ProjectConfig() { 1, false, }; -} - -/** - *@brief Initializes the structures with blank data to prevent empty memory - *sectors and nullptr errors. - *@brief This is to be called in setup() before loading the config. - */ -void ProjectConfig::initConfig() { - if (_configName.empty()) { - log_e("[Project Config]: Config name is null\n"); - _configName = "easynetwork"; - } - - bool success = begin(_configName.c_str()); log_i("[Project Config]: Config name: %s", _configName.c_str()); log_i("[Project Config]: Config loaded: %s", success ? "true" : "false"); @@ -123,32 +125,31 @@ void ProjectConfig::save() { if (this->reboot) { log_i("[Project Config]: Project config saved and system is rebooting"); + //* clear struct data + this->config.device = { + "", + 0, + }; + + this->config.mdns = { + "", + }; + + this->config.ap_network = { + "", + "", + 1, + false, + }; + + this->config.networks.clear(); + ESP.restart(); return; } log_w("[Project Config]: Reboot is disabled, triggering observer"); this->_already_loaded = false; - - //* clear struct data - this->config.device = { - "", - 0, - }; - - this->config.mdns = { - "", - }; - - this->config.ap_network = { - "", - "", - 1, - false, - }; - - this->config.networks.clear(); - this->notifyAll(Event_e::configSaved); } @@ -300,10 +301,11 @@ void ProjectConfig::setWifiConfig(const std::string& networkName, it->adhoc = false; if (shouldNotify) { - wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected); + this->setState("WiFiHandler", + WiFiState_e::WiFiState_Disconnected); WiFi.disconnect(); this->wifiConfigSave(); - this->notifyAll(Event_e::networksConfigUpdated); + this->notify("WiFiHandler", Event_e::networksConfigUpdated); } return; @@ -330,10 +332,10 @@ void ProjectConfig::setWifiConfig(const std::string& networkName, } if (shouldNotify) { - wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected); + this->setState("WiFiHandler", WiFiState_e::WiFiState_Disconnected); WiFi.disconnect(); this->wifiConfigSave(); - this->notifyAll(Event_e::networksConfigUpdated); + this->notify("WiFiHandler", Event_e::networksConfigUpdated); } } @@ -470,4 +472,4 @@ Project_Config::DeviceDataJson_t& ProjectConfig::getDeviceDataJson() { void ProjectConfig::registerUserConfig( _custom_config_interface_t custom_config_interface) { this->_custom_config_interface = custom_config_interface; -} \ No newline at end of file +} diff --git a/NetworkManager/src/data/statemanager/state_manager.cpp b/NetworkManager/src/data/statemanager/state_manager.cpp deleted file mode 100644 index 466a6d4..0000000 --- a/NetworkManager/src/data/statemanager/state_manager.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -StateManager stateManager; -StateManager eventManager; -StateManager wifiStateManager; -StateManager webServerStateManager; -StateManager mdnsStateManager; diff --git a/NetworkManager/src/network/mdns/mdns_manager.cpp b/NetworkManager/src/network/mdns/mdns_manager.cpp index ae70e8c..967d232 100644 --- a/NetworkManager/src/network/mdns/mdns_manager.cpp +++ b/NetworkManager/src/network/mdns/mdns_manager.cpp @@ -16,12 +16,14 @@ bool MDNSHandler::begin() { auto mdnsConfig = configManager.getMDNSConfig(); log_d("%s", mdnsConfig.hostname.c_str()); if (!MDNS.begin(mdnsConfig.hostname.c_str())) { - mdnsStateManager.setState(MDNSState_e::MDNSState_Error); + this->configManager.setState(this->getName(), + MDNSState_e::MDNSState_Error); log_e("Error initializing MDNS"); return false; } - mdnsStateManager.setState(MDNSState_e::MDNSState_Starting); + this->configManager.setState(this->getName(), + MDNSState_e::MDNSState_Starting); MDNS.addService(service_name.c_str(), proto.c_str(), atoi(value.c_str())); MDNS.addServiceTxt( service_name.c_str(), proto.c_str(), key.c_str(), @@ -29,21 +31,20 @@ bool MDNSHandler::begin() { log_d("%s %s %s %s %s", service_name.c_str(), proto.c_str(), service_text.c_str(), key.c_str(), value.c_str()); log_i("MDNS initialized!"); - mdnsStateManager.setState(MDNSState_e::MDNSState_Started); + this->configManager.setState(this->getName(), + MDNSState_e::MDNSState_Started); return true; } -void MDNSHandler::update(const Event_e& event) { - switch (event) { - case Event_e::mdnsConfigUpdated: - MDNS.end(); - begin(); - break; - default: - break; - } -} - -std::string MDNSHandler::getName() { - return this->service_name; +void MDNSHandler::update(const StateVariant& event) { + updateWrapper(event, [this](Event_e _event) { + switch (_event) { + case Event_e::mdnsConfigUpdated: + MDNS.end(); + this->begin(); + break; + default: + break; + } + }); } diff --git a/NetworkManager/src/network/wifihandler/wifi_handler.cpp b/NetworkManager/src/network/wifihandler/wifi_handler.cpp index 942c0fa..07a630a 100644 --- a/NetworkManager/src/network/wifihandler/wifi_handler.cpp +++ b/NetworkManager/src/network/wifihandler/wifi_handler.cpp @@ -3,7 +3,7 @@ WiFiHandler::WiFiHandler(ProjectConfig& configManager, const std::string& ssid, const std::string& password, uint8_t channel) : configManager(configManager), - txpower(configManager.getWifiTxPowerConfig()), + txpower(this->configManager.getWifiTxPowerConfig()), ssid(ssid), password(password), channel(channel), @@ -13,18 +13,18 @@ WiFiHandler::WiFiHandler(ProjectConfig& configManager, const std::string& ssid, WiFiHandler::~WiFiHandler() {} void WiFiHandler::begin() { - if (this->_enable_adhoc || - wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_ADHOC) { - this->setUpADHOC(); + if (this->_enable_adhoc) { + this->configManager.setState(this->getName(), + WiFiState_e::WiFiState_ADHOC); return; } WiFi.mode(WIFI_STA); + // WiFi.onEvent(); WiFi.setSleep(WIFI_PS_NONE); Serial.print("Initializing connection to wifi \n\r"); - wifiStateManager.setState(WiFiState_e::WiFiState_Connecting); - auto networks = configManager.getWifiConfigs(); + auto networks = this->configManager.getWifiConfigs(); if (networks.empty()) { Serial.print( @@ -71,7 +71,7 @@ void WiFiHandler::begin() { void WiFiHandler::adhoc(const std::string& ssid, uint8_t channel, const std::string& password) { - wifiStateManager.setState(WiFiState_e::WiFiState_ADHOC); + this->configManager.setState(this->getName(), WiFiState_e::WiFiState_ADHOC); log_i("\n[INFO]: Setting Access Point...\n"); log_i("\n[INFO]: Configuring access point...\n"); WiFi.mode(WIFI_AP); @@ -88,8 +88,9 @@ void WiFiHandler::adhoc(const std::string& ssid, uint8_t channel, void WiFiHandler::setUpADHOC() { log_i("\n[INFO]: Setting Access Point...\n"); - size_t ssidLen = configManager.getAPWifiConfig().ssid.length(); - size_t passwordLen = configManager.getAPWifiConfig().password.length(); + size_t ssidLen = this->configManager.getAPWifiConfig().ssid.length(); + size_t passwordLen = + this->configManager.getAPWifiConfig().password.length(); if (ssidLen <= 0) { this->adhoc("EasyNetworkManager", 1, "12345678"); return; @@ -99,20 +100,21 @@ void WiFiHandler::setUpADHOC() { log_i( "\n[INFO]: Configuring access point without a " "password\n"); - this->adhoc(configManager.getAPWifiConfig().ssid, - configManager.getAPWifiConfig().channel); + this->adhoc(this->configManager.getAPWifiConfig().ssid, + this->configManager.getAPWifiConfig().channel); return; } - this->adhoc(configManager.getAPWifiConfig().ssid, - configManager.getAPWifiConfig().channel, - configManager.getAPWifiConfig().password); + this->adhoc(this->configManager.getAPWifiConfig().ssid, + this->configManager.getAPWifiConfig().channel, + this->configManager.getAPWifiConfig().password); log_i("\n[INFO]: Configuring access point...\n"); log_d("\n[DEBUG]: ssid: %s\n", - configManager.getAPWifiConfig().ssid.c_str()); + this->configManager.getAPWifiConfig().ssid.c_str()); log_d("\n[DEBUG]: password: %s\n", - configManager.getAPWifiConfig().password.c_str()); - log_d("\n[DEBUG]: channel: %d\n", configManager.getAPWifiConfig().channel); + this->configManager.getAPWifiConfig().password.c_str()); + log_d("\n[DEBUG]: channel: %d\n", + this->configManager.getAPWifiConfig().channel); } bool WiFiHandler::iniSTA(const std::string& ssid, const std::string& password, @@ -121,10 +123,8 @@ bool WiFiHandler::iniSTA(const std::string& ssid, const std::string& password, unsigned long startingMillis = currentMillis; int connectionTimeout = 45000; // 30 seconds int progress = 0; - - wifiStateManager.setState(WiFiState_e::WiFiState_Connecting); Serial.printf("Trying to connect to: %s \n\r", ssid.c_str()); - auto mdnsConfig = configManager.getMDNSConfig(); + auto mdnsConfig = this->configManager.getMDNSConfig(); WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); // need to call before // setting hostname @@ -137,17 +137,21 @@ bool WiFiHandler::iniSTA(const std::string& ssid, const std::string& password, delay(1000); log_v("."); if ((currentMillis - startingMillis) >= connectionTimeout) { - wifiStateManager.setState(WiFiState_e::WiFiState_Error); + this->configManager.setState(this->getName(), + WiFiState_e::WiFiState_Error); log_e("Connection to: %s TIMEOUT \n\r", ssid.c_str()); + this->configManager.setState(this->getName(), + WiFiState_e::WiFiState_Connecting); delay(8000); return false; } } - wifiStateManager.setState(WiFiState_e::WiFiState_Connected); + this->configManager.setState(this->getName(), + WiFiState_e::WiFiState_Connected); Serial.printf("Successfully connected to %s \n\r", ssid.c_str()); - Serial.printf("Setting TX power to: %d \n\r", (uint8_t)power); - WiFi.setTxPower(power); + // Serial.printf("Setting TX power to: %d \n\r", (uint8_t)power); + // WiFi.setTxPower(power); return true; } @@ -156,16 +160,38 @@ void WiFiHandler::toggleAdhoc(bool enable) { _enable_adhoc = enable; } -void WiFiHandler::update(const Event_e& event) { - switch (event) { - case Event_e::networksConfigUpdated: - this->begin(); - break; - default: - break; - } +void WiFiHandler::update(const StateVariant& event) { + updateWrapper(event, [this](WiFiState_e _event) { + switch (_event) { + case WiFiState_e::WiFiState_Connecting: + Serial.print("WiFiState_Connecting \n\r"); + this->begin(); + break; + case WiFiState_e::WiFiState_Connected: + Serial.print("WiFiState_Connected \n\r"); + break; + case WiFiState_e::WiFiState_Disconnected: + Serial.print("WiFiState_Disconnected \n\r"); + break; + case WiFiState_e::WiFiState_Error: + Serial.print("WiFiState_Error \n\r"); + break; + case WiFiState_e::WiFiState_ADHOC: + Serial.print("WiFiState_ADHOC \n\r"); + this->setUpADHOC(); + break; + default: + break; + } + }); + + //updateWrapper(event, [this](Event_e _event) { + // switch (_event) { + // case Event_e::configSaved: + // this->begin(); + // break; + // default: + // break; + // } + //}); } - -std::string WiFiHandler::getName() { - return "WiFiHandler"; -} \ No newline at end of file diff --git a/NetworkManager/src/utilities/network_utilities.cpp b/NetworkManager/src/utilities/network_utilities.cpp index f8d41bb..3c6a69d 100644 --- a/NetworkManager/src/utilities/network_utilities.cpp +++ b/NetworkManager/src/utilities/network_utilities.cpp @@ -89,34 +89,3 @@ std::string Network_Utilities::generateDeviceID() { std::string deviceID = (const char*)chipId; return deviceID; } - -/** - * @brief Function to map the WiFi status to the WiFiState_e enum - * @note Call this function in the loop() function - */ -void Network_Utilities::checkWiFiState() { - if (wifiStateManager.getCurrentState() == WiFiState_e::WiFiState_ADHOC) { - return; - } - - switch (WiFi.status()) { - case wl_status_t::WL_IDLE_STATUS: - wifiStateManager.setState(WiFiState_e::WiFiState_Idle); - case wl_status_t::WL_NO_SSID_AVAIL: - wifiStateManager.setState(WiFiState_e::WiFiState_Error); - case wl_status_t::WL_SCAN_COMPLETED: - wifiStateManager.setState(WiFiState_e::WiFiState_None); - case wl_status_t::WL_CONNECTED: - wifiStateManager.setState(WiFiState_e::WiFiState_Connected); - case wl_status_t::WL_CONNECT_FAILED: - wifiStateManager.setState(WiFiState_e::WiFiState_Error); - case wl_status_t::WL_CONNECTION_LOST: - wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected); - case wl_status_t::WL_DISCONNECTED: - wifiStateManager.setState(WiFiState_e::WiFiState_Disconnected); - default: - wifiStateManager.setState(WiFiState_e::WiFiState_None); - } -} - -// TODO: move to using the WiFi classes event system diff --git a/NetworkManager/wokwi.toml b/NetworkManager/wokwi.toml index 2f34b35..b97faa3 100644 --- a/NetworkManager/wokwi.toml +++ b/NetworkManager/wokwi.toml @@ -1,7 +1,7 @@ [wokwi] version = 1 -elf = ".pio/build/esp32dev_debug/EasyNetworkManager-v4.5.6-esp32dev_debug-f07add0-main.elf" -firmware = ".pio/build/esp32dev_debug/EasyNetworkManager-v4.5.6-esp32dev_debug-f07add0-main.bin" +elf = ".pio/build/esp32dev_debug/EasyNetworkManager-v4.5.7-esp32dev_debug-c9e4acc-main.elf" +firmware = ".pio/build/esp32dev_debug/EasyNetworkManager-v4.5.7-esp32dev_debug-c9e4acc-main.bin" [[net.forward]] from = "localhost:8180" to = "target:80"