116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef WIFIFINGERPRINT_H
|
||
#define WIFIFINGERPRINT_H
|
||
|
||
|
||
#include "../../../geo/Point3.h"
|
||
#include "../WiFiMeasurements.h"
|
||
|
||
#include <unordered_map>
|
||
|
||
/**
|
||
* denotes a wifi fingerprint:
|
||
* known position and 1-n measurements [wifi-scan on all channels] conducted at this position
|
||
*
|
||
* if more than one measurement is conducted, each AP is contained more than once!
|
||
*/
|
||
struct WiFiFingerprint {
|
||
|
||
|
||
/** real-world-position that was measured */
|
||
Point3 pos_m;
|
||
|
||
/** seen APs at the given location */
|
||
WiFiMeasurements measurements;
|
||
|
||
|
||
/** ctor */
|
||
WiFiFingerprint() {;}
|
||
|
||
/** ctor */
|
||
WiFiFingerprint(const Point3 pos_m) : pos_m(pos_m) {;}
|
||
|
||
/** ctor */
|
||
WiFiFingerprint(const Point3 pos_m, const WiFiMeasurements& measurements) : pos_m(pos_m), measurements(measurements) {;}
|
||
|
||
|
||
/** as each AP might be contained more than once (scanned more than once), group them by MAC and use the average RSSI */
|
||
WiFiMeasurements average() {
|
||
|
||
// group scans by MAC (all measurements for one AP)
|
||
std::unordered_map<MACAddress, WiFiMeasurements> group;
|
||
for (WiFiMeasurement& m : measurements.entries) {
|
||
group[m.getAP().getMAC()].entries.push_back(m);
|
||
}
|
||
|
||
// create the output that contains the AP's average
|
||
WiFiMeasurements res;
|
||
for (auto& it : group) {
|
||
const WiFiMeasurements& apMeasurements = it.second;
|
||
WiFiMeasurement avg = apMeasurements.entries.front(); // average starts with a copy of the first entry (to get all data-fields beside the rssi)
|
||
for (int i = 1; i < (int)apMeasurements.entries.size(); ++i) { // sum up all other entries [1:end]
|
||
avg.setRssi(avg.getRSSI() + apMeasurements.entries[i].getRSSI());
|
||
}
|
||
avg.setRssi(avg.getRSSI() / apMeasurements.entries.size());
|
||
res.entries.push_back(avg); // add to output
|
||
}
|
||
|
||
// done
|
||
return res;
|
||
|
||
}
|
||
|
||
/** get all measurements for the given MAC */
|
||
std::vector<WiFiMeasurement> getAllForMAC(const MACAddress& mac) const {
|
||
std::vector<WiFiMeasurement> res;
|
||
for (const WiFiMeasurement& m : measurements.entries) {
|
||
if (m.getAP().getMAC() == mac) {res.push_back(m);}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
/** serialize */
|
||
void write(std::ostream& out) const {
|
||
out << "pos: " << pos_m.x << " " << pos_m.y << " " << pos_m.z << "\n";
|
||
out << "num: " << measurements.entries.size() << "\n";
|
||
for (const WiFiMeasurement& wm : measurements.entries) {
|
||
out << wm.getTimestamp().ms() << " " << wm.getAP().getMAC().asString() << " " << wm.getRSSI() << "\n";
|
||
}
|
||
}
|
||
|
||
/** deserialize */
|
||
void read(std::istream& inp) {
|
||
std::string tmp;
|
||
|
||
// read the position
|
||
inp >> tmp; if ("pos:" != tmp) {throw "error";}
|
||
inp >> pos_m.x >> pos_m.y >> pos_m.z;
|
||
|
||
// number of entries
|
||
inp >> tmp; if ("num:" != tmp) {throw "error";}
|
||
int numEntries; inp >> numEntries;
|
||
|
||
// read the entries
|
||
for (int i = 0; i < numEntries; ++i) {
|
||
uint64_t ms; inp >> ms;
|
||
std::string mac; inp >> mac;
|
||
float rssi; inp >> rssi;
|
||
WiFiMeasurement wm(AccessPoint(MACAddress(mac)), rssi, Timestamp::fromMS(ms));
|
||
measurements.entries.push_back(wm);
|
||
}
|
||
|
||
}
|
||
|
||
};
|
||
|
||
#endif // WIFIFINGERPRINT_H
|