Search code examples
c++cwifiesp32esp-idf

Switch WiFi mode from AP to STA


I'm working on project with ESP32-S2-Saola-1M board in C/C++ via ESP-IDF framework. At the beginning I initialize a Wi-Fi in an AP mode and starts the HTTP WebServer to get WiFi data from user through browser. After the user saves his Wi-Fi data (SSID and Passwd) throught page, the HTTP server should shut down and Wi-Fi switch from AP mode to STA mode - connect to user's Wi-Fi. I have problem with this part. I don't know how to solve this elegantly and in principle correctly. So can someone describe me any solutions or better ideas please?

I thought of using method with while cycle and POST handler. After the data comes from page via POST request, handler saves them and set some bool property (e.g. hasData in code below) to true and while cycle in method breaks/stops and other code in application can continue. Something like semaphore. Simply:

  1. start Wi-Fi (AP mode)
  2. start webserver
  3. wait until user sends his Wi-Fi data
  4. stop webserver
  5. stop Wi-Fi AP mode -> switch to STA mode
  6. next actions... (measure, send data out, deep sleep etc.)

Pseudo code:


bool hasData = false;

static esp_err_t postHandler(httpd_req_t *request)
{
    .
    . //saves data from POST request
    . 

    hasData = true;

    return ESP_OK;
}


void waitForUser(void)
{
    while(hasData != true) {
        //just wait
    }
}


static const httpd_uri_t postData = {
    .uri = "/connection",
    .method = HTTP_POST,
    .handler = postHandler,
    .user_ctx = NULL
    };


static httpd_handle_t start_webserver(void)
{
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();

    if (httpd_start(&server, &config) == ESP_OK) {

        httpd_register_uri_handler(server, &postData);

        return server;
    }

    return NULL;
}

void stop_webserver(httpd_handle_t server)
{
    if (server) {
        httpd_stop(server);
    }
}


void wifiAPInit(void)
{
    .
    . //Initialize wifi config for AP mode and start wifi
    .
}


void app_main(void)
{
    .
    . //Initialize NVS and others...
    .

    httpd_handle_t server = NULL;
    wifiAPinit();
    server = start_webserver();
    waitForUser();
    stop_webserver(server);
    .
    . // start Wifi in STA mode and continue...
    .
}

Is this principle correct?

Thanks for advice!


Solution

  • By far the easiest approach is to just reboot (esp_restart()) after saving new configuration.

    Then select the right mode after reading the configuration on boot.

    void app_main()
    {
        // init NVS
        // load configuration from NVS
        if (config.wifiSSID.empty()) {
            startAPmode();
        } else {
            startSTAmode(config.wifiSSID, config.wifiPassword);
        }
        start_webserver();
        // etc ...
    }