Problema connessione Blynk - dati inseriti in AP Mode e salvati in EEPROM

Salve a tutti.

Come da titolo sto tentando di collegarmi a Blynk, con i dati di SSID, Password della wifi e token che vengono inseriti dapprima in AP Mode dalla pagina 192.168.4.1 e poi salvati in EEPROM (che sostituirò con una SD nel caso, non vorrei danneggiarla per sovrascritture anche se comunque saranno dati che non verranno sempre modificati.

Il codice funziona così: in un primo momento se non ci sono dati già inseriti in EEPROM, ci sarà una la modalità AP che alla pagina 192.168.4.1 mi farà inserire i dati, fatto questo, al riavvio se ci sono dati già salvati, verranno utilizzati questi per connettersi a Blynk. Inoltre nei 5 secondi iniziali di avvio se premo il pulsante sul pin D7, i dati inseriti in EEPROM verranno cancellati e quindi avrò di nuovo la possibilità di avere l'AP mode, e di inserire nuovi dati.

Il tutto funziona tranne che per l'inizializzazione di Blynk.begin - infatti il codice si ferma a questa, e non va avanti, non riesce a connettersi. Ho provato anche con il metodo Blynk.config(auth) e Blynk.connected. Ma non riesco a stabilire una connessione.

Se provo a collegarmi a blynk con il metodo tradizionale, ovvero così:


#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char ssid[] = "miossid";
char pass[] = "miapass";
#define BLYNK_AUTH_TOKEN "oD************************7Iz"


void setup(){
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}

non ho assolutamente problemi. Se invece provo a collegarmi come descritto prima, non riesce ad andare avanti rispetto al Blynk.begin(). Questo è il codice:

#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>
#include <BlynkSimpleEsp8266.h>

#define buttonPin D7
const char* ssid = "ESP8266-AP";
const char* password = "password";

AsyncWebServer server(80);

void handleForm(AsyncWebServerRequest *request){
  if(request->args() > 0){
    String SSID_inserita;
    String Password_inserita;
    String BLYNK_TEMPLATE_ID;
    String BLYNK_TEMPLATE_NAME;
    String BLYNK_AUTH_TOKEN;
    for(uint8_t i=0; i<request->args(); i++){
      if(request->argName(i) == "SSID"){
        SSID_inserita = request->arg(i);
      }
      if(request->argName(i) == "password"){
        Password_inserita = request->arg(i);
      }
      if(request->argName(i) == "template_id"){
        BLYNK_TEMPLATE_ID = request->arg(i);
      }
      if(request->argName(i) == "template_name"){
        BLYNK_TEMPLATE_NAME = request->arg(i);
      }
      if(request->argName(i) == "auth_token"){
        BLYNK_AUTH_TOKEN = request->arg(i);
      }
    }

    // Stampa i dati inseriti
    Serial.println("SSID inserita: " + SSID_inserita);
    Serial.println("Password inserita: " + Password_inserita);
    Serial.println("BLYNK_TEMPLATE_ID inserita: " + BLYNK_TEMPLATE_ID);
    Serial.println("BLYNK_TEMPLATE_NAME inserita: " + BLYNK_TEMPLATE_NAME);
    Serial.println("BLYNK_AUTH_TOKEN inserita: " + BLYNK_AUTH_TOKEN);
    // Salva l'SSID, la password e le altre variabili nell'EEPROM
    int indirizzo = 0;
    for (int i = 0; i < SSID_inserita.length(); i++) {
      EEPROM.write(indirizzo, SSID_inserita[i]);
      indirizzo++;
    }
    EEPROM.write(indirizzo, '\0');
    indirizzo++;
    for (int i = 0; i < Password_inserita.length(); i++) {
      EEPROM.write(indirizzo, Password_inserita[i]);
      indirizzo++;
    }
    EEPROM.write(indirizzo, '\0');
    indirizzo++;
    for (int i = 0; i < BLYNK_TEMPLATE_ID.length(); i++) {
      EEPROM.write(indirizzo, BLYNK_TEMPLATE_ID[i]);
      indirizzo++;
    }
    EEPROM.write(indirizzo, '\0');
    indirizzo++;
    for (int i = 0; i < BLYNK_TEMPLATE_NAME.length(); i++) {
      EEPROM.write(indirizzo, BLYNK_TEMPLATE_NAME[i]);
      indirizzo++;
    }
    EEPROM.write(indirizzo, '\0');
    indirizzo++;
    for (int i = 0; i < BLYNK_AUTH_TOKEN.length(); i++) {
      EEPROM.write(indirizzo, BLYNK_AUTH_TOKEN[i]);
      indirizzo++;
    }
    EEPROM.write(indirizzo, '\0');
    EEPROM.commit();

    // Accendi il LED sul pin D4
    pinMode(2, OUTPUT);
    digitalWrite(2, HIGH);

    request->send(200, "text/html", 
      "<html>"
        "<head>"
          "<style>"
            "body {"
              "background-color: #F2F2F2;"
              "font-family: Arial, sans-serif;"
              "text-align: center;"
            "}"
            "h1 {"
              "color: #4A90E2;"
              "margin-top: 50px;"
            "}"
          "</style>"
        "</head>"
        "<body>"
          "<h1>In connessione</h1>"
        "</body>"
      "</html>"
    );
  }
  else{
    request->send(200, "text/html", 
      "<html>"
        "<head>"
          "<style>"
            "body {"
              "background-color: #F2F2F2;"
              "font-family: Arial, sans-serif;"
              "text-align: center;"
            "}"
            "h1 {"
              "color: #4A90E2;"
              "margin-top: 50px;"
            "}"
            "form {"
              "background-color: white;"
              "border: 1px solid #BFBFBF;"
              "box-shadow: 0px 0px 10px #BFBFBF;"
              "border-radius: 10px;"
              "margin: 0 auto;"
              "padding: 30px;"
              "width: 500px;"
            "}"
            "input[type='text'], input[type='password'] {"
              "background-color: #EAEAEA;"
              "border: none;"
              "border-radius: 5px;"
              "font-size: 16px;"
              "margin: 10px 0;"
              "padding: 10px;"
              "width: 100%;"
            "}"
            "input[type='submit'] {"
              "background-color: #4A90E2;"
              "border: none;"
              "border-radius: 5px;"
              "color: white;"
              "cursor: pointer;"
              "font-size: 16px;"
              "margin: 10px 0;"
              "padding: 10px 20px;"
              "width: 100%;"
            "}"
          "</style>"
        "</head>"
        "<body>"
          "<h1>ESP32 Web Page</h1>"
          "<form action='/' method='post'>"
            "<input type='text' name='SSID' placeholder='Nome reti WiFi'>"
            "<input type='password' name='password' placeholder='Password'>"
            "<input type='text' name='template_id' placeholder='BLYNK_TEMPLATE_ID'>"
            "<input type='text' name='template_name' placeholder='BLYNK_TEMPLATE_NAME'>"
            "<input type='text' name='auth_token' placeholder='BLYNK_AUTH_TOKEN'>"
            "<input type='submit' value='Connetti'>"
          "</form>"
        "</body>"
      "</html>"
    );
  }
}

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);

  pinMode(buttonPin, INPUT_PULLUP);  // Configura il pin del pulsante come input con pull-up

  // Controlla se il pulsante è premuto entro 5 secondi dall'accensione
  unsigned long startTime = millis();
  while (millis() - startTime < 5000) {
    if (digitalRead(buttonPin) == LOW) {
      // Se il pulsante è premuto, cancella le stringhe nell'EEPROM
      for (int i = 0; i < 512; i++) {
        EEPROM.write(i, 0);
      }
      EEPROM.commit();
      Serial.println("Le stringhe nell'EEPROM sono state cancellate.");
      break;
    }
    yield(); 
  }

  String SSID_salvata = "";
  String Password_salvata = "";
  String BLYNK_TEMPLATE_ID_salvata = "";
  String BLYNK_TEMPLATE_NAME_salvata = "";
  String BLYNK_AUTH_TOKEN_salvata = "";

  int indirizzo = 0;
  char ch = EEPROM.read(indirizzo);
  while (ch != '\0') {
    SSID_salvata += ch;
    indirizzo++;
    ch = EEPROM.read(indirizzo);
  }

  indirizzo++;
  ch = EEPROM.read(indirizzo);
  while (ch != '\0') {
    Password_salvata += ch;
    indirizzo++;
    ch = EEPROM.read(indirizzo);
  }

  indirizzo++;
  ch = EEPROM.read(indirizzo);
  while (ch != '\0') {
    BLYNK_TEMPLATE_ID_salvata += ch;
    indirizzo++;
    ch = EEPROM.read(indirizzo);
  }

  indirizzo++;
  ch = EEPROM.read(indirizzo);
  while (ch != '\0') {
    BLYNK_TEMPLATE_NAME_salvata += ch;
    indirizzo++;
    ch = EEPROM.read(indirizzo);
  }

  indirizzo++;
  ch = EEPROM.read(indirizzo);
  while (ch != '\0') {
    BLYNK_AUTH_TOKEN_salvata += ch;
    indirizzo++;
    ch = EEPROM.read(indirizzo);
  }

  // Rimani nel setup finché non vengono inseriti tutti i dati
  while (SSID_salvata == "" || Password_salvata == "" || BLYNK_TEMPLATE_ID_salvata == "" || BLYNK_TEMPLATE_NAME_salvata == "" || BLYNK_AUTH_TOKEN_salvata == "") {
    WiFi.mode(WIFI_AP);
    WiFi.softAP(ssid, password);
    server.on("/", HTTP_GET, handleForm);
    server.on("/", HTTP_POST, handleForm);
    server.begin();
    Serial.println("Dati non presenti, collegati a: ");

    // Stampa l'indirizzo IP assegnato all'ESP32
    Serial.println(WiFi.softAPIP());
    Serial.println("per inserire i dati");

    delay(1000); // Aggiungi un ritardo per evitare un ciclo infinito troppo veloce
  }

  // Una volta inseriti tutti i dati, passa alla modalità WIFI_STA e tenta di connettersi alla rete WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID_salvata.c_str(), Password_salvata.c_str());
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connessione alla rete WiFi...");
  }
  Serial.println("Connesso alla rete WiFi");
  
 char blynk_auth[33];
