Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handleRequest() use DHCP for reconnect to STA #400

Closed
DanielSamp4 opened this issue Sep 15, 2021 · 3 comments · Fixed by #409
Closed

handleRequest() use DHCP for reconnect to STA #400

DanielSamp4 opened this issue Sep 15, 2021 · 3 comments · Fixed by #409
Labels
bug Something isn't working

Comments

@DanielSamp4
Copy link

Sometimes when my ESP32 stay up for long period, i got 4WAY_HANDSHAKE_TIMEOUT and got STA_DISCONNECTED, but fine we all know that disconnects from a Wifi network its pretty common, so i configure the AutoConnectConfig.reconnectInterval so that my ESP may reconnect to the network and work perfctly.

But i notice that if i have setted a Static IP Address and lose Wifi conection when the ESP reconnect the IP Address assigned was not what i chose anymore, as if DHCP config was enable.

Nonetheless when i restart the ESP, the IP Address that i have assigned was restored, so i realize that the problem have to be on handleRequest() function. because when i start the ESP i use Begin method to configure the connection, but when i'm in the loop section handleRequest() that handle the connection issues.

So i dive into handleRequest() and Begin() method to see if i can recoginize the diferences between the two.

in Begin method i can see that you firstly restore the current STA configuration for them configure the STA, as the blue arrows show:

fig1

But in handleRequest there is no restoration of STA consfiguration

fig2

So i add this remember part into the handleRequest method
fig3

and work like i wanted, when my ESP get disconnected from the wifi and i have been setted with static IP addres, reconnect with the same IP address i have been assigned.

So, i'd like to know if my alteration can causely some strange behavior in the library in general, since my project uses your library a lot, or if that is a simple way to resolve this. Thanks!!

Sorry for my english, its not my first language.

@Hieromon
Copy link
Owner

Hieromon commented Oct 5, 2021

@DanielSamp4 Sorry for the late reply and thank you for the appropriate advice on AutoConnect's reconnect feature.
The Arduino core ESP8266 and ESP32 were updated at the same time, both with many breaking changes, so I was busy dealing with them and didn't have enough time to scrutinize for your useful advice.

