Supports lower RSSI limit.

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

@ -2,8 +2,8 @@
* Declaration of AutoConnect class and accompanying AutoConnectConfig class. * Declaration of AutoConnect class and accompanying AutoConnectConfig class.
* @file AutoConnect.h * @file AutoConnect.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.1.1 * @version 1.1.5
* @date 2019-10-17 * @date 2020-03-16
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -50,6 +50,12 @@ typedef enum AC_ONBOOTURI {
AC_ONBOOTURI_HOME AC_ONBOOTURI_HOME
} AC_ONBOOTURI_t; } 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 { class AutoConnectConfig {
public: public:
/** /**
@ -58,10 +64,6 @@ class AutoConnectConfig {
* assigned from macro. Password is same as above too. * assigned from macro. Password is same as above too.
*/ */
AutoConnectConfig() : AutoConnectConfig() :
#ifdef INC_RSSI_USE_SUP //!!!
conMinRSSI(AUTOCONNECT_CON_MIN_RSSI),
conFindMaxRSSI(AUTOCONNECT_CON_FIND_MAX_RSSI),
#endif
apip(AUTOCONNECT_AP_IP), apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW), gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM), netmask(AUTOCONNECT_AP_NM),
@ -69,8 +71,10 @@ class AutoConnectConfig {
psk(String(AUTOCONNECT_PSK)), psk(String(AUTOCONNECT_PSK)),
channel(AUTOCONNECT_AP_CH), channel(AUTOCONNECT_AP_CH),
hidden(0), hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO), autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT), bootUri(AC_ONBOOTURI_ROOT),
wifiDisp(AC_WIFIDISP_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET), boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME), uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true), autoRise(true),
@ -94,10 +98,6 @@ class AutoConnectConfig {
* Configure by SSID for the captive portal access point and password. * 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) : 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), apip(AUTOCONNECT_AP_IP),
gateway(AUTOCONNECT_AP_GW), gateway(AUTOCONNECT_AP_GW),
netmask(AUTOCONNECT_AP_NM), netmask(AUTOCONNECT_AP_NM),
@ -105,8 +105,10 @@ class AutoConnectConfig {
psk(String(password)), psk(String(password)),
channel(channel), channel(channel),
hidden(0), hidden(0),
minRSSI(AUTOCONNECT_MIN_RSSI),
autoSave(AC_SAVECREDENTIAL_AUTO), autoSave(AC_SAVECREDENTIAL_AUTO),
bootUri(AC_ONBOOTURI_ROOT), bootUri(AC_ONBOOTURI_ROOT),
wifiDisp(AC_WIFIDISP_RECENT),
boundaryOffset(AC_IDENTIFIER_OFFSET), boundaryOffset(AC_IDENTIFIER_OFFSET),
uptime(AUTOCONNECT_STARTUPTIME), uptime(AUTOCONNECT_STARTUPTIME),
autoRise(true), autoRise(true),
@ -130,10 +132,6 @@ class AutoConnectConfig {
~AutoConnectConfig() {} ~AutoConnectConfig() {}
AutoConnectConfig& operator=(const AutoConnectConfig& o) { AutoConnectConfig& operator=(const AutoConnectConfig& o) {
#ifdef INC_RSSI_USE_SUP //!!!
conMinRSSI=o.conMinRSSI;
conFindMaxRSSI=o.conFindMaxRSSI;
#endif
apip = o.apip; apip = o.apip;
gateway = o.gateway; gateway = o.gateway;
netmask = o.netmask; netmask = o.netmask;
@ -141,8 +139,10 @@ class AutoConnectConfig {
psk = o.psk; psk = o.psk;
channel = o.channel; channel = o.channel;
hidden = o.hidden; hidden = o.hidden;
minRSSI=o.minRSSI;
autoSave = o.autoSave; autoSave = o.autoSave;
bootUri = o.bootUri; bootUri = o.bootUri;
wifiDisp = o.wifiDisp;
boundaryOffset = o.boundaryOffset; boundaryOffset = o.boundaryOffset;
uptime = o.uptime; uptime = o.uptime;
autoRise = o.autoRise; 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 apip; /**< SoftAP IP address */
IPAddress gateway; /**< SoftAP gateway address */ IPAddress gateway; /**< SoftAP gateway address */
IPAddress netmask; /**< SoftAP subnet mask */ IPAddress netmask; /**< SoftAP subnet mask */
@ -177,8 +173,10 @@ class AutoConnectConfig {
String psk; /**< SoftAP password */ String psk; /**< SoftAP password */
uint8_t channel; /**< SoftAP used wifi channel */ uint8_t channel; /**< SoftAP used wifi channel */
uint8_t hidden; /**< SoftAP SSID hidden */ 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_SAVECREDENTIAL_t autoSave; /**< Auto save credential */
AC_ONBOOTURI_t bootUri; /**< An uri invoking after reset */ 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 */ uint16_t boundaryOffset; /**< The save storage offset of EEPROM */
int uptime; /**< Length of start up time */ int uptime; /**< Length of start up time */
bool autoRise; /**< Automatic starting the captive portal */ bool autoRise; /**< Automatic starting the captive portal */
@ -245,7 +243,7 @@ class AutoConnect {
void _startWebServer(void); void _startWebServer(void);
void _startDNSServer(void); void _startDNSServer(void);
void _handleNotFound(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); void _stopPortal(void);
bool _classifyHandle(HTTPMethod mothod, String uri); bool _classifyHandle(HTTPMethod mothod, String uri);
void _handleUpload(const String& requestUri, const HTTPUpload& upload); void _handleUpload(const String& requestUri, const HTTPUpload& upload);

@ -2,8 +2,8 @@
* Predefined AutoConnect configuration parameters. * Predefined AutoConnect configuration parameters.
* @file AutoConnectDefs.h * @file AutoConnectDefs.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 1.1.0 * @version 1.1.5
* @date 2019-10-11 * @date 2020-03-16
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -14,10 +14,6 @@
#define INC_RSSI_USE_SUP 1 #define INC_RSSI_USE_SUP 1
#ifdef INC_RSSI_USE_SUP //!!! #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 #ifndef AUTOCONNECT_CON_FIND_MAX_RSSI
#define AUTOCONNECT_CON_FIND_MAX_RSSI false // use first available #define AUTOCONNECT_CON_FIND_MAX_RSSI false // use first available
#endif #endif
@ -188,6 +184,11 @@
#endif #endif
#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 // ArduinoJson buffer size
#ifndef AUTOCONNECT_JSONBUFFER_SIZE #ifndef AUTOCONNECT_JSONBUFFER_SIZE
#define AUTOCONNECT_JSONBUFFER_SIZE 256 #define AUTOCONNECT_JSONBUFFER_SIZE 256

Loading…
Cancel
Save