#ifndef WIFIFINGERPRINTS_H #define WIFIFINGERPRINTS_H #include #include "WiFiFingerprint.h" #include /** * helper class to load and save fingerprints. * fingerprints are wifi-measurements given at some known location * those can be used to e.g. optimize access-point models etc. */ class WiFiFingerprints { static constexpr const char* name = "Fingerprints"; private: // /** the file to save the calibration model to */ // std::string file; /** all fingerprints (position -> measurements) within the model */ std::vector fingerprints; public: /** empty ctor */ WiFiFingerprints() { } /** ctor from file */ WiFiFingerprints(const std::string& file) { load(file); } const std::vector& getFingerprints() const { return fingerprints; } std::vector& getFingerprints() { return fingerprints; } /** attach the given fingerprint */ void add(const WiFiFingerprint& fp) { fingerprints.push_back(fp); } /** get all fingerprints that measured exactly the given mac [no VAP grouping] */ const std::vector getFingerprintsFor(const MACAddress& mac) const { std::vector res; // process each fingerprint location for (const WiFiFingerprint& _fp : fingerprints) { // start with an empty copy WiFiFingerprint fp = _fp; fp.measurements.entries.clear(); // only add the measurements that belong to the requested mac for (const WiFiMeasurement& _m : _fp.measurements.entries) { if (_m.getAP().getMAC() == mac) { fp.measurements.entries.push_back(_m); } } if (fp.measurements.entries.size() > 0) { // got some measurements for this AP? res.push_back(fp); } } return res; } /** deserialize the model */ void load(const std::string& file) { // open and check std::ifstream inp(file.c_str()); if (inp.bad() || inp.eof() || ! inp.is_open()) { return; } // read all entries while (!inp.eof()) { // each section starts with [fingerprint] std::string section; inp >> section; if (inp.eof()) {break;} if (section != "[fingerprint]") {throw Exception("error!");} // deserialize it WiFiFingerprint wfp; wfp.read(inp); if (wfp.measurements.entries.empty()) {continue;} fingerprints.push_back(wfp); } Log::add(name, "loaded " + std::to_string(fingerprints.size()) + " fingerprints"); inp.close(); } /** serialize the model */ void save(const std::string& file) { // open and check std::ofstream out(file.c_str()); if (out.bad()) {throw Exception("error while opening " + file + " for write");} // write all entries for (const WiFiFingerprint& wfp : fingerprints) { out << "[fingerprint]\n"; wfp.write(out); } // done out.close(); } /** get the fingerprint for the given location. if no fingerprint exists, an empty one is created! */ WiFiFingerprint& getFingerprint(const Point3 pos_m) { // try to find an existing one for (WiFiFingerprint& wfp : fingerprints) { // get within range of floating-point rounding issues if (wfp.pos_m.getDistance(pos_m) < 0.01) {return wfp;} } // create a new one and return its reference WiFiFingerprint wfp(pos_m); fingerprints.push_back(wfp); return fingerprints.back(); } }; #endif // WIFIFINGERPRINTS_H