From 8ce0ea086063d725dda0e03f18580c84ec099269 Mon Sep 17 00:00:00 2001 From: ZanzyTHEbar Date: Mon, 15 Aug 2022 05:54:06 +0100 Subject: [PATCH] update - Fix preferences lib - Fix ADHOC - Optimize API - Implement full preferences lib - Implement API with preferences lib --- ESP/lib/src/data/config/project_config.cpp | 102 +++++- ESP/lib/src/data/config/project_config.hpp | 26 +- .../src/io/SerialManager/serialmanager.cpp | 34 +- .../src/io/SerialManager/serialmanager.hpp | 1 + ESP/lib/src/network/OTA/OTA.cpp | 2 +- .../src/network/WifiHandler/WifiHandler.hpp | 16 +- .../src/network/WifiHandler/wifiHandler.cpp | 217 ++++++------ ESP/lib/src/network/mDNS/MDNSManager.cpp | 2 +- .../network/webserver/webserverHandler.cpp | 314 ++++++++++-------- .../network/webserver/webserverHandler.hpp | 19 +- ESP/platformio.ini | 13 +- ESP/src/main.cpp | 1 + 12 files changed, 449 insertions(+), 298 deletions(-) diff --git a/ESP/lib/src/data/config/project_config.cpp b/ESP/lib/src/data/config/project_config.cpp index 8a2d368..7e86b8f 100644 --- a/ESP/lib/src/data/config/project_config.cpp +++ b/ESP/lib/src/data/config/project_config.cpp @@ -2,7 +2,7 @@ Preferences preferences; -ProjectConfig::ProjectConfig() : Config(&preferences ,"config"), _already_loaded(false) {} +ProjectConfig::ProjectConfig() : Config(&preferences, "config"), _already_loaded(false) {} ProjectConfig::~ProjectConfig() {} @@ -18,19 +18,28 @@ void ProjectConfig::initConfig() "", 0, }; + this->config.camera = { 0, 0, 0, 0, }; + this->config.networks = { { "", "", "", + 0, }, }; + + this->config.ap_network = { + "", + "", + 0, + }; } void ProjectConfig::load() @@ -42,13 +51,41 @@ void ProjectConfig::load() return; } - bool device_success = this->read("device", this->config.device); - bool camera_success = this->read("camera", this->config.camera); - bool network_info_success = this->read("network_info", this->config.networks); + bool device_name_success = this->read("device_name", this->config.device.name); + bool device_otapassword_success = this->read("ota_pass", this->config.device.OTAPassword); + bool device_otaport_success = this->read("ota_port", this->config.device.OTAPort); + + bool device_success = device_name_success && device_otapassword_success && device_otaport_success; + + bool camera_vflip_success = this->read("camera_vflip", this->config.camera.vflip); + bool camera_framesize_success = this->read("cameraFrmsz", this->config.camera.framesize); + bool camera_href_success = this->read("camera_href", this->config.camera.href); + bool camera_quality_success = this->read("camera_quality", this->config.camera.quality); + + bool camera_success = camera_vflip_success && camera_framesize_success && camera_href_success && camera_quality_success; + + bool network_info_success; + for (int i = 0; i < this->config.networks.size(); i++) + { + char buff[25]; + snprintf(buff, sizeof(buff), "%d_name", i); + bool networks_name_success = this->read(buff, this->config.networks[i].name); + snprintf(buff, sizeof(buff), "%d_ssid", i); + bool networks_ssid_success = this->read(buff, this->config.networks[i].ssid); + snprintf(buff, sizeof(buff), "%d_password", i); + bool networks_password_success = this->read(buff, this->config.networks[i].password); + snprintf(buff, sizeof(buff), "%d_channel", i); + bool networks_channel_success = this->read(buff, this->config.networks[i].channel); + + network_info_success = networks_name_success && networks_ssid_success && networks_password_success && networks_channel_success; + } if (!device_success || !camera_success || !network_info_success) { - log_e("Failed to load project config"); + log_e("Failed to load project config - Generating config and restarting"); + save(); + delay(1000); + ESP.restart(); return; } @@ -59,9 +96,28 @@ void ProjectConfig::load() void ProjectConfig::save() { log_d("Saving project config"); - this->write("device", this->config.device); - this->write("camera", this->config.camera); - this->write("network_info", this->config.networks); + + this->write("device_name", this->config.device.name); + this->write("ota_pass", this->config.device.OTAPassword); + this->write("ota_port", this->config.device.OTAPort); + + this->write("camera_vflip", this->config.camera.vflip); + this->write("cameraFrmsz", this->config.camera.framesize); + this->write("camera_href", this->config.camera.href); + this->write("camera_quality", this->config.camera.quality); + + for (int i = 0; i < this->config.networks.size(); i++) + { + char buff[25]; + snprintf(buff, sizeof(buff), "%d_name", i); + this->write(buff, this->config.networks[i].name); + snprintf(buff, sizeof(buff), "%d_ssid", i); + this->write(buff, this->config.networks[i].ssid); + snprintf(buff, sizeof(buff), "%d_password", i); + this->write(buff, this->config.networks[i].password); + snprintf(buff, sizeof(buff), "%d_channel", i); + this->write(buff, this->config.networks[i].channel); + } } void ProjectConfig::reset() @@ -79,8 +135,8 @@ void ProjectConfig::setDeviceConfig(const char *name, const char *OTAPassword, i { log_d("Updating device config"); this->config.device = { - name, - OTAPassword, + (char *)name, + (char *)OTAPassword, *OTAPort, }; if (shouldNotify) @@ -105,13 +161,13 @@ void ProjectConfig::setCameraConfig(uint8_t *vflip, uint8_t *framesize, uint8_t } } -void ProjectConfig::setWifiConfig(const char *networkName, const char *ssid, const char *password, bool shouldNotify) +void ProjectConfig::setWifiConfig(const char *networkName, const char *ssid, const char *password, uint8_t *channel, bool shouldNotify) { WiFiConfig_t *networkToUpdate = nullptr; for (int i = 0; i < this->config.networks.size(); i++) { - if (strcmp(this->config.networks[i].name, networkName) == 0) + if (strcmp(this->config.networks[i].name.c_str(), networkName) == 0) networkToUpdate = &this->config.networks[i]; } @@ -119,13 +175,29 @@ void ProjectConfig::setWifiConfig(const char *networkName, const char *ssid, con { this->config.networks = { { - networkName, - ssid, - password, + (char *)networkName, + (char *)ssid, + (char *)password, + *channel, }, }; if (shouldNotify) this->notify(ObserverEvent::networksConfigUpdated); } log_d("Updating wifi config"); +} + +void ProjectConfig::setAPWifiConfig(const char *ssid, const char *password, uint8_t *channel, bool shouldNotify) +{ + this->config.ap_network = { + (char *)ssid, + (char *)password, + *channel, + }; + + log_d("Updating access point config"); + if (shouldNotify) + { + this->notify(ObserverEvent::networksConfigUpdated); + } } \ No newline at end of file diff --git a/ESP/lib/src/data/config/project_config.hpp b/ESP/lib/src/data/config/project_config.hpp index 9b56d23..20bd0fd 100644 --- a/ESP/lib/src/data/config/project_config.hpp +++ b/ESP/lib/src/data/config/project_config.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "data/utilities/Observer.hpp" @@ -19,8 +20,8 @@ public: struct DeviceConfig_t { - const char *name; - const char *OTAPassword; + std::string name; + std::string OTAPassword; int OTAPort; bool data_json; bool config_json; @@ -40,9 +41,17 @@ public: struct WiFiConfig_t { - const char *name; - const char *ssid; - const char *password; + std::string name; + std::string ssid; + std::string password; + uint8_t channel; + }; + + struct AP_WiFiConfig_t + { + std::string ssid; + std::string password; + uint8_t channel; }; struct TrackerConfig_t @@ -50,16 +59,19 @@ public: DeviceConfig_t device; CameraConfig_t camera; std::vector networks; + AP_WiFiConfig_t ap_network; }; DeviceConfig_t *getDeviceConfig() { return &this->config.device; } CameraConfig_t *getCameraConfig() { return &this->config.camera; } std::vector *getWifiConfigs() { return &this->config.networks; } + AP_WiFiConfig_t *getAPWifiConfig() { return &this->config.ap_network; } void setDeviceConfig(const char *name, const char *OTAPassword, int *OTAPort, bool shouldNotify); void setCameraConfig(uint8_t *vflip, uint8_t *framesize, uint8_t *href, uint8_t *quality, bool shouldNotify); - void setWifiConfig(const char *networkName, const char *ssid, const char *password, bool shouldNotify); - + void setWifiConfig(const char *networkName, const char *ssid, const char *password, uint8_t *channel, bool shouldNotify); + void setAPWifiConfig(const char *ssid, const char *password, uint8_t *channel, bool shouldNotify); + private: const char *configFileName; TrackerConfig_t config; diff --git a/ESP/lib/src/io/SerialManager/serialmanager.cpp b/ESP/lib/src/io/SerialManager/serialmanager.cpp index 54db530..0df354d 100644 --- a/ESP/lib/src/io/SerialManager/serialmanager.cpp +++ b/ESP/lib/src/io/SerialManager/serialmanager.cpp @@ -1,20 +1,21 @@ #include "serialmanager.hpp" SerialManager::SerialManager(ProjectConfig *projectConfig) : projectConfig(projectConfig), - serialManagerActive(false), - newData(false), - tempBuffer{0}, - serialBuffer{0}, - device_config_name{0}, - device_config_OTAPassword{0}, - device_config_OTAPort(0), - camera_config_vflip{0}, - camera_config_href{0}, - camera_config_framesize{0}, - camera_config_quality{0}, - wifi_config_name{0}, - wifi_config_ssid{0}, - wifi_config_password{0} {} + serialManagerActive(false), + newData(false), + tempBuffer{0}, + serialBuffer{0}, + device_config_name{0}, + device_config_OTAPassword{0}, + device_config_OTAPort(0), + camera_config_vflip{0}, + camera_config_href{0}, + camera_config_framesize{0}, + camera_config_quality{0}, + wifi_config_name{0}, + wifi_config_ssid{0}, + wifi_config_password{0}, + wifi_config_channel(0) {} SerialManager::~SerialManager() {} @@ -104,6 +105,9 @@ void SerialManager::parseData() strtokIndx = strtok(NULL, ","); strcpy(wifi_config_password, strtokIndx); + + strtokIndx = strtok(NULL, ","); + wifi_config_channel = atoi(strtokIndx); } void SerialManager::handleSerial() @@ -115,7 +119,7 @@ void SerialManager::handleSerial() parseData(); // split the data into tokens and store them in the data structure projectConfig->setDeviceConfig(device_config_name, device_config_OTAPassword, &device_config_OTAPort, true); // set the values in the project config projectConfig->setCameraConfig(&camera_config_vflip, &camera_config_framesize, &camera_config_href, &camera_config_quality, true); // set the values in the project config - projectConfig->setWifiConfig(wifi_config_name, wifi_config_ssid, wifi_config_password, true); // set the values in the project config + projectConfig->setWifiConfig(wifi_config_name, wifi_config_ssid, wifi_config_password, &wifi_config_channel, true); // set the values in the project config projectConfig->save(); // save the config to the EEPROM newData = false; // reset new data } diff --git a/ESP/lib/src/io/SerialManager/serialmanager.hpp b/ESP/lib/src/io/SerialManager/serialmanager.hpp index 3ab5659..c949c84 100644 --- a/ESP/lib/src/io/SerialManager/serialmanager.hpp +++ b/ESP/lib/src/io/SerialManager/serialmanager.hpp @@ -30,6 +30,7 @@ public: char wifi_config_name[32]; char wifi_config_ssid[100]; char wifi_config_password[100]; + uint8_t wifi_config_channel; private: diff --git a/ESP/lib/src/network/OTA/OTA.cpp b/ESP/lib/src/network/OTA/OTA.cpp index 2fcde6f..7abd36d 100644 --- a/ESP/lib/src/network/OTA/OTA.cpp +++ b/ESP/lib/src/network/OTA/OTA.cpp @@ -9,7 +9,7 @@ void OTA::SetupOTA() log_e("Setting up OTA updates"); auto localConfig = _deviceConfig->getDeviceConfig(); - if (strcmp(localConfig->OTAPassword, "") == 0) + if (strcmp(localConfig->OTAPassword.c_str(), "") == 0) { log_e("THE PASSWORD IS REQUIRED, [[ABORTING]]"); return; diff --git a/ESP/lib/src/network/WifiHandler/WifiHandler.hpp b/ESP/lib/src/network/WifiHandler/WifiHandler.hpp index 46aadc0..fd77729 100644 --- a/ESP/lib/src/network/WifiHandler/WifiHandler.hpp +++ b/ESP/lib/src/network/WifiHandler/WifiHandler.hpp @@ -6,25 +6,17 @@ #include "data/StateManager/StateManager.hpp" #include "data/config/project_config.hpp" -extern "C" -{ -#include -#include -#include -} - class WiFiHandler { public: WiFiHandler(ProjectConfig *configManager, StateManager *stateManager); virtual ~WiFiHandler(); void setupWifi(); + ProjectConfig *configManager; + StateManager *stateManager; +private: void setUpADHOC(); void adhoc(const char *ssid, const char *password, uint8_t channel); - void setWiFiConf(const char *value, uint8_t *location, wifi_config_t *conf); - std::unique_ptr conf; - ProjectConfig *configManager; -private: - StateManager *stateManager; + void iniSTA(); }; #endif // WIFIHANDLER_HPP diff --git a/ESP/lib/src/network/WifiHandler/wifiHandler.cpp b/ESP/lib/src/network/WifiHandler/wifiHandler.cpp index 9186aa6..7ab4d9b 100644 --- a/ESP/lib/src/network/WifiHandler/wifiHandler.cpp +++ b/ESP/lib/src/network/WifiHandler/wifiHandler.cpp @@ -1,132 +1,153 @@ #include "WifiHandler.hpp" #include -WiFiHandler::WiFiHandler(ProjectConfig *configManager, StateManager *stateManager) : conf(new wifi_config_t), - configManager(configManager), - stateManager(stateManager) {} +WiFiHandler::WiFiHandler(ProjectConfig *configManager, StateManager *stateManager) : configManager(configManager), + stateManager(stateManager) {} WiFiHandler::~WiFiHandler() {} void WiFiHandler::setupWifi() { - if (ENABLE_ADHOC || stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) - { - this->setUpADHOC(); - return; - } - log_i("Initializing connection to wifi"); - stateManager->setState(WiFiState_e::WiFiState_Connecting); + if (ENABLE_ADHOC || stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) + { + this->setUpADHOC(); + return; + } + log_i("Initializing connection to wifi"); + stateManager->setState(WiFiState_e::WiFiState_Connecting); - std::vector *networks = configManager->getWifiConfigs(); - int connection_timeout = 30000; // 30 seconds + std::vector *networks = configManager->getWifiConfigs(); + int connection_timeout = 30000; // 30 seconds - int count = 0; - unsigned long currentMillis = millis(); - unsigned long _previousMillis = currentMillis; + int count = 0; + unsigned long currentMillis = millis(); + unsigned long _previousMillis = currentMillis; - for (auto networkIterator = networks->begin(); networkIterator != networks->end(); ++networkIterator) - { - log_i("Trying to connect to the %s network", networkIterator->ssid); + for (auto networkIterator = networks->begin(); networkIterator != networks->end(); ++networkIterator) + { + log_i("Trying to connect to the %s network", networkIterator->ssid); - WiFi.begin(networkIterator->ssid, networkIterator->password); - count++; + WiFi.begin(networkIterator->ssid.c_str(), networkIterator->password.c_str()); + count++; - if (!WiFi.isConnected()) - log_i("\n\rCould not connect to %s, trying another network\n\r", networkIterator->ssid); - else - { - log_i("\n\rSuccessfully connected to %s\n\r", networkIterator->ssid); - stateManager->setState(WiFiState_e::WiFiState_Connected); - return; - } + if (!WiFi.isConnected()) + log_i("\n\rCould not connect to %s, trying another network\n\r", networkIterator->ssid); + else + { + log_i("\n\rSuccessfully connected to %s\n\r", networkIterator->ssid); + stateManager->setState(WiFiState_e::WiFiState_Connected); + return; + } - while (WiFi.status() != WL_CONNECTED) - { - stateManager->setState(ProgramStates::DeviceStates::WiFiState_e::WiFiState_Connecting); - currentMillis = millis(); - Serial.print("."); - delay(300); - if (((currentMillis - _previousMillis) >= connection_timeout) && count >= networks->size()) - { - log_i("[INFO]: WiFi connection timed out.\n"); - // we've tried all saved networks, none worked, let's error out - log_e("Could not connect to any of the save networks, check your Wifi credentials"); - stateManager->setState(WiFiState_e::WiFiState_Error); - this->setUpADHOC(); - log_w("Setting up adhoc"); - log_w("Please set your WiFi credentials and reboot the device"); - stateManager->setState(WiFiState_e::WiFiState_ADHOC); - return; - } - } - } + while (WiFi.status() != WL_CONNECTED) + { + stateManager->setState(ProgramStates::DeviceStates::WiFiState_e::WiFiState_Connecting); + currentMillis = millis(); + Serial.print("."); + delay(300); + if (((currentMillis - _previousMillis) >= connection_timeout) && count >= networks->size()) + { + log_i("[INFO]: WiFi connection timed out.\n"); + // we've tried all saved networks, none worked, let's error out + log_e("Could not connect to any of the save networks, check your Wifi credentials"); + stateManager->setState(WiFiState_e::WiFiState_Error); + this->iniSTA(); + log_w("Setting up adhoc"); + log_w("Please set your WiFi credentials and reboot the device"); + stateManager->setState(WiFiState_e::WiFiState_ADHOC); + return; + } + } + } } void WiFiHandler::adhoc(const char *ssid, const char *password, uint8_t channel) { - log_i("[INFO]: Setting Access Point...\n"); + log_i("[INFO]: Setting Access Point...\n"); - log_i("[INFO]: Configuring access point...\n"); - WiFi.mode(WIFI_AP); + log_i("[INFO]: Configuring access point...\n"); + WiFi.mode(WIFI_AP); - Serial.printf("\r\nStarting AP. \r\nAP IP address: "); - IPAddress IP = WiFi.softAPIP(); - Serial.printf("[INFO]: AP IP address: %s.\r\n", IP.toString().c_str()); + Serial.printf("\r\nStarting AP. \r\nAP IP address: "); + IPAddress IP = WiFi.softAPIP(); + Serial.printf("[INFO]: AP IP address: %s.\r\n", IP.toString().c_str()); - // You can remove the password parameter if you want the AP to be open. - WiFi.softAP(ssid, password, channel, 0, 3); // AP mode with password + // You can remove the password parameter if you want the AP to be open. + WiFi.softAP(ssid, password, channel, 0, 3); // AP mode with password - WiFi.setTxPower(WIFI_POWER_11dBm); - stateManager->setState(WiFiState_e::WiFiState_ADHOC); + WiFi.setTxPower(WIFI_POWER_11dBm); + stateManager->setState(WiFiState_e::WiFiState_ADHOC); } +/* +* * +*/ void WiFiHandler::setUpADHOC() { - size_t ssidLen = strlen((char *)conf->ap.ssid); - size_t passwordLen = strlen((char *)conf->ap.password); - char ap_ssid[ssidLen + 1]; - char ap_password[passwordLen + 1]; - auto ret = esp_wifi_get_config(WIFI_IF_STA, &*conf); - if (ret == ESP_OK) - { - memcpy(ap_ssid, conf->ap.ssid, ssidLen); - memcpy(ap_password, conf->ap.password, passwordLen); + log_i("[INFO]: Setting Access Point...\n"); + size_t ssidLen = strlen(configManager->getAPWifiConfig()->ssid.c_str()); + size_t passwordLen = strlen(configManager->getAPWifiConfig()->password.c_str()); + char ssid[ssidLen + 1]; + char password[passwordLen + 1]; + uint8_t channel = configManager->getAPWifiConfig()->channel; + if (ssidLen > 0 || passwordLen > 0) + { + strcpy(ssid, configManager->getAPWifiConfig()->ssid.c_str()); + strcpy(password, configManager->getAPWifiConfig()->password.c_str()); + channel = configManager->getAPWifiConfig()->channel; + } + else + { + strcpy(ssid, WIFI_AP_SSID); + strcpy(password, WIFI_AP_PASSWORD); + channel = ADHOC_CHANNEL; + } - ap_ssid[ssidLen] = '\0'; // Null-terminate the string - ap_password[passwordLen] = '\0'; // Null-terminate the string - return; - } - - if (ssidLen == 0) - { - strcpy(ap_ssid, WIFI_SSID); - strcpy(ap_password, WIFI_PASSWORD); - conf->ap.channel = ADHOC_CHANNEL; - } + this->adhoc(ssid, password, channel); - this->adhoc(ap_ssid, ap_password, conf->ap.channel); + log_i("[INFO]: Configuring access point...\n"); + log_d("[DEBUG]: ssid: %s\n", ssid); + log_d("[DEBUG]: password: %s\n", password); + log_d("[DEBUG]: channel: %d\n", channel); } -// we can't assign wifiManager.resetSettings(); to reset, somehow it gets called straight away. -/** - * @brief Resets the wifi settings to the chosen settings. - * - * @param value - value to store - string. - * @param location - location to store the value. byte array - conf - */ -void WiFiHandler::setWiFiConf(const char *value, uint8_t *location, wifi_config_t *conf) +void WiFiHandler::iniSTA() { - assert(conf != nullptr); -#if defined(ESP32) - if (WiFiGenericClass::getMode() != WIFI_MODE_NULL) - { - esp_wifi_get_config(WIFI_IF_STA, conf); + log_i("[INFO]: Setting up station...\n"); + int connection_timeout = 30000; // 30 seconds + unsigned long currentMillis = millis(); + unsigned long _previousMillis = currentMillis; - memset(location, 0, sizeof(location)); - for (int i = 0; i < sizeof(value) / sizeof(value[0]) && i < sizeof(location); i++) - location[i] = value[i]; + log_i("Trying to connect to the %s network", WIFI_SSID); - esp_wifi_set_config(WIFI_IF_STA, conf); - } -#endif + WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL); + + if (!WiFi.isConnected()) + log_i("\n\rCould not connect to %s, please try another network\n\r", WIFI_SSID); + else + { + log_i("\n\rSuccessfully connected to %s\n\r", WIFI_SSID); + stateManager->setState(WiFiState_e::WiFiState_Connected); + return; + } + + while (WiFi.status() != WL_CONNECTED) + { + stateManager->setState(ProgramStates::DeviceStates::WiFiState_e::WiFiState_Connecting); + currentMillis = millis(); + Serial.print("."); + delay(300); + if ((currentMillis - _previousMillis) >= connection_timeout) + { + log_i("[INFO]: WiFi connection timed out.\n"); + // we've tried all saved networks, none worked, let's error out + log_e("Could not connect to any of the save networks, check your Wifi credentials"); + stateManager->setState(WiFiState_e::WiFiState_Error); + this->iniSTA(); + log_w("Setting up adhoc"); + log_w("Please set your WiFi credentials and reboot the device"); + stateManager->setState(WiFiState_e::WiFiState_ADHOC); + return; + } + } } \ No newline at end of file diff --git a/ESP/lib/src/network/mDNS/MDNSManager.cpp b/ESP/lib/src/network/mDNS/MDNSManager.cpp index 7c5ad13..3c261ac 100644 --- a/ESP/lib/src/network/mDNS/MDNSManager.cpp +++ b/ESP/lib/src/network/mDNS/MDNSManager.cpp @@ -4,7 +4,7 @@ void MDNSHandler::startMDNS() { ProjectConfig::DeviceConfig_t *deviceConfig = configManager->getDeviceConfig(); - if (MDNS.begin(deviceConfig->name)) + if (MDNS.begin(deviceConfig->name.c_str())) { stateManager->setState(MDNSState_e::MDNSState_Starting); MDNS.addService("openIrisTracker", "tcp", 80); diff --git a/ESP/lib/src/network/webserver/webserverHandler.cpp b/ESP/lib/src/network/webserver/webserverHandler.cpp index 1f2651a..f313df0 100644 --- a/ESP/lib/src/network/webserver/webserverHandler.cpp +++ b/ESP/lib/src/network/webserver/webserverHandler.cpp @@ -10,114 +10,118 @@ const char *APIServer::MIMETYPE_HTML{"text/html"}; // const char *APIServer::MIMETYPE_ICO{"image/x-icon"}; const char *APIServer::MIMETYPE_JSON{"application/json"}; +bool APIServer::ssid_write = false; +bool APIServer::pass_write = false; +bool APIServer::channel_write = false; + //********************************************************************************************* //! API Server //********************************************************************************************* APIServer::APIServer(int CONTROL_PORT, CameraHandler *cameraHandler, WiFiHandler *network) : network(network), - server(new AsyncWebServer(CONTROL_PORT)), - cameraHandler(cameraHandler) {} + server(new AsyncWebServer(CONTROL_PORT)), + cameraHandler(cameraHandler) {} void APIServer::startAPIServer() { - begin(); - /* this->server->on( - "/control", - HTTP_GET, - std::bind(&APIServer::command_handler, this, std::placeholders::_1)); */ + begin(); + /* this->server->on( + "/control", + HTTP_GET, + std::bind(&APIServer::command_handler, this, std::placeholders::_1)); */ - //! i have changed this to use lambdas instead of std::bind to avoid the overhead. Lambdas are always more preferable. - server->on("/", HTTP_GET, [&](AsyncWebServerRequest *request) - { request->send(200); }); + //! i have changed this to use lambdas instead of std::bind to avoid the overhead. Lambdas are always more preferable. + server->on("/", HTTP_GET, [&](AsyncWebServerRequest *request) + { request->send(200); }); - // preflight cors check - server->on("/", HTTP_OPTIONS, [&](AsyncWebServerRequest *request) - { + // preflight cors check + server->on("/", HTTP_OPTIONS, [&](AsyncWebServerRequest *request) + { AsyncWebServerResponse* response = request->beginResponse(204); response->addHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS"); response->addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization, FileSize"); response->addHeader("Access-Control-Allow-Credentials", "true"); request->send(response); }); - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); - // std::bind(&APIServer::API_Utilities::notFound, &api_utilities, std::placeholders::_1); - server->onNotFound([&](AsyncWebServerRequest *request) - { api_utilities.notFound(request); }); - // Hex value of BUTT_PLUG_CONTROLLER == 425554545f504c55475f434f4e54524f4c4c4552 - this->server->on("/control", HTTP_GET, [&](AsyncWebServerRequest *request) - { command_handler(request); }); + // std::bind(&APIServer::API_Utilities::notFound, &api_utilities, std::placeholders::_1); + server->onNotFound([&](AsyncWebServerRequest *request) + { api_utilities.notFound(request); }); + // Hex value of BUTT_PLUG_CONTROLLER == 425554545f504c55475f434f4e54524f4c4c4552 + this->server->on("/control", HTTP_GET, [&](AsyncWebServerRequest *request) + { command_handler(request); }); - log_d("Initializing REST API"); - this->server->begin(); + log_d("Initializing REST API"); + this->server->begin(); } void APIServer::findParam(AsyncWebServerRequest *request, const char *param, String &value) { - if (request->hasParam(param)) - { - value = request->getParam(param)->value(); - } + if (request->hasParam(param)) + { + value = request->getParam(param)->value(); + } } void APIServer::begin() { - command_map_wifi_conf.emplace("ssid", [this](const char *value) -> void - { setSSID(value); }); - command_map_wifi_conf.emplace("password", [this](const char *value) -> void - { setPass(value); }); - command_map_wifi_conf.emplace("channel", [this](const char *value) -> void - { setChannel(value); }); + command_map_wifi_conf.emplace("ssid", [this](const char *value) -> void + { setSSID(value); }); + command_map_wifi_conf.emplace("password", [this](const char *value) -> void + { setPass(value); }); + command_map_wifi_conf.emplace("channel", [this](const char *value) -> void + { setChannel(value); }); - command_map_funct.emplace("reboot_device", [this](void) -> void - { rebootDevice(); }); - command_map_funct.emplace("reset_config", [this](void) -> void - { factoryReset(); }); + command_map_funct.emplace("reboot_device", [this](void) -> void + { rebootDevice(); }); + command_map_funct.emplace("reset_config", [this](void) -> void + { factoryReset(); }); - command_map_json.emplace("data_json", [this](AsyncWebServerRequest *request) -> void - { setDataJson(request); }); - command_map_json.emplace("config_json", [this](AsyncWebServerRequest *request) -> void - { setConfigJson(request); }); - command_map_json.emplace("settings_json", [this](AsyncWebServerRequest *request) -> void - { setSettingsJson(request); }); + command_map_json.emplace("data_json", [this](AsyncWebServerRequest *request) -> void + { setDataJson(request); }); + command_map_json.emplace("config_json", [this](AsyncWebServerRequest *request) -> void + { setConfigJson(request); }); + command_map_json.emplace("settings_json", [this](AsyncWebServerRequest *request) -> void + { setSettingsJson(request); }); } void APIServer::command_handler(AsyncWebServerRequest *request) { - int params = request->params(); - for (int i = 0; i < params; i++) - { - AsyncWebParameter *param = request->getParam(i); - { - command_map_wifi_conf_t::const_iterator it_wifi_conf = command_map_wifi_conf.find(param->name().c_str()); - command_map_funct_t::const_iterator it_funct = command_map_funct.find(param->name().c_str()); - command_map_json_t::const_iterator it_json = command_map_json.find(param->name().c_str()); + int params = request->params(); + for (int i = 0; i < params; i++) + { + AsyncWebParameter *param = request->getParam(i); + { + command_map_wifi_conf_t::const_iterator it_wifi_conf = command_map_wifi_conf.find(param->name().c_str()); + command_map_funct_t::const_iterator it_funct = command_map_funct.find(param->name().c_str()); + command_map_json_t::const_iterator it_json = command_map_json.find(param->name().c_str()); - if (it_wifi_conf != command_map_wifi_conf.end()) - { - command_map_wifi_conf.at(param->name().c_str())(param->value().c_str()); - auto &key_it = it_wifi_conf->first; - log_i("Command %s executed", key_it.c_str()); - } - else if (it_funct != command_map_funct.end()) - { - command_map_funct.at(param->name().c_str())(); - auto &key_it_funct = it_funct->first; - log_i("Command %s executed", key_it_funct.c_str()); - } - else if (it_json != command_map_json.end()) - { - command_map_json.at(param->name().c_str())(request); - auto &key_it_json = it_json->first; - log_i("Command %s executed", key_it_json.c_str()); - } - else - { - log_i("Command not found"); - } - } - log_i("GET[%s]: %s\n", param->name().c_str(), param->value().c_str()); - } + if (it_wifi_conf != command_map_wifi_conf.end()) + { + command_map_wifi_conf.at(param->name().c_str())(param->value().c_str()); + auto &key_it = it_wifi_conf->first; + log_i("Command %s executed", key_it.c_str()); + } + else if (it_funct != command_map_funct.end()) + { + command_map_funct.at(param->name().c_str())(); + auto &key_it_funct = it_funct->first; + log_i("Command %s executed", key_it_funct.c_str()); + } + else if (it_json != command_map_json.end()) + { + command_map_json.at(param->name().c_str())(request); + auto &key_it_json = it_json->first; + log_i("Command %s executed", key_it_json.c_str()); + } + else + { + log_i("Command not found"); + } + } + log_i("GET[%s]: %s\n", param->name().c_str(), param->value().c_str()); + } } //********************************************************************************************* @@ -125,67 +129,86 @@ void APIServer::command_handler(AsyncWebServerRequest *request) //********************************************************************************************* void APIServer::setSSID(const char *value) { -#if ENABLE_ADHOC - network->setWiFiConf(value, network->conf->ap.ssid, &*network->conf); -#else - network->setWiFiConf(value, network->conf->sta.ssid, &*network->conf); -#endif // ENABLE_ADHOC + if (network->stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) + this->wifiConfig.local_WifiConfig[0].ssid = value; + else + this->wifiConfig.local_WifiConfig[1].ssid = value; + ssid_write = true; } void APIServer::setPass(const char *value) { -#if ENABLE_ADHOC - network->setWiFiConf(network->conf->ap.password, value, &*network->conf); -#else - network->setWiFiConf(value, network->conf->sta.password, &*network->conf); -#endif // ENABLE_ADHOC + if (network->stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) + this->wifiConfig.local_WifiConfig[0].pass = value; + else + this->wifiConfig.local_WifiConfig[1].pass = value; + pass_write = true; } void APIServer::setChannel(const char *value) { -#if ENABLE_ADHOC - network->setWiFiConf(value, network->conf->ap.channel, &*network->conf); -#else - network->setWiFiConf(value, &network->conf->sta.channel, &*network->conf); -#endif // ENABLE_ADHOC + if (network->stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) + this->wifiConfig.local_WifiConfig[0].channel = atoi(value); + else + this->wifiConfig.local_WifiConfig[1].channel = atoi(value); + channel_write = true; +} + +/** + * * Trigger in main loop to save config to flash + * ? Should we force the users to update all config params before triggering a config write? + */ +void APIServer::triggerWifiConfigWrite() +{ + if (ssid_write && pass_write && channel_write) + { + ssid_write = false; + pass_write = false; + channel_write = false; + if (network->stateManager->getCurrentState() == WiFiState_e::WiFiState_ADHOC) + network->configManager->setWifiConfig(wifiConfig.local_WifiConfig[0].ssid.c_str(), wifiConfig.local_WifiConfig[0].ssid.c_str(), wifiConfig.local_WifiConfig[0].pass.c_str(), &wifiConfig.local_WifiConfig[0].channel, true); + else + network->configManager->setWifiConfig(wifiConfig.local_WifiConfig[1].ssid.c_str(), wifiConfig.local_WifiConfig[1].ssid.c_str(), wifiConfig.local_WifiConfig[1].pass.c_str(), &wifiConfig.local_WifiConfig[1].channel, true); + network->configManager->save(); + } } void APIServer::setDataJson(AsyncWebServerRequest *request) { - network->configManager->getDeviceConfig()->data_json = true; - api_utilities.my_delay(1L); - String temp = network->configManager->getDeviceConfig()->data_json_string; - request->send(200, MIMETYPE_JSON, temp); - temp = ""; + network->configManager->getDeviceConfig()->data_json = true; + api_utilities.my_delay(1L); + String temp = network->configManager->getDeviceConfig()->data_json_string; + request->send(200, MIMETYPE_JSON, temp); + temp = ""; } void APIServer::setConfigJson(AsyncWebServerRequest *request) { - network->configManager->getDeviceConfig()->config_json = true; - api_utilities.my_delay(1L); - String temp = network->configManager->getDeviceConfig()->config_json_string; - request->send(200, MIMETYPE_JSON, temp); - temp = ""; + network->configManager->getDeviceConfig()->config_json = true; + api_utilities.my_delay(1L); + String temp = network->configManager->getDeviceConfig()->config_json_string; + request->send(200, MIMETYPE_JSON, temp); + temp = ""; } void APIServer::setSettingsJson(AsyncWebServerRequest *request) { - network->configManager->getDeviceConfig()->settings_json = true; - api_utilities.my_delay(1L); - String temp = network->configManager->getDeviceConfig()->settings_json_string; - request->send(200, MIMETYPE_JSON, temp); - temp = ""; + network->configManager->getDeviceConfig()->settings_json = true; + api_utilities.my_delay(1L); + String temp = network->configManager->getDeviceConfig()->settings_json_string; + request->send(200, MIMETYPE_JSON, temp); + temp = ""; } void APIServer::rebootDevice() { - delay(20000); - ESP.restart(); + delay(20000); + ESP.restart(); } void APIServer::factoryReset() { - network->configManager->reset(); + network->configManager->reset(); } //********************************************************************************************* @@ -194,56 +217,55 @@ void APIServer::factoryReset() APIServer::API_Utilities::API_Utilities() {} -std::string -APIServer::API_Utilities::shaEncoder(std::string data) +std::string APIServer::API_Utilities::shaEncoder(std::string data) { - const char *data_c = data.c_str(); - int size = 20; - uint8_t hash[size]; - mbedtls_md_context_t ctx; - mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + const char *data_c = data.c_str(); + int size = 20; + uint8_t hash[size]; + mbedtls_md_context_t ctx; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; - const size_t len = strlen(data_c); - mbedtls_md_init(&ctx); - mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, (const unsigned char *)data_c, len); - mbedtls_md_finish(&ctx, hash); - mbedtls_md_free(&ctx); + const size_t len = strlen(data_c); + mbedtls_md_init(&ctx); + mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0); + mbedtls_md_starts(&ctx); + mbedtls_md_update(&ctx, (const unsigned char *)data_c, len); + mbedtls_md_finish(&ctx, hash); + mbedtls_md_free(&ctx); - std::string hash_string = ""; - for (uint16_t i = 0; i < size; i++) - { - std::string hex = String(hash[i], HEX).c_str(); - if (hex.length() < 2) - { - hex = "0" + hex; - } - hash_string += hex; - } - return hash_string; + std::string hash_string = ""; + for (uint16_t i = 0; i < size; i++) + { + std::string hex = String(hash[i], HEX).c_str(); + if (hex.length() < 2) + { + hex = "0" + hex; + } + hash_string += hex; + } + return hash_string; } void APIServer::API_Utilities::notFound(AsyncWebServerRequest *request) { - try - { - log_i("%s", _networkMethodsMap[request->method()]); - } - catch (const std::exception &e) - { - log_i("UNKNOWN"); - } + try + { + log_i("%s", _networkMethodsMap[request->method()]); + } + catch (const std::exception &e) + { + log_i("UNKNOWN"); + } - log_i(" http://%s%s/\n", request->host().c_str(), request->url().c_str()); - request->send(404, "text/plain", "Not found."); + log_i(" http://%s%s/\n", request->host().c_str(), request->url().c_str()); + request->send(404, "text/plain", "Not found."); } void APIServer::API_Utilities::my_delay(volatile long delay_time) { - delay_time = delay_time * 1e6L; - for (volatile long count = delay_time; count > 0L; count--) - ; + delay_time = delay_time * 1e6L; + for (volatile long count = delay_time; count > 0L; count--) + ; } APIServer::API_Utilities api_utilities; \ No newline at end of file diff --git a/ESP/lib/src/network/webserver/webserverHandler.hpp b/ESP/lib/src/network/webserver/webserverHandler.hpp index 75673ff..d78590d 100644 --- a/ESP/lib/src/network/webserver/webserverHandler.hpp +++ b/ESP/lib/src/network/webserver/webserverHandler.hpp @@ -21,7 +21,6 @@ #include "io/camera/cameraHandler.hpp" #include "network/WifiHandler/WifiHandler.hpp" - class APIServer { private: @@ -62,11 +61,29 @@ private: /* static const char *MIMETYPE_JPG; */ /* static const char *MIMETYPE_ICO; */ static const char *MIMETYPE_JSON; + static bool ssid_write; + static bool pass_write; + static bool channel_write; + + struct LocalWifiConfig + { + std::string ssid; + std::string pass; + uint8_t channel; + }; + + struct WifiConfig + { + std::vector local_WifiConfig; + }; + + WifiConfig wifiConfig; public: APIServer(int CONTROL_PORT, CameraHandler *cameraHandler, WiFiHandler *network); void begin(); void startAPIServer(); + void triggerWifiConfigWrite(); void findParam(AsyncWebServerRequest *request, const char *param, String &value); class API_Utilities diff --git a/ESP/platformio.ini b/ESP/platformio.ini index 7157017..daf34a5 100644 --- a/ESP/platformio.ini +++ b/ESP/platformio.ini @@ -14,8 +14,11 @@ default_envs = esp32Cam ; do not change this value ; The below options are available for all environments ; The ssid and password are requried for the trackers to connect to your network!!! [wifi] -ssid="EyeTrackVR" ; your wifi network name goes here -password="test" ; Place your Wifi password here +ssid="" ; your wifi network name goes here +password="" ; your wifi network password goes here +channel=10 ; wifi channel +ap_ssid="EyeTrackVR" ; your AP wifi network name goes here +ap_password="test" ; Place your AP Wifi password here OTAPassword="" ; if empty, no password will be required OTAServerPort=3232 enableADHOC=0 ; 0 = disable, 1 = enable @@ -80,6 +83,8 @@ build_flags = -DENABLE_ADHOC=${wifi.enableADHOC} ; -DADHOC_CHANNEL=${wifi.adhocChannel} ; + + -DWIFI_CHANNEL=${wifi.channel} ; '-DMDNS_TRACKER_NAME="OpenIrisTracker"' ; Set the tracker name - The string literal tells platformio to include the quatations in the string - making sure that the compiler sees the string as a cstring @@ -89,6 +94,10 @@ build_flags = '-DWIFI_PASSWORD=${wifi.password}' ; Set the users wifi network password + '-DWIFI_AP_SSID=${wifi.ap_ssid}' ; Set the users wifi network name + + '-DWIFI_AP_PASSWORD=${wifi.ap_password}' ; Set the users wifi network password + -DDEBUG_ESP_PORT=Serial -DCORE_DEBUG_LEVEL=4 diff --git a/ESP/src/main.cpp b/ESP/src/main.cpp index 72de9bb..45865ca 100644 --- a/ESP/src/main.cpp +++ b/ESP/src/main.cpp @@ -77,5 +77,6 @@ void loop() { ota.HandleOTAUpdate(); ledManager->displayStatus(); + apiServer->triggerWifiConfigWrite(); // serialManager->handleSerial(); } \ No newline at end of file