char blynk_ssid[33];
char blynk_pass[33];

BLYNK_AUTH_TOKEN_salvata.toCharArray(blynk_auth, sizeof(blynk_auth));
SSID_salvata.toCharArray(blynk_ssid, sizeof(blynk_ssid));
Password_salvata.toCharArray(blynk_pass, sizeof(blynk_pass));

// Avvia Blynk
Blynk.begin(blynk_auth, blynk_ssid, blynk_pass);
  
}



void loop() {
  Blynk.run();
}

Ci sto sbattendo la testa, ma non riesco a venire fuori. Grazie per eventuali suggerimenti.

Due cose:

  • l'ESP8266 non dipone di alcun tipo di EEPROM, la libreria in questione "emula" una EEPROM usando la memoria flash della MCU.
  • la libreria EEPROM.h dispone dei metodi get() e put() che ti evitano di fare tutto quel giro per recuperare le variabili.

Ciò detto, il metodo begin() di Blynk si aspetta SSID e password perché la connessione viene gestita dalla libreria stessa, mentre tu ti stai connettendo prima

Grazie mille per la risposta!
Quindi da come ho capito dovrei eliminare:

  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID_salvata.c_str(), Password_salvata.c_str());
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connessione alla rete WiFi...");
  }
  Serial.println("Connesso alla rete WiFi");

