Captive portal e Android

solo io sto avendo problemi a realizzare un captive portal?

in sostanza, android riceve l'indirizzo ip dal modulo wifi dell'esp32, tutto correttamente MA non imposta i DNS che gli fornisce il modulo stesso (ovvero l'IP del wifi in modalità AP). piuttosto android utilizza quelli della connessione dati, in pratica ip assegnato da arduino, DNS della connessione dati

questo ovviamente spacca ogni cosa perché quando si è connessi ad arduino, non c'è connessione ad internet di conseguenza i DNS non sono raggiungibili (causando ogni sorta di timeout lato android) e soprattutto non può funzionare il captive portal visto che non riesco ad intercettare le richieste fatte verso i domini/URL utilizzati da Android per il controllo connettività

sto diventando matto, se stacco la connessione dati, tutto funziona ed i DNS vengono correttamente assegnati.

che sia un problema di Android? che android voglia usare dei DNS solo in determinate condizioni ? (quali?)

In questa libreria, gestisco il captive portal intercettando direttamente le richieste HTTP che vengono fatte dal sistema operativo (Android compreso) quando viene fatta la connessione ad un nuovo SSID e funziona tutto senza problemi.

    // Captive Portal redirect
    webserver->on("/redirect", HTTP_GET, std::bind(&FSWebServer::captivePortal, this));
    // Windows
    webserver->on("/connecttest.txt", HTTP_GET, std::bind(&FSWebServer::captivePortal, this));
    // Apple
    webserver->on("/hotspot-detect.html", HTTP_GET, std::bind(&FSWebServer::captivePortal, this));
    // Android
    webserver->on("/generate_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this));
    webserver->on("/gen_204", HTTP_GET, std::bind(&FSWebServer::captivePortal, this));

/**
 * Redirect to captive portal if we got a request.
 */
bool FSWebServer::captivePortal() {
  IPAddress ip = webserver->client().localIP();
  char serverLoc [sizeof("https:://255.255.255.255/")+ sizeof(m_apWebpage) + 1];
  snprintf(serverLoc, sizeof(serverLoc), "http://%d.%d.%d.%d%s", ip[0], ip[1], ip[2], ip[3], m_apWebpage);

  // redirect if hostheader not server ip, prevent redirect loops
  if (strcmp(serverLoc, webserver->hostHeader().c_str())) {
    webserver->sendHeader(F("Location"), serverLoc, true);
    webserver->send(302, F("text/html"), "");       // Empty content inhibits Content-length header so we have to close the socket ourselves.
    webserver->client().stop();                     // Stop is needed because we sent no content length
    return true;
  }
  return false;
}

Io però non uso la libreria ESPAsyncWebServer, ma la classica WebServer già inclusa nel core ESP32 (che non ha nulla da invidiare a ESPAsyncWebServer secondo me, anzi!).

1 Like

la WebServer integrata però non è asincrona...

A parte questo , il mio problema è che il captive portal per funzionare richiede di intercettare le richieste DNS verso i domini di test utilizzati da google (ad esempio) Infatti se guardi nei vari esempi, fanno tutti uso del DNSServer di arduino per intercettare ogni dominio ("*") fornendo l'ip dell'access point.

E funziona, se stacco la connessione dati, Android si prende i dns forniti da Arduino e tutto funziona a meraviglia. Il mio problema è che con una connessione dati attiva, non so per quale motivo, Android preferisce usare i nameserver della connessione dati e non quelli forniti da Arduino.

Il perchè di questo motivo lo ignoro. Il risultato è che non potrà MAI funzionare, perchè Android continuerà ad interrogare i dns della connessione dati, che giocoforza non sono raggiungibili (sono collegato all'access point arduino) generando mille-mila timeout infatti anche l'accesso manuale alla pagina web del capitve portal è lentissimo.

Non so come risolvere ma devo risolvere, non posso chiedere agli utenti di disattivare la connessione dati, nessuno lo fa. quando ti colleghi ad un dispositivo, ci pensa il telefono a staccare i dati, te, utente, lo fai solo il collegamento wifi.

Per quelle che sono state le mie considerazioni fatte a suo tempo, il vantaggio che ne consegue non vale lo sforzo. Alla fine nella maggioranza dei casi, un webserver integrato nell'ESP non è che deve servire centinaia di client, ma 2/3 nella peggiore delle ipotesi (se dovessi fare una connessione server/client che prevede una rete più estesa, personalmente non farei affidamento al protocollo HTTP).

Ad ogni modo questo ha poco a che vedere con il tuo problema. Nella libreria di cui sopra, fintanto che l'ESP si trova in modalità Access Point, c'è un'istanza della libreria <DNSServer.h> che processa le richieste cosi da gestire il redirect al captive portal e ti posso assicurare che funziona senza problemi con Android anche con i dati inseriti.

Fino ad ora ho avuto modo di testarlo con successo usando dispositivi Android, Windows, iOS e macOS (mi dimentico sempre di farlo con Linux).

Con linux funziona, confermo io, visto che uso linux.
Sai dirmi dov'è il codice che assegna, via dhcp, gli IP ed i nameserver ?

Credo che siano funzionalità gestite direttamente nei core.
Non ho mai approfondito nei dettagli ad essere sincero.

ho fatto downgrade alla 1.0.6 di Arduino esp32 e funziona tutto come previsto quindi dalla 1.0.6 alle 2.0.3 si è spaccato qualcosa (se riesco, perché non mi è ben chiaro come fare) proverò ad aggiornare ogni singola versione per capire in quale si spacca

(onestamente pensavo fosse più affidabile, sto riscontrando parecchi bug nel porting ESP32 di Arduino e nelle varie librerie sviluppate)

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