mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Get time zone offset in a more standard way (#17)
* Clang Tidy fixes * Get time zone offset in a more standard way Account for leap seconds Use GNSS-SDR.osnma_mode=strict to check for local time * Fix for C++20 * Initialize tm in a more portable way * Remove unnecessary data members in osnma_msg_receiver --------- Co-authored-by: cesaaargm <cesare.martinez@proton.me>
This commit is contained in:
		| @@ -61,15 +61,18 @@ namespace wht = std; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath) | ||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, bool strict_mode) | ||||
| { | ||||
|     return osnma_msg_receiver_sptr(new osnma_msg_receiver(pemFilePath, merkleFilePath)); | ||||
|     return osnma_msg_receiver_sptr(new osnma_msg_receiver(pemFilePath, merkleFilePath, strict_mode)); | ||||
| } | ||||
|  | ||||
|  | ||||
| osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath) : gr::block("osnma_msg_receiver", | ||||
| osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, | ||||
|     const std::string& merkleFilePath, | ||||
|     bool strict_mode) : gr::block("osnma_msg_receiver", | ||||
|                             gr::io_signature::make(0, 0, 0), | ||||
|                                                                                                                 gr::io_signature::make(0, 0, 0)) | ||||
|                             gr::io_signature::make(0, 0, 0)), | ||||
|                         d_strict_mode(strict_mode) | ||||
| { | ||||
|     d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>(); | ||||
|     d_crypto = std::make_unique<Gnss_Crypto>(crtFilePath, merkleFilePath); | ||||
| @@ -114,23 +117,20 @@ osnma_msg_receiver::osnma_msg_receiver(const std::string& crtFilePath, const std | ||||
|         boost::bind(&osnma_msg_receiver::msg_handler_osnma, this, _1)); | ||||
| #endif | ||||
| #endif | ||||
|     std::chrono::time_point<std::chrono::system_clock> now; | ||||
|     if (d_flag_debug) | ||||
|  | ||||
|     if (d_strict_mode) | ||||
|         { | ||||
|             // d_GST_Rx = d_helper->compute_gst(d_initial_debug_time); | ||||
|             LOG(WARNING) << "Galileo OSNMA: Debug mode, time artificially set up."; | ||||
|             std::cout << "Galileo OSNMA: Debug mode, time artificially set up." << std::endl; | ||||
|             // TODO - need to synchronize time lapse with Gnss_Synchro? | ||||
|             d_GST_Rx = d_helper->compute_gst_now(); | ||||
|             const auto WN = d_helper->get_WN(d_GST_Rx); | ||||
|             const auto TOW = d_helper->get_TOW(d_GST_Rx); | ||||
|             LOG(INFO) << "Galileo OSNMA: initial receiver time GST=[" << WN << " " << TOW << "]"; | ||||
|             std::cout << "Galileo OSNMA: initial receiver time GST=[" << WN << " " << TOW << "]" << std::endl; | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             d_GST_Rx = d_helper->compute_gst_now(); | ||||
|             LOG(WARNING) << "Galileo OSNMA: in non-strict mode, local system time is not checked."; | ||||
|             std::cout << "Galileo OSNMA: in non-strict mode, local system time is not checked." << std::endl; | ||||
|         } | ||||
|  | ||||
|     d_WN = d_helper->get_WN(d_GST_Rx); | ||||
|     d_TOW = d_helper->get_TOW(d_GST_Rx); | ||||
|     LOG(WARNING) << "Galileo OSNMA: initial receiver time GST=[" << d_WN << " " << d_TOW << "]"; | ||||
|     std::cout << "Galileo OSNMA: initial receiver time GST=[" << d_WN << " " << d_TOW << "]" << std::endl; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -167,13 +167,13 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) | ||||
|                         { | ||||
|                             d_last_received_GST = d_GST_SIS; | ||||
|                         } | ||||
|                     if (d_flag_debug) | ||||
|                     if (d_strict_mode) | ||||
|                         { | ||||
|                             d_GST_Rx = d_last_received_GST; | ||||
|                             d_GST_Rx = d_helper->compute_gst_now(); | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             d_GST_Rx = d_helper->compute_gst_now(); | ||||
|                             d_GST_Rx = d_last_received_GST; | ||||
|                         } | ||||
|                     LOG(INFO) << "Galileo OSNMA: Receiver Time GST=[" << d_helper->get_WN(d_GST_Rx) << " " << d_helper->get_TOW(d_GST_Rx) << "]"; | ||||
|                     std::cout << "Galileo OSNMA: Receiver Time GST=[" << d_helper->get_WN(d_GST_Rx) << " " << d_helper->get_TOW(d_GST_Rx) << "]" << std::endl; | ||||
| @@ -1425,6 +1425,7 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(Tag& tag) const | ||||
|     return m; | ||||
| } | ||||
|  | ||||
|  | ||||
| void osnma_msg_receiver::display_data() | ||||
| { | ||||
|     //    if(d_satellite_nav_data.empty()) | ||||
| @@ -1489,6 +1490,7 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector<uint8_t>& key, uint32_t TO | ||||
|     return d_tesla_key_verified; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Removes the tags that have been verified from the multimap d_tags_awaiting_verify. | ||||
|  * | ||||
| @@ -1560,6 +1562,7 @@ void osnma_msg_receiver::remove_verified_tags() | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @brief Control the size of the tags awaiting verification multimap. | ||||
|  * | ||||
| @@ -1948,6 +1951,7 @@ std::vector<MACK_tag_and_info> osnma_msg_receiver::verify_macseq_new(const MACK_ | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void osnma_msg_receiver::send_data_to_pvt(const std::vector<OSNMA_NavData>& data) | ||||
| { | ||||
|     if (!data.empty()) | ||||
| @@ -1960,6 +1964,7 @@ void osnma_msg_receiver::send_data_to_pvt(const std::vector<OSNMA_NavData>& data | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| bool osnma_msg_receiver::store_dsm_kroot(const std::vector<uint8_t>& dsm, const uint8_t nma_header) const | ||||
| { | ||||
|     std::ofstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::out); | ||||
| @@ -1978,6 +1983,7 @@ bool osnma_msg_receiver::store_dsm_kroot(const std::vector<uint8_t>& dsm, const | ||||
|     return file.good(); | ||||
| } | ||||
|  | ||||
|  | ||||
| std::pair<std::vector<uint8_t>, uint8_t> osnma_msg_receiver::parse_dsm_kroot() const | ||||
| { | ||||
|     std::ifstream file(KROOTFILE_DEFAULT, std::ios::binary | std::ios::in); | ||||
|   | ||||
| @@ -36,8 +36,8 @@ | ||||
| #include <map>               // for std::map, std::multimap | ||||
| #include <memory>            // for std::shared_ptr | ||||
| #include <string>            // for std::string | ||||
| #include <vector>                  // for std::vector | ||||
| #include <utility>           // for std::pair | ||||
| #include <vector>            // for std::vector | ||||
|  | ||||
| /** \addtogroup Core | ||||
|  * \{ */ | ||||
| @@ -51,7 +51,7 @@ class osnma_msg_receiver; | ||||
|  | ||||
| using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>; | ||||
|  | ||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath); | ||||
| osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, bool strict_mode = false); | ||||
|  | ||||
| /*! | ||||
|  * \brief GNU Radio block that receives asynchronous OSNMA messages | ||||
| @@ -66,8 +66,8 @@ public: | ||||
|     std::unique_ptr<Gnss_Crypto> d_crypto;          // access to cryptographic functions | ||||
|     void msg_handler_osnma(const pmt::pmt_t& msg);  // GnssCrypto and the message handler are needed by public method within TestVectors fixture | ||||
| private: | ||||
|     friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath); | ||||
|     osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath); | ||||
|     friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath, bool strict_mode); | ||||
|     osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath, bool strict_mode); | ||||
|  | ||||
|     void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg); | ||||
|     void read_nma_header(uint8_t nma_header); | ||||
| @@ -103,6 +103,7 @@ private: | ||||
|     std::map<uint32_t, std::vector<uint8_t>> d_tesla_keys;                       // tesla keys over time, sorted by TOW | ||||
|     std::multimap<uint32_t, Tag> d_tags_awaiting_verify;                         // container with tags to verify from arbitrary SVIDs, sorted by TOW | ||||
|  | ||||
|     std::vector<uint8_t> d_new_public_key; | ||||
|     std::vector<uint8_t> d_tags_to_verify{0, 4, 12}; | ||||
|     std::vector<MACK_message> d_macks_awaiting_MACSEQ_verification; | ||||
|  | ||||
| @@ -125,30 +126,28 @@ private: | ||||
|     uint32_t d_GST_SIS{};                 // GST coming from W6 and W5 of SIS | ||||
|     uint32_t d_GST_PKR_PKREV_start{}; | ||||
|     uint32_t d_GST_PKR_AM_start{}; | ||||
|     uint32_t d_WN{}; | ||||
|     uint32_t d_TOW{}; | ||||
|  | ||||
|     uint8_t const d_T_L{30};        // s RG Section 2.1 | ||||
|  | ||||
|     bool d_new_data{false}; | ||||
|     bool d_public_key_verified{false}; | ||||
|     bool d_kroot_verified{false}; | ||||
|     bool d_tesla_key_verified{false}; | ||||
|     bool d_flag_debug{true}; | ||||
|     bool d_flag_hot_start{false}; | ||||
|     bool d_flag_PK_renewal{false}; | ||||
|     bool d_flag_PK_revocation{false}; | ||||
|     uint8_t d_new_public_key_id{}; | ||||
|     std::vector<uint8_t> d_new_public_key; | ||||
|     bool d_flag_NPK_set{false}; | ||||
|     bool d_flag_alert_message{false}; | ||||
|  | ||||
|     // Provide access to inner functions to Gtest | ||||
|     uint32_t d_count_successful_tags{0}; | ||||
|     uint32_t d_count_failed_tags{0}; | ||||
|     uint32_t d_count_failed_Kroot{0}; | ||||
|     uint32_t d_count_failed_pubKey{0};  // failed public key verifications against Merkle root | ||||
|     uint32_t d_count_failed_macseq{0}; | ||||
|  | ||||
|     uint8_t const d_T_L{30};  // s RG Section 2.1 | ||||
|     uint8_t d_new_public_key_id{}; | ||||
|  | ||||
|     bool d_new_data{false}; | ||||
|     bool d_public_key_verified{false}; | ||||
|     bool d_kroot_verified{false}; | ||||
|     bool d_tesla_key_verified{false}; | ||||
|     bool d_strict_mode{false}; | ||||
|     bool d_flag_hot_start{false}; | ||||
|     bool d_flag_PK_renewal{false}; | ||||
|     bool d_flag_PK_revocation{false}; | ||||
|     bool d_flag_NPK_set{false}; | ||||
|     bool d_flag_alert_message{false}; | ||||
|  | ||||
|     // Provide access to inner functions to Gtest | ||||
|     FRIEND_TEST(OsnmaMsgReceiverTest, TeslaKeyVerification); | ||||
|     FRIEND_TEST(OsnmaMsgReceiverTest, TagVerification); | ||||
|     FRIEND_TEST(OsnmaMsgReceiverTest, BuildTagMessageM0); | ||||
|   | ||||
| @@ -126,7 +126,13 @@ void GNSSFlowgraph::init() | ||||
|             enable_osnma_rx_ = true; | ||||
|             const auto certFilePath = configuration_->property("GNSS-SDR.osnma_public_key", CRTFILE_DEFAULT); | ||||
|             const auto merKleTreePath = configuration_->property("GNSS-SDR.osnma_merkletree", MERKLEFILE_DEFAULT); | ||||
|             osnma_rx_ = osnma_msg_receiver_make(certFilePath, merKleTreePath); | ||||
|             std::string osnma_mode = configuration_->property("GNSS-SDR.osnma_mode", std::string("")); | ||||
|             bool strict_mode = false; | ||||
|             if (osnma_mode == "strict") | ||||
|                 { | ||||
|                     strict_mode = true; | ||||
|                 } | ||||
|             osnma_rx_ = osnma_msg_receiver_make(certFilePath, merKleTreePath, strict_mode); | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|   | ||||
| @@ -16,15 +16,26 @@ | ||||
|  | ||||
| #include "osnma_helper.h" | ||||
| #include <bitset> | ||||
| #include <chrono> | ||||
| #include <iomanip> | ||||
| #include <ios> | ||||
| #include <sstream> | ||||
| #include <ctime>  // timezone | ||||
|  | ||||
| uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const{ | ||||
|  | ||||
| Osnma_Helper::Osnma_Helper() | ||||
| { | ||||
|     GST_START_EPOCH.tm_mday = 22; | ||||
|     GST_START_EPOCH.tm_mon = 7;  // August (0-based) | ||||
|     GST_START_EPOCH.tm_year = 1999 - 1900; | ||||
| } | ||||
|  | ||||
|  | ||||
| uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const | ||||
| { | ||||
|     return (WN & 0x00000FFF) << 20 | (TOW & 0x000FFFFF); | ||||
| } | ||||
|  | ||||
|  | ||||
| uint32_t Osnma_Helper::compute_gst(tm& input) | ||||
| { | ||||
|     auto epoch_time_point = std::chrono::system_clock::from_time_t(mktime(&GST_START_EPOCH)); | ||||
| @@ -34,23 +45,28 @@ uint32_t Osnma_Helper::compute_gst(tm& input) | ||||
|     auto duration_sec = std::chrono::duration_cast<std::chrono::seconds>(input_time_point - epoch_time_point); | ||||
|  | ||||
|     // Calculate the week number (WN) and time of week (TOW) | ||||
|     uint32_t sec_in_week = 7 * 24 * 60 * 60; | ||||
|     uint32_t week_number = duration_sec.count() / sec_in_week; | ||||
|     uint32_t time_of_week = duration_sec.count() % sec_in_week; | ||||
|     const uint32_t sec_in_week = 604800; | ||||
|     const uint32_t week_number = duration_sec.count() / sec_in_week; | ||||
|     const uint32_t time_of_week = duration_sec.count() % sec_in_week; | ||||
|     return compute_gst(week_number, time_of_week); | ||||
| } | ||||
|  | ||||
|  | ||||
| uint32_t Osnma_Helper::compute_gst_now() | ||||
| { | ||||
|     std::chrono::time_point epoch_time_point = std::chrono::system_clock::from_time_t(mktime(&GST_START_EPOCH) - timezone); | ||||
| //    auto time_utc = std::chrono::time_point_cast<std::chrono::seconds>(time).time_since_epoch(); | ||||
|     time_t now = time(nullptr); | ||||
|     struct tm local_tm = *std::localtime(&now); | ||||
|     struct tm utc_tm = *std::gmtime(&now); | ||||
|     auto timezone_offset = std::mktime(&utc_tm) - std::mktime(&local_tm); | ||||
|     auto epoch_time_point = std::chrono::system_clock::from_time_t(std::mktime(&GST_START_EPOCH) - timezone_offset) + std::chrono::seconds(13); | ||||
|     auto duration_sec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - epoch_time_point); | ||||
|     uint32_t sec_in_week = 7 * 24 * 60 * 60; | ||||
|     uint32_t week_number = duration_sec.count() / sec_in_week; | ||||
|     uint32_t time_of_week = duration_sec.count() % sec_in_week; | ||||
|     const uint32_t sec_in_week = 604800; | ||||
|     const uint32_t week_number = duration_sec.count() / sec_in_week; | ||||
|     const uint32_t time_of_week = duration_sec.count() % sec_in_week; | ||||
|     return compute_gst(week_number, time_of_week); | ||||
| } | ||||
|  | ||||
|  | ||||
| std::vector<uint8_t> Osnma_Helper::gst_to_uint8(uint32_t GST) const | ||||
| { | ||||
|     std::vector<uint8_t> res; | ||||
| @@ -145,12 +161,15 @@ std::vector<uint8_t> Osnma_Helper::convert_from_hex_string(const std::string& he | ||||
|  | ||||
|     return result; | ||||
| } | ||||
| uint32_t Osnma_Helper::get_WN(uint32_t GST) | ||||
|  | ||||
|  | ||||
| uint32_t Osnma_Helper::get_WN(uint32_t GST) const | ||||
| { | ||||
|     return (GST & 0xFFF00000) >> 20; | ||||
| } | ||||
| uint32_t Osnma_Helper::get_TOW(uint32_t GST) | ||||
|  | ||||
|  | ||||
| uint32_t Osnma_Helper::get_TOW(uint32_t GST) const | ||||
| { | ||||
|     return GST & 0x000FFFFF; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -18,27 +18,34 @@ | ||||
| #define GNSS_SDR_OSNMA_HELPER_H | ||||
|  | ||||
|  | ||||
| #include <chrono> | ||||
| #include <cstdint> | ||||
| #include <ctime> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| /** \addtogroup Core | ||||
|  * \{ */ | ||||
| /** \addtogroup System_Parameters | ||||
|  * \{ */ | ||||
|  | ||||
| class Osnma_Helper | ||||
| { | ||||
| public: | ||||
|     Osnma_Helper() = default; | ||||
|     Osnma_Helper(); | ||||
|     ~Osnma_Helper() = default; | ||||
|     uint32_t compute_gst(uint32_t WN, uint32_t TOW) const; | ||||
|     uint32_t compute_gst(std::tm& input); | ||||
|     uint32_t compute_gst_now(); | ||||
|     uint32_t get_WN(uint32_t GST); | ||||
|     uint32_t get_TOW(uint32_t GST); | ||||
|     uint32_t get_WN(uint32_t GST) const; | ||||
|     uint32_t get_TOW(uint32_t GST) const; | ||||
|     std::vector<uint8_t> gst_to_uint8(uint32_t GST) const; | ||||
|     std::vector<uint8_t> bytes(const std::string& binaryString) const; | ||||
|     std::string verification_status_str(int status) const; | ||||
|     std::string convert_to_hex_string(const std::vector<uint8_t>& vector) const; | ||||
|     std::vector<uint8_t> convert_from_hex_string(const std::string& hex_string) const;  // TODO remove similar function in gnss_crypto | ||||
|  | ||||
|     std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0, 0, 0, 0, 0}; | ||||
|     std::tm GST_START_EPOCH{}; | ||||
| }; | ||||
|  | ||||
| /** \} */ | ||||
| /** \} */ | ||||
| #endif  // GNSS_SDR_OSNMA_HELPER_H | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez