Page 1 of 1

WiFi APSTA keeps disconnecting clients

Posted: Thu May 25, 2023 6:31 pm
by dizcza
If a wifi STA connection fails, I start WIFI_APSTA wifi to provision clients that changed their home wifi SSID and therefore the ESP board is unable to connect.

Code: Select all

#define WIFI_RECONNECT_TIMEOUT_S       30


static const char *TAG = "wifi_apsta";

static esp_timer_handle_t m_timer_reconnect;
static bool m_ap_connected = false;


static void wifi_apsta_reconnect(void* arg) {
    if (!bsp_stopped() && !m_ap_connected) {
        esp_wifi_connect();
    }
}


static esp_timer_handle_t wifi_apsta_timer_init() {
    esp_timer_handle_t timer_reconnect = NULL;
    const esp_timer_create_args_t timer_args = {
            .callback = wifi_apsta_reconnect,
            .arg = NULL,
            .name = "wifi_reconnect",
            .skip_unhandled_events = false
    };
    esp_timer_create(&timer_args, &timer_reconnect);
    return timer_reconnect;
}


static void wifi_apsta_event_handler(void* arg, esp_event_base_t event_base,
                                     int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
        m_ap_connected = true;
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        if (!m_ap_connected) {
            esp_wifi_connect();
        }
    } else if (event_base == WIFI_EVENT
            && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_apsta_reconnect(NULL);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ESP_LOGI(TAG, "STA connected, restarting...");
        esp_restart();
    }
}


esp_err_t wifi_apsta_start(const wifi_creds_t* wifi_creds)
{
    ESP_ERROR_CHECK(bsp_nvs_flash_init());

    ESP_ERROR_CHECK(esp_netif_init());

    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    esp_netif_create_default_wifi_ap();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_apsta_event_handler,
                                                        NULL,
                                                        NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &wifi_apsta_event_handler,
                                                        NULL,
                                                        NULL));

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
    m_timer_reconnect = wifi_apsta_timer_init();

    wifi_config_t wifi_config_sta;
    wifi_sta_config_init(&wifi_config_sta, wifi_creds);
    ESP_LOGI(TAG, "Connecting to '%s' AUTH %d", wifi_config_sta.sta.ssid, wifi_config_sta.sta.threshold.authmode);

    wifi_config_t wifi_config_softap;
    wifi_softap_config_init(&wifi_config_softap);

    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config_softap));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config_sta));

    ESP_ERROR_CHECK(esp_wifi_start());

    esp_netif_ip_info_t ip_info;
    esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info);

    nvs_flash_deinit();

    char ip_addr[16];
    inet_ntoa_r(ip_info.ip.addr, ip_addr, 16);
    ESP_LOGI(TAG, "Set up softAP with IP:%s SSID:%s", ip_addr, wifi_config_softap.ap.ssid);

    return ESP_OK;
}
But my clients (including myself) cannot join this APSTA network in the softap mode: it keeps disconnecting the clients by trying to reconnect using the latest wifi credentials even though my logic forbids that. Either STA or SOFTAP mode works fine standalone, but not when the logic is merged into the APSTA mode. Why APSTA and not just SOFTAP till the user logins and saves the credentials? Because most of the time connection losses are due to home wifi issues and not because the password (or ssid) is changed, and therefore I don't want clients to provision the app each time the connection is lost.

Here are the logs:

Code: Select all

D (661776) wifi:perform scan: ss_state=0x9, chan<1,0>, dur<0,120>
D (661896) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (661926) wifi:perform scan: ss_state=0x9, chan<2,0>, dur<0,120>
D (662046) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662076) wifi:perform scan: ss_state=0x9, chan<3,0>, dur<0,120>
D (662206) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662236) wifi:perform scan: ss_state=0x9, chan<4,0>, dur<0,120>
D (662356) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662386) wifi:perform scan: ss_state=0x9, chan<5,0>, dur<0,120>
D (662506) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662536) wifi:perform scan: ss_state=0x9, chan<6,0>, dur<0,120>
D (662656) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662686) wifi:perform scan: ss_state=0x9, chan<7,0>, dur<0,120>
D (662806) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662836) wifi:perform scan: ss_state=0x9, chan<8,0>, dur<0,120>
D (662966) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (662996) wifi:perform scan: ss_state=0x9, chan<9,0>, dur<0,120>
D (663116) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (663146) wifi:perform scan: ss_state=0x9, chan<10,0>, dur<0,120>
D (663266) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (663296) wifi:perform scan: ss_state=0x9, chan<11,0>, dur<0,120>
D (663416) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (663446) wifi:perform scan: ss_state=0x9, chan<12,0>, dur<360,360>
D (663806) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (663836) wifi:perform scan: ss_state=0x9, chan<13,0>, dur<360,360>
D (664206) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (664236) wifi:perform scan: ss_state=0x9, chan<14,0>, dur<360,360>
D (664596) wifi:scan end: arg=0x0, status=0, ss_state=0x3
D (664626) wifi:filter: set rx policy=4
D (664626) wifi:first chan=1
D (664626) wifi:handoff_cb: status=0
D (664626) wifi:clear rc list
D (664626) wifi:clear blacklist
D (664626) wifi:Send disconnect event, reason=201
D (664636) wifi:connect status 1 -> 3
D (664636) wifi:disable connect timer
D (664636) wifi:clear scan ap list
D (00:11:03.353) event: running post WIFI_EVENT:5 with handler 0x400fb39c and context 0x3ffcbce4 on loop 0x3ffc90d4
0x400fb39c: wifi_default_action_sta_disconnected at /home/dizcza/tools/esp-idf/components/esp_wifi/src/wifi_default.c:104

