【问题标题】:Switch WiFi mode from AP to STA将 WiFi 模式从 AP 切换到 STA
【发布时间】:2021-04-07 12:19:14
【问题描述】:

我正在通过 ESP-IDF 框架在 C/C++ 中使用 ESP32-S2-Saola-1M 板开发项目。一开始,我在 AP 模式下初始化 Wi-Fi,并启动 HTTP WebServer 以通过浏览器从用户那里获取 WiFi 数据。用户通过页面保存他的 Wi-Fi 数据(SSID 和 Passwd)后, HTTP 服务器应该关闭并且 Wi-Fi 从 AP 模式切换到 STA 模式 - 连接到用户的 Wi-Fi。我对这部分有问题。我不知道如何优雅地原则上正确地解决这个问题。那么有人可以向我描述任何解决方案或更好的想法吗?

我想过使用带有 while 循环和 POST 处理程序的方法。在通过 POST 请求从页面获取数据后,处理程序保存它们并将一些 bool 属性(例如,下面代码中的 hasData)设置为 true,并且 while 在方法中断/停止和应用程序中的其他代码可以继续。信号量之类的东西。简单地说:

  1. 启动 Wi-Fi(AP 模式)
  2. 启动网络服务器
  3. 等到用户发送他的 Wi-Fi 数据
  4. 停止网络服务器
  5. 停止 Wi-Fi AP 模式 -> 切换到 STA 模式
  6. 下一步行动...(测量、发送数据、深度睡眠等)

伪代码:


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...
    .
}

这个原则正确吗?

感谢您的建议!

【问题讨论】:

  • 我不明白“切换到STA模式并连接到wifi”它连接到什么wifi?
  • 我的意思是ESP连接到用户的Wi-Fi作为站

标签: c++ c wifi esp32 esp-idf


【解决方案1】:

到目前为止,最简单的方法是在保存新配置后重新启动 (esp_restart())。

然后在开机读取配置后选择正确的模式。

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

【讨论】:

  • 这可能是,但是当 ESP 处于 STA 模式时,网络服务器应该停止。下一个问题,如果用户想重新配置 SSID 和密码怎么办?
  • 然后将start_webserver();移动到if (AP mode) { ... }内部。但是,您将如何重新配置​​ SSID?您可以添加“硬重置”按钮来删除配置,或者为 UART 控制台添加命令行界面。您可以在 this project 中查看命令行界面,尽管该项目可能有点大,无法浏览。
  • 好的。使用 NVS 存储 SSID 和 Passwd 并重新启动很好。我还有下一个问题。我将保持 WebServer 设置为 ON 以进行重新配置。但在 start_webserver() 之后,我需要创建 xTask 进行测量、发送测量数据并将 ESP 设置为深度睡眠。整个设备将由电池供电。因此,如果我在任务之后立即创建并随后引入深度睡眠,则无法更改配置。因为我认为,该网络服务器不能在深度睡眠模式下工作,对吧?那么您知道如何等待可能的重新配置并在此之后开始测量吗?
  • 如果这个问题得到了回答,最好接受它并提出一个新的问题。我必须承认我不知道如何处理深度睡眠模式。我认为在深度睡眠中无线网络也已关闭。也许你可以使用 MQTT 或类似的东西。
【解决方案2】:

您可以同时使用 Sta 和 Ap

void connectSTA(char *ssid, char *pass)
{
    wifi_config_t wifi_config;
    memset(&wifi_config, 0, sizeof(wifi_config));
    strcpy((char *)wifi_config.sta.ssid, said);
    strcpy((char *)wifi_config.sta.password, pass);
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
}

void connectAP()
{
    wifi_config_t wifi_config =
        {
            .ap = {
                .ssid = "my esp32",
                .password = "P@ssword",
                .max_connection = 4,
                .authmode = WIFI_AUTH_WPA_WPA2_PSK}};
    esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config);
}

void wifiInit(void *params)
{

    ESP_ERROR_CHECK(nvs_flash_init());

    tcpip_adapter_init();
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

    nvs_handle_t nvs;
    nvs_open("wifiCreds", NVS_READWRITE, &nvs);

    size_t ssidLen, passLen;
    char *ssid = NULL, *pass = NULL;

    if (nvs_get_str(nvs, "ssid", NULL, &ssidLen) == ESP_OK)
    {
        if (ssidLen > 0)
        {
            ssid = malloc(ssidLen);
            nvs_get_str(nvs, "ssid", ssid, &ssidLen);
        }
    }

    if (nvs_get_str(nvs, "pass", NULL, &passLen) == ESP_OK)
    {
        if (passLen > 0)
        {
            pass = malloc(passLen);
            nvs_get_str(nvs, "pass", pass, &passLen);
        }
    }

    wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
    connectAP();
    if (ssid != NULL && pass != NULL)
    {
        connectSTA(ssid, pass);
    }

    ESP_ERROR_CHECK(esp_wifi_start());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2022-01-17
    • 1970-01-01
    • 2020-03-22
    • 2012-09-22
    • 2011-07-12
    • 1970-01-01
    相关资源
    最近更新 更多