diff --git a/src/CHANGES.md b/src/CHANGES.md index 9405fb15..4d492205 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,7 +5,8 @@ ## 0.5.77 * fix wrong filename for automatically created manifest (online installer) #620 * added rotate display feature #619 -* improved Prometheus endpoint #615, thx to fsck-block +* improved Prometheus endpoint #615, thx to @fsck-block +* improved wifi to connect always to strongest RSSI, thx to @beegee3 #611 ## 0.5.76 * reduce MQTT retry interval from maximum speed to one second diff --git a/src/web/RestApi.h b/src/web/RestApi.h index ec4fd61f..3a5ba0b1 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -601,6 +601,7 @@ class RestApi { bool setSetup(JsonObject jsonIn, JsonObject jsonOut) { if(F("scan_wifi") == jsonIn[F("cmd")]) { + DPRINTLN(DBG_INFO, F("rqst scan")); mApp->scanAvailNetworks(); } else if(F("set_time") == jsonIn[F("cmd")]) diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 6f7725eb..6b5c13a5 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,6 +25,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; + mLastApClients = 0; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -64,21 +65,44 @@ void ahoywifi::tickWifiLoop() { #if !defined(AP_ONLY) if(mStaConn != GOT_IP) { if (WiFi.softAPgetStationNum() > 0) { // do not reconnect if any AP connection exists - mDns.processNextRequest(); - if((WIFI_AP_STA == WiFi.getMode()) && !mScanActive) { - DBGPRINTLN(F("AP client connected")); - welcome(mApIp.toString()); - WiFi.mode(WIFI_AP); - mAppWifiCb(true); + if(WIFI_AP_STA == WiFi.getMode()) { + if(mScanActive && (mLastApClients != WiFi.softAPgetStationNum())) + mScanActive = false; + + if(mLastApClients != WiFi.softAPgetStationNum()) { + mLastApClients = WiFi.softAPgetStationNum(); + WiFi.scanDelete(); + WiFi.mode(WIFI_AP); + //mDns.start(53, "*", mApIp); + mAppWifiCb(true); + DBGPRINTLN(F("AP client connected")); + welcome(mApIp.toString()); + } } + mDns.processNextRequest(); return; } else if(WIFI_AP == WiFi.getMode()) { + mLastApClients = 0; mCnt = 0; + DPRINTLN(DBG_INFO, "DNS stop"); + mDns.stop(); WiFi.mode(WIFI_AP_STA); } mCnt++; + if(!mScanActive && mBSSIDList.empty()) { // start scanning APs with the given SSID + DBGPRINT(F("scanning APs with SSID ")); + DBGPRINTLN(String(mConfig->sys.stationSsid)); + mScanActive = true; + #if defined(ESP8266) + WiFi.scanNetworks(true, false, 0U, (uint8_t *)mConfig->sys.stationSsid); + #else + WiFi.scanNetworks(true, false, false, 300U, 0U, mConfig->sys.stationSsid); + #endif + return; + } + uint8_t timeout = 10; // seconds if (mStaConn == CONNECTED) // connected but no ip @@ -87,10 +111,27 @@ void ahoywifi::tickWifiLoop() { DBGPRINT(F("reconnect in ")); DBGPRINT(String(timeout-mCnt)); DBGPRINTLN(F(" seconds")); + if(mScanActive) { + getBSSIDs(); + if(!mScanActive) // scan completed + if ((mCnt % timeout) < 8) + mCnt = timeout - 2; + } if((mCnt % timeout) == 0) { // try to reconnect after x sec without connection if(mStaConn != CONNECTED) mStaConn = CONNECTING; - WiFi.reconnect(); + if(mBSSIDList.size() > 0) { // get first BSSID in list + DBGPRINT("try to connect to AP with BSSID:"); + uint8_t bssid[6]; + for (int j = 0; j < 6; j++) { + bssid[j] = mBSSIDList.front(); + mBSSIDList.pop_front(); + DBGPRINT(" " + String(bssid[j], HEX)); + } + DBGPRINTLN(""); + WiFi.disconnect(); + WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); + } mCnt = 0; } } @@ -135,7 +176,7 @@ void ahoywifi::setupStation(void) { if(!WiFi.config(ip, gateway, mask, dns1, dns2)) DPRINTLN(DBG_ERROR, F("failed to set static IP!")); } - mStaConn = (WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd) != WL_CONNECTED) ? DISCONNECTED : CONNECTED; + mBSSIDList.clear(); if(String(mConfig->sys.deviceName) != "") WiFi.hostname(mConfig->sys.deviceName); WiFi.mode(WIFI_AP_STA); @@ -206,40 +247,72 @@ void ahoywifi::sendNTPpacket(IPAddress& address) { mUdp.endPacket(); } +//----------------------------------------------------------------------------- +void ahoywifi::sortRSSI(int *sort, int n) { + for (int i = 0; i < n; i++) + sort[i] = i; + for (int i = 0; i < n; i++) + for (int j = i + 1; j < n; j++) + if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) + std::swap(sort[i], sort[j]); +} //----------------------------------------------------------------------------- void ahoywifi::scanAvailNetworks(void) { + DPRINTLN(DBG_INFO, "start scan"); if(-2 == WiFi.scanComplete()) { mScanActive = true; if(WIFI_AP == WiFi.getMode()) WiFi.mode(WIFI_AP_STA); WiFi.scanNetworks(true); } + else + DPRINTLN(DBG_INFO, "complete!"); } - //----------------------------------------------------------------------------- void ahoywifi::getAvailNetworks(JsonObject obj) { JsonArray nets = obj.createNestedArray("networks"); + DPRINTLN(DBG_INFO, "getAvailNetworks"); int n = WiFi.scanComplete(); + if (n < 0) + return; if(n > 0) { int sort[n]; - for (int i = 0; i < n; i++) - sort[i] = i; - for (int i = 0; i < n; i++) - for (int j = i + 1; j < n; j++) - if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) - std::swap(sort[i], sort[j]); + sortRSSI(&sort[0], n); for (int i = 0; i < n; ++i) { - nets[i]["ssid"] = WiFi.SSID(sort[i]); - nets[i]["rssi"] = WiFi.RSSI(sort[i]); + DPRINTLN(DBG_INFO, "found network: " + WiFi.SSID(sort[i])); + nets[i]["ssid"] = WiFi.SSID(sort[i]); + nets[i]["rssi"] = WiFi.RSSI(sort[i]); } - mScanActive = false; - WiFi.scanDelete(); } + mScanActive = false; + WiFi.scanDelete(); } +//----------------------------------------------------------------------------- +void ahoywifi::getBSSIDs() { + int n = WiFi.scanComplete(); + if (n < 0) + return; + if(n > 0) { + mBSSIDList.clear(); + int sort[n]; + sortRSSI(&sort[0], n); + for (int i = 0; i < n; i++) { + DBGPRINT("BSSID " + String(i) + ":"); + uint8_t *bssid = WiFi.BSSID(sort[i]); + for (int j = 0; j < 6; j++){ + DBGPRINT(" " + String(bssid[j], HEX)); + mBSSIDList.push_back(bssid[j]); + } + DBGPRINTLN(""); + } + } + mScanActive = false; + WiFi.scanDelete(); +} //----------------------------------------------------------------------------- void ahoywifi::connectionEvent(WiFiStatus_t status) { @@ -248,15 +321,19 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) { if(mStaConn != CONNECTED) { mStaConn = CONNECTED; DBGPRINTLN(F("\n[WiFi] Connected")); - WiFi.mode(WIFI_STA); - DBGPRINTLN(F("[WiFi] AP disabled")); - mDns.stop(); } break; case GOT_IP: mStaConn = GOT_IP; + if (mScanActive) { // maybe another scan has started + WiFi.scanDelete(); + mScanActive = false; + } welcome(WiFi.localIP().toString() + F(" (Station)")); + mDns.stop(); + WiFi.mode(WIFI_STA); + DBGPRINTLN(F("[WiFi] AP disabled")); mAppWifiCb(true); break; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 7155a427..549bf716 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -50,7 +50,8 @@ class ahoywifi { void onWiFiEvent(WiFiEvent_t event); #endif void welcome(String msg); - + void sortRSSI(int *sort, int n); + void getBSSIDs(void); settings_t *mConfig; appWifiCb mAppWifiCb; @@ -68,9 +69,8 @@ class ahoywifi { uint8_t mLoopCnt; bool mScanActive; + uint8_t mLastApClients; - void sortRSSI(int *sort, int n); - void getBSSIDs(void); std::list mBSSIDList; };