D (00:11:03.363) esp_netif_handlers: esp_netif action disconnected with netif0x3ffce508 from event_id=5
D (00:11:03.372) esp_netif_lwip: check: remote, if=0x3ffce508 fn=0x400f8bd4
0x400f8bd4: esp_netif_down_api at /home/dizcza/tools/esp-idf/components/esp_netif/lwip/esp_netif_lwip.c:1634


D (00:11:03.379) esp_netif_lwip: esp_netif_down_api esp_netif:0x3ffce508
D (00:11:03.386) esp_netif_lwip: esp_netif_start_ip_lost_timer esp_netif:0x3ffce508
D (00:11:03.394) esp_netif_lwip: if0x3ffce508 start ip lost tmr: no need start because netif=0x3ffcbb58 interval=120 ip=0
D (00:11:03.405) esp_netif_lwip: check: local, if=0x3ffce508 fn=0x400f940c
0x400f940c: esp_netif_update_default_netif_lwip at /home/dizcza/tools/esp-idf/components/esp_netif/lwip/esp_netif_lwip.c:327


D (00:11:03.412) esp_netif_lwip: esp_netif_update_default_netif_lwip 0x3ffce508
D (00:11:03.419) esp_netif_lwip: call api in lwip: ret=0x0, give sem
D (00:11:03.426) event: running post WIFI_EVENT:5 with handler 0x400daedc and context 0x3ffcb570 on loop 0x3ffc90d4
0x400daedc: wifi_apsta_event_handler at /home/dizcza/Projects/Embedded/eclipse-workspace/esp32-sdpsensor/components_esp32/wifi_apsta/wifi_apsta.c:68

D (664726) wifi:Start wifi connect
D (664726) wifi:connect status 3 -> 0
D (664736) wifi:connect chan=0
D (664736) wifi:first chan=1
D (664736) wifi:connect status 0 -> 1
D (664746) wifi:filter: set rx policy=3
D (664746) wifi:clear scan ap list
D (664746) wifi:start scan: type=0x50f, priority=2, cb=0x4012b4d4, arg=0x0, ss_state=0x1, time=646013090, index=0
0x4012b4d4: cnx_start_handoff_cb at ??:?
These logs keep repeating forever even after a client is joined --> the client gets disconnected.

ESP-IDF v5.1-dev-4528-g420ebd208a

Any ideas on how to solve this problem? And why this occurs in the first place... And why the connection happens each ~5 seconds instead of 30 secs as I've specified?

Re: WiFi APSTA keeps disconnecting clients

Posted: Thu May 25, 2023 9:32 pm
by MicroController
I don't see your code starting the timer anywhere.

Also, could this be part of the issue:

Code: Select all

if (event_base == WIFI_EVENT
            && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_apsta_reconnect(NULL);
?

Re: WiFi APSTA keeps disconnecting clients

Posted: Fri May 26, 2023 7:57 am
by dizcza
MicroController wrote:
Thu May 25, 2023 9:32 pm
I don't see your code starting the timer anywhere.

Also, could this be part of the issue:

Code: Select all

if (event_base == WIFI_EVENT
            && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_apsta_reconnect(NULL);
?
WRONG:

The timer is obsolete, sorry, I should have removed it.
And yes, this function block in the `wifi_apsta_reconnect` causes the errors. I call `wifi_apsta_reconnect` intentionally to connect to the previously remembered SSID. What I don't understand is why scanning of networks is performed each 3-5 sec instead of 30 sec as I specified.


EDITED:
My bad, I've fooled myself. Of course, I need to start the timer.

Code: Select all

static void wifi_apsta_event_handler(void* arg, esp_event_base_t event_base,
                                     int32_t event_id, void* event_data)
{
    wifi_softap_event_handler(arg, event_base, event_id, event_data);

    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
        m_ap_connected = true;
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        wifi_apsta_reconnect(NULL);
    } else if (event_base == WIFI_EVENT
            && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_timer_start_once(m_timer_reconnect, WIFI_RECONNECT_TIMEOUT_S * SECOND_US);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ESP_LOGI(TAG, "STA connected, restarting...");
        esp_restart();
    }
}
It works so far and I cannot reproduce the issue I had. I'll return to this topic once I can reproduce it.