robust handshake for SSID List, next check the confirmations

This commit is contained in:
2025-12-18 22:08:07 -06:00
parent 3e07f81728
commit 74a11de043
9 changed files with 250 additions and 49 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

View File

@@ -3,9 +3,14 @@
#include "WiFi.hpp" #include "WiFi.hpp"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "defines.h" #include "defines.h"
#include <mutex>
#include "bmHTTP.hpp"
std::atomic<bool> flag_scan_requested{false}; std::atomic<bool> flag_scan_requested{false};
std::atomic<bool> credsGiven{false}; std::atomic<bool> credsGiven{false};
std::atomic<bool> tokenGiven{false};
std::atomic<bool> isBLEClientConnected{false};
std::atomic<bool> scanBlock{false};
std::mutex dataMutex; std::mutex dataMutex;
wifi_auth_mode_t auth; wifi_auth_mode_t auth;
@@ -17,6 +22,10 @@ static std::string UNAME = "";
// Global pointers to characteristics for notification support // Global pointers to characteristics for notification support
NimBLECharacteristic* ssidListChar = nullptr; NimBLECharacteristic* ssidListChar = nullptr;
NimBLECharacteristic* connectConfirmChar = nullptr; NimBLECharacteristic* connectConfirmChar = nullptr;
NimBLECharacteristic* authConfirmChar = nullptr;
NimBLECharacteristic* credsChar = nullptr;
NimBLECharacteristic* tokenChar = nullptr;
NimBLECharacteristic* ssidRefreshChar = nullptr;
NimBLEAdvertising* initBLE() { NimBLEAdvertising* initBLE() {
NimBLEDevice::init("BlindMaster-C6"); NimBLEDevice::init("BlindMaster-C6");
@@ -40,23 +49,37 @@ NimBLEAdvertising* initBLE() {
// 0x0000 - SSID List (READ + NOTIFY) // 0x0000 - SSID List (READ + NOTIFY)
ssidListChar = pService->createCharacteristic( ssidListChar = pService->createCharacteristic(
"0000", "0000",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY NIMBLE_PROPERTY::READ
); );
ssidListChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications ssidListChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications
// 0x0001 - Credentials JSON (WRITE) - Replaces separate SSID/Password/Token // 0x0001 - Credentials JSON (WRITE) - Replaces separate SSID/Password/Uname
// Expected JSON format: {"ssid":"network","password":"pass","token":"optional"} // Expected JSON format: {"ssid":"network","password":"pass"}
NimBLECharacteristic *credsChar = pService->createCharacteristic( credsChar = pService->createCharacteristic(
"0001", "0001",
NIMBLE_PROPERTY::WRITE NIMBLE_PROPERTY::WRITE
); );
credsChar->setCallbacks(charCallbacks); credsChar->setCallbacks(charCallbacks);
// 0x0004 - SSID Refresh (WRITE) // 0x0002 - Token (WRITE)
NimBLECharacteristic *ssidRefreshChar = pService->createCharacteristic( tokenChar = pService->createCharacteristic(
"0004", "0002",
NIMBLE_PROPERTY::WRITE NIMBLE_PROPERTY::WRITE
); );
tokenChar->setCallbacks(charCallbacks);
// 0x0003 - Auth Confirmation (READ + NOTIFY)
authConfirmChar = pService->createCharacteristic(
"0003",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
);
authConfirmChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications
// 0x0004 - SSID Refresh (WRITE)
ssidRefreshChar = pService->createCharacteristic(
"0004",
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
);
ssidRefreshChar->setCallbacks(charCallbacks); ssidRefreshChar->setCallbacks(charCallbacks);
// 0x0005 - Connect Confirmation (READ + NOTIFY) // 0x0005 - Connect Confirmation (READ + NOTIFY)
@@ -82,14 +105,28 @@ NimBLEAdvertising* initBLE() {
return pAdvertising; return pAdvertising;
} }
void notifyConnectionStatus(bool success) {
connectConfirmChar->setValue(success ? "Connected" : "Error");
connectConfirmChar->notify();
connectConfirmChar->setValue(""); // Clear value after notify
}
void notifyAuthStatus(bool success) {
authConfirmChar->setValue(success ? "Authenticated" : "Error");
authConfirmChar->notify();
authConfirmChar->setValue(""); // Clear value after notify
}
bool BLEtick(NimBLEAdvertising* pAdvertising) { bool BLEtick(NimBLEAdvertising* pAdvertising) {
if(flag_scan_requested) { if(flag_scan_requested) {
flag_scan_requested = false; flag_scan_requested = false;
if (!scanBlock) {
scanBlock = true;
printf("Scanning WiFi...\n"); printf("Scanning WiFi...\n");
scanAndUpdateSSIDList(); scanAndUpdateSSIDList();
} }
else printf("Duplicate scan request\n");
}
else if (credsGiven) { else if (credsGiven) {
credsGiven = false;
std::string tmpSSID; std::string tmpSSID;
std::string tmpUNAME; std::string tmpUNAME;
std::string tmpPASS; std::string tmpPASS;
@@ -100,18 +137,25 @@ bool BLEtick(NimBLEAdvertising* pAdvertising) {
tmpUNAME = UNAME; tmpUNAME = UNAME;
tmpPASS = PASS; tmpPASS = PASS;
tmpAUTH = auth; tmpAUTH = auth;
credsGiven = false;
} }
bool wifiConnect; bool wifiConnect;
if (tmpAUTH == WIFI_AUTH_WPA2_ENTERPRISE || tmpAUTH == WIFI_AUTH_WPA3_ENTERPRISE) if (tmpAUTH == WIFI_AUTH_WPA2_ENTERPRISE || tmpAUTH == WIFI_AUTH_WPA3_ENTERPRISE)
wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpUNAME.c_str(), tmpPASS.c_str(), tmpAUTH); wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpUNAME.c_str(), tmpPASS.c_str(), tmpAUTH);
else wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpPASS.c_str(), tmpAUTH); else wifiConnect = bmWiFi.attemptConnect(tmpSSID.c_str(), tmpPASS.c_str(), tmpAUTH);
if (!wifiConnect) return false; if (!wifiConnect) {
// notify errored
notifyConnectionStatus(false);
return false;
}
nvs_handle_t WiFiHandle; nvs_handle_t WiFiHandle;
esp_err_t err = nvs_open(nvsWiFi, NVS_READWRITE, &WiFiHandle); esp_err_t err = nvs_open(nvsWiFi, NVS_READWRITE, &WiFiHandle);
if (err != ESP_OK) { if (err != ESP_OK) {
printf("ERROR Saving Credentials\n"); printf("ERROR Saving Credentials\n");
// notify errored
notifyConnectionStatus(false);
return false; return false;
} }
else { else {
@@ -122,12 +166,85 @@ bool BLEtick(NimBLEAdvertising* pAdvertising) {
if (err == ESP_OK) nvs_commit(WiFiHandle); if (err == ESP_OK) nvs_commit(WiFiHandle);
nvs_close(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;
}
// Authenticate with server here // 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");
notifyAuthStatus(success);
return success;
} }
return false; return false;
} }
void reset() {
esp_wifi_scan_stop();
scanBlock = false;
flag_scan_requested = false;
credsGiven = false;
tokenGiven = false;
}
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
isBLEClientConnected = true;
printf("Client connected\n");
reset();
};
void MyServerCallbacks::onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) {
isBLEClientConnected = false;
printf("Client disconnected - reason: %d\n", reason);
reset();
}
void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) { void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) {
std::string val = pChar->getValue(); std::string val = pChar->getValue();
std::string uuidStr = pChar->getUUID().toString(); std::string uuidStr = pChar->getUUID().toString();
@@ -135,7 +252,7 @@ void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connI
printf("onWrite called! UUID: %s, Value length: %d\n", uuidStr.c_str(), val.length()); printf("onWrite called! UUID: %s, Value length: %d\n", uuidStr.c_str(), val.length());
// Check which characteristic was written to // Check which characteristic was written to
if (uuidStr.find("0001") != std::string::npos) { if (pChar == credsChar) {
// Credentials JSON characteristic // Credentials JSON characteristic
if (val.length() > 0) { if (val.length() > 0) {
printf("Received JSON: %s\n", val.c_str()); printf("Received JSON: %s\n", val.c_str());
@@ -145,7 +262,6 @@ void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connI
if (root != NULL) { if (root != NULL) {
cJSON *ssid = cJSON_GetObjectItem(root, "ssid"); cJSON *ssid = cJSON_GetObjectItem(root, "ssid");
cJSON *password = cJSON_GetObjectItem(root, "password"); cJSON *password = cJSON_GetObjectItem(root, "password");
cJSON *token = cJSON_GetObjectItem(root, "token");
cJSON *authType = cJSON_GetObjectItem(root, "auth"); cJSON *authType = cJSON_GetObjectItem(root, "auth");
cJSON *uname = cJSON_GetObjectItem(root, "uname"); cJSON *uname = cJSON_GetObjectItem(root, "uname");
@@ -169,8 +285,7 @@ void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connI
bool ssidPresent = cJSON_IsString(ssid) && ssid->valuestring != NULL; bool ssidPresent = cJSON_IsString(ssid) && ssid->valuestring != NULL;
bool passPresent = cJSON_IsString(password) && password->valuestring != NULL; bool passPresent = cJSON_IsString(password) && password->valuestring != NULL;
bool unamePresent = cJSON_IsString(uname) && uname->valuestring != NULL; bool unamePresent = cJSON_IsString(uname) && uname->valuestring != NULL;
bool tokenPresent = cJSON_IsString(token) && token->valuestring != NULL; bool tempCredsGiven = ssidPresent && (passPresent || open) &&
bool tempCredsGiven = tokenPresent && ssidPresent && (passPresent || open) &&
(unamePresent || !enterprise); (unamePresent || !enterprise);
if (tempCredsGiven) { if (tempCredsGiven) {
@@ -179,7 +294,6 @@ void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connI
auth = (wifi_auth_mode_t)(authType->valueint); auth = (wifi_auth_mode_t)(authType->valueint);
SSID = ssid->valuestring; SSID = ssid->valuestring;
TOKEN = token->valuestring;
PASS = passPresent ? password->valuestring : ""; PASS = passPresent ? password->valuestring : "";
UNAME = unamePresent ? uname->valuestring : ""; UNAME = unamePresent ? uname->valuestring : "";
credsGiven = tempCredsGiven; // update the global flag. credsGiven = tempCredsGiven; // update the global flag.
@@ -192,10 +306,24 @@ void MyCharCallbacks::onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connI
} }
} }
} }
else if (uuidStr.find("0004") != std::string::npos) { else if (pChar == tokenChar) {
if (val.length() > 0) {
printf("Received Token: %s\n", val.c_str());
std::lock_guard<std::mutex> lock(dataMutex);
TOKEN = val;
tokenGiven = true;
}
}
else if (pChar == ssidRefreshChar) {
if (val == "Start") {
// Refresh characteristic // Refresh characteristic
printf("Refresh Requested\n"); printf("Refresh Requested\n");
flag_scan_requested = true; flag_scan_requested = true;
} }
else if (val == "Done") {
printf("Data read complete\n");
scanBlock = false;
}
}
else printf("Unknown UUID: %s\n", uuidStr.c_str()); else printf("Unknown UUID: %s\n", uuidStr.c_str());
} }

View File

@@ -4,26 +4,21 @@
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "cJSON.h" #include "cJSON.h"
#include <atomic> #include <atomic>
#include <mutex>
#include <string> #include <string>
#include "esp_wifi_types.h" #include "esp_wifi_types.h"
// Global pointers to characteristics for notification support // Global pointers to characteristics for notification support
extern NimBLECharacteristic* ssidListChar; extern NimBLECharacteristic* ssidListChar;
extern NimBLECharacteristic* connectConfirmChar; extern NimBLECharacteristic* ssidRefreshChar;
extern std::atomic<bool> isBLEClientConnected{false};
class MyServerCallbacks : public NimBLEServerCallbacks { class MyServerCallbacks : public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) { void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo);
printf("Client connected\n"); void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason);
};
void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) {
printf("Client disconnected - reason: %d\n", reason);
// Advertising will restart automatically
}
}; };
class MyCharCallbacks : public NimBLECharacteristicCallbacks { class MyCharCallbacks : public NimBLECharacteristicCallbacks {
void onRead(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo);
void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo); void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo);
}; };

