From f67f95d1ceed98a4b72ed9d600101d5c6816328b Mon Sep 17 00:00:00 2001 From: kazu Date: Mon, 17 Apr 2017 16:47:02 +0200 Subject: [PATCH] added first draft of a wifi quality analyzer --- sensors/radio/WiFiQualityAnalyzer.h | 106 ++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 sensors/radio/WiFiQualityAnalyzer.h diff --git a/sensors/radio/WiFiQualityAnalyzer.h b/sensors/radio/WiFiQualityAnalyzer.h new file mode 100644 index 0000000..994b2ec --- /dev/null +++ b/sensors/radio/WiFiQualityAnalyzer.h @@ -0,0 +1,106 @@ +#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 = -90; + const float maxRSSI = -65; + 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