dato che lo fa già la libreria, dando in pasto ssid e pass ai parametri insieme al auth token.

Ho provato ad eliminare il Wifi.begin facendo gestire il tutto al begin di Blynk ma nulla purtroppo, non riesce a connettersi.
Grazie comunque per la puntualizzazione sulla EEPROM e per i metodi get() e put() che hai menzionato, lì utilizzerò per sfoltire il tutto.

PS. quelle variabili intermedie hai ragione non servono, ma provando e riprovando vari metodi per dare in pasto l'array char, ne ho provate di tutti i colori. Possono anche essere eliminate.

Prova a stampare SSID e password che recuperi dalla EEPROM per verificare che siano corrette.

Allora forse ho trovato il problema:

#define BLYNK_TEMPLATE_ID 
#define BLYNK_TEMPLATE_NAME

Queste due #define se vengono incluse globalmente con ovviamente le stringhe del nome del template e del ID del template, la connessione viene eseguita.

Il problema è solo per queste due e non per l'auth token. Nonostante io le dichiari tipo così, anzichè come due define:

char BLYNK_TEMPLATE_ID [] = "";
char BLYNK_TEMPLATE_NAME [] = "";

ho sempre lo stesso problema, evidentemente la libreria si aspetta due costanti, e il problema è che io queste due credenziali le volevo inserire tramite la pagina web a 192.168.4.1 quando ero in AP Mode!

