Supports lower RSSI limit.

pull/200/head
Hieromon Ikasamo 4 years ago
parent 13bd4c7ac5
commit 5fd6240af3
  1. 143
      src/AutoConnect.cpp
  2. 36
      src/AutoConnect.h
  3. 13
      src/AutoConnectDefs.h

@ -2,8 +2,8 @@
* AutoConnect class implementation.
* @file AutoConnect.cpp
* @author hieromon@gmail.com
* @version 1.1.1
* @date 2019-10-17
* @version 1.1.5
* @date 2019-03-17
* @copyright MIT license.
*/
@ -95,15 +95,6 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
_ticker->start(AUTOCONNECT_FLICKER_PERIODDC, (uint8_t)AUTOCONNECT_FLICKER_WIDTHDC);
}
// Advance configuration for STA mode. Restore previous configuration of STA.
station_config_t current;
if (_getConfigSTA(&current)) {
AC_DBG("Current:%.32s\n", current.ssid);
_loadAvailCredential(reinterpret_cast<const char*>(current.ssid));
}
if (!_configSTA(_apConfig.staip, _apConfig.staGateway, _apConfig.staNetmask, _apConfig.dns1, _apConfig.dns2))
return false;
// If the portal is requested promptly skip the first WiFi.begin and
// immediately start the portal.
if (_apConfig.immediateStart) {
@ -112,29 +103,47 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
AC_DBG("Start the portal immediately\n");
}
else {
// Try to connect by STA immediately.
if (ssid == nullptr && passphrase == nullptr)
WiFi.begin();
else {
_disconnectWiFi(false);
WiFi.begin(ssid, passphrase);
cs = true;
// Prepare valid configuration according to the WiFi connection right order.
const char* c_ssid = ssid;
const char* c_password = passphrase;
station_config_t current;
if (_getConfigSTA(&current))
AC_DBG("Current:%.32s\n", current.ssid);
if (_apConfig.wifiDisp == AC_WIFIDISP_RSSI && (ssid == nullptr && passphrase == nullptr)) {
// AC_WIFIDISP_RSSI is available when SSID and password are not provided.
// Find the strongest signal from the broadcast among the saved credentials.
if ((cs = _loadAvailCredential(nullptr, AC_WIFIDISP_RSSI, false))) {
memcpy(current.ssid, _credential.ssid, sizeof(station_config_t::ssid));
memcpy(current.password, _credential.password, sizeof(station_config_t::password));
c_ssid = reinterpret_cast<const char*>(current.ssid);
c_password = reinterpret_cast<const char*>(current.password);
AC_DBG("Adopted:%.32s\n", c_ssid);
}
}
AC_DBG("WiFi.begin(%s%s%s)\n", ssid == nullptr ? "" : ssid, passphrase == nullptr ? "" : ",", passphrase == nullptr ? "" : passphrase);
cs = _waitForConnect(_connectTimeout) == WL_CONNECTED;
#ifdef INC_RSSI_USE_SUP //!!!
if(cs==true) {
if(WiFi.RSSI()<_apConfig.conMinRSSI || _apConfig.conFindMaxRSSI==true) {
_disconnectWiFi(false);
cs=false;
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 (c_ssid == nullptr && c_password == nullptr)
WiFi.begin();
else {
_disconnectWiFi(false);
WiFi.begin(c_ssid, c_password);
}
AC_DBG("WiFi.begin(%s%s%s)\n", c_ssid == nullptr ? "" : c_ssid, c_password == nullptr ? "" : ",", c_password == nullptr ? "" : c_password);
cs = _waitForConnect(_connectTimeout) == WL_CONNECTED;
}
#endif
}
// Reconnect with a valid credential as the autoReconnect option is enabled.
if (!cs && _apConfig.autoReconnect && (ssid == nullptr && passphrase == nullptr)) {
// Load a valid credential.
if (_loadAvailCredential(nullptr)) {
if (_loadAvailCredential(nullptr, _apConfig.wifiDisp, true)) {
// Try to reconnect with a stored credential.
char ssid_c[sizeof(station_config_t::ssid) + sizeof('\0')];
char password_c[sizeof(station_config_t::password) + sizeof('\0')];
@ -142,7 +151,7 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long
strncat(ssid_c, reinterpret_cast<const char*>(_credential.ssid), sizeof(ssid_c) - sizeof('\0'));
*password_c = '\0';
strncat(password_c, reinterpret_cast<const char*>(_credential.password), sizeof(password_c) - sizeof('\0'));
AC_DBG("autoReconnect loaded SSID:%s\n", ssid_c);
AC_DBG("autoReconnect loaded:%s(%s)\n", ssid_c, _apConfig.wifiDisp == AC_WIFIDISP_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));
WiFi.begin(ssid_c, psk);
@ -620,9 +629,11 @@ void AutoConnect::onNotFound(WebServerClass::THandlerFunction fn) {
/**
* Load stored credentials that match nearby WLANs.
* @param ssid SSID which should be loaded. If nullptr is assigned, search SSID with WiFi.scan.
* @param wifiDisp WiFi connection disposition.
* @param excludeCurrent Skip loading the current SSID.
* @return true A matched credential of BSSID was loaded.
*/
bool AutoConnect::_loadAvailCredential(const char* ssid) {
bool AutoConnect::_loadAvailCredential(const char* ssid, const AC_WIFIDISP_t wifiDisp, const bool excludeCurrent) {
AutoConnectCredential credential(_apConfig.boundaryOffset);
if (credential.entries() > 0) {
@ -632,49 +643,55 @@ bool AutoConnect::_loadAvailCredential(const char* ssid) {
int8_t nn = WiFi.scanNetworks(false, true);
AC_DBG("%d network(s) found\n", (int)nn);
if (nn > 0) {
// Determine valid credentials by BSSID.
#ifdef INC_RSSI_USE_SUP //!!!
int maxRSSIWifiIndex=-1;
int maxRSSICredIndex=-1;
#endif
station_config_t validConfig; // Temporary to find the strongest RSSI.
int32_t minRSSI = -120; // Min value to find the strongest RSSI.
// Seek SSID
const char* currentSSID = WiFi.SSID().c_str();
const bool skipCurrent = excludeCurrent & (strlen(currentSSID) > 0);
for (uint8_t i = 0; i < credential.entries(); i++) {
credential.load(i, &_credential);
// Seek valid configuration according to the WiFi connection disposition.
// Verify that an available SSIDs meet AC_WIFIDISP_t requirements.
for (uint8_t n = 0; n < nn; n++) {
#ifdef INC_RSSI_USE_SUP //!!!
if (skipCurrent && !strcmp(currentSSID, WiFi.SSID(n).c_str()))
continue;
if (!memcmp(_credential.bssid, WiFi.BSSID(n), sizeof(station_config_t::bssid))) {
if(WiFi.RSSI(n)>=_apConfig.conMinRSSI) {
if(_apConfig.conFindMaxRSSI!=true) {
return true;
}
if(maxRSSIWifiIndex<0) {
maxRSSIWifiIndex=n;
maxRSSICredIndex=i;
} else {
if(WiFi.RSSI(n)>WiFi.RSSI(maxRSSIWifiIndex)) {
maxRSSIWifiIndex=n;
maxRSSICredIndex=i;
}
}
}
}
#else
if (!memcmp(_credential.bssid, WiFi.BSSID(n), sizeof(station_config_t::bssid)))
return true;
#endif
// Excepts SSID that has weak RSSI under the lower limit.
if (WiFi.RSSI(n) < _apConfig.minRSSI) {
AC_DBG("%s:%" PRId32 "dBm, rejected\n", reinterpret_cast<const char*>(_credential.ssid), WiFi.RSSI(n));
continue;
}
// Determine valid credential
switch (wifiDisp) {
case AC_WIFIDISP_RECENT:
// By BSSID, exit to keep the credential just loaded.
return true;
case AC_WIFIDISP_RSSI:
// Verify that most strong radio signal.
// Continue seeking to find the strongest WIFI signal SSID.
if (WiFi.RSSI(n) > minRSSI) {
minRSSI = WiFi.RSSI(n);
memcpy(&validConfig, &_credential, sizeof(station_config_t));
}
break;
}
break;
}
}
}
#ifdef INC_RSSI_USE_SUP //!!!
if(maxRSSIWifiIndex>=0) {
credential.load(maxRSSICredIndex, &_credential);
return true;
}
#endif
// Increasing the minSSI will indicate the successfully sought for AC_WIFIDISP_RSSI.
// Restore the credential that has maximum RSSI.
if (minRSSI > -120) {
memcpy(&_credential, &validConfig, sizeof(station_config_t));
return true;
}
}
}
// The SSID to load was specified.
// Set the IP configuration globally from the saved credential.
else if (strlen(ssid))
if (credential.load(ssid, &_credential) >= 0) {
if (_credential.dhcp == STA_STATIC) {

@ -2,8 +2,8 @@
* Declaration of AutoConnect class and accompanying AutoConnectConfig class.
* @file AutoConnect.h
* @author hieromon@gmail.com
* @version 1.1.1
* @date 2019-10-17
* @version 1.1.5
* @date 2020-03-16
* @copyright MIT license.
*/
@ -50,6 +50,12 @@ typedef enum AC_ONBOOTURI {
AC_ONBOOTURI_HOME
} AC_ONBOOTURI_t;
/** WiFi connection disposition, it specifies the order of WiFI connecting with saved credentials. */
typedef enum AC_WIFIDISP {
AC_WIFIDISP_RECENT,
AC_WIFIDISP_RSSI
} AC_WIFIDISP_t;
class AutoConnectConfig {
public:
/**
@ -58,10 +64,6 @@ class AutoConnectConfig {
* assigned from macro. Password is same as above too.
*/
AutoConnectConfig() :
#ifdef INC_RSSI_USE_SUP //!!!
conMinRSSI(AUTOCONNECT_CON_MIN_RSSI),
conFindMaxRSSI(AUTOCONNECT_CON_FIND_MAX_RSSI),
#endif
apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM),
@ -69,8 +71,10 @@ class AutoConnectConfig {
psk(String(AUTOCONNECT_PSK)),
channel(AUTOCONNECT_AP_CH),
hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT),
wifiDisp(AC_WIFIDISP_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
@ -94,10 +98,6 @@ class AutoConnectConfig {
* Configure by SSID for the captive portal access point and password.
*/
AutoConnectConfig(const char* ap, const char* password, const unsigned long portalTimeout = 0, const uint8_t channel = AUTOCONNECT_AP_CH) :
#ifdef INC_RSSI_USE_SUP //!!!
conMinRSSI(AUTOCONNECT_CON_MIN_RSSI),
conFindMaxRSSI(AUTOCONNECT_CON_FIND_MAX_RSSI),
#endif
apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM),
@ -105,8 +105,10 @@ class AutoConnectConfig {
psk(String(password)),
channel(channel),
hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT),
wifiDisp(AC_WIFIDISP_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true),
@ -130,10 +132,6 @@ class AutoConnectConfig {
~AutoConnectConfig() {}
AutoConnectConfig& operator=(const AutoConnectConfig& o) {
#ifdef INC_RSSI_USE_SUP //!!!
conMinRSSI=o.conMinRSSI;
conFindMaxRSSI=o.conFindMaxRSSI;
#endif
apip = o.apip;
gateway = o.gateway;
netmask = o.netmask;
@ -141,8 +139,10 @@ class AutoConnectConfig {
psk = o.psk;
channel = o.channel;
hidden = o.hidden;
minRSSI=o.minRSSI;
autoSave = o.autoSave;
bootUri = o.bootUri;
wifiDisp = o.wifiDisp;
boundaryOffset = o.boundaryOffset;
uptime = o.uptime;
autoRise = o.autoRise;
@ -166,10 +166,6 @@ class AutoConnectConfig {
}
#ifdef INC_RSSI_USE_SUP //!!!
int conMinRSSI; /**< Minimum AP signal strength accepted for connection */
bool conFindMaxRSSI; /**< Find stored AP with highest signal strength for connection */
#endif
IPAddress apip; /**< SoftAP IP address */
IPAddress gateway; /**< SoftAP gateway address */
IPAddress netmask; /**< SoftAP subnet mask */
@ -177,8 +173,10 @@ class AutoConnectConfig {
String psk; /**< SoftAP password */
uint8_t channel; /**< SoftAP used wifi channel */
uint8_t hidden; /**< SoftAP SSID hidden */
int16_t minRSSI; /**< Lowest WiFi signal strength (RSSI) that can be connected. */
AC_SAVECREDENTIAL_t autoSave; /**< Auto save credential */
AC_ONBOOTURI_t bootUri; /**< An uri invoking after reset */
AC_WIFIDISP_t wifiDisp; /**< WiFI connection disposition */
uint16_t boundaryOffset; /**< The save storage offset of EEPROM */
int uptime; /**< Length of start up time */
bool autoRise; /**< Automatic starting the captive portal */
@ -245,7 +243,7 @@ class AutoConnect {
void _startWebServer(void);
void _startDNSServer(void);
void _handleNotFound(void);
bool _loadAvailCredential(const char* ssid);
bool _loadAvailCredential(const char* ssid, const AC_WIFIDISP_t wifiDisp = AC_WIFIDISP_RECENT, const bool excludeCurrent = false);
void _stopPortal(void);
bool _classifyHandle(HTTPMethod mothod, String uri);
void _handleUpload(const String& requestUri, const HTTPUpload& upload);

@ -2,8 +2,8 @@
* Predefined AutoConnect configuration parameters.
* @file AutoConnectDefs.h
* @author hieromon@gmail.com
* @version 1.1.0
* @date 2019-10-11
* @version 1.1.5
* @date 2020-03-16
* @copyright MIT license.
*/
@ -14,10 +14,6 @@
#define INC_RSSI_USE_SUP 1
#ifdef INC_RSSI_USE_SUP //!!!
#ifndef AUTOCONNECT_CON_MIN_RSSI
#define AUTOCONNECT_CON_MIN_RSSI -100 // no limit
#endif
#ifndef AUTOCONNECT_CON_FIND_MAX_RSSI
#define AUTOCONNECT_CON_FIND_MAX_RSSI false // use first available
#endif
@ -188,6 +184,11 @@
#endif
#endif
// Lowest WiFi signal strength (RSSI) that can be connected.
#ifndef AUTOCONNECT_MIN_RSSI
#define AUTOCONNECT_MIN_RSSI -120 // No limit
#endif // !AUTOCONNECT_MIN_RSSI
// ArduinoJson buffer size
#ifndef AUTOCONNECT_JSONBUFFER_SIZE
#define AUTOCONNECT_JSONBUFFER_SIZE 256

Loading…
Cancel
Save