diff --git a/owlps-positioner/src/inputcsv.cc b/owlps-positioner/src/inputcsv.cc index 1f4b705..56304c9 100644 --- a/owlps-positioner/src/inputcsv.cc +++ b/owlps-positioner/src/inputcsv.cc @@ -56,8 +56,8 @@ bool InputCSV::fill_current_request() current_request->set_mobile(&mobile) ; // Read request type - uint8_t type ; - uint16_t type_r ; + uint_fast8_t type ; + uint_fast16_t type_r ; if (! file.read_field(type_r)) { // Wrong number of fields @@ -68,6 +68,17 @@ bool InputCSV::fill_current_request() type = type_r ; current_request->set_type(type) ; + // Read the number of packets + uint_fast16_t nb_packets ; + if (! file.read_field(nb_packets)) + { + // Wrong number of fields + if (Configuration::is_configured("verbose")) + cerr << "InputCSV: cannot read the number of packets.\n" ; + return false ; + } + current_request->set_nb_packets(nb_packets) ; + // Read Timestamp field Timestamp timestamp ; if (! file.read_timestamp(timestamp)) @@ -108,12 +119,21 @@ bool InputCSV::fill_current_request() string mac_ap ; while (file.read_field(mac_ap)) { - int ss ; + uint_fast16_t packet_id ; + if (! file.read_field(packet_id)) + { + // Wrong number of fields + if (Configuration::is_configured("verbose")) + cerr << "InputCSV: cannot read the packet ID.\n" ; + return false ; + } + + int_fast16_t ss ; if (! file.read_field(ss)) { // Wrong number of fields if (Configuration::is_configured("verbose")) - cerr << "InputCSV: cannot read mac_ap.\n" ; + cerr << "InputCSV: cannot read the signal strength.\n" ; return false ; } PosUtil::to_upper(mac_ap) ; @@ -124,7 +144,7 @@ bool InputCSV::fill_current_request() const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; - measurements[mac_ap].add_ss(ss) ; + measurements[mac_ap].add_ss(packet_id, ss) ; } if (measurements.empty()) return false ; diff --git a/owlps-positioner/src/inputcsv.hh b/owlps-positioner/src/inputcsv.hh index 0688144..33733c4 100644 --- a/owlps-positioner/src/inputcsv.hh +++ b/owlps-positioner/src/inputcsv.hh @@ -16,7 +16,8 @@ /// Reads \link Request requests \endlink from a CSV file /** * CSV format is: - * Mobile_MAC;Timestamp;X;Y;Z;Direction;AP_MAC_1;SS_1;…;AP_MAC_n;SS_n + * Mobile_MAC;Request_type;Number_of_packets;Timestamp;X;Y;Z;Direction; + * AP_MAC_1;Packet_ID_1;SS_1;…;AP_MAC_n;Packet_ID_n;SS_n */ class InputCSV: public InputMedium { diff --git a/owlps-positioner/src/inputlogcsv.cc b/owlps-positioner/src/inputlogcsv.cc index 84ceed5..df2e87f 100644 --- a/owlps-positioner/src/inputlogcsv.cc +++ b/owlps-positioner/src/inputlogcsv.cc @@ -28,6 +28,7 @@ const string InputLogCSV::request_to_csv(const Request &request) const csv_line << request.get_mobile()->get_mac_addr() ; csv_line << ';' << static_cast(request.get_type()) + << ';' << request.get_nb_packets() << ';' << request.get_time_sent() << ';' ; @@ -48,18 +49,7 @@ const string InputLogCSV::request_to_csv(const Request &request) const request.get_measurements() ; for (unordered_map::const_iterator i = measurements.begin() ; i != measurements.end() ; ++i) - { - const vector &ss_list = i->second.get_ss_list() ; - const string &ap_mac = i->second.get_ap() != NULL - ? i->second.get_ap()->get_mac_addr() - : "" ; - for (vector::const_iterator i = ss_list.begin() ; - i != ss_list.end() ; ++i) - { - csv_line << ';' << ap_mac ; - csv_line << ';' << *i ; - } - } + csv_line << i->second.to_csv() ; csv_line << '\n' ; return csv_line.str() ; diff --git a/owlps-positioner/src/inputudpsocket.cc b/owlps-positioner/src/inputudpsocket.cc index 803a804..ff8ff06 100644 --- a/owlps-positioner/src/inputudpsocket.cc +++ b/owlps-positioner/src/inputudpsocket.cc @@ -104,6 +104,7 @@ bool InputUDPSocket::fill_current_request() } // Endianess conversions + request.nb_packets = ntohs(request.nb_packets) ; owl_ntoh_timestamp(&request.request_time) ; request.nb_info = ntohs(request.nb_info) ; request.x_position = owl_ntohf(request.x_position) ; @@ -120,6 +121,7 @@ bool InputUDPSocket::fill_current_request() cout << "*** Request received from the aggregator ***" << "\n\tType: " << static_cast(request.type) + << "\n\tNumber of packets: " << request.nb_packets << "\n\tMobile MAC: " << mac_mobile << "\n\tRequest timestamp: " << Timestamp(request.request_time) << "\n\tPosition X: " << request.x_position @@ -146,6 +148,9 @@ bool InputUDPSocket::fill_current_request() // Request type current_request->set_type(request.type) ; + // Number of packets + current_request->set_nb_packets(request.nb_packets) ; + // Timestamp current_request->set_time_sent(Timestamp(request.request_time)) ; @@ -167,6 +172,8 @@ bool InputUDPSocket::fill_current_request() return false ; } + uint_fast16_t packet_id = ntohs(request_info.packet_id) ; + string mac_ap( owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ; PosUtil::to_upper(mac_ap) ; @@ -179,6 +186,7 @@ bool InputUDPSocket::fill_current_request() if (Configuration::is_configured("verbose")) cout << "\t* Packet received from the aggregator:" + << "\n\t\tPacket number: " << packet_id << "\n\t\tAP MAC: " << mac_ap << "\n\t\tSignal: " << ss << " dBm" @@ -195,7 +203,7 @@ bool InputUDPSocket::fill_current_request() const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; - measurements[mac_ap].add_ss(ss) ; + measurements[mac_ap].add_ss(packet_id, ss) ; } if (measurements.empty()) return false ; diff --git a/owlps-positioner/src/measurement.cc b/owlps-positioner/src/measurement.cc index c74cb3c..8e7c809 100644 --- a/owlps-positioner/src/measurement.cc +++ b/owlps-positioner/src/measurement.cc @@ -8,6 +8,9 @@ #include "measurement.hh" #include "posexcept.hh" +#include +#include + using namespace std ; @@ -15,23 +18,6 @@ using namespace std ; /* *** Constructors *** */ -Measurement::Measurement(const AccessPoint *_ap): - ap(const_cast(_ap)), average_ss(0) -{ - ss_list.reserve(10) ; -} - - -Measurement::Measurement(const AccessPoint *_ap, - const vector &_ss_list): - ap(const_cast(_ap)), ss_list(_ss_list) -{ - ss_list.reserve(10) ; - update_average_ss() ; -} - - - /** * Note that values pointed by #ap are not deleted. */ @@ -46,31 +32,48 @@ Measurement::~Measurement() /** + * @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 ss_t &ss_dbm) +void Measurement:: +add_ss(const uint_fast16_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 - - ss_list.push_back(ss_dbm) ; // Add new value (dBm) - - // Update average converting back in dBm + (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()) ; } -void Measurement::set_ss_list(const std::vector &_ss_list) +/** + * 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) { - ss_list = _ss_list ; - update_average_ss() ; -} + // 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 ; - -void Measurement::add_ss_list(const std::vector &_ss_list) -{ - ss_list.insert(ss_list.end(), _ss_list.begin(), _ss_list.end()) ; update_average_ss() ; } @@ -117,10 +120,10 @@ void Measurement::update_average_ss() double total_ss_mwatts = 0 ; - for (vector::const_iterator i = ss_list.begin() ; - i != ss_list.end() ; ++i) + 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) / 10.0) ; + 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()) ; @@ -157,23 +160,51 @@ bool Measurement::operator==(const Measurement &m) const +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 != NULL ? m.ap->get_mac_addr() : "Unknown_AP") + << "AP: " << (m.ap ? m.ap->get_mac_addr() : "Unknown_AP") << ": " ; // List of SS if (m.ss_list.empty()) os << "No values" ; else - for (vector::const_iterator i = m.ss_list.begin() ; - i != m.ss_list.end() ; ++i) + for (map::const_iterator + i = m.ss_list.begin() ; i != m.ss_list.end() ; ++i) { - os << *i ; - if (i != m.ss_list.end() - 1) - os << ";" ; + if (i != m.ss_list.begin()) + os << ';' ; + os << static_cast(i->second) + << '(' << i->first << ')' ; } os << " [AVG=" << m.average_ss << "]" ; diff --git a/owlps-positioner/src/measurement.hh b/owlps-positioner/src/measurement.hh index 449fb54..950964c 100644 --- a/owlps-positioner/src/measurement.hh +++ b/owlps-positioner/src/measurement.hh @@ -10,7 +10,7 @@ #include "accesspoint.hh" -#include +#include #include #include @@ -23,7 +23,7 @@ protected: /// The AccessPoint that performed the measurement AccessPoint *ap ; /// List of signal strengths captured (in dBm) - std::vector ss_list ; + std::map ss_list ; /// Average of all signal strength captured (dBm) double average_ss ; @@ -35,10 +35,8 @@ protected: public: - Measurement(const AccessPoint *_ap = NULL) ; - - Measurement(const AccessPoint *_ap, - const std::vector &_ss_list) ; + Measurement(const AccessPoint *_ap = NULL): + ap(const_cast(_ap)), average_ss(0) {} Measurement(const Measurement &source): ap(source.ap), ss_list(source.ss_list), @@ -49,7 +47,6 @@ public: /** @name Read accessors */ //@{ AccessPoint* get_ap() const ; - const std::vector& get_ss_list() const ; double get_average_ss() const ; int get_ss_list_size() const ; //@} @@ -57,11 +54,10 @@ public: /** @name Write accessors */ //@{ void set_ap(const AccessPoint *_ap) ; - void set_ss_list(const std::vector &_ss_list) ; /// Adds a signal strength to #ss_list - void add_ss(const ss_t &ss_dbm) ; + void add_ss(const uint_fast16_t packet_id, const ss_t ss_dbm) ; /// Adds several signal strengths to #ss_list - void add_ss_list(const std::vector &_ss_list) ; + void add_ss_list(const std::map &_ss_list) ; /// Merges a given Measurement into the current Measurement void merge(const Measurement &source) ; void clear(void) ; @@ -83,6 +79,12 @@ public: operator bool(void) const ; //@} + /** @name Conversion accessors */ + //@{ + /// Converts to a CSV string + const std::string to_csv(void) const ; + //@} + /// Displays a Measurement friend std::ostream &operator<<(std::ostream &os, const Measurement &m) ; } ; @@ -98,12 +100,6 @@ inline AccessPoint* Measurement::get_ap() const } -inline const std::vector& Measurement::get_ss_list() const -{ - return ss_list ; -} - - inline double Measurement::get_average_ss() const { return average_ss ; diff --git a/owlps-positioner/src/posutil.cc b/owlps-positioner/src/posutil.cc index ef17518..aeffcf9 100644 --- a/owlps-positioner/src/posutil.cc +++ b/owlps-positioner/src/posutil.cc @@ -48,7 +48,7 @@ void PosUtil::complete_with_dummy_measurements( assert(! measurements2.empty()) ; Measurement dummy ; - dummy.add_ss(-98) ; // FIXME: should be the smallest possible value + dummy.add_ss(1, -98) ; // FIXME: should be the smallest possible value for (unordered_map::const_iterator i = measurements1.begin() ; i != measurements1.end() ; ++i) diff --git a/owlps-positioner/src/request.cc b/owlps-positioner/src/request.cc index 98d2b57..54d7367 100644 --- a/owlps-positioner/src/request.cc +++ b/owlps-positioner/src/request.cc @@ -49,6 +49,8 @@ void Request::set_real_position(const Point3D &_real_position) /** + * - #nb_packets is set to 1 (this is the default value when + * constructing a Request). * - #mobile is NULLified, but the value it pointed to is not deleted. * - The fields of #time_sent are initialised to 0. * - #measurements is cleared. @@ -56,6 +58,7 @@ void Request::set_real_position(const Point3D &_real_position) void Request::clear() { type = OWL_REQUEST_UNDEFINED ; + nb_packets = 1 ; mobile = NULL ; time_sent.clear() ; measurements.clear() ; @@ -91,6 +94,7 @@ Request& Request::operator=(const Request &source) return *this ; type = source.type ; + nb_packets = source.nb_packets ; mobile = source.mobile ; time_sent = source.time_sent ; measurements = source.measurements ; @@ -116,6 +120,7 @@ bool Request::operator==(const Request &source) const return real_position_equal && type == source.type && + nb_packets == source.nb_packets && mobile == source.mobile && time_sent == source.time_sent && measurements == source.measurements ; @@ -134,6 +139,7 @@ ostream& operator<<(ostream &os, const Request &r) // MAC address os << "Type: " << static_cast(r.type) + << ", Number of packets sent: " << r.nb_packets << ", Mobile: " << (r.mobile != NULL ? r.mobile->get_mac_addr() : "Unknown_Mobile") << ":" ; @@ -160,6 +166,7 @@ size_t hash_value(const Request &source) size_t seed = 0 ; boost::hash_combine(seed, source.type) ; + boost::hash_combine(seed, source.nb_packets) ; boost::hash_combine(seed, source.time_sent) ; if (source.mobile) boost::hash_combine(seed, source.mobile->get_mac_addr()) ; diff --git a/owlps-positioner/src/request.hh b/owlps-positioner/src/request.hh index 20f379c..12c3eef 100644 --- a/owlps-positioner/src/request.hh +++ b/owlps-positioner/src/request.hh @@ -25,6 +25,8 @@ class Request protected: /// Type of the request uint_fast8_t type ; + /// Number of packets sent by the mobile for this request + uint_fast16_t nb_packets ; /// The mobile that sent the request Mobile *mobile ; /// Local date of the request on the mobile @@ -48,25 +50,25 @@ public: const std::tr1::unordered_map &_measurements = std::tr1::unordered_map()): - type(OWL_REQUEST_UNDEFINED), + type(OWL_REQUEST_UNDEFINED), nb_packets(1), mobile(const_cast(_mobile)), time_sent(_time_sent), measurements(_measurements), real_position(NULL) {} Request(const std::tr1::unordered_map &_measurements): - type(OWL_REQUEST_UNDEFINED), + type(OWL_REQUEST_UNDEFINED), nb_packets(1), mobile(NULL), measurements(_measurements), real_position(NULL) {} Request(const Timestamp &_time_sent, const std::tr1::unordered_map &_measurements = std::tr1::unordered_map()): - type(OWL_REQUEST_UNDEFINED), + type(OWL_REQUEST_UNDEFINED), nb_packets(1), mobile(NULL), time_sent(_time_sent), measurements(_measurements), real_position(NULL) {} Request(const Request &source): - type(source.type), + type(source.type), nb_packets(1), mobile(source.mobile), time_sent(source.time_sent), measurements(source.measurements), real_position(NULL) {} @@ -74,7 +76,8 @@ public: /** @name Read accessors */ //@{ - uint8_t get_type(void) const ; + uint_fast8_t get_type(void) const ; + uint_fast16_t get_nb_packets(void) const ; Mobile* get_mobile(void) const ; const Timestamp& get_time_sent(void) const ; const std::tr1::unordered_map& @@ -84,7 +87,8 @@ public: /** @name Write accessors */ //@{ - void set_type(const uint8_t _type) ; + void set_type(const uint_fast8_t _type) ; + void set_nb_packets(const uint_fast16_t _nb_packets) ; void set_mobile(const Mobile *_mobile) ; void set_time_sent(const Timestamp &_time_sent) ; void set_measurements(const std::tr1::unordered_map @@ -121,12 +125,18 @@ public: -inline uint8_t Request::get_type() const +inline uint_fast8_t Request::get_type() const { return type ; } +inline uint_fast16_t Request::get_nb_packets() const +{ + return nb_packets ; +} + + inline Mobile* Request::get_mobile() const { return mobile ; @@ -156,12 +166,18 @@ inline const Point3D* Request::get_real_position(void) const /* *** Write accessors *** */ -inline void Request::set_type(const uint8_t _type) +inline void Request::set_type(const uint_fast8_t _type) { type = _type ; } +inline void Request::set_nb_packets(const uint_fast16_t _nb_packets) +{ + nb_packets = _nb_packets ; +} + + inline void Request::set_mobile(const Mobile *_mobile) { mobile = const_cast(_mobile) ; @@ -194,8 +210,8 @@ inline bool Request::operator!=(const Request &comp) const /** * @return \em false if the Request is empty. - * @return \em true if at least one attribute (other than #type) is - * initialised. + * @return \em true if at least one attribute (other than #type and + * #nb_packets) is initialised. */ inline Request::operator bool() const { diff --git a/owlps-positioner/src/stock.cc b/owlps-positioner/src/stock.cc index 1d7b89d..2a20dd5 100644 --- a/owlps-positioner/src/stock.cc +++ b/owlps-positioner/src/stock.cc @@ -598,7 +598,7 @@ void Stock::generate_reference_point(const Point3D &point) /* Create the measurement, add it to the list */ Measurement m(&rx->second) ; - m.add_ss(rx_ss) ; + m.add_ss(1, rx_ss) ; measurements[rx->second.get_mac_addr()] = m ; }