Compilable version with wifi support - need to test
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@
|
|||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
68
.vscode/settings.json
vendored
68
.vscode/settings.json
vendored
@@ -1,5 +1,71 @@
|
|||||||
{
|
{
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"nimbledevice.h": "c"
|
"nimbledevice.h": "c",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"text_encoding": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"variant": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
bool flag_scan_requested = false;
|
bool flag_scan_requested = false;
|
||||||
|
|
||||||
std::string SSID = "";
|
std::string tempSSID = "";
|
||||||
std::string password = "";
|
std::string tempPassword = "";
|
||||||
bool SSIDGiven = false;
|
bool SSIDGiven = false;
|
||||||
bool passGiven = false;
|
bool passGiven = false;
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
extern bool flag_scan_requested;
|
extern bool flag_scan_requested;
|
||||||
|
|
||||||
extern std::string SSID;
|
extern std::string tempSSID;
|
||||||
extern std::string password;
|
extern std::string tempPassword;
|
||||||
extern bool SSIDGiven;
|
extern bool SSIDGiven;
|
||||||
extern bool passGiven;
|
extern bool passGiven;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ class MyCharCallbacks : public NimBLECharacteristicCallbacks {
|
|||||||
// SSID characteristic
|
// SSID characteristic
|
||||||
if (val.length() > 0) {
|
if (val.length() > 0) {
|
||||||
printf("Received SSID: %s\n", val.c_str());
|
printf("Received SSID: %s\n", val.c_str());
|
||||||
SSID = val;
|
tempSSID = val;
|
||||||
SSIDGiven = true;
|
SSIDGiven = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ class MyCharCallbacks : public NimBLECharacteristicCallbacks {
|
|||||||
if (val.length() > 0) {
|
if (val.length() > 0) {
|
||||||
printf("Received Password: %s\n", val.c_str());
|
printf("Received Password: %s\n", val.c_str());
|
||||||
passGiven = true;
|
passGiven = true;
|
||||||
password = val;
|
tempPassword = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (uuidStr.find("0003") != std::string::npos) {
|
else if (uuidStr.find("0003") != std::string::npos) {
|
||||||
|
|||||||
158
include/WiFi.cpp
158
include/WiFi.cpp
@@ -1,10 +1,61 @@
|
|||||||
#include "WiFi.hpp"
|
#include "WiFi.hpp"
|
||||||
#include "esp_wifi.h"
|
#include "esp_eap_client.h"
|
||||||
#include "esp_event.h"
|
|
||||||
#include "cJSON.h" // Native replacement for ArduinoJson
|
#include "cJSON.h" // Native replacement for ArduinoJson
|
||||||
#include "BLE.hpp"
|
#include "BLE.hpp"
|
||||||
|
|
||||||
void init_wifi() {
|
bool WiFi::authFailed = false;
|
||||||
|
EventGroupHandle_t WiFi::s_wifi_event_group = NULL;
|
||||||
|
esp_netif_t* WiFi::netif = NULL;
|
||||||
|
esp_event_handler_instance_t WiFi::instance_any_id = NULL;
|
||||||
|
esp_event_handler_instance_t WiFi::instance_got_ip = NULL;
|
||||||
|
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
|
||||||
|
// The Event Handler (The engine room)
|
||||||
|
void WiFi::event_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data) {
|
||||||
|
|
||||||
|
// We got disconnected -> Retry automatically
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
|
// 1. Cast the data to the correct struct
|
||||||
|
wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
|
||||||
|
|
||||||
|
printf("WiFi Disconnected. Reason Code: %d\n", event->reason);
|
||||||
|
|
||||||
|
// 2. Check specific Reason Codes
|
||||||
|
switch (event->reason) {
|
||||||
|
case WIFI_REASON_AUTH_EXPIRE: // Reason 2
|
||||||
|
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: // Reason 15 (Most Common for Wrong Pass)
|
||||||
|
case WIFI_REASON_BEACON_TIMEOUT: // Reason 200
|
||||||
|
case WIFI_REASON_AUTH_FAIL: // Reason 203
|
||||||
|
case WIFI_REASON_ASSOC_FAIL: // Reason 204
|
||||||
|
case WIFI_REASON_HANDSHAKE_TIMEOUT: // Reason 205
|
||||||
|
printf("ERROR: Likely Wrong Password!\n");
|
||||||
|
// OPTIONAL: Don't retry immediately if password is wrong
|
||||||
|
authFailed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIFI_REASON_NO_AP_FOUND: // Reason 201
|
||||||
|
printf("ERROR: SSID Not Found\n");
|
||||||
|
authFailed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Retrying...\n");
|
||||||
|
esp_wifi_connect(); // Retry for other reasons (interference, etc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
// 3. We got an IP Address -> Success!
|
||||||
|
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;
|
||||||
|
printf("Got IP: " IPSTR "\n", IP2STR(&event->ip_info.ip));
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
@@ -16,9 +67,110 @@ void init_wifi() {
|
|||||||
|
|
||||||
// 3. Set Mode to Station (Client)
|
// 3. Set Mode to Station (Client)
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||||
|
WIFI_EVENT, // The "Topic" (Base)
|
||||||
|
ESP_EVENT_ANY_ID, // The specific "Subject" (Any ID)
|
||||||
|
&event_handler, // The Function to call
|
||||||
|
NULL, // Argument to pass to the function (optional)
|
||||||
|
&instance_any_id // Where to store the registration handle
|
||||||
|
));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||||
|
IP_EVENT,
|
||||||
|
IP_EVENT_STA_GOT_IP,
|
||||||
|
&event_handler,
|
||||||
|
NULL,
|
||||||
|
&instance_got_ip
|
||||||
|
));
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- CHECK STATUS ---
|
||||||
|
bool WiFi::isConnected() {
|
||||||
|
if (s_wifi_event_group == NULL) return false;
|
||||||
|
EventBits_t bits = xEventGroupGetBits(s_wifi_event_group);
|
||||||
|
return (bits & WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- GET IP AS STRING ---
|
||||||
|
std::string WiFi::getIP() {
|
||||||
|
esp_netif_ip_info_t ip_info;
|
||||||
|
esp_netif_get_ip_info(netif, &ip_info);
|
||||||
|
char buf[20];
|
||||||
|
sprintf(buf, IPSTR, IP2STR(&ip_info.ip));
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiFi::attemptConnect(char *SSID, char *PW, wifi_auth_mode_t authMode) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
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::attemptConnectEnterprise(char *SSID, char *username, char *PW, wifi_auth_mode_t authMode) {
|
||||||
|
std::string ssid = SSID;
|
||||||
|
std::string uname = username;
|
||||||
|
std::string password = PW;
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
wifi_config.sta.threshold.authmode = authMode;
|
||||||
|
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
||||||
|
|
||||||
|
// 3. Set the calculated identity (using new ESP-IDF v5.x API)
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiFi::awaitConnected() {
|
||||||
|
authFailed = false;
|
||||||
|
if (esp_wifi_connect() != ESP_OK) return false;
|
||||||
|
|
||||||
|
uint8_t attempts = 0;
|
||||||
|
while (!isConnected() && attempts < 20) {
|
||||||
|
if (authFailed) {
|
||||||
|
printf("SSID/Password was wrong! Aborting connection attempt.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vTaskDelay(500);
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
if (isConnected()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------- non-class --------------
|
||||||
void scanAndUpdateSSIDList() {
|
void scanAndUpdateSSIDList() {
|
||||||
printf("Starting WiFi Scan...\n");
|
printf("Starting WiFi Scan...\n");
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,28 @@
|
|||||||
#ifndef WIFI_H
|
#ifndef WIFI_H
|
||||||
#define WIFI_H
|
#define WIFI_H
|
||||||
|
|
||||||
void init_wifi();
|
#include "esp_wifi.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class WiFi {
|
||||||
|
public:
|
||||||
|
static void init();
|
||||||
|
static bool attemptConnect(char *SSID, char *PW, wifi_auth_mode_t authMode);
|
||||||
|
static bool attemptConnectEnterprise(char *SSID, char *username,
|
||||||
|
char *PW, wifi_auth_mode_t authMode);
|
||||||
|
private:
|
||||||
|
static bool authFailed;
|
||||||
|
static bool awaitConnected();
|
||||||
|
static esp_event_handler_instance_t instance_any_id;
|
||||||
|
static esp_event_handler_instance_t instance_got_ip;
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
static esp_netif_t* netif;
|
||||||
|
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void* event_data);
|
||||||
|
static bool isConnected();
|
||||||
|
static std::string getIP();
|
||||||
|
};
|
||||||
|
|
||||||
void scanAndUpdateSSIDList();
|
void scanAndUpdateSSIDList();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
12
include/setup.cpp
Normal file
12
include/setup.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "setup.hpp"
|
||||||
|
#include "BLE.hpp"
|
||||||
|
#include "WiFi.hpp"
|
||||||
|
|
||||||
|
void initialSetup() {
|
||||||
|
NimBLEAdvertising* pAdv = initBLE();
|
||||||
|
|
||||||
|
while (1) { // try to connect to wifi too.
|
||||||
|
BLEtick(pAdv);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
6
include/setup.hpp
Normal file
6
include/setup.hpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SETUP_H
|
||||||
|
#define SETUP_H
|
||||||
|
|
||||||
|
void initialSetup();
|
||||||
|
|
||||||
|
#endif
|
||||||
43
src/main.cpp
43
src/main.cpp
@@ -5,9 +5,10 @@
|
|||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
#include "BLE.hpp"
|
#include "BLE.hpp"
|
||||||
#include "WiFi.hpp"
|
#include "WiFi.hpp"
|
||||||
|
#include "setup.hpp"
|
||||||
|
|
||||||
extern "C" void app_main() {
|
extern "C" void app_main() {
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init(); // change to secure init logic soon!!
|
||||||
// 2. If NVS is full or corrupt (common after flashing new code), erase and retry
|
// 2. If NVS is full or corrupt (common after flashing new code), erase and retry
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
@@ -15,11 +16,43 @@ extern "C" void app_main() {
|
|||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
init_wifi();
|
WiFi bmWiFi;
|
||||||
NimBLEAdvertising* pAdv = initBLE();
|
bmWiFi.init();
|
||||||
|
|
||||||
|
nvs_handle_t WiFiHandle;
|
||||||
|
nvs_open("WiFiCreds", NVS_READWRITE, &WiFiHandle);
|
||||||
|
size_t ssidSize;
|
||||||
|
esp_err_t WiFiPrefsError = nvs_get_str(WiFiHandle, "SSID", NULL, &ssidSize);
|
||||||
|
size_t pwSize;
|
||||||
|
WiFiPrefsError |= nvs_get_str(WiFiHandle, "PW", NULL, &pwSize);
|
||||||
|
uint8_t authMode;
|
||||||
|
WiFiPrefsError |= nvs_get_u8(WiFiHandle, "AuthMode", &authMode);
|
||||||
|
|
||||||
|
if (WiFiPrefsError == ESP_ERR_NVS_NOT_FOUND) {
|
||||||
|
// Make the RGB LED a certain color (Blue?)
|
||||||
|
nvs_close(WiFiHandle);
|
||||||
|
initialSetup();
|
||||||
|
} else if (WiFiPrefsError == ESP_OK) {
|
||||||
|
char ssid[ssidSize];
|
||||||
|
nvs_get_str(WiFiHandle, "SSID", ssid, &ssidSize);
|
||||||
|
char pw[pwSize];
|
||||||
|
nvs_get_str(WiFiHandle, "PW", pw, &pwSize);
|
||||||
|
nvs_close(WiFiHandle);
|
||||||
|
// TODO: add enterprise support
|
||||||
|
if (!bmWiFi.attemptConnect(ssid, pw, (wifi_auth_mode_t)authMode)) {
|
||||||
|
// Make RGB LED certain color (Blue?)
|
||||||
|
initialSetup();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Make RGB LED certain color (Blue?)
|
||||||
|
nvs_close(WiFiHandle);
|
||||||
|
printf("Program error in Wifi Connection\n");
|
||||||
|
initialSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main loop
|
||||||
while (1) {
|
while (1) {
|
||||||
BLEtick(pAdv);
|
// Your main application logic here
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user