esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
15.98k stars 13.33k forks source link

WiFi.scanNetworks() always returns zero inside ESPAsyncWebServer handler #3748

Closed klaasdc closed 6 years ago

klaasdc commented 6 years ago

Basic Infos

Hardware

Hardware: NodeMCU ESP12E Core Version: 2.3.0 stable

Description

I'm trying to set up a captive portal in WIFI_AP_STA mode. I want to show the user the active networks on the root page using ESPAsyncWebserver. When calling Wifi.scanNetworks() inside the ESPAsyncWebServer handler, it always returns immediately with zero. However, putting the scanNetworks() in the main loop() does work, but creates other issues. I can workaround by using the main loop() to keep updating a network list, but I don't see why it would not work from outside of it.

Below is the minimal working example I could make that exhibits my problem.

Settings in IDE

Module: NodeMCU ESP12E Flash Size: 4MB CPU Frequency: 160Mhz? Flash Mode: ?qio? Flash Frequency: ?40Mhz? Upload Using: SERIAL Reset Method: nodemcu

Sketch

#include "ESP8266WiFi.h"
#include <DNSServer.h>
#include "ESPAsyncWebServer.h"

DNSServer dnsServer;
AsyncWebServer server(80);

IPAddress captiveIP(192,168,4,1);
IPAddress subnet(255,255,255,0);

void onRoot(AsyncWebServerRequest *request){
  int n = WiFi.scanNetworks();
  Serial.println(n);
  request->send(200, "text/html", "Empty page");
}

class CaptiveRequestHandler : public AsyncWebHandler {
//Source: https://github.com/me-no-dev/ESPAsyncWebServer/issues/228
public:
  CaptiveRequestHandler() {}
  virtual ~CaptiveRequestHandler() {}

  bool canHandle(AsyncWebServerRequest *request){
    return true;
  }

  void handleRequest(AsyncWebServerRequest *request) {
    AsyncResponseStream *response = request->beginResponseStream("text/html");
    response->print("<!DOCTYPE html><html><head><title>Captive Portal</title></head><body>");
    response->printf("<p><a href='http://%s'>root</a></p>", WiFi.softAPIP().toString().c_str());
    response->print("</body></html>");
    request->send(response);
  }
};

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

  WiFi.mode(WIFI_AP_STA); 

  WiFi.softAPConfig(captiveIP, captiveIP, subnet);
  WiFi.softAP("Controller");
  delay(500);

  dnsServer.start(53, "*", WiFi.softAPIP());
  server.on("/", HTTP_GET, onRoot);
  server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//capture all other requests and only when requested from AP
  server.begin();
}

void loop(){
  dnsServer.processNextRequest();
  yield();
}
Pablo2048 commented 6 years ago

You have to set async mode to true to work with ESPAsyncWebServer (please see the example in ESPAsyncWebServer repository - we are off-topic here IMHO...).

klaasdc commented 6 years ago

Actually, I thought it would have been off topic for ESPAsyncWebserver instead :)

There is only one example in the ESPAsyncwebserver repository but it doesn't say anything about "async mode"? Can you post some more info? Thanks!

Pablo2048 commented 6 years ago

:-) try not to read only examples, but documentation also (for example readme.md) https://github.com/me-no-dev/ESPAsyncWebServer#scanning-for-available-wifi-networks , https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/scan-class.html

klaasdc commented 6 years ago

Ouch, I missed that. Thanks for pointing!

devyte commented 6 years ago

@klaasdc from a quick look, you're using it wrong. You have to check the return value, and kick off another scan. First one is always empty. Also, wrong repo, this is the core. The EspAsyncWebserver is hosted elsewhere. Closing due to user error, and off topic.