107 lines
2.1 KiB
C++
107 lines
2.1 KiB
C++
#ifndef WIFIQUALITYANALYZER_H
|
|
#define WIFIQUALITYANALYZER_H
|
|
|
|
#include "WiFiMeasurements.h"
|
|
#include <unordered_set>
|
|
|
|
class WiFiQualityAnalyzer {
|
|
|
|
private:
|
|
|
|
int historySize = 3;
|
|
std::vector<WiFiMeasurements> 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<MACAddress> 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
|