This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/sensors/radio/WiFiQualityAnalyzer.h
k-a-z-u a8123d532d added wifi per-floor optimization
added plot to wifi-quality-analyzer
changes to per-floor wifi models
minor fixes
2018-05-16 13:02:06 +02:00

140 lines
2.9 KiB
C++

#ifndef WIFIQUALITYANALYZER_H
#define WIFIQUALITYANALYZER_H
#include "WiFiMeasurements.h"
#include <unordered_set>
#ifdef WITH_DEBUG_PLOT
#include <KLib/misc/gnuplot/Gnuplot.h>
#include <KLib/misc/gnuplot/GnuplotPlot.h>
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
#endif
class WiFiQualityAnalyzer {
private:
int historySize = 3;
std::vector<WiFiMeasurements> history;
float quality = 0;
#ifdef WITH_DEBUG_PLOT
K::Gnuplot gp;
K::GnuplotPlot plot;
K::GnuplotPlotElementLines line1;
K::GnuplotPlotElementLines line2;
int gpX = 0;
#endif
public:
WiFiQualityAnalyzer() {
#ifdef WITH_DEBUG_PLOT
plot.add(&line1);
plot.add(&line2);
plot.setTitle("WiFi Quality");
#endif
}
/** 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;
#ifdef WITH_DEBUG_PLOT
line1.add(K::GnuplotPoint2(gpX,qAvgdB)); line1.setTitle("dB"); line1.getStroke().setWidth(2);
line2.add(K::GnuplotPoint2(gpX,qCnt)); line2.setTitle("visible");
while(line1.size() > 50) {line1.remove(0);}
while(line2.size() > 50) {line2.remove(0);}
++gpX;
gp.draw(plot);
gp.flush();
#endif
}
/** 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