/* * This file is part of the Owl Positioning System (OwlPS). * OwlPS is a project of the University of Franche-Comté * (Université de Franche-Comté), France. */ #include "measurement.hh" #include "posexcept.hh" #include #include using namespace std ; /* *** Constructors *** */ /** * Note that values pointed by #ap are not deleted. */ Measurement::~Measurement() { ss_list.clear() ; } /* *** Write accessors *** */ /** * @param packet_id The sequence number of the packet in the request, * as sent by the mobile. * @param ss_dbm The signal strength to add to #ss_list (in dBm). */ void Measurement:: add_ss(const pkt_id_t packet_id, const ss_t ss_dbm) { unsigned int ss_list_size = ss_list.size() ; // Add the new value (in dBm) along with the packet identifier: pair packet(make_pair(packet_id, ss_dbm)) ; if (! ss_list.insert(packet).second) { cerr << "Cannot insert the packet (#" << packet_id << ", " << static_cast(ss_dbm) << " dBm)\n" ; return ; } // Update the average with the new value double total_ss_mwatts = pow(10, static_cast(ss_dbm) / 10.0) + // New SS in mW (ss_list_size * pow(10, average_ss / 10.0)) ; // Other values in mW // Convert the average back in dBm: average_ss = 10.0 * log10(total_ss_mwatts / ss_list.size()) ; } /** * Add an SS list to the current Measurement's SS list. * If the new SS list contains a packet with the same ID, the old one * is overwritten. */ void Measurement:: add_ss_list(const map &_ss_list) { // We cannot use insert() here because we want to overwrite the // previous values with the same ID, if any. for (map::const_iterator i = _ss_list.begin() ; i != _ss_list.end() ; ++i) ss_list[i->first] = i->second ; update_average_ss() ; } /** * Merge consists of adding the SS values of \em source to #ss_list. It * is possible only if the #ap of the two Measurement are identical. * @throw cannot_merge if the AP of the two Measurement are different. */ void Measurement::merge(const Measurement &source) { if (ap != source.ap) throw cannot_merge( "error when trying to merge measurements, APs are different") ; add_ss_list(source.ss_list) ; } /** * - #ap is not deleted, only initialised to NULL. * - #ss_list is cleared. * - #average_ss is initialised to 0. */ void Measurement::clear() { ss_list.clear() ; average_ss = 0 ; ap = NULL ; } /* *** Operations *** */ void Measurement::update_average_ss() { if (ss_list.empty()) { average_ss = 0 ; return ; } double total_ss_mwatts = 0 ; for (map::const_iterator i = ss_list.begin() ; i != ss_list.end() ; ++i) // Add the current value in mW to the total total_ss_mwatts += pow(10, static_cast(i->second) / 10.0) ; // Compute the average in mW and convert it to dBm average_ss = 10 * log10(total_ss_mwatts / ss_list.size()) ; } /* *** Operators *** */ Measurement& Measurement::operator=(const Measurement &m) { if (this == &m) return *this ; ap = m.ap ; ss_list = m.ss_list ; average_ss = m.average_ss ; return *this ; } bool Measurement::operator==(const Measurement &m) const { if (this == &m) return true ; return ap == m.ap && ss_list == m.ss_list && average_ss == m.average_ss ; } const string Measurement::to_csv() const { ostringstream csv_line ; if (ss_list.empty()) return "" ; string mac_ap("") ; if (ap) mac_ap = ap->get_mac_addr() ; for (map::const_iterator i = ss_list.begin() ; i != ss_list.end() ; ++i) { if (i != ss_list.begin()) csv_line << ';' ; csv_line << mac_ap << ';' << i->first << ';' << static_cast(i->second) ; } return csv_line.str() ; } ostream &operator<<(ostream &os, const Measurement &m) { // MAC address os << "AP: " << (m.ap ? m.ap->get_mac_addr() : "Unknown_AP") << ": " ; // List of SS if (m.ss_list.empty()) os << "No values" ; else for (map::const_iterator i = m.ss_list.begin() ; i != m.ss_list.end() ; ++i) { if (i != m.ss_list.begin()) os << ';' ; os << static_cast(i->second) << '(' << i->first << ')' ; } os << " [AVG=" << m.average_ss << "]" ; return os ; }