ESP32 coneccion modo STA

Hola a tod@s,

EL contexto es el siguiente :

en el codigo, al usar el modo STA, usando unas varias const char para conectar a una red usando el WiFi.begin(ssid,pswd), no conecta, pero al usar SSID y las clave de forma directa en la clase, conecta enseguida.

En el monitor no veo mayor problema y lo que muestra el WiFi.printDialog(Serial), de una forma u otra, es lo mismo, salvo que de una forma se conecta y de la otra no.

PD : tanto el ssid como las pswd, son rescatados de un json.

parte del codigo de coneccion :

    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    WiFi.begin(ssidSTA,passwordSTA);
    //WiFi.begin("MARIA PAZ 2.4","RM0300CM");

En el monitor usando solo las variables , se obtenie lo siguiente :

[  5528][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 0 - WIFI_READY
[  557[6 ] [5E5]7[6W]i[FVi]S[TWAi.FcipGpe:n2e3r7i]c .bcepgpi:n3(4)1:]  p_aasrsdpuhirnaos_ee vteonot _lcobn(g)!: 
STA Started
[  5587][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 2 - STA_START

Mode: STA
Channel: 1
SSID (13): MARIA PAZ 2.4
Passphrase (8): RM0300CM
BSSID set: 0

Connecting to WiFi .............................

Al usar texto directo en la clase, se obteniene lo siguiente :

---- Se abrió el puerto de serie /dev/ttyACM0 ----
Credenciales encontradas [004]:
MARIA PAZ 2.4/RM0300CM
/[  5528][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 0 - WIFI_READY
[  5572][V][WiFiGeneric.cpp:341] _arduino_event_cb(): STA Started
[  5573][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
[  5590][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 2 - STA_START

Mode: STA
Channel: 3
SSID (13): MARIA PAZ 2.4
Passphrase (8): RM0300CM
BSSID set: 0

Connecting to WiFi ...[  6616][V][WiFiGeneric.cpp:363] _arduino_event_cb(): STA Disconnected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Reason: 2
[  6627][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[  6635][W][WiFiGeneric.cpp:1062] _eventCallback(): Reason: 2 - AUTH_EXPIRE
[  6642][D][WiFiGeneric.cpp:1082] _eventCallback(): WiFi Reconnect Running
[  6650][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
.[  7674][V][WiFiGeneric.cpp:363] _arduino_event_cb(): STA Disconnected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Reason: 2
[  7686][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[  7694][W][WiFiGeneric.cpp:1062] _eventCallback(): Reason: 2 - AUTH_EXPIRE
[  7700][D][WiFiGeneric.cpp:1086] _eventCallback(): WiFi AutoReconnect Running
[  7709][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
.[  8733][V][WiFiGeneric.cpp:363] _arduino_event_cb(): STA Disconnected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Reason: 2
[  8745][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[  8752][W][WiFiGeneric.cpp:1062] _eventCallback(): Reason: 2 - AUTH_EXPIRE
[  8759][D][WiFiGeneric.cpp:1086] _eventCallback(): WiFi AutoReconnect Running
[  8767][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
.[  9792][V][WiFiGeneric.cpp:363] _arduino_event_cb(): STA Disconnected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Reason: 2
[  9803][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[  9811][W][WiFiGeneric.cpp:1062] _eventCallback(): Reason: 2 - AUTH_EXPIRE
[  9818][D][WiFiGeneric.cpp:1086] _eventCallback(): WiFi AutoReconnect Running
[  9826][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
.[ 10849][V][WiFiGeneric.cpp:363] _arduino_event_cb(): STA Disconnected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Reason: 2
[ 10860][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[ 10868][W][WiFiGeneric.cpp:1062] _eventCallback(): Reason: 2 - AUTH_EXPIRE
[ 10875][D][WiFiGeneric.cpp:1086] _eventCallback(): WiFi AutoReconnect Running
[ 10883][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
[ 10942][V][WiFiGeneric.cpp:356] _arduino_event_cb(): STA Connected: SSID: MARIA PAZ 2.4, BSSID: c4:69:f0:cc:bb:88, Channel: 3, Auth: WPA_WPA2_PSK
[ 10955][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 4 - STA_CONNECTED
..[ 13182][V][WiFiGeneric.cpp:370] _arduino_event_cb(): STA Got New IP:192.168.110.15
[ 13190][D][WiFiGeneric.cpp:1040] _eventCallback(): Arduino Event: 7 - STA_GOT_IP
[ 13197][D][WiFiGeneric.cpp:1103] _eventCallback(): STA IP: 192.168.110.15, MASK: 255.255.255.0, GW: 192.168.110.1
.192.168.110.15
---- Se cerró el puerto de serie /dev/ttyACM0 ----

Pienso que puede ser algo en las cadenas de texto, pero no logro descifrar que puede ser o el o los motivos. Tanto con las variables como de forma directa, el ssid o el pswd, tienen la misma cantidad de caracteres y/o longitud. Me llama la atencion que :

con usar las variables , selecciona el canal 1 y al usar texto directo, selecciona otro canal 3.

Saludos y gracias de ante mano.

Por el momento, he modificado el while de conección del modo STA, y un contador de 1 a 14, cumpliendo los 20 segundos, realizo un WiFi.reconect() y termina de conectarse en el canal 3 al cumplirse los primeros 20 segundos.

Por lo que he notado , no logro o no se puede setear el canal de conección. Pero con el reconectar, al parecer hace una búsqueda de la ssid en todos los canales y terminando de encontrar la señal en el canal 3.

Si alguien me puede explicar, sería genial.

Y el código 1 y 2 para hacer pruebas y darte una respuesta?

Hola @Surbyte , con respecto al código 1 y 2, me refiero a que ...
Usando variables en begin no pasaba y
Usando texto directo en el begin si funciona.

Ahora, después de varias pruebas, tengo las siguientes conclusiones:

Realizó un disconnect false/true, por lo que entiendo, esto desconecta y elimina credenciales.
Realizo un begin con la función String(), para ssid y pswd en el modo STA, con consigo nuevamente entrar las credenciales. De esta forma, la librería consigue buscar nuevamente la red y su canal, realizando la conección y las 4 segundos conecta a red.

Por lo que veo, al setear nuevamente las credenciales, intenta buscar la red , desde el canal 0 a n canal, pasando desde 0,1,2,3 y conecta.

También me he dado cuenta que, a pesar de que las variables ssid y pswd declaradas como const char*, aplicadas directamente en begin o softAP, no funcionan correctamente y por ese motivo, realizo un disconnect al inicio de cada modo y seteo usando la función String().

También, todo funciona mejor si se setea el txPower a 8_5.

Con todo lo anterior se logra correr los dos modos sin mayor problema.

Es lo que he sacado en limpio después de varias pruebas.

¿Al final ssid y pswd son constantes o variables?

Como no has puesto el código es difícil sacar conclusiones pero "MARIA PAZ 2.4" (literal) tiene 14 caracteres, no 13, porque tiene un caracter 0 como final de cadena.
¿La cadena que recuperas del json tiene el caracter de final de cadena '\0'?
Tal vez ese es tu problema.

A mi ese nombre de SSID no me gusta, contiene muchas cosas problemáticas.
Espacios y caracteres especiales ".", prueba solo por probar con un simple nombre sin nada raro. algo que lleve el nombre de "TPLINK" por decir algo.

Si, entiendo, a mí tampoco, estoy acostumbrado a la antigua (8 carácteres) jajaja. Pero al día de hoy, la programación se debe adaptar a todos los posibles casos.

Pero más que los nombres, pienso que las librerías algunas no tienen tanto detalle. Cómo el porque setear el TxPower a 8_5. O la forma correcta de cambiar el AP o el STA. Ya que la mayoría se los ejemplos, tanto públicos como los mismos ejemplos de las librerías son prácticamente iguales.

Parece que la librería WiFi.h almacena la credencial de última STA conectada. Y a pesar de que sus parámetros deben ser char , acepta sin problema los String.

La verdad que de modo estructural, si claro , tiene un \0 y si se puede consultar y validar,pero las mismas funciones de la misma librería se saltan eso y las funciones que cuentan carácteres no consideran ese carácter.

Adaptá lo que gustes, estoy de acuerdo, pero eliminá las dudas o es un camino interminable.
Primero probá algo y luego avanzá determinando que funciona y qué no.
Si te digo que en MicroPython todo funciona perfecto que me decis?
He hecho pruebas que en Arduino no conectan y digamos lo mas o menos similar en MicroPython conecta instantáneo.
Luego logré que conectara y tardaba como 5 seg, no quise portar todo el código, asi que quedó asi, pero algo pasa no?
Y no hablo de mi código, hablo de ejemplos básicos de conexión Wifi.

sizeof() si lo cuenta, salvo que uses la cadena en formato c.

Como te dije, sin ver código es solo especular.

Aun sigo sin entender algunos pasos, que probablemente o lo mas seguro es que algo no este haciendo como corresponde.

les dejo el codigo y explico brevemente parte de la logica :

hay dos archivos para guardar credenciales de red, uno para AP y otro para STA. Si estos archivos existen, se pasa lo almacenado a las variables ssid y pswd, segun corresponda.

para el modo STA, inicialmente las const char* ssid y pswd estan vacias, los datos almacenados contienen las credenciales.

La funciona que carga los datos, no veo que tena problemas, la funciona que inicia el modo STA, tampoco veo que tenga mayores problemas.

ahora, al ver esto por el monitor, se puede apreciar que las const char reciben correctamente los datos, estos son presentados en el terminar y finalmente se pasan al begin, pero es ahi donde por algun motivo , la const se comporta extraño y despues al visualizarla nuevamente se ve "distinto" por decir algo.

MONITOR

SPIFFS OK!
Credenciales encontradas [003]:
Modo STA autoseleccionado
Variables desde la funcion setupSTAMode()
SSID WF : MARIA PAZ 2.4
PSWD WF : RM0300CM
[ 13796][E][WiFiSTA.cpp:232] begin(): SSID too long or missing!

Mode: STA
Channel: 1
SSID (0): 
Passphrase (0): 
BSSID set: 0

Conetando a red wifi ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥ÍÍ... ..
---- Se cerró el puerto de serie /dev/ttyACM0 ----

main.cpp

#include <Arduino.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include "funciones.h"

void setup() {
  pinMode(RGB_LED,OUTPUT);
  RGBLed(0);
  Serial.begin(115200);
  delay(5000);
  int ntiempo = 0;
  while(!SPIFFS.begin(true) && ntiempo < 20){
    Serial.print(".");
    delay(1000);
    ntiempo++;
  }
  if (!SPIFFS.begin(true)) {
    Serial.println("An error has occurred while mounting SPIFFS");
    return;
  }else{
    Serial.println("SPIFFS OK!"); 
  }

  loadWiFiCredentials();

  if (isAPMode) {
    loadAPCredentials();
    RGBLed(2);
    setupAPMode();
  } else {
    RGBLed(5);
    setupSTAMode();
  }

  WebServerIni();
  // Guardar el tiempo de inicio
  startTime = millis();
}

void loop() {
  // El bucle principal puede permanecer vacío ya que no hay tareas periódicas necesarias
  chkTimeBootAP();
  if(Serial.read()=='1'){ESP.restart();};
  if(Serial.read()=='8'){DelCredencials(8);};
  if(Serial.read()=='9'){DelCredencials(9);};
}

funciones.h

#define RGB_LED 48
bool isAPMode = true;
// Constantes y variables globales
const char* ssidAP = "CAMCARESP32";
const char* passwordAP = "ESP32S3CAM";
const char* ssidSTA = ""; // To be loaded from SPIFFS
const char* passwordSTA = ""; // To be loaded from SPIFFS

unsigned long startTime;
const unsigned long timeout = 120000; // 2 minutos en milisegundos
AsyncWebServer server(80);

String scanNetworks() {
    String wifiList = "";
    int n = WiFi.scanNetworks();
    for (int i = 0; i < n; ++i) {
        wifiList += "<button type=\"button\" class=\"list-group-item list-group-item-action\" value=\"" + WiFi.SSID(i) + "\" onclick=\"clickbtn()\">" + WiFi.SSID(i) + " (" + WiFi.RSSI(i) + " dBm)</button>";
    }
    return wifiList;
}

void RGBLed(int numColor){
  /*
  0 = Blanco
  1 = Rojo
  2 = Azul
  3 = Verde
  4 = Amarillo
  */
  int r = 0;
  int g = 0;
  int b = 0;
  switch (numColor){
    case 0:
      r=255;g=255;b=255;
      break;
    case 1:
      r=255;g=3;b=3;
      break;
    case 2:
      r=0;g=0;b=255;
      break;
    case 3:
      r=0;g=255;b=0;
      break;
    case 4:
      r=200;g=255;b=3;
      break;
    case 5:
      r=240;g=10;b=255;
      break;
    case 6:
      r=10;g=255;b=100;
      break;
  default:
    r=255;g=255;b=255;
    break;
  }
  digitalWrite(RGB_LED,LOW);
  neopixelWrite(RGB_LED,r,g,b);
  digitalWrite(RGB_LED,HIGH);

}

String insertValues(String html) {
  html.replace("{{cpuFreq}}", String(ESP.getCpuFreqMHz()));
  html.replace("{{flashSize}}", String(ESP.getFlashChipSize() / (1024 * 1024)));
  html.replace("{{ramSize}}", String(ESP.getFreeHeap() / 1024));
  html.replace("{{networkMode}}", String(WiFi.getMode() == WIFI_STA ? "WIFI_STA" : "WIFI_AP"));
  if(WiFi.getMode() == WIFI_STA){
    html.replace("{{ssid}}", String(WiFi.SSID()));
    html.replace("{{ipAddress}}", WiFi.localIP().toString());
    html.replace("{{subnetMask}}", WiFi.subnetMask().toString());
    html.replace("{{gateway}}", WiFi.gatewayIP().toString());
  }else{
    html.replace("{{ssid}}", String(WiFi.SSID()));
    html.replace("{{ipAddress}}", WiFi.softAPIP().toString());
    html.replace("{{subnetMask}}", String(WiFi.softAPSubnetCIDR()));
    html.replace("{{gateway}}", WiFi.softAPIP().toString());    
  }
  html.replace("{{btStatus}}", "Activo"); // Supongamos que está activo
  html.replace("{{btMac}}", "AA:BB:CC:DD:EE:FF"); // Reemplazar con la MAC real si es necesario
  html.replace("{{sdkVersion}}", String(ESP.getSdkVersion()));
  html.replace("{{uptime}}", String(millis() / (1000 * 60)));
  html.replace("{{cpuTemp}}", String(temperatureRead()));
  
  return html;
}

String insertValuesAP(String html) {
  html.replace("{{valueSSID}}", String(ssidAP));
  html.replace("{{valuePSWD}}", String(passwordAP));
  html.replace("{{valueIP}}", String(WiFi.softAPIP().toString()));
  
  return html;
}

void setupAPMode() {
  RGBLed(0);
  Serial.println("Iniciando modo AP...");
  delay(1000);
  WiFi.mode(WIFI_AP);
  WiFi.setTxPower(WIFI_POWER_8_5dBm);
  WiFi.softAP(ssidAP,passwordAP,random(2,13) );
  delay(1000);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP Address: ");
  Serial.println(IP);
  Serial.print("SSID AP : ");Serial.println(String(ssidAP));
  Serial.print("PSWD AP : ");Serial.println(String(passwordAP));
  isAPMode = true;
  RGBLed(3);
}

void setupSTAMode() {
    Serial.println("Variables desde la funcion setupSTAMode()");
    Serial.print("SSID WF : ");Serial.println(ssidSTA);
    Serial.print("PSWD WF : ");Serial.println(passwordSTA);
    int nseg = 0;
    int nchannel = 1;

    WiFi.mode(WIFI_STA);
    WiFi.setTxPower(WIFI_POWER_8_5dBm); 
    WiFi.channel(nchannel);
    WiFi.begin(ssidSTA,passwordSTA);
 
    delay(2000);
    Serial.println();
    WiFi.printDiag(Serial);
    Serial.println();
    delay(1000);
    Serial.print("Conetando a red wifi " + String(&ssidSTA[0]) + "... ");
    while (WiFi.status() != WL_CONNECTED && nchannel <= 14) {
      delay(1000);
      Serial.print(".");
      nseg++;
      if(nseg==10){
        Serial.println();
        nchannel++;
        WiFi.channel(nchannel);
        WiFi.reconnect();
        Serial.println();
        WiFi.printDiag(Serial);
        nseg=0;
        Serial.println();
      }
    }
    if(WiFi.status() == WL_CONNECTED){
      Serial.println(WiFi.localIP());
      isAPMode = false;
      RGBLed(6);
    }else{
      Serial.println("No se pudo conectar a la red WIFI almacenada");
      isAPMode = true;
      RGBLed(1);
    }
}

void loadWiFiCredentials() {
    File root = SPIFFS.open("/");
    File WFJson;
    bool lFile = false;
    String NombreFile = "";
    File file = root.openNextFile();
    while (file) {
        if (!file.isDirectory()) {
            if(String(file.name())=="wifi_credentials.json"){
                lFile = true;
                NombreFile = file.name();
                WFJson = SPIFFS.open("/" + NombreFile, "r");
                break;
            }
        }
        file = root.openNextFile();
    }
  delay(3000);
  if (!lFile) {
    Serial.println("No se encontraron credenciales WiFi guardadas.");
    RGBLed(1);
    delay(3000);
    return;
  }else{
    size_t size = WFJson.size();
    std::unique_ptr<char[]> buf(new char[size]);
    file.readBytes(buf.get(), size);
    JsonDocument doc;
    deserializeJson(doc, buf.get());

    Serial.println("Credenciales encontradas [003]:");

    ssidSTA = doc["ssid"].as<const char*>();
    passwordSTA = doc["password"].as<const char*>();

    doc.clear();
    //Serial.println("Variables desde la funcion loadWiFiCredentials()");
    //Serial.print("SSID WF : ");Serial.println(ssidSTA);Serial.print("PSWD WF : ");Serial.println(passwordSTA);
    RGBLed(2);
    delay(5000);
    if(ssidSTA != nullptr && ssidSTA[0] != '\0' && passwordSTA != nullptr && passwordSTA[0] != '\0'){
        isAPMode=false;
        Serial.println("Modo STA autoseleccionado");
    }else{
      Serial.println("Credenciales corruptas!!![002]");
      SPIFFS.remove(NombreFile);
      Serial.println("Credenciales ELIMINADAS[006]");
      RGBLed(6);
      isAPMode = true;
    }
    WFJson.close();
  }
}

void loadAPCredentials() {
    File root = SPIFFS.open("/");
    File APJson;
    bool lFile = false;
    String NombreFile = "";
    File file = root.openNextFile();
    while (file) {
        if (!file.isDirectory()) {
            if(String(file.name())=="ap_credentials.json"){
                lFile = true;
                NombreFile = file.name();
                APJson = SPIFFS.open("/" + NombreFile, "r");
                break;
            }
        }
        file = root.openNextFile();
    }
  if (!lFile) {
    Serial.println("No se encontraron credenciales AP guardadas.");
    RGBLed(1);
    return;
  }else{
    if(isAPMode){
        Serial.println("credenciales AP encontradas.[008]");
        size_t size = APJson.size();
        std::unique_ptr<char[]> buf(new char[size]);
        file.readBytes(buf.get(), size);
        JsonDocument doc;
        deserializeJson(doc, buf.get());
        String auxssid = doc["ssid"].as<const char*>();
        String auxpswd = doc["password"].as<const char*>();
        doc.clear();
        auxssid.trim();
        auxpswd.trim();
        ssidAP = auxssid.c_str();
        passwordAP = auxpswd.c_str();
        Serial.print("SSID AP : ");Serial.println(String(ssidAP));
        Serial.print("PSWD AP : ");Serial.println(String(passwordAP));
        APJson.close();
    }
  }
}

void saveWiFiCredentials(const String& ssid, const String& password) {
    JsonDocument doc;
    doc["ssid"] = ssid;
    doc["password"] = password;
    File file = SPIFFS.open("/wifi_credentials.json", "w");
    serializeJson(doc, file);
    file.close();
    isAPMode = false;
    doc.clear();
}

void saveAPCredentials(const String& ssid, const String& password) {
  JsonDocument doc;
  doc["ssid"] = ssid;
  doc["password"] = password;
  File file = SPIFFS.open("/ap_credentials.json", "w");
  serializeJson(doc, file);
  file.close();
  doc.clear();
}

void listSPIFFSFiles() {
    // Comprobar si SPIFFS está montado correctamente
    if (!SPIFFS.begin()) {
        Serial.println("No se pudo montar SPIFFS");
        return;
    }

    // Abre el directorio raíz
    File root = SPIFFS.open("/");
    if (!root) {
        Serial.println("Fallo al abrir el directorio raíz");
        return;
    }

    // Comprueba si es un directorio
    if (!root.isDirectory()) {
        Serial.println("No es un directorio");
        return;
    }

    // Abre el directorio
    File file = root.openNextFile();
    while (file) {
        if (file.isDirectory()) {
            Serial.print("Directorio: ");
            Serial.println(file.name());
        } else {
            Serial.print("Archivo: ");
            Serial.print(file.name());
            Serial.print(" Tamaño: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }

    // Cerrar el directorio y finalizar SPIFFS
    file.close();
    //SPIFFS.end();
}

void DelCredencials(int Credencials){
    File root = SPIFFS.open("/");
    String NombreFile = "";
    File file = root.openNextFile();
    bool fEncontrado = false;
    switch (Credencials)
    {
    case 8:
        NombreFile = "ap_credentials.json";
        break;
    case 9:
        NombreFile = "wifi_credentials.json";
        break;
    default:
        NombreFile = ".";
        break;
    }

    while (file) {
        if (!file.isDirectory()) {
            if(String(file.name())==NombreFile){
                SPIFFS.remove("/" + NombreFile);
                Serial.print("Archivo ");
                Serial.print(NombreFile);Serial.println(" Eliminado!");
                fEncontrado = true;
                break;
            }
        }
        file = root.openNextFile();
    }
    if(!fEncontrado){
        Serial.println();Serial.println("Archivo de credenciales no encontrado");
    }
}

void WebServerIni(){
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
      String htmlContent;
      File file = SPIFFS.open("/index.html", "r");
      if (file) {
          htmlContent = file.readString();
          file.close();
      }
      if(isAPMode){
        // Reemplaza los marcadores de posición con los valores reales
        htmlContent.replace("{SSID_AP}", WiFi.softAPSSID());
        htmlContent.replace("{IP_AP}", WiFi.softAPIP().toString());
        htmlContent.replace("{AP_PSWD}", String(passwordAP));
      }else{
        if (WiFi.status() == WL_CONNECTED) {
            htmlContent.replace("{SSID_AP}", String(WiFi.SSID()));
            htmlContent.replace("{IP_AP}", WiFi.localIP().toString());
        } else {
            htmlContent.replace("{SSID_AP}", "No conectado");
            htmlContent.replace("{IP_AP}", "N/A");
        }   
      }  
      // Envía el contenido modificado al cliente
      request->send(200,"text/html",htmlContent);
  });

  server.on("/wifi_sta", HTTP_GET, [](AsyncWebServerRequest *request){
      String htmlContent;
      File file = SPIFFS.open("/wifi_sta.html", "r");
      if (file) {
          htmlContent = file.readString();
          file.close();
      }
      // Reemplaza {{WIFI_LIST}} con la lista de redes WiFi escaneadas
      htmlContent.replace("{{WIFI_LIST}}", scanNetworks());
      request->send(200, "text/html",htmlContent );
  });

  server.on("/save_wifi", HTTP_POST, [](AsyncWebServerRequest *request){
      String ssid;
      String password;

      if (request->hasParam("lstSSID", true)) {
          ssid = request->getParam("lstSSID", true)->value();
      }
      if (request->hasParam("inputPassword2", true)) {
          password = request->getParam("inputPassword2", true)->value();
      }

      // Guarda las credenciales WiFi
      if (ssid.length() > 0 && password.length() > 0) {
          saveWiFiCredentials(ssid, password);
          delay(5000);
          request->send(200, "text/plain", "Credenciales guardadas. Reinicia el ESP32.[000]");
          delay(10000);
          ESP.restart();
      }else{
          request->send(200, "text/plain", "Credenciales corruptas! ERROR[001]");
          delay(10000);
      }      
  });

  server.on("/setup_ap", HTTP_GET, [](AsyncWebServerRequest *request){
      String htmlContent;
      File file = SPIFFS.open("/setup_ap.html", "r");
      if (file) {
          htmlContent = file.readString();
          file.close();
      }
        // Insertar los valores dinámicos en el HTML
      htmlContent = insertValuesAP(htmlContent);
      request->send(200, "text/html",htmlContent );
  });

  server.on("/save_ap", HTTP_POST, [](AsyncWebServerRequest *request){
      String ssid;
      String password;

      if (request->hasParam("ssidAP", true)) {
          ssid = request->getParam("ssidAP", true)->value();
      }
      if (request->hasParam("pswdAP", true)) {
          password = request->getParam("pswdAP", true)->value();
      }

      // Guarda las credenciales WiFi
      if (ssid.length() > 0 && password.length() > 0) {
          saveAPCredentials(ssid, password);
          delay(5000);
          request->send(200, "text/plain", "Credenciales guardadas. Reinicia el ESP32.[000]");
          delay(10000);
          ESP.restart();
      }else{
          request->send(200, "text/plain", "Credenciales corruptas! ERROR[001]");
          delay(10000);
      }      
  });

  server.on("/estado_ap", HTTP_GET, [](AsyncWebServerRequest *request){
      request->send(SPIFFS, "/estado_ap.html", "text/html");
    });

  server.on("/del_credencials", HTTP_GET, [](AsyncWebServerRequest *request){
    DelCredencials(8);
    DelCredencials(9);
    request->send(200, "text/plain", "Accion ejecutada!");
    delay(2000);
    request->send(SPIFFS, "/", "text/html");
    });

  server.on("/elimina_credenciales", HTTP_GET, [](AsyncWebServerRequest *request){
      request->send(SPIFFS, "/elimina_credenciales.html", "text/html");
    });

    server.on("/info_esp32", HTTP_GET, [](AsyncWebServerRequest *request){
      String htmlContent;
      File file = SPIFFS.open("/info_esp32.html", "r");
      if (file) {
          htmlContent = file.readString();
          file.close();
      }
      htmlContent = insertValues(htmlContent);
      request->send(200, "text/html",htmlContent );
    });

  server.on("/jquery-3.2.1.slim.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/jquery-3.2.1.slim.min.js", "application/javascript");
  });

  server.on("/popper.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/popper.min.js", "application/javascript");
  });

  server.on("/bootstrap.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/bootstrap.min.js", "application/javascript");
  });
  server.on("/bootstrap.min.js.map", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/bootstrap.min.js.map", "application/javascript");
  });
  server.on("/bootstrap.min.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/bootstrap.min.css", "text/css");
  });
  server.on("/bootstrap.min.css.map", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/bootstrap.min.css.map", "text/css");
  });
  server.on("/banneresp32camcar.png", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/banneresp32camcar.png", "image/png");
  });

  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/favicon.ico", "image/x-icon");
  });

  server.begin();

}

void chkTimeBootAP(){

Esta linea, le ha impreso de diferentes formas y el resultado es el mismo que se ve en el monitor.

Serial.print("Conetando a red wifi " + String(&ssidSTA[0]) + "... ");

Saludos.

Porque no pruebas esto

el ejemplo Basic es suficiente.

@Surbyte hola, si, ya he visto y es una librería bien solucionada y he visto que funciona bastante bien. Pero me gusta entender el como y el porque. Generalmente cuando ya entiendo como funciona, busco bypass para ahorrar tiempo, pero en este caso, si me llegase a pasar temas similares quedaria donde mismo y seguiria sin poder resolver la duda.
Ahora mismo, no me queda claro, si los temas que estoy teniendo, son por logica, por equipo o por libreria.

Pareciera que la const char se ensuciara despues de utilizarla con el Serial.print y no se si eso sea algo que puede suceder u otra cosa.

data.zip (255,7 KB)
Ese el data para el esp32 si alguien quiere ir mas allá. son html/bootstrap y una pequeña imagen.

Quizás digo una tontería, pero ya que el error indica SSID demasiado largo o inexistente, y dado que sí existe, ¿no tendrás "blancos" al final hasta superar los 32 caracteres de tope para un SSID? Por probar, ¿y si pones un serial.print("<") después del print del ssid para verificarlo?
Quizás si ya no le es correcto el SSID ya no lo,guarda internamente y por eso en el printDiag(serial) te lo imprime como vacío.

Hola @bestbit , jajaja... Nada es tontería, a pesar que existe la posibilidad, en los datos monitor, tanto el ssid como el pswd estaban pegados , después simplemente use un println para formatearlos y me consta que, cuando he logrado que lo reconozca, da la longitud que corresponde+1 , y eso está bien.

Ahora por lo que he notado, al usar en reiteradas ocasiones las const char de ssid y pswd, ya sea, para el modo AP, como para el modo STA, es cuando estás aparecen como si se ensuciaran. El dejar de imprimirlas en el monitor, aparecen bien y logran pasarse tanto al softAP como begin respectivamente.

Es como si el puerto serial se saturara y empezará a dejar solo con basura estás const char.

De hecho estoy comprobando esto y de momento parece ser así. Si así lo fuese , me bastaría empezar a ver el porque. No sé si el puerto serial trabajara con buffer y a lo mejor habría que limpiarlo cada ciertas impresiones.

En el archivo data.zip de #14 no has incluido archivos de muestra con las claves (.json).
Sería interesante ver que es lo que se está guardando.

@MaximoEsfuerzo hola, No los incluí, porque si ejecutas todo, puedes crearlos al acceder al modo AP y porque no me introducido en el modo de descargar archivos de la partición spiffs.

Claro pero eso implica que tengo que tener tiempo disponible para sentarme en la computadora, conectar la placa, subir el código y bla, bla, no como ahora que te estoy respondiendo desde el móvil y con el que podría revisar los archivos tal y como hice con datos.zip
Además que no obtendría el mismo resultado, tus archivos y los míos serían diferentes..

Justamente el finde estuve viendo como usar wifimanager desde python. Hay una librería en la que resulta que el autor no contempló la posibilidad de ssid con espacios, por ej. "mi wifi", y que el navegador envía como "mi+wifi", por lo que tuve que modificarla sino nunca se conectaría.
Tampoco contempló passwords con caracteres especiales que se envían desde el navegador como la representación de sus códigos ASCII hexadecimales (' ' = "%20", '#' = "%23", por dar un par de ejemplos).
Si hubiese tenido que pedir ayuda, cualquiera me hubiese respondido que la librería funciona bien (salvo que su ssid también tuviese algún espacio y/o su pass algún caracter especial) si yo no pusiera ejemplos de mi ssid y password. ¿Me explico?