View File

@@ -3,7 +3,7 @@
#include "cJSON.h" // Native replacement for ArduinoJson #include "cJSON.h" // Native replacement for ArduinoJson
#include "BLE.hpp" #include "BLE.hpp"
bool WiFi::authFailed = false; std::atomic<bool> WiFi::authFailed{false};
EventGroupHandle_t WiFi::s_wifi_event_group = NULL; EventGroupHandle_t WiFi::s_wifi_event_group = NULL;
esp_netif_t* WiFi::netif = NULL; esp_netif_t* WiFi::netif = NULL;
esp_event_handler_instance_t WiFi::instance_any_id = NULL; esp_event_handler_instance_t WiFi::instance_any_id = NULL;
@@ -49,6 +49,13 @@ void WiFi::event_handler(void* arg, esp_event_base_t event_base,
} }
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT); xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
} }
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_SCAN_DONE) {
// This is triggered when the scan finishes!
printf("Scan complete, processing results...\n");
// Call a function to process results and notify BLE
processScanResults();
}
// 3. We got an IP Address -> Success! // 3. We got an IP Address -> Success!
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
@@ -62,7 +69,7 @@ void WiFi::init() {
// 1. Init Network Interface // 1. Init Network Interface
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta(); netif = esp_netif_create_default_wifi_sta();
// 2. Init WiFi Driver // 2. Init WiFi Driver
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
@@ -155,6 +162,11 @@ bool WiFi::awaitConnected() {
uint8_t attempts = 0; uint8_t attempts = 0;
while (!isConnected() && attempts < 20) { while (!isConnected() && attempts < 20) {
if (!isBLEClientConnected) {
printf("BLE Disconnected: Aborting WiFi connection attempt.\n");
esp_wifi_disconnect();
return false;
}
if (authFailed) { if (authFailed) {
printf("SSID/Password was wrong! Aborting connection attempt.\n"); printf("SSID/Password was wrong! Aborting connection attempt.\n");
return false; return false;
@@ -167,24 +179,29 @@ bool WiFi::awaitConnected() {
} }
// ------------- non-class -------------- // ------------- non-class --------------
void scanAndUpdateSSIDList() { void WiFi::scanAndUpdateSSIDList() {
printf("Starting WiFi Scan...\n"); printf("Starting WiFi Scan...\n");
// 1. Start Scan (Blocking Mode = true) // 1. Start Scan (Blocking Mode = true)
// In blocking mode, this function waits here until scan is done (~2 seconds) // In blocking mode, this function waits here until scan is done (~2 seconds)
esp_wifi_sta_enterprise_disable();
esp_wifi_disconnect();
wifi_scan_config_t scan_config = { wifi_scan_config_t scan_config = {
.ssid = NULL, .ssid = NULL,
.bssid = NULL, .bssid = NULL,
.channel = 0, .channel = 0,
.show_hidden = false .show_hidden = false
}; };
esp_err_t err = esp_wifi_scan_start(&scan_config, true); esp_err_t err = esp_wifi_scan_start(&scan_config, false);
if (err != ESP_OK) { if (err != ESP_OK) {
printf("Scan failed!\n"); printf("Scan failed!\n");
return; return;
} }
}
void WiFi::processScanResults() {
// 2. Get the results // 2. Get the results
uint16_t ap_count = 0; uint16_t ap_count = 0;
esp_wifi_scan_get_ap_num(&ap_count); esp_wifi_scan_get_ap_num(&ap_count);
@@ -215,11 +232,12 @@ void scanAndUpdateSSIDList() {
// 5. Update BLE // 5. Update BLE
if (ssidListChar != nullptr) { if (ssidListChar != nullptr) {
ssidListChar->setValue(std::string(json_string)); ssidListChar->setValue(json_string);
ssidListChar->notify(); ssidRefreshChar->setValue("Ready");
ssidRefreshChar->notify();
} }
// 6. Cleanup Memory (CRITICAL in C++) // 6. Cleanup Memory
free(ap_list); free(ap_list);
cJSON_Delete(root); // This deletes all children (items) too cJSON_Delete(root); // This deletes all children (items) too
free(json_string); // cJSON_Print allocates memory, you must free it free(json_string); // cJSON_Print allocates memory, you must free it

View File

@@ -11,8 +11,11 @@ class WiFi {
const wifi_auth_mode_t authMode); const wifi_auth_mode_t authMode);
static bool attemptConnect(const std::string ssid, const std::string uname, static bool attemptConnect(const std::string ssid, const std::string uname,
const std::string password, const wifi_auth_mode_t authMode); const std::string password, const wifi_auth_mode_t authMode);
static bool isConnected();
static void scanAndUpdateSSIDList();
private: private:
static bool authFailed; static void processScanResults();
static std::atomic<bool> authFailed;
static bool awaitConnected(); static bool awaitConnected();
static esp_event_handler_instance_t instance_any_id; static esp_event_handler_instance_t instance_any_id;
static esp_event_handler_instance_t instance_got_ip; static esp_event_handler_instance_t instance_got_ip;
@@ -20,7 +23,6 @@ class WiFi {
static esp_netif_t* netif; static esp_netif_t* netif;
static void event_handler(void* arg, esp_event_base_t event_base, static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data); int32_t event_id, void* event_data);
static bool isConnected();
static std::string getIP(); static std::string getIP();
}; };

47
include/bmHTTP.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "bmHTTP.hpp"
#include "esp_http_client.h"
#define httpSrv "http://192.168.1.190:3000/"
std::string webToken;
bool httpGET(std::string endpoint, std::string token, cJSON* &JSONresponse) {
std::string url = std::string(httpSrv) + endpoint;
esp_http_client_config_t config = {};
config.url = url.c_str();
config.method = HTTP_METHOD_GET;
esp_http_client_handle_t client = esp_http_client_init(&config);
// Add authorization header
std::string authHeader = "Bearer " + token;
esp_http_client_set_header(client, "Authorization", authHeader.c_str());
esp_err_t err = esp_http_client_perform(client);
bool success = false;
if (err == ESP_OK) {
int status_code = esp_http_client_get_status_code(client);
int content_length = esp_http_client_get_content_length(client);
printf("HTTP Status = %d, content_length = %d\n", status_code, content_length);
if (status_code == 200) {
std::string responseData = "";
char buffer[512]; // Read in 512-byte blocks
int read_len;
// Read until the server stops sending (read_len <= 0)
while ((read_len = esp_http_client_read(client, buffer, sizeof(buffer))) > 0)
responseData.append(buffer, read_len);
if (!responseData.empty()) {
JSONresponse = cJSON_Parse(responseData.c_str());
success = (JSONresponse != NULL);
}
}
} else printf("HTTP request failed: %s\n", esp_err_to_name(err));
esp_http_client_cleanup(client);
return success;
}

10
include/bmHTTP.hpp Normal file
View File

@@ -0,0 +1,10 @@
#ifndef BMHTTP
#define BMHTTP
#include <string>
#include "cJSON.h"
extern std::string webToken;
bool httpGET(std::string endpoint, std::string token, cJSON* &JSONresponse);
#endif

View File

@@ -12,6 +12,8 @@
#define passTag "PW" #define passTag "PW"
#define authTag "AuthMode" #define authTag "AuthMode"
#define unameTag "UNAME" #define unameTag "UNAME"
#define nvsAuth "AUTH"
#define tokenTag "TOKEN"
#define getMovingCW(port) ((movingCW & (1 << port)) >> port) #define getMovingCW(port) ((movingCW & (1 << port)) >> port)
#define setMovingCW(port) (movingCW |= (1 << port)) #define setMovingCW(port) (movingCW |= (1 << port))

View File

@@ -5,8 +5,7 @@
void initialSetup() { void initialSetup() {
NimBLEAdvertising* pAdv = initBLE(); NimBLEAdvertising* pAdv = initBLE();
while (1) { // try to connect to wifi too. while (!BLEtick(pAdv)) {
BLEtick(pAdv);
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
} }
} }