#ifndef WIFIFINGERPRINT_H #define WIFIFINGERPRINT_H #include "../../../geo/Point3.h" #include "../WiFiMeasurements.h" #include /** * denotes a wifi fingerprint * known position and several measurements conducted at this position * * as several measurements were conducted, each AP is usually contained more than once! */ struct WiFiFingerprint { /** real-world-position that was measured */ Point3 pos_m; /** measurements (APs) at the given location */ WiFiMeasurements measurements; /** ctor */ WiFiFingerprint() {;} /** ctor */ WiFiFingerprint(const Point3 pos_m) : pos_m(pos_m) {;} /** as each AP is 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 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; } /** 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