将 WiFi 模式从 AP 切换到 STA
Switch WiFi mode from AP to STA
我正在使用 ESP32-S2-Saola-1M 板在 C/C++ 通过 ESP-IDF 框架。一开始我在 AP 模式下初始化 Wi-Fi 并启动 HTTP WebServer 通过浏览器从用户那里获取 WiFi 数据。用户通过页面保存他的 Wi-Fi 数据(SSID 和密码)后,
HTTP 服务器应该关闭并且 Wi-Fi 从 AP 模式切换到 STA 模式 - 连接到用户的 Wi-Fi。我对这部分有疑问。我不知道如何优雅且原则上正确地解决这个问题。那么有人可以向我描述任何解决方案或更好的想法吗?
我想到了使用带有 while 循环和 POST 处理程序的方法。在数据通过 POST 请求来自页面后,处理程序保存它们并将一些 bool 属性(例如下面代码中的 hasData)设置为 true 和 while 方法中的循环 breaks/stops 和应用程序中的其他代码可以继续。信号量之类的东西。只需:
- 启动 Wi-Fi(AP 模式)
- 启动网络服务器
- 等到用户发送他的 Wi-Fi 数据
- 停止网络服务器
- 停止 Wi-Fi AP 模式 -> 切换到 STA 模式
- 下一步行动...(测量、发送数据、深度睡眠等)
伪代码:
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...
.
}
这个原则正确吗?
感谢指教!
到目前为止,最简单的方法是在保存新配置后重启 (esp_restart()
)。
然后select在启动时读取配置后的正确模式。
void app_main()
{
// init NVS
// load configuration from NVS
if (config.wifiSSID.empty()) {
startAPmode();
} else {
startSTAmode(config.wifiSSID, config.wifiPassword);
}
start_webserver();
// etc ...
}
您可以同时使用 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());
}
我正在使用 ESP32-S2-Saola-1M 板在 C/C++ 通过 ESP-IDF 框架。一开始我在 AP 模式下初始化 Wi-Fi 并启动 HTTP WebServer 通过浏览器从用户那里获取 WiFi 数据。用户通过页面保存他的 Wi-Fi 数据(SSID 和密码)后, HTTP 服务器应该关闭并且 Wi-Fi 从 AP 模式切换到 STA 模式 - 连接到用户的 Wi-Fi。我对这部分有疑问。我不知道如何优雅且原则上正确地解决这个问题。那么有人可以向我描述任何解决方案或更好的想法吗?
我想到了使用带有 while 循环和 POST 处理程序的方法。在数据通过 POST 请求来自页面后,处理程序保存它们并将一些 bool 属性(例如下面代码中的 hasData)设置为 true 和 while 方法中的循环 breaks/stops 和应用程序中的其他代码可以继续。信号量之类的东西。只需:
- 启动 Wi-Fi(AP 模式)
- 启动网络服务器
- 等到用户发送他的 Wi-Fi 数据
- 停止网络服务器
- 停止 Wi-Fi AP 模式 -> 切换到 STA 模式
- 下一步行动...(测量、发送数据、深度睡眠等)
伪代码:
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...
.
}
这个原则正确吗?
感谢指教!
到目前为止,最简单的方法是在保存新配置后重启 (esp_restart()
)。
然后select在启动时读取配置后的正确模式。
void app_main()
{
// init NVS
// load configuration from NVS
if (config.wifiSSID.empty()) {
startAPmode();
} else {
startSTAmode(config.wifiSSID, config.wifiPassword);
}
start_webserver();
// etc ...
}
您可以同时使用 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());
}