Last active
September 30, 2025 19:06
-
-
Save IgorDePaula/7ca3289721337121b3c02c3c9f2aeccf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <WiFi.h> | |
| #include <BLEDevice.h> | |
| #include <BLEServer.h> | |
| #include <BLEUtils.h> | |
| #include <BLE2902.h> | |
| #include "Preferences.h" // Para salvar SSID/senha | |
| // UUIDs originais para SSID e Senha | |
| #define UUID_SSID "c505b1de-4a31-11ef-9d90-47f7f9b3a434" | |
| #define UUID_PASS "c505b49e-4a31-11ef-9d90-47f7f9b3a434" | |
| // Novas UUIDs para comando scan, resultado e status WiFi | |
| #define UUID_SCAN_CMD "c505b600-4a31-11ef-9d90-47f7f9b3a434" | |
| #define UUID_SCAN_RESULT "c505b601-4a31-11ef-9d90-47f7f9b3a434" | |
| #define UUID_WIFI_STATUS "c505b602-4a31-11ef-9d90-47f7f9b3a434" | |
| BLEServer* pServer; | |
| BLECharacteristic* pScanCmdChar; | |
| BLECharacteristic* pScanResultChar; | |
| BLECharacteristic* pWifiStatusChar; | |
| Preferences preferences; // NVS | |
| BLEAdvertising* pAdvertising; | |
| // --- Função que faz scan WiFi e retorna JSON --- | |
| String performWifiScanAsJson() { | |
| int n = WiFi.scanNetworks(true); // show_hidden = true | |
| int o = WiFi.scanComplete(); | |
| if(o >= 0){ // scan terminou | |
| // gerar JSON e enviar Notify | |
| WiFi.scanDelete(); // limpa resultado | |
| } | |
| String json = "["; | |
| for (int i = 0; i < n; i++) { | |
| String ssid = WiFi.SSID(i); | |
| if (ssid.length() == 0) ssid = "<OCULTO>"; | |
| json += "{\"ssid\":\"" + ssid + "\",\"rssi\":" + String(WiFi.RSSI(i)) + "}"; | |
| if (i < n - 1) json += ","; | |
| } | |
| json += "]"; | |
| return json; | |
| } | |
| // --- Callbacks para comando SCAN --- | |
| class ScanCmdCallbacks : public BLECharacteristicCallbacks { | |
| void onWrite(BLECharacteristic* pCharacteristic) { | |
| String value = pCharacteristic->getValue(); | |
| if (value == "SCAN") { | |
| Serial.println("Comando SCAN recebido via BLE..."); | |
| // Pausa Advertising BLE | |
| pAdvertising->stop(); | |
| delay(200); | |
| // Scan WiFi | |
| String jsonResult = performWifiScanAsJson(); | |
| // Reativa Advertising BLE | |
| pAdvertising->start(); | |
| // Envia resultado via Notify | |
| pScanResultChar->setValue(jsonResult.c_str()); | |
| pScanResultChar->notify(); | |
| Serial.println("Scan concluído e JSON enviado via BLE Notify:"); | |
| Serial.println(jsonResult); | |
| } | |
| } | |
| }; | |
| // --- Callbacks para SSID/Password --- | |
| class WifiCredentialsCallbacks : public BLECharacteristicCallbacks { | |
| void onWrite(BLECharacteristic* pCharacteristic) { | |
| String value = pCharacteristic->getValue(); | |
| static String ssid = ""; | |
| static String pass = ""; | |
| if (pCharacteristic->getUUID().toString() == UUID_SSID) { | |
| ssid = String(value.c_str()); | |
| Serial.println("SSID recebido: " + ssid); | |
| } else if (pCharacteristic->getUUID().toString() == UUID_PASS) { | |
| pass = String(value.c_str()); | |
| Serial.println("Senha recebida: " + pass); | |
| } | |
| if (ssid.length() > 0 && pass.length() > 0) { | |
| Serial.println("Tentando conectar à rede WiFi..."); | |
| WiFi.begin(ssid.c_str(), pass.c_str()); | |
| int timeout = 0; | |
| while (WiFi.status() != WL_CONNECTED && timeout < 20) { // ~10s | |
| delay(500); | |
| Serial.print("."); | |
| timeout++; | |
| } | |
| Serial.println(); | |
| if (WiFi.status() == WL_CONNECTED) { | |
| Serial.println("WiFi conectado! IP: " + WiFi.localIP().toString()); | |
| pWifiStatusChar->setValue("OK"); | |
| pWifiStatusChar->notify(); | |
| // Salva SSID/senha na NVS | |
| preferences.begin("wifi", false); | |
| preferences.putString("ssid", ssid); | |
| preferences.putString("pass", pass); | |
| preferences.end(); | |
| } else { | |
| Serial.println("Falha na conexão WiFi"); | |
| pWifiStatusChar->setValue("ERROR"); | |
| pWifiStatusChar->notify(); | |
| } | |
| ssid = ""; | |
| pass = ""; | |
| } | |
| } | |
| }; | |
| void setup() { | |
| Serial.begin(115200); | |
| delay(500); | |
| // --- Inicializa BLE --- | |
| BLEDevice::init("MeuESP32"); | |
| pServer = BLEDevice::createServer(); | |
| BLEService *pService = pServer->createService(BLEUUID((uint16_t)0x180A)); | |
| BLECharacteristic* pSSIDChar = pService->createCharacteristic(UUID_SSID, BLECharacteristic::PROPERTY_WRITE); | |
| BLECharacteristic* pPassChar = pService->createCharacteristic(UUID_PASS, BLECharacteristic::PROPERTY_WRITE); | |
| pSSIDChar->setCallbacks(new WifiCredentialsCallbacks()); | |
| pPassChar->setCallbacks(new WifiCredentialsCallbacks()); | |
| pScanCmdChar = pService->createCharacteristic(UUID_SCAN_CMD, BLECharacteristic::PROPERTY_WRITE); | |
| pScanCmdChar->setCallbacks(new ScanCmdCallbacks()); | |
| pScanResultChar = pService->createCharacteristic(UUID_SCAN_RESULT, BLECharacteristic::PROPERTY_NOTIFY); | |
| pScanResultChar->addDescriptor(new BLE2902()); | |
| pWifiStatusChar = pService->createCharacteristic(UUID_WIFI_STATUS, BLECharacteristic::PROPERTY_NOTIFY); | |
| pWifiStatusChar->addDescriptor(new BLE2902()); | |
| pService->start(); | |
| pAdvertising = BLEDevice::getAdvertising(); | |
| pAdvertising->addServiceUUID(pService->getUUID()); | |
| pAdvertising->start(); | |
| Serial.println("BLE iniciado e advertising ativo."); | |
| // --- Inicializa WiFi --- | |
| WiFi.mode(WIFI_STA); | |
| WiFi.disconnect(true); | |
| Serial.println("WiFi pronto."); | |
| // --- Reconecta automaticamente usando NVS --- | |
| preferences.begin("wifi", false); | |
| String savedSSID = preferences.getString("ssid", ""); | |
| String savedPass = preferences.getString("pass", ""); | |
| preferences.end(); | |
| if (savedSSID.length() > 0) { | |
| Serial.println("Reconectando ao WiFi salvo: " + savedSSID); | |
| WiFi.begin(savedSSID.c_str(), savedPass.c_str()); | |
| int timeout = 0; | |
| while (WiFi.status() != WL_CONNECTED && timeout < 20) { | |
| delay(500); | |
| Serial.print("."); | |
| timeout++; | |
| } | |
| Serial.println(); | |
| if (WiFi.status() == WL_CONNECTED) { | |
| Serial.println("Reconexão bem sucedida! IP: " + WiFi.localIP().toString()); | |
| } else { | |
| Serial.println("Falha na reconexão automática"); | |
| } | |
| } | |
| } | |
| void loop() { | |
| // --- Loop principal --- | |
| // Verifica WiFi a cada 10s | |
| static unsigned long lastCheck = 0; | |
| if (millis() - lastCheck > 10000) { | |
| lastCheck = millis(); | |
| if (WiFi.status() != WL_CONNECTED) { | |
| Serial.println("WiFi caiu, tentando reconectar..."); | |
| preferences.begin("wifi", false); | |
| String savedSSID = preferences.getString("ssid", ""); | |
| String savedPass = preferences.getString("pass", ""); | |
| preferences.end(); | |
| if (savedSSID.length() > 0) { | |
| WiFi.begin(savedSSID.c_str(), savedPass.c_str()); | |
| int timeout = 0; | |
| while (WiFi.status() != WL_CONNECTED && timeout < 20) { | |
| delay(500); | |
| Serial.print("."); | |
| timeout++; | |
| } | |
| Serial.println(); | |
| if (WiFi.status() == WL_CONNECTED) { | |
| Serial.println("Reconexão WiFi bem sucedida! IP: " + WiFi.localIP().toString()); | |
| } else { | |
| Serial.println("Falha na reconexão WiFi"); | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment