Skip to content

Instantly share code, notes, and snippets.

@IgorDePaula
Last active September 30, 2025 19:06
Show Gist options
  • Select an option

  • Save IgorDePaula/7ca3289721337121b3c02c3c9f2aeccf to your computer and use it in GitHub Desktop.

Select an option

Save IgorDePaula/7ca3289721337121b3c02c3c9f2aeccf to your computer and use it in GitHub Desktop.
#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