2025-11-29 16:24:56 -06:00
|
|
|
#include "setup.hpp"
|
|
|
|
|
#include "BLE.hpp"
|
|
|
|
|
#include "WiFi.hpp"
|
2025-12-24 18:39:21 -06:00
|
|
|
#include "nvs_flash.h"
|
|
|
|
|
#include "defines.h"
|
|
|
|
|
#include "bmHTTP.hpp"
|
|
|
|
|
#include "socketIO.hpp"
|
2026-01-03 22:59:36 -06:00
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
|
|
// External declarations from BLE.cpp
|
|
|
|
|
extern std::mutex dataMutex;
|
|
|
|
|
extern wifi_auth_mode_t auth;
|
|
|
|
|
extern std::string SSID;
|
|
|
|
|
extern std::string PASS;
|
|
|
|
|
extern std::string UNAME;
|
|
|
|
|
extern std::string TOKEN;
|
|
|
|
|
extern std::atomic<bool> scanBlock;
|
|
|
|
|
extern std::atomic<bool> finalAuth;
|
|
|
|
|
|
|
|
|
|
// External functions from BLE.cpp
|
|
|
|
|
extern void notifyConnectionStatus(bool success);
|
|
|
|
|
extern void notifyAuthStatus(bool success);
|
|
|
|
|
|
|
|
|
|
// BLE setup task - event-driven instead of polling
|
|
|
|
|
void bleSetupTask(void* arg) {
|
|
|
|
|
NimBLEAdvertising* pAdvertising = initBLE();
|
|
|
|
|
EventBits_t bits;
|
|
|
|
|
|
|
|
|
|
printf("BLE setup task started\n");
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
// Wait for BLE events instead of polling
|
|
|
|
|
bits = xEventGroupWaitBits(
|
|
|
|
|
g_system_events,
|
|
|
|
|
EVENT_BLE_SCAN_REQUEST | EVENT_BLE_CREDS_RECEIVED | EVENT_BLE_TOKEN_RECEIVED,
|
|
|
|
|
pdTRUE, // Clear bits on exit
|
|
|
|
|
pdFALSE, // Wait for ANY bit (not all)
|
|
|
|
|
portMAX_DELAY // Block forever until event
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (bits & EVENT_BLE_SCAN_REQUEST) {
|
|
|
|
|
if (!scanBlock) {
|
|
|
|
|
scanBlock = true;
|
|
|
|
|
printf("Scanning WiFi...\n");
|
|
|
|
|
bmWiFi.scanAndUpdateSSIDList();
|
|
|
|
|
}
|
|
|
|
|
else printf("Duplicate scan request\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bits & EVENT_BLE_CREDS_RECEIVED) {
|
|
|
|
|
std::string tmpSSID;
|
|
|
|
|
std::string tmpUNAME;
|
|
|
|
|
std::string tmpPASS;
|
|
|
|
|
wifi_auth_mode_t tmpAUTH;
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> 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, tmpUNAME, tmpPASS, tmpAUTH);
|
|
|
|
|
else wifiConnect = bmWiFi.attemptConnect(tmpSSID, tmpPASS, tmpAUTH);
|
|
|
|
|
|
|
|
|
|
if (!wifiConnect) {
|
|
|
|
|
notifyConnectionStatus(false);
|
|
|
|
|
printf("Connection failed\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvs_handle_t WiFiHandle;
|
|
|
|
|
esp_err_t err = nvs_open(nvsWiFi, NVS_READWRITE, &WiFiHandle);
|
|
|
|
|
if (err == ESP_OK) {
|
|
|
|
|
esp_err_t saveErr = ESP_OK;
|
|
|
|
|
saveErr |= nvs_set_str(WiFiHandle, ssidTag, tmpSSID.c_str());
|
|
|
|
|
saveErr |= nvs_set_str(WiFiHandle, passTag, tmpPASS.c_str());
|
|
|
|
|
saveErr |= nvs_set_u8(WiFiHandle, authTag, (uint8_t)tmpAUTH);
|
|
|
|
|
|
|
|
|
|
if (tmpUNAME.length() > 0) {
|
|
|
|
|
saveErr |= nvs_set_str(WiFiHandle, unameTag, tmpUNAME.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (saveErr == ESP_OK) {
|
|
|
|
|
nvs_commit(WiFiHandle);
|
|
|
|
|
printf("WiFi credentials saved to NVS\n");
|
|
|
|
|
notifyConnectionStatus(true);
|
|
|
|
|
} else {
|
|
|
|
|
printf("Failed to save WiFi credentials\n");
|
|
|
|
|
notifyConnectionStatus(false);
|
|
|
|
|
}
|
|
|
|
|
nvs_close(WiFiHandle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bits & EVENT_BLE_TOKEN_RECEIVED) {
|
|
|
|
|
std::string tmpTOKEN;
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(dataMutex);
|
|
|
|
|
tmpTOKEN = TOKEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cJSON* JSONresponse = NULL;
|
|
|
|
|
if (httpGET("api/devices/auth", tmpTOKEN, JSONresponse)) {
|
|
|
|
|
cJSON *success = cJSON_GetObjectItem(JSONresponse, "success");
|
|
|
|
|
bool authSuccess = cJSON_IsTrue(success);
|
|
|
|
|
|
|
|
|
|
if (authSuccess) {
|
|
|
|
|
nvs_handle_t authHandle;
|
|
|
|
|
if (nvs_open(nvsAuth, NVS_READWRITE, &authHandle) == ESP_OK) {
|
|
|
|
|
if (nvs_set_str(authHandle, tokenTag, tmpTOKEN.c_str()) == ESP_OK) {
|
|
|
|
|
nvs_commit(authHandle);
|
|
|
|
|
printf("Token saved to NVS\n");
|
|
|
|
|
notifyAuthStatus(true);
|
|
|
|
|
finalAuth = true;
|
|
|
|
|
|
|
|
|
|
// Task complete - delete itself
|
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
}
|
|
|
|
|
nvs_close(authHandle);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
printf("Token authentication failed\n");
|
|
|
|
|
notifyAuthStatus(false);
|
|
|
|
|
}
|
|
|
|
|
cJSON_Delete(JSONresponse);
|
|
|
|
|
} else {
|
|
|
|
|
printf("HTTP request failed\n");
|
|
|
|
|
notifyAuthStatus(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-29 16:24:56 -06:00
|
|
|
|
|
|
|
|
void initialSetup() {
|
2025-12-23 17:21:44 -06:00
|
|
|
printf("Entered Setup\n");
|
2026-01-03 22:59:36 -06:00
|
|
|
|
|
|
|
|
// Create BLE setup task instead of polling loop
|
|
|
|
|
xTaskCreate(bleSetupTask, "ble_setup", 8192, NULL, BLE_TASK_PRIORITY, NULL);
|
|
|
|
|
|
|
|
|
|
// Wait for BLE setup to complete (finalAuth = true)
|
|
|
|
|
while (!finalAuth) {
|
2025-12-23 17:21:44 -06:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
2025-11-29 16:24:56 -06:00
|
|
|
}
|
2026-01-03 22:59:36 -06:00
|
|
|
|
|
|
|
|
printf("BLE setup complete\n");
|
2025-12-24 18:39:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setupLoop() {
|
|
|
|
|
bool initSuccess = false;
|
|
|
|
|
while(!initSuccess) {
|
|
|
|
|
nvs_handle_t WiFiHandle;
|
|
|
|
|
if (nvs_open(nvsWiFi, NVS_READONLY, &WiFiHandle) == ESP_OK) {
|
|
|
|
|
size_t ssidSize;
|
|
|
|
|
esp_err_t WiFiPrefsError = nvs_get_str(WiFiHandle, ssidTag, NULL, &ssidSize);
|
|
|
|
|
size_t pwSize;
|
|
|
|
|
WiFiPrefsError |= nvs_get_str(WiFiHandle, passTag, NULL, &pwSize);
|
|
|
|
|
uint8_t authMode;
|
|
|
|
|
WiFiPrefsError |= nvs_get_u8(WiFiHandle, authTag, &authMode);
|
|
|
|
|
if (WiFiPrefsError == ESP_ERR_NVS_NOT_FOUND) {
|
|
|
|
|
printf("Didn't find creds\n");
|
|
|
|
|
// Make the RGB LED a certain color (Blue?)
|
|
|
|
|
nvs_close(WiFiHandle);
|
|
|
|
|
initialSetup();
|
|
|
|
|
} else if (WiFiPrefsError == ESP_OK) {
|
|
|
|
|
char ssid[ssidSize];
|
|
|
|
|
nvs_get_str(WiFiHandle, ssidTag, ssid, &ssidSize);
|
|
|
|
|
char pw[pwSize];
|
|
|
|
|
nvs_get_str(WiFiHandle, passTag, pw, &pwSize);
|
|
|
|
|
nvs_close(WiFiHandle);
|
|
|
|
|
if (!bmWiFi.attemptConnect(ssid, pw, (wifi_auth_mode_t)authMode)) {
|
|
|
|
|
// Make RGB LED certain color (Blue?)
|
|
|
|
|
printf("Found credentials, failed to connect.\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("Connected to WiFi from NVS credentials\n");
|
|
|
|
|
nvs_handle_t authHandle;
|
|
|
|
|
if (nvs_open(nvsAuth, NVS_READONLY, &authHandle) == ESP_OK) {
|
|
|
|
|
size_t tokenSize;
|
|
|
|
|
if (nvs_get_str(authHandle, tokenTag, NULL, &tokenSize) == ESP_OK) {
|
|
|
|
|
char token[tokenSize];
|
|
|
|
|
nvs_get_str(authHandle, tokenTag, token, &tokenSize);
|
|
|
|
|
nvs_close(authHandle);
|
|
|
|
|
|
|
|
|
|
// Use permanent device token to connect to Socket.IO
|
|
|
|
|
// The server will verify the token during connection handshake
|
|
|
|
|
webToken = std::string(token);
|
|
|
|
|
printf("Connecting to Socket.IO server with saved token...\n");
|
|
|
|
|
initSocketIO();
|
|
|
|
|
|
2026-01-03 22:59:36 -06:00
|
|
|
// Wait for connection event with timeout
|
|
|
|
|
EventBits_t bits = xEventGroupWaitBits(
|
|
|
|
|
g_system_events,
|
|
|
|
|
EVENT_SOCKETIO_CONNECTED | EVENT_SOCKETIO_DISCONNECTED,
|
|
|
|
|
pdTRUE, // Clear on exit
|
|
|
|
|
pdFALSE, // Wait for ANY bit
|
|
|
|
|
pdMS_TO_TICKS(10000) // 10 second timeout
|
|
|
|
|
);
|
2025-12-24 18:39:21 -06:00
|
|
|
|
2026-01-03 22:59:36 -06:00
|
|
|
if (bits & EVENT_SOCKETIO_CONNECTED) {
|
2025-12-24 18:39:21 -06:00
|
|
|
initSuccess = connected;
|
|
|
|
|
if (!initSuccess) {
|
|
|
|
|
printf("Device authentication failed - entering setup\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
2026-01-03 22:59:36 -06:00
|
|
|
} else {
|
|
|
|
|
printf("Timeout waiting for connection\n");
|
|
|
|
|
stopSocketIO();
|
|
|
|
|
initSuccess = false;
|
|
|
|
|
initialSetup();
|
2025-12-24 18:39:21 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("Token read unsuccessful, entering setup.\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("Auth NVS segment doesn't exist, entering setup.\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Make RGB LED certain color (Blue?)
|
|
|
|
|
nvs_close(WiFiHandle);
|
|
|
|
|
printf("Program error in Wifi Connection\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("WiFi NVS segment doesn't exist, entering setup.\n");
|
|
|
|
|
initialSetup();
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-29 16:24:56 -06:00
|
|
|
}
|