#ifndef WIFIQUALITYANALYZER_H #define WIFIQUALITYANALYZER_H #include "WiFiMeasurements.h" #include class WiFiQualityAnalyzer { private: int historySize = 3; std::vector history; float quality = 0; public: /** attach the current measurement and infer the quality */ void add(const WiFiMeasurements& mes) { // update the history history.push_back(mes); while(history.size() > historySize) { history.erase(history.begin()); } // recalculate update(); } /** get a quality score for the WiFi */ float getQuality() const { return quality; } private: /** re-calculate the current quality */ void update() { const float qCnt = getQualityByCount(); const float qAvgdB = getQualityByAvgDB(); quality = qAvgdB; } /** score [0:1] based on the average sig-strength. the higher the better */ float getQualityByAvgDB() const { // stats float sum = 0; float sum2 = 0; float cnt = 0; for (const WiFiMeasurements& mes : history) { for (const WiFiMeasurement& m : mes.entries) { const float rssi = m.getRSSI(); sum += rssi; sum2 += rssi*rssi; ++cnt; } } // average sig strength const float avg = sum/cnt; const float avg2 = sum2/cnt; const float stdDev = std::sqrt(avg2 - avg*avg); // avg rssi score const float minRSSI = -85; const float maxRSSI = -70; float score1 = (avg-minRSSI) / (maxRSSI-minRSSI); // min = 0; max = 1 if (score1 > 1) {score1 = 1;} if (score1 < 0) {score1 = 0;} //const float score1 = 1.0 - std::exp(-0.07 * (avg-minRSSI)); // std dev score const float score2 = 1.0 - std::exp(-1.0 * stdDev); return score1 * score2; } /** quality score [0:1] according to the number of seen APs */ float getQualityByCount() const { // distinct macs std::unordered_set macs; for (const WiFiMeasurements& mes : history) { for (const WiFiMeasurement& m : mes.entries) { macs.insert(m.getAP().getMAC()); } } // number of distinct macs const int cnt = macs.size(); // see function plot. function between [0.0:1.0] has 0.5 around 7 seen APs return 1.0 - std::exp(-0.1 * cnt); } }; #endif // WIFIQUALITYANALYZER_H