To grasp the meaning of your advice, I started by tracing the source code. And I realized that the phenomenon you encountered might occur under the following process sequence:

  1. AutoConnect has a credential that consists of a static IP and has already established a connection with the access point based on that credential at least once.
  2. The sketch was able to connect to the access point by the last connected SSID. (which the SDK saves)
    That is, the 1st-WiFi.begin is successful. At this point the valid IP configuration has been restored to _apConfig. (That's what your analysis shows)
    station_config_t current;
    // Restore current STA configuration
    if (_getConfigSTA(&current))
    AC_DBG("Current:%.32s\n", current.ssid);
    // Prepare valid configuration according to the WiFi connection right order.
    cs = true;
    _rfAdHocBegin = ssid == nullptr ? false : (strlen(ssid) > 0);
    if (_rfAdHocBegin) {
    // Save for autoReconnect
    strcpy(reinterpret_cast<char*>(_credential.ssid), ssid);
    if (passphrase)
    strcpy(reinterpret_cast<char*>(_credential.password), passphrase);
    }
    else {
    // AC_PRINCIPLE_RSSI is available when SSID and password are not provided.
    if (_apConfig.principle == AC_PRINCIPLE_RSSI) {
    // Find the strongest signal from the broadcast among the saved credentials.
    if ((cs = _loadCurrentCredential(reinterpret_cast<char*>(current.ssid), reinterpret_cast<char*>(current.password), AC_PRINCIPLE_RSSI, false))) {
    ssid = reinterpret_cast<const char*>(current.ssid);
    passphrase = reinterpret_cast<const char*>(current.password);
    AC_DBG("Adopted:%.32s\n", ssid);
    }
    }
    _loadAvailCredential(reinterpret_cast<const char*>(current.ssid));
    }
    if (cs) {
    // Advance configuration for STA mode. Restore previous configuration of STA.
    // _loadAvailCredential(reinterpret_cast<const char*>(current.ssid));
    if (!_configSTA(_apConfig.staip, _apConfig.staGateway, _apConfig.staNetmask, _apConfig.dns1, _apConfig.dns2))
    return false;
    // Try to connect by STA immediately.
    if (!_rfAdHocBegin)
    cs = WiFi.begin() != WL_CONNECT_FAILED;
    else {
    _disconnectWiFi(false);
    cs = WiFi.begin(ssid, passphrase) != WL_CONNECT_FAILED;
    }
    AC_DBG("WiFi.begin(%s%s%s)", ssid == nullptr ? "" : ssid, passphrase == nullptr ? "" : ",", passphrase == nullptr ? "" : passphrase);
  3. The handleClient started, but WiFi was disconnected for some reason. On the other hand, _apConfig still holds the current static IP configuration and will be used for reconnection in the handleRequest.
  4. But if AutoConnect fails the 1st-WiFi.begin and the autoReconnect loads a different credential than the current configuration remembered by the SDK, _apConfig will still have the old configuration settings. The reason I didn't load the configuration data for autoReconnect into _apConfig is to avoid overwriting the configuration settings regardless of the sketch's intent. _apConfig instance will keep a copy of AutoConnectConfig settings by the sketch.
    if (!cs && _apConfig.autoReconnect && !_rfAdHocBegin) {
    // Load a valid credential.
    char ssid_c[sizeof(station_config_t::ssid) + sizeof('\0')];
    char password_c[sizeof(station_config_t::password) + sizeof('\0')];
    AC_DBG("autoReconnect");
    if ((cs = _loadCurrentCredential(ssid_c, password_c, _apConfig.principle, strlen(reinterpret_cast<const char*>(current.ssid)) > 0))) {
    // Try to reconnect with a stored credential.
    AC_DBG_DUMB(", %s(%s) loaded\n", ssid_c, _apConfig.principle == AC_PRINCIPLE_RECENT ? "RECENT" : "RSSI");
    const char* psk = strlen(password_c) ? password_c : nullptr;
    _configSTA(IPAddress(_credential.config.sta.ip), IPAddress(_credential.config.sta.gateway), IPAddress(_credential.config.sta.netmask), IPAddress(_credential.config.sta.dns1), IPAddress(_credential.config.sta.dns2));
    cs = WiFi.begin(ssid_c, psk) != WL_CONNECT_FAILED;
    AC_DBG("WiFi.begin(%s%s%s)", ssid_c, psk == nullptr ? "" : ",", psk == nullptr ? "" : psk);

Apparently, the problem is with refreshing the _apConfig it will matche the fix you offered. If my trace is correct, the conditions for reproducing the problem are as follows:

  1. Sketch has been connected to the plurality of SSIDs, which have dynamic IP and static IP.
  2. The access point that established the connection immediately before was a DHCP.
  3. The next access point the sketch tried to connect to was a static IP, but the 1st-WIFI.begin to it failed and the sketch was able to connect with autoReconnect.
  4. The connection was broken while the handleClient was running, but reconnection was attempted again with the help of autoReconnect.
  5. However, the configuration data held by _apConfig is based on the SSID maintained by the SDK and is inconsistent with the reconnected access point. AutoConnect::_configSTA uses old configuration so autoReconnect in handleClient doesn't work correctly In the case of DHCP it just happens to work.

Does the above conditions for reproduction match the scene in which you encountered the problem?
I would like you to get an AC_DEBUG trace and post it on this topic if possible. In that case, set the debug level of the ESP32 Arduino core to Verbose and build. The IP address, SSID, and password are displayed in the AC_DEBUG log, so please mask them before posting.
It's a lot of work, but the problems you discover are also valuable to other users. I would like to fix it so please cooperate.

Thank you for your contribution.

P.S.
AutoConnect has been updated to v130, but you do not need to update the ESP32 arduino core to 2.0.0 to reproduce the issue. I recommend that you maintain the status quo if possible.

@Hieromon Hieromon added awaiting Waiting for reply or activity bug Something isn't working Under investigation It is under investigation and new information is posted on a sequential basis. labels Oct 5, 2021
@Hieromon
Copy link
Owner

Hieromon commented Oct 7, 2021

@DanielSamp4 I have scrutinized your proposed amendment further. As a result, I have unfortunately come to the conclusion that your modification will induce a different dysfunction.

Let’s suppose that you still have established a connection with any access point, you entered a new connection setting with Configure new AP menu. AutoConnect::_induceConnect will receive the APPLY request and will retrieve the static IP settings contained in the POST request. The retrieved configuration settings (which are the values you entered using Configure new AP menu) are passed to _apConfig and become parameters for _configSTA on the next handleRequest turn.

_apConfig.staip = static_cast<IPAddress>(_credential.config.sta.ip);
_apConfig.staGateway = static_cast<IPAddress>(_credential.config.sta.gateway);
_apConfig.staNetmask = static_cast<IPAddress>(_credential.config.sta.netmask);
_apConfig.dns1 = static_cast<IPAddress>(_credential.config.sta.dns1);
_apConfig.dns2 = static_cast<IPAddress>(_credential.config.sta.dns2);
// Determine the connection channel based on the scan result.
_connectCh = 0;
for (uint8_t nn = 0; nn < _scanCount; nn++) {
String ssid = WiFi.SSID(nn);
if (!strncmp(ssid.c_str(), reinterpret_cast<const char*>(_credential.ssid), sizeof(station_config_t::ssid))) {
_connectCh = WiFi.channel(nn);
break;
}
}
// Turn on the trigger to start WiFi.begin().
_rfConnect = true;

So your fix will overwrite the static IP settings that the user entered using Configure new AP menu.
However, the problem you find should be fixed, and I will consider taking effective measures.

@Hieromon Hieromon removed the awaiting Waiting for reply or activity label Oct 7, 2021
@Hieromon
Copy link
Owner

Hieromon commented Oct 7, 2021

@DanielSamp4 I committed the fix. Please evaluate a fix with the enhance/v131 branch.
If you still have an issue with your environment, please provide the reproduction conditions with the AC_DEBUG log.
Thank you.

@Hieromon Hieromon removed the Under investigation It is under investigation and new information is posted on a sequential basis. label Oct 7, 2021
@Hieromon Hieromon mentioned this issue Oct 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants