Thank you very much @Moriki !!!
I studied your solution and finally I've made it work!
I don't know if it's exactly how you would implement it, however it switches quickly betweens the two modalities (I use UART commands in order to control which mode must be active).
Also, if AP is active but I select AP again, it restarts the AP without any crash (STA mode does the same).
I share with the community the parts of code I wrote to make it work.
-- Part of code inside the app_main (it enables AP by default) --
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_wifi_set_mode(WIFI_MODE_NULL);
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
&wifi_event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&wifi_event_handler, NULL, &instance_got_ip));
esp_wifi_set_storage(WIFI_STORAGE_RAM);
wifiAP = esp_netif_create_default_wifi_ap();
esp_netif_create_default_wifi_sta();
from_sta_to_ap();
The code that enables the access point AP checks also if the station mode STA is active, so it deactivates this modality, then it proceeds enabling the access point.
-- from_sta_to_ap (uses the global variable ap_sta to understand the previous state) --
void from_sta_to_ap(void){
printf("## Entering from_sta_to_ap.\n");
esp_netif_ip_info_t ipInfo;
if(ap_sta == 1){
ESP_ERROR_CHECK(esp_wifi_disconnect());
ESP_ERROR_CHECK(esp_wifi_stop());
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
}
IP4_ADDR(&ipInfo.ip, 192,168,2,1);
IP4_ADDR(&ipInfo.gw, 192,168,2,1);
IP4_ADDR(&ipInfo.netmask, 255,255,255,0);
esp_netif_dhcps_stop(wifiAP);
esp_netif_set_ip_info(wifiAP, &ipInfo);
esp_netif_dhcps_start(wifiAP);
ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ipInfo.ip));
ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ipInfo.gw));
ESP_LOGI(TAG, "Mask: " IPSTR, IP2STR(&ipInfo.netmask));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s", EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
ap_sta = 0;
}
This code that deactivates the access point AP (if active) and then enables the STA mode.
-- from_ap_to_sta (uses the global variable ap_sta to understand the previous state) --
void from_ap_to_sta(void){
printf("## Entering from_ap_to_sta.\n");
if(ap_sta == 0){
ESP_ERROR_CHECK(esp_wifi_stop());
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
}
s_wifi_event_group = xEventGroupCreate();
wifi_config_t wifi_config = {
.sta = {
.ssid = ESP_WIFI_SSID,
.password = ESP_WIFI_PASS,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {
.capable = true,
.required = false
},
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE,
pdFALSE, portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", ESP_WIFI_SSID, ESP_WIFI_PASS);
}
else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", ESP_WIFI_SSID, ESP_WIFI_PASS);
}
else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
vEventGroupDelete(s_wifi_event_group);
ap_sta = 1;
}
I won't publish the event handler because it is sufficient to merge the handlers of the simple access point example and station example.
Regards,
Filippo