From 857526a3586fac3230968e630d6eefdd54a2f136 Mon Sep 17 00:00:00 2001 From: pulipakaa24 Date: Wed, 17 Dec 2025 21:52:00 -0600 Subject: [PATCH] Ready for NVS and Auth --- include/BLE.cpp | 137 +++++++++++++++++++++++++++++++++++++---------- include/BLE.hpp | 58 +++----------------- include/WiFi.cpp | 38 ++++++------- include/WiFi.hpp | 11 ++-- 4 files changed, 139 insertions(+), 105 deletions(-) diff --git a/include/BLE.cpp b/include/BLE.cpp index 08e5374..bac7ab3 100644 --- a/include/BLE.cpp +++ b/include/BLE.cpp @@ -2,15 +2,15 @@ #include "NimBLEDevice.h" #include "WiFi.hpp" -bool flag_scan_requested = false; +std::atomic flag_scan_requested{false}; +std::atomic credsGiven{false}; +std::mutex dataMutex; -std::string tempSSID = ""; -std::string tempPassword = ""; -bool SSIDGiven = false; -bool passGiven = false; - -std::string token = ""; -bool tokenGiven = false; +wifi_auth_mode_t auth; +static std::string SSID = ""; +static std::string TOKEN = ""; +static std::string PASS = ""; +static std::string UNAME = ""; // Global pointers to characteristics for notification support NimBLECharacteristic* ssidListChar = nullptr; @@ -42,26 +42,13 @@ NimBLEAdvertising* initBLE() { ); ssidListChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications - // 0x0001 - SSID (WRITE) - NimBLECharacteristic *ssidChar = pService->createCharacteristic( + // 0x0001 - Credentials JSON (WRITE) - Replaces separate SSID/Password/Token + // Expected JSON format: {"ssid":"network","password":"pass","token":"optional"} + NimBLECharacteristic *credsChar = pService->createCharacteristic( "0001", NIMBLE_PROPERTY::WRITE ); - ssidChar->setCallbacks(charCallbacks); - - // 0x0002 - Password (WRITE) - NimBLECharacteristic *passChar = pService->createCharacteristic( - "0002", - NIMBLE_PROPERTY::WRITE - ); - passChar->setCallbacks(charCallbacks); - - // 0x0003 - Token (WRITE) - NimBLECharacteristic *tokenChar = pService->createCharacteristic( - "0003", - NIMBLE_PROPERTY::WRITE - ); - tokenChar->setCallbacks(charCallbacks); + credsChar->setCallbacks(charCallbacks); // 0x0004 - SSID Refresh (WRITE) NimBLECharacteristic *ssidRefreshChar = pService->createCharacteristic( @@ -93,10 +80,106 @@ NimBLEAdvertising* initBLE() { return pAdvertising; } -void BLEtick(NimBLEAdvertising* pAdvertising) { +bool BLEtick(NimBLEAdvertising* pAdvertising) { if(flag_scan_requested) { flag_scan_requested = false; printf("Scanning WiFi...\n"); scanAndUpdateSSIDList(); } -} \ No newline at end of file + else if (credsGiven) { + credsGiven = false; + std::string tmpSSID; + std::string tmpUNAME; + std::string tmpPASS; + wifi_auth_mode_t tmpAUTH; + { + std::lock_guard lock(dataMutex); + tmpSSID = SSID; + tmpUNAME = UNAME; + tmpPASS = PASS; + tmpAUTH = auth; + } + + bool wifiConnect; + if (tmpAUTH == WIFI_AUTH_WPA2_ENTERPRISE || tmpAUTH == WIFI_AUTH_WPA3_ENTERPRISE) + wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpUNAME.c_str(), tmpPASS.c_str(), tmpAUTH); + else wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpPASS.c_str(), tmpAUTH); + if (!wifiConnect) return false; + + // save wifi credentials here + // Authenticate with server here + } + return false; +} + +void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) { + std::string val = pChar->getValue(); + std::string uuidStr = pChar->getUUID().toString(); + + printf("onWrite called! UUID: %s, Value length: %d\n", uuidStr.c_str(), val.length()); + + // Check which characteristic was written to + if (uuidStr.find("0001") != std::string::npos) { + // Credentials JSON characteristic + if (val.length() > 0) { + printf("Received JSON: %s\n", val.c_str()); + + // Parse JSON using cJSON + cJSON *root = cJSON_Parse(val.c_str()); + if (root != NULL) { + cJSON *ssid = cJSON_GetObjectItem(root, "ssid"); + cJSON *password = cJSON_GetObjectItem(root, "password"); + cJSON *token = cJSON_GetObjectItem(root, "token"); + cJSON *authType = cJSON_GetObjectItem(root, "auth"); + cJSON *uname = cJSON_GetObjectItem(root, "uname"); + + bool enterprise = false; + bool open = false; + bool error = false; + if (cJSON_IsNumber(authType)) { + enterprise = authType->valueint == WIFI_AUTH_WPA2_ENTERPRISE || + authType->valueint == WIFI_AUTH_WPA3_ENTERPRISE; + open = authType->valueint == WIFI_AUTH_OPEN; + error = authType->valueint < 0 || authType->valueint >= WIFI_AUTH_MAX; + } + else error = true; + if (error) { + printf("ERROR: Invalid Auth mode passed in with JSON.\n"); + credsGiven = false; + cJSON_Delete(root); + return; + } + + bool ssidPresent = cJSON_IsString(ssid) && ssid->valuestring != NULL; + bool passPresent = cJSON_IsString(password) && password->valuestring != NULL; + bool unamePresent = cJSON_IsString(uname) && uname->valuestring != NULL; + bool tokenPresent = cJSON_IsString(token) && token->valuestring != NULL; + bool tempCredsGiven = tokenPresent && ssidPresent && (passPresent || open) && + (unamePresent || !enterprise); + + if (tempCredsGiven) { + printf("Received credentials, will attempt connection\n"); + std::lock_guard lock(dataMutex); + + auth = (wifi_auth_mode_t)(authType->valueint); + SSID = ssid->valuestring; + TOKEN = token->valuestring; + PASS = passPresent ? password->valuestring : ""; + UNAME = unamePresent ? uname->valuestring : ""; + credsGiven = tempCredsGiven; // update the global flag. + } + else printf("ERROR: Did not receive necessary credentials.\n"); + cJSON_Delete(root); + } else { + printf("Failed to parse JSON\n"); + credsGiven = false; + } + } + } + else if (uuidStr.find("0004") != std::string::npos) { + // Refresh characteristic + printf("Refresh Requested\n"); + flag_scan_requested = true; + } + else printf("Unknown UUID: %s\n", uuidStr.c_str()); + } \ No newline at end of file diff --git a/include/BLE.hpp b/include/BLE.hpp index 23a91fa..57ac57d 100644 --- a/include/BLE.hpp +++ b/include/BLE.hpp @@ -2,16 +2,11 @@ #define BLE_H #include "NimBLEDevice.h" - -extern bool flag_scan_requested; - -extern std::string tempSSID; -extern std::string tempPassword; -extern bool SSIDGiven; -extern bool passGiven; - -extern std::string token; -extern bool tokenGiven; +#include "cJSON.h" +#include +#include +#include +#include "esp_wifi_types.h" // Global pointers to characteristics for notification support extern NimBLECharacteristic* ssidListChar; @@ -29,49 +24,10 @@ class MyServerCallbacks : public NimBLEServerCallbacks { }; class MyCharCallbacks : public NimBLECharacteristicCallbacks { - void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) { - std::string val = pChar->getValue(); - std::string uuidStr = pChar->getUUID().toString(); - - printf("onWrite called! UUID: %s, Value length: %d\n", uuidStr.c_str(), val.length()); - - // Check which characteristic was written to - if (uuidStr.find("0001") != std::string::npos) { - // SSID characteristic - if (val.length() > 0) { - printf("Received SSID: %s\n", val.c_str()); - tempSSID = val; - SSIDGiven = true; - } - } - else if (uuidStr.find("0002") != std::string::npos) { - // Password characteristic - if (val.length() > 0) { - printf("Received Password: %s\n", val.c_str()); - passGiven = true; - tempPassword = val; - } - } - else if (uuidStr.find("0003") != std::string::npos) { - // Token characteristic - if (val.length() > 0) { - printf("Received Token: %s\n", val.c_str()); - tokenGiven = true; - token = val; - } - } - else if (uuidStr.find("0004") != std::string::npos) { - // Refresh characteristic - printf("Refresh Requested\n"); - flag_scan_requested = true; - } - else { - printf("Unknown UUID: %s\n", uuidStr.c_str()); - } - } + void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo); }; NimBLEAdvertising* initBLE(); -void BLEtick(NimBLEAdvertising* pAdvertising); +bool BLEtick(NimBLEAdvertising* pAdvertising); #endif \ No newline at end of file diff --git a/include/WiFi.cpp b/include/WiFi.cpp index fb1c126..e56a242 100644 --- a/include/WiFi.cpp +++ b/include/WiFi.cpp @@ -58,6 +58,7 @@ void WiFi::event_handler(void* arg, esp_event_base_t event_base, } void WiFi::init() { + s_wifi_event_group = xEventGroupCreate(); // 1. Init Network Interface ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); @@ -105,53 +106,46 @@ std::string WiFi::getIP() { return std::string(buf); } -bool WiFi::attemptConnect(char *SSID, char *PW, wifi_auth_mode_t authMode) { +bool WiFi::attemptConnect(const std::string ssid, const std::string password, + const wifi_auth_mode_t authMode) { + esp_wifi_sta_enterprise_disable(); + esp_wifi_disconnect(); + wifi_config_t wifi_config = {}; - strncpy((char*)wifi_config.sta.ssid, SSID, sizeof(wifi_config.sta.ssid)); - strncpy((char*)wifi_config.sta.password, PW, sizeof(wifi_config.sta.password)); + snprintf((char*)wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), "%s", ssid.c_str()); + snprintf((char*)wifi_config.sta.password, sizeof(wifi_config.sta.password), "%s", password.c_str()); wifi_config.sta.threshold.authmode = authMode; wifi_config.sta.pmf_cfg.capable = true; wifi_config.sta.pmf_cfg.required = false; esp_wifi_set_config(WIFI_IF_STA, &wifi_config); - return awaitConnected(); } -bool WiFi::attemptConnect(char *SSID, char *username, char *PW, wifi_auth_mode_t authMode) { - std::string ssid = SSID; - std::string uname = username; - std::string password = PW; +bool WiFi::attemptConnect(const std::string ssid, const std::string uname, + const std::string password, const wifi_auth_mode_t authMode) { + esp_wifi_disconnect(); + // 1. Auto-generate the Identity std::string identity = "anonymous"; - - // Check if the username is an email (contains '@') size_t atPos = uname.find('@'); - if (atPos != std::string::npos) { - // Append the domain from the real username - // Example: "user@gmail.com" -> "anonymous@gmail.com" - identity += uname.substr(atPos); - } + if (atPos != std::string::npos) identity += uname.substr(atPos); printf("Real User: %s\n", uname.c_str()); printf("Outer ID : %s (Privacy Safe)\n", identity.c_str()); - // 2. Clear & Config - esp_wifi_disconnect(); - wifi_config_t wifi_config = {}; - strncpy((char*)wifi_config.sta.ssid, ssid.c_str(), sizeof(wifi_config.sta.ssid)); + snprintf((char*)wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), "%s", ssid.c_str()); wifi_config.sta.threshold.authmode = authMode; - esp_wifi_set_config(WIFI_IF_STA, &wifi_config); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); // 3. Set the calculated identity (using new ESP-IDF v5.x API) + esp_wifi_sta_enterprise_enable(); esp_eap_client_set_identity((uint8_t *)identity.c_str(), identity.length()); esp_eap_client_set_username((uint8_t *)uname.c_str(), uname.length()); esp_eap_client_set_password((uint8_t *)password.c_str(), password.length()); - esp_wifi_sta_enterprise_enable(); - return awaitConnected(); } diff --git a/include/WiFi.hpp b/include/WiFi.hpp index 06826ec..297cfd8 100644 --- a/include/WiFi.hpp +++ b/include/WiFi.hpp @@ -4,14 +4,13 @@ #include "esp_wifi.h" #include -extern WiFi bmWiFi; - class WiFi { public: static void init(); - static bool attemptConnect(char *SSID, char *PW, wifi_auth_mode_t authMode); - static bool attemptConnect(char *SSID, char *username, char *PW, - wifi_auth_mode_t authMode); + static bool attemptConnect(const std::string ssid, const std::string password, + const wifi_auth_mode_t authMode); + static bool attemptConnect(const std::string ssid, const std::string uname, + const std::string password, const wifi_auth_mode_t authMode); private: static bool authFailed; static bool awaitConnected(); @@ -25,6 +24,8 @@ class WiFi { static std::string getIP(); }; +extern WiFi bmWiFi; + void scanAndUpdateSSIDList(); #endif \ No newline at end of file