init
This commit is contained in:
411
include/BLE.cpp
411
include/BLE.cpp
@@ -6,10 +6,10 @@
|
||||
#include "defines.h"
|
||||
#include <mutex>
|
||||
#include "bmHTTP.hpp"
|
||||
#include <freertos/queue.h>
|
||||
#include "setup.hpp"
|
||||
|
||||
std::atomic<bool> flag_scan_requested{false};
|
||||
std::atomic<bool> credsGiven{false};
|
||||
std::atomic<bool> tokenGiven{false};
|
||||
std::atomic<bool> isBLEClientConnected{false};
|
||||
std::atomic<bool> scanBlock{false};
|
||||
std::atomic<bool> finalAuth{false};
|
||||
@@ -29,7 +29,14 @@ std::atomic<NimBLECharacteristic*> credsChar = nullptr;
|
||||
std::atomic<NimBLECharacteristic*> tokenChar = nullptr;
|
||||
std::atomic<NimBLECharacteristic*> ssidRefreshChar = nullptr;
|
||||
|
||||
static QueueHandle_t BLE_event_queue = NULL;
|
||||
static TaskHandle_t BLE_manager_task_handle = NULL;
|
||||
|
||||
SemaphoreHandle_t BLE_Queue_Shutdown_Semaphore = NULL;
|
||||
|
||||
NimBLEAdvertising* initBLE() {
|
||||
BLE_event_queue = xQueueCreate(10, sizeof(BLE_event_type_t));
|
||||
xTaskCreate(BLE_manager_task, "BLE", 8192, NULL, 5, &BLE_manager_task_handle);
|
||||
finalAuth = false;
|
||||
|
||||
NimBLEDevice::init("BlindMaster-C6");
|
||||
@@ -120,126 +127,18 @@ void notifyAuthStatus(bool success) {
|
||||
tmpConfChar->notify();
|
||||
tmpConfChar->setValue(""); // Clear value after notify
|
||||
}
|
||||
|
||||
bool BLEtick(NimBLEAdvertising* pAdvertising) {
|
||||
printf("BleTick\n");
|
||||
if(flag_scan_requested) {
|
||||
flag_scan_requested = false;
|
||||
if (!scanBlock) {
|
||||
scanBlock = true;
|
||||
printf("Scanning WiFi...\n");
|
||||
bmWiFi.scanAndUpdateSSIDList();
|
||||
}
|
||||
else printf("Duplicate scan request\n");
|
||||
}
|
||||
else if (credsGiven) {
|
||||
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;
|
||||
credsGiven = false;
|
||||
}
|
||||
|
||||
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) {
|
||||
// notify errored
|
||||
notifyConnectionStatus(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
nvs_handle_t WiFiHandle;
|
||||
esp_err_t err = nvs_open(nvsWiFi, NVS_READWRITE, &WiFiHandle);
|
||||
if (err != ESP_OK) {
|
||||
printf("ERROR Saving Credentials\n");
|
||||
// notify errored
|
||||
notifyConnectionStatus(false);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
err = nvs_set_str(WiFiHandle, ssidTag, tmpSSID.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_str(WiFiHandle, passTag, tmpPASS.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_str(WiFiHandle, unameTag, tmpUNAME.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_u8(WiFiHandle, authTag, (uint8_t)tmpAUTH);
|
||||
if (err == ESP_OK) nvs_commit(WiFiHandle);
|
||||
nvs_close(WiFiHandle);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
// notify connected
|
||||
notifyConnectionStatus(true);
|
||||
}
|
||||
else {
|
||||
// notify connected
|
||||
notifyConnectionStatus(false);
|
||||
}
|
||||
}
|
||||
else if (tokenGiven) {
|
||||
tokenGiven = false;
|
||||
if (!bmWiFi.isConnected()) {
|
||||
printf("ERROR: token given without WiFi connection\n");
|
||||
notifyAuthStatus(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// HTTP request to verify device with token
|
||||
std::string tmpTOKEN;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
tmpTOKEN = TOKEN;
|
||||
}
|
||||
|
||||
cJSON *responseRoot;
|
||||
bool success = httpGET("verify_device", tmpTOKEN, responseRoot);
|
||||
if (!success) return false;
|
||||
success = false;
|
||||
|
||||
if (responseRoot != NULL) {
|
||||
cJSON *tokenItem = cJSON_GetObjectItem(responseRoot, "token");
|
||||
if (cJSON_IsString(tokenItem) && tokenItem->valuestring != NULL) {
|
||||
printf("New token received: %s\n", tokenItem->valuestring);
|
||||
|
||||
// Save token to NVS
|
||||
nvs_handle_t AuthHandle;
|
||||
esp_err_t nvs_err = nvs_open(nvsAuth, NVS_READWRITE, &AuthHandle);
|
||||
if (nvs_err == ESP_OK) {
|
||||
nvs_err = nvs_set_str(AuthHandle, tokenTag, tokenItem->valuestring);
|
||||
if (nvs_err == ESP_OK) {
|
||||
nvs_commit(AuthHandle);
|
||||
success = true;
|
||||
webToken = tokenItem->valuestring;
|
||||
}
|
||||
else printf("ERROR: could not save webToken to NVS\n");
|
||||
nvs_close(AuthHandle);
|
||||
}
|
||||
else printf("ERROR: Couldn't open NVS for auth token\n");
|
||||
}
|
||||
cJSON_Delete(responseRoot);
|
||||
}
|
||||
else printf("Failed to parse JSON response\n");
|
||||
|
||||
finalAuth = true;
|
||||
notifyAuthStatus(success);
|
||||
if (success) NimBLEDevice::deinit(true); // deinitialize BLE
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
BLE_Queue_Shutdown_Semaphore = xSemaphoreCreateBinary();
|
||||
BLE_event_type_t event_type = EVENT_SHUTDOWN;
|
||||
xQueueSend(BLE_event_queue, &event_type, portMAX_DELAY);
|
||||
xSemaphoreTake(BLE_Queue_Shutdown_Semaphore, portMAX_DELAY);
|
||||
vQueueDelete(BLE_event_queue);
|
||||
esp_wifi_scan_stop();
|
||||
if (!finalAuth) esp_wifi_disconnect();
|
||||
scanBlock = false;
|
||||
flag_scan_requested = false;
|
||||
credsGiven = false;
|
||||
tokenGiven = false;
|
||||
vSemaphoreDelete(BLE_Queue_Shutdown_Semaphore);
|
||||
BLE_event_queue = xQueueCreate(10, sizeof(BLE_event_type_t));
|
||||
xTaskCreate(BLE_manager_task, "BLE", 8192, NULL, 5, &BLE_manager_task_handle);
|
||||
}
|
||||
|
||||
void MyServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
||||
@@ -259,89 +158,231 @@ void MyCharCallbacks::onRead(NimBLECharacteristic* pChar, NimBLEConnInfo& connIn
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// Load atomic pointers for comparison
|
||||
NimBLECharacteristic* currentCredsChar = credsChar.load();
|
||||
NimBLECharacteristic* currentTokenChar = tokenChar.load();
|
||||
NimBLECharacteristic* currentRefreshChar = ssidRefreshChar.load();
|
||||
|
||||
// Check which characteristic was written to
|
||||
if (pChar == currentCredsChar) {
|
||||
// Credentials JSON characteristic
|
||||
if (val.length() > 0) {
|
||||
printf("Received JSON: %s\n", val.c_str());
|
||||
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());
|
||||
|
||||
// Load atomic pointers for comparison
|
||||
NimBLECharacteristic* currentCredsChar = credsChar.load();
|
||||
NimBLECharacteristic* currentTokenChar = tokenChar.load();
|
||||
NimBLECharacteristic* currentRefreshChar = ssidRefreshChar.load();
|
||||
|
||||
// Check which characteristic was written to
|
||||
if (pChar == currentCredsChar) {
|
||||
// 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 *authType = cJSON_GetObjectItem(root, "auth");
|
||||
cJSON *uname = cJSON_GetObjectItem(root, "uname");
|
||||
|
||||
// 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 *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 tempCredsGiven = ssidPresent && (passPresent || open) &&
|
||||
(unamePresent || !enterprise);
|
||||
|
||||
if (tempCredsGiven) {
|
||||
printf("Received credentials, will attempt connection\n");
|
||||
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");
|
||||
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 tempCredsGiven = ssidPresent && (passPresent || open) &&
|
||||
(unamePresent || !enterprise);
|
||||
|
||||
if (tempCredsGiven) {
|
||||
printf("Received credentials, will attempt connection\n");
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
|
||||
auth = (wifi_auth_mode_t)(authType->valueint);
|
||||
SSID = ssid->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;
|
||||
BLE_event_type_t event_type = EVENT_CREDS_GIVEN;
|
||||
if (xQueueSend(BLE_event_queue, &event_type, pdMS_TO_TICKS(10)) == pdPASS)
|
||||
printf("Successfully added credsGiven to event queue\n");
|
||||
else printf("CredsGiven event queue addition failed\n");
|
||||
}
|
||||
else printf("ERROR: Did not receive necessary credentials.\n");
|
||||
cJSON_Delete(root);
|
||||
} else {
|
||||
printf("Failed to parse JSON\n");
|
||||
}
|
||||
}
|
||||
else if (pChar == currentTokenChar) {
|
||||
if (val.length() > 0) {
|
||||
printf("Received Token: %s\n", val.c_str());
|
||||
}
|
||||
else if (pChar == currentTokenChar) {
|
||||
if (val.length() > 0) {
|
||||
printf("Received Token: %s\n", val.c_str());
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
TOKEN = val;
|
||||
tokenGiven = true;
|
||||
}
|
||||
BLE_event_type_t event_type = EVENT_TOKEN_GIVEN;
|
||||
if (xQueueSend(BLE_event_queue, &event_type, pdMS_TO_TICKS(10)) == pdPASS)
|
||||
printf("Successfully added tokenGiven to event queue\n");
|
||||
else printf("TokenGiven event queue addition failed\n");
|
||||
}
|
||||
else if (pChar == currentRefreshChar) {
|
||||
if (val == "Start") {
|
||||
// Refresh characteristic
|
||||
}
|
||||
else if (pChar == currentRefreshChar) {
|
||||
if (val == "Start") {
|
||||
// Refresh characteristic
|
||||
BLE_event_type_t event_type = EVENT_SCAN_REQUESTED;
|
||||
if (xQueueSend(BLE_event_queue, &event_type, pdMS_TO_TICKS(10)) == pdPASS) {
|
||||
printf("Event queue addition success for scan start\n");
|
||||
}
|
||||
else printf("Scan start event queue addition failed\n");
|
||||
}
|
||||
else if (val == "Done") {
|
||||
printf("Data read complete\n");
|
||||
scanBlock = false;
|
||||
}
|
||||
}
|
||||
else printf("Unknown UUID: %s\n", uuidStr.c_str());
|
||||
}
|
||||
|
||||
void BLE_manager_task(void *pvParameters) {
|
||||
BLE_event_type_t received_event_type;
|
||||
|
||||
while (true) {
|
||||
if (xQueueReceive(BLE_event_queue, &received_event_type, portMAX_DELAY)) {
|
||||
if (received_event_type == EVENT_SCAN_REQUESTED) {
|
||||
printf("Refresh Requested\n");
|
||||
flag_scan_requested = true;
|
||||
if (!scanBlock) {
|
||||
scanBlock = true;
|
||||
printf("Scanning WiFi...\n");
|
||||
bmWiFi.scanAndUpdateSSIDList();
|
||||
}
|
||||
else printf("Duplicate scan request\n");
|
||||
}
|
||||
else if (val == "Done") {
|
||||
printf("Data read complete\n");
|
||||
scanBlock = false;
|
||||
else if (received_event_type == EVENT_TOKEN_GIVEN) {
|
||||
if (tokenCheck()) {
|
||||
vQueueDelete(BLE_event_queue);
|
||||
if (setupTaskHandle != NULL) {
|
||||
xTaskNotifyGive(setupTaskHandle);
|
||||
printf("Setup complete.\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (received_event_type == EVENT_CREDS_GIVEN)
|
||||
attemptUseWiFiCreds();
|
||||
else if (received_event_type == EVENT_SHUTDOWN) break;
|
||||
}
|
||||
else printf("Unknown UUID: %s\n", uuidStr.c_str());
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(BLE_Queue_Shutdown_Semaphore);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
bool tokenCheck() {
|
||||
if (!bmWiFi.isConnected()) {
|
||||
printf("ERROR: token given without WiFi connection\n");
|
||||
notifyAuthStatus(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// HTTP request to verify device with token
|
||||
std::string tmpTOKEN;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
tmpTOKEN = TOKEN;
|
||||
}
|
||||
|
||||
cJSON *responseRoot;
|
||||
bool success = httpGET("verify_device", tmpTOKEN, responseRoot);
|
||||
if (!success) return false;
|
||||
success = false;
|
||||
|
||||
if (responseRoot != NULL) {
|
||||
cJSON *tokenItem = cJSON_GetObjectItem(responseRoot, "token");
|
||||
if (cJSON_IsString(tokenItem) && tokenItem->valuestring != NULL) {
|
||||
printf("New token received: %s\n", tokenItem->valuestring);
|
||||
|
||||
// Save token to NVS
|
||||
nvs_handle_t AuthHandle;
|
||||
esp_err_t nvs_err = nvs_open(nvsAuth, NVS_READWRITE, &AuthHandle);
|
||||
if (nvs_err == ESP_OK) {
|
||||
nvs_err = nvs_set_str(AuthHandle, tokenTag, tokenItem->valuestring);
|
||||
if (nvs_err == ESP_OK) {
|
||||
nvs_commit(AuthHandle);
|
||||
success = true;
|
||||
webToken = tokenItem->valuestring;
|
||||
}
|
||||
else printf("ERROR: could not save webToken to NVS\n");
|
||||
nvs_close(AuthHandle);
|
||||
}
|
||||
else printf("ERROR: Couldn't open NVS for auth token\n");
|
||||
}
|
||||
cJSON_Delete(responseRoot);
|
||||
}
|
||||
else printf("Failed to parse JSON response\n");
|
||||
|
||||
finalAuth = true;
|
||||
notifyAuthStatus(success);
|
||||
if (success) NimBLEDevice::deinit(true); // deinitialize BLE
|
||||
return success;
|
||||
}
|
||||
|
||||
bool attemptUseWiFiCreds() {
|
||||
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.c_str(), tmpUNAME.c_str(), tmpPASS.c_str(), tmpAUTH);
|
||||
else wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpPASS.c_str(), tmpAUTH);
|
||||
if (!wifiConnect) {
|
||||
// notify errored
|
||||
notifyConnectionStatus(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nvs_handle_t WiFiHandle;
|
||||
esp_err_t err = nvs_open(nvsWiFi, NVS_READWRITE, &WiFiHandle);
|
||||
if (err != ESP_OK) {
|
||||
printf("ERROR Saving Credentials\n");
|
||||
// notify errored
|
||||
notifyConnectionStatus(false);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
err = nvs_set_str(WiFiHandle, ssidTag, tmpSSID.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_str(WiFiHandle, passTag, tmpPASS.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_str(WiFiHandle, unameTag, tmpUNAME.c_str());
|
||||
if (err == ESP_OK) err = nvs_set_u8(WiFiHandle, authTag, (uint8_t)tmpAUTH);
|
||||
if (err == ESP_OK) nvs_commit(WiFiHandle);
|
||||
nvs_close(WiFiHandle);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
// notify connected
|
||||
notifyConnectionStatus(true);
|
||||
}
|
||||
else {
|
||||
// notify connected
|
||||
notifyConnectionStatus(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user