owlps/owlps-positioner/src/measurement.cc

213 lines
4.4 KiB
C++
Raw Normal View History

/*
* 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 <iostream>
#include <sstream>
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<pkt_id_t, ss_t> packet(make_pair(packet_id, ss_dbm)) ;
if (! ss_list.insert(packet).second)
{
cerr
<< "Cannot insert the packet (#" << packet_id << ", "
<< static_cast<int_fast16_t>(ss_dbm) << " dBm)\n" ;
return ;
}
// Update the average with the new value
double total_ss_mwatts =
pow(10, static_cast<double>(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<pkt_id_t, ss_t> &_ss_list)
{
// We cannot use insert() here because we want to overwrite the
// previous values with the same ID, if any.
for (map<pkt_id_t, ss_t>::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<pkt_id_t, ss_t>::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<double>(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<pkt_id_t, ss_t>::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<int_fast16_t>(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<pkt_id_t, ss_t>::const_iterator
i = m.ss_list.begin() ; i != m.ss_list.end() ; ++i)
{
if (i != m.ss_list.begin())
os << ';' ;
os << static_cast<int_fast16_t>(i->second)
<< '(' << i->first << ')' ;
}
os << " [AVG=" << m.average_ss << "]" ;
return os ;
}