Una soluzione l'ho trovata. Ossia fare il downgrade alla versione 1.1.0 della libreria Blynk, in questo caso, non viene richiesto il nome e l'id del template per collegarsi.
E' una soluzione valida per il mio scopo ma ovviamente in futuro per chi dovesse rileggere questo thread, suggerisco sempre di avere la libreria aggiornata all'ultima versione.

Ma io alla loro pagina "Get started with Blynk" vedo


ed è fatto con dei vettori di char, non con delle define

Le #define a cui faccio riferimento sono queste:

#define BLYNK_TEMPLATE_ID "++++++++++++"
#define BLYNK_TEMPLATE_NAME "Name"

mentre per quanto concerne, ssid, password, e Auth Token come già ho specificato, vanno bene gli array di char.
Il problema (se si può parlare di tale) risiede nel nome e ID del template che hai creato sull'app Blynk. Ripeto e non su ssid, password, e Auth Token. Questo soltanto a partire dalla nuova versione della libreria, ossia dalla 1.3 in poi.

L'esempio che hai trovato sarà sicuramente un'immagine non aggiornata, perchè non presenta le define di ID e nome template che nell'ultima versione viene invece richiesto necessariamente per stabilire una connessione.

Scusa ma al tuo primo post non dici di voler dare da eeprom i tre dati che sono okay come stringa? Non parlavi dei due define. Anche nome e ID del template vuoi passarlo dopo?

Dove stanno quelle define? Se le metti array di char (stringa classica del c) non funziona o non compila?

Nel corso, provando e ragionando, ho capito che si devono dare in pasto queste define del nome e ID template:

Allora forse ho trovato il problema:

#define BLYNK_TEMPLATE_ID 
#define BLYNK_TEMPLATE_NAME

Queste due #define se vengono incluse globalmente con ovviamente le stringhe del nome del template e del ID del template, la connessione viene eseguita.

Questo l'ho capito dopo. E' da tanto che non usavo Blynk ed ero rimasto al fatto che gli unici dati da inserire fossero quelli di ssid, pass, e auth token.
Infatti il primissimo codice era stato fatto su un pc che accendo raramente a casa dei miei, sul quale già c'era la libreria ma non aggiornata. Mi riferisco a questo:

Se provo a collegarmi a blynk con il metodo tradizionale, ovvero così:

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char ssid[] = "miossid";
char pass[] = "miapass";
#define BLYNK_AUTH_TOKEN "oD************************7Iz"

Mentre il secondo sketch, scritto sempre nel primo post di questo thread, lo avevo provato a casa mia con blynk alla versione 1.2 la quale non aveva alcun riferimento di errore se eludevi il template ID e Name.
Restando a casa mia e provando l'uno e l'altro sketch con la libreria 1.2 ho constatato che quindi il problema risiedeva nel template name e ID. Quindi aggiornando alla versione ancora più nuova ossia 1.3, in questa se eludevo il nome e ID del template allora mi dava errore nella compilazione, e questo è stato un altro indizio che mi ha fatto capire dove era il problema (ripeto, sempre se si può definire tale).

Non voglio tirarla per le lunghe perchè già tutta l'esplicazione dell'esperienza può sembrare contorta, ma è tutto frutto di prove su prove ovviamente. Quindi in sintesi, Soltanto successivamente, parlo del periodo successivo alla pubblicazione di questo thread, ho capito che era ID e name template a dare problemi alla connessione se scritti come array di char.

Quindi con la nuova libreria di Blynk, non solo ti darà errore durante la compilazione se non inserisci le due define ID e Name, ma inoltre non ti garantisce la connessione e resta piantato nel Blynk.begin() se le inserisci come array di char (in quest'ultimo caso non hai errore nella compilazione, ma al contempo non riesci ad inizializzare perchè si aspetta delle costanti).

Un errore di compilazione potrebbe essere possibile sistemarlo

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.