0

我正在通过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,同时方法中的循环中断/停止,应用程序中的其他代码可以继续。信号量之类的东西。简单地:

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

这个原则正确吗?

谢谢你的建议!

4

2 回答 2

0

您可以同时使用 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());
}
于 2021-04-27T14:51:24.993 回答
0

到目前为止,最简单的方法是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 ...
}
于 2021-04-07T12:36:26.983 回答