/* * This file is part of the Owl Positioning System (OwlPS) project. * It is subject to the copyright notice and license terms in the * COPYRIGHT.t2t file found in the top-level directory of this * distribution and at * https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t * No part of the OwlPS Project, including this file, may be copied, * modified, propagated, or distributed except according to the terms * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be * distributed along with this file, either separately or by replacing * this notice by the COPYRIGHT.t2t file's contents. */ #include "posutil.hh" #include "posexcept.hh" #include "stock.hh" #include "configuration.hh" #include "measurement.hh" #include #include using namespace std ; /* *** Maths *** */ double PosUtil::deg2rad(const double degrees) { return degrees / (180.0 / M_PI) ; } double PosUtil::rad2deg(const double radians) { return radians * (180.0 / M_PI) ; } /* *** Measurements *** */ /** * CPs that have not captured a Request must not have too much weight in * the computation. Thus, in the measurements lists we compare, we add * missing CPs with a very low SS value. * * Both lists can be completed, depending of the CPs they contain. * Both lists must initially contain at least one measurement. */ void PosUtil::complete_with_dummy_measurements( unordered_map &measurements1, unordered_map &measurements2) { assert(! measurements1.empty()) ; assert(! measurements2.empty()) ; Measurement dummy ; dummy.add_ss(1, Configuration::int_value("positioning.smallest-ss")) ; for (auto i = measurements1.begin() ; i != measurements1.end() ; ++i) if (measurements2.find(i->first) == measurements2.end()) { dummy.set_cp(&Stock::get_cp(i->first)) ; measurements2[i->first] = dummy ; } for (auto i = measurements2.begin() ; i != measurements2.end() ; ++i) if (measurements1.find(i->first) == measurements1.end()) { dummy.set_cp(&Stock::get_cp(i->first)) ; measurements1[i->first] = dummy ; } } /** * Both lists must have the same size and contain the same keys: * you should call complete_with_dummy_measurements() before this * function. * * The similarity between the two lists is computed by averaging the * similarities between the elements of both lists, two by two, calling * Measurement::similarity(). */ float PosUtil::similarity( unordered_map &measurements1, unordered_map &measurements2) { assert(! measurements1.empty()) ; assert(measurements1.size() == measurements2.size()) ; float similarity = 0 ; for (auto i1 = measurements1.begin() ; i1 != measurements1.end() ; ++i1) { auto i2 = measurements2.find(i1->first) ; assert(i2 != measurements2.end()) ; similarity += i1->second.similarity(i2->second) ; } return similarity / measurements1.size() ; } /* *** Wi-Fi *** */ /** * @param channel A IEEE 802.11 channel or frequency in MHz or in Hz. * @returns The frequency in Hz. * @throw bad_channel if `channel` is not a valid channel or * frequency value. */ unsigned long PosUtil::wifi_channel_to_hz(const unsigned long &channel) { switch (channel) { case 1: case OWL_80211_MHZ_CHANNEL_1: case OWL_80211_HZ_CHANNEL_1: return OWL_80211_HZ_CHANNEL_1 ; case 2: case OWL_80211_MHZ_CHANNEL_2: case OWL_80211_HZ_CHANNEL_2: return OWL_80211_HZ_CHANNEL_2 ; case 3: case OWL_80211_MHZ_CHANNEL_3: case OWL_80211_HZ_CHANNEL_3: return OWL_80211_HZ_CHANNEL_3 ; case 4: case OWL_80211_MHZ_CHANNEL_4: case OWL_80211_HZ_CHANNEL_4: return OWL_80211_HZ_CHANNEL_4 ; case 5: case OWL_80211_MHZ_CHANNEL_5: case OWL_80211_HZ_CHANNEL_5: return OWL_80211_HZ_CHANNEL_5 ; case 6: case OWL_80211_MHZ_CHANNEL_6: case OWL_80211_HZ_CHANNEL_6: return OWL_80211_HZ_CHANNEL_6 ; case 7: case OWL_80211_MHZ_CHANNEL_7: case OWL_80211_HZ_CHANNEL_7: return OWL_80211_HZ_CHANNEL_7 ; case 8: case OWL_80211_MHZ_CHANNEL_8: case OWL_80211_HZ_CHANNEL_8: return OWL_80211_HZ_CHANNEL_8 ; case 9: case OWL_80211_MHZ_CHANNEL_9: case OWL_80211_HZ_CHANNEL_9: return OWL_80211_HZ_CHANNEL_9 ; case 10: case OWL_80211_MHZ_CHANNEL_10: case OWL_80211_HZ_CHANNEL_10: return OWL_80211_HZ_CHANNEL_10 ; case 11: case OWL_80211_MHZ_CHANNEL_11: case OWL_80211_HZ_CHANNEL_11: return OWL_80211_HZ_CHANNEL_11 ; case 12: case OWL_80211_MHZ_CHANNEL_12: case OWL_80211_HZ_CHANNEL_12: return OWL_80211_HZ_CHANNEL_12 ; case 13: case OWL_80211_MHZ_CHANNEL_13: case OWL_80211_HZ_CHANNEL_13: return OWL_80211_HZ_CHANNEL_13 ; case 14: case OWL_80211_MHZ_CHANNEL_14: case OWL_80211_HZ_CHANNEL_14: return OWL_80211_HZ_CHANNEL_14 ; } // Error: wrong channel value throw bad_channel(channel) ; } /* *** Strings *** */ string PosUtil::int_to_mac(const uint32_t source) { uint8_t bytes[6] ; memset(bytes, 0, 6) ; for (int i = 0 ; i < 4 ; ++i) bytes[i+2] = reinterpret_cast(&source)[i] ; char mac_cstr[OWL_ETHER_ADDR_STRLEN] ; owl_mac_bytes_to_string_r(bytes, mac_cstr) ; string mac(mac_cstr) ; to_upper(mac) ; return mac ; }