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/beacon/setup/BeaconFingerprint.h
mail@toni-fetzer.de 96c63ac3ec added measurement grouping for beacons
had to change the parameter boundaries of the wifi optimizer to be able to use it for bluetooth... this should be refactored to something more generic..
some minor changes in ble
2019-06-10 16:57:02 +02:00

104 lines
3.4 KiB
C++

#ifndef BEACONFINGERPRINT_H
#define BEACONFINGERPRINT_H
#include "../../../geo/Point3.h"
#include "../BeaconMeasurements.h"
#include <unordered_map>
/**
* denotes a beacon fingerprint:
* known position and 1-n measurements [ble-advertisment-scan on all channels] conducted at this position
*
* if more than one measurement is conducted, each AP is contained more than once!
*/
struct BeaconFingerprint {
/** real-world-position that was measured */
Point3 pos_m;
/** seen APs at the given location */
BeaconMeasurements measurements;
/** ctor */
BeaconFingerprint() {;}
/** ctor */
BeaconFingerprint(const Point3 pos_m) : pos_m(pos_m) {;}
/** ctor */
BeaconFingerprint(const Point3 pos_m, const BeaconMeasurements& 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 */
BeaconMeasurements average() {
// group scans by MAC (all measurements for one AP)
std::unordered_map<MACAddress, BeaconMeasurements> group;
for (BeaconMeasurement& bm : measurements.entries) {
group[bm.getBeacon().getMAC()].entries.push_back(bm);
}
// create the output that contains the AP's average
BeaconMeasurements res;
for (auto& it : group) {
const BeaconMeasurements& apMeasurements = it.second;
BeaconMeasurement 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<BeaconMeasurement> getAllForMAC(const MACAddress& mac) const {
std::vector<BeaconMeasurement> res;
for (const BeaconMeasurement& m : measurements.entries) {
if (m.getBeacon().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 BeaconMeasurement& bm : measurements.entries) {
out << bm.getTimestamp().ms() << " " << bm.getBeacon().getMAC().asString() << " " << bm.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;
BeaconMeasurement bm(Timestamp::fromMS(ms), Beacon(MACAddress(mac)), rssi);
measurements.entries.push_back(bm);
}
}
};
#endif // BEACONFINGERPRINT_H