1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-12 11:10:33 +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:
Carles Fernandez 2024-08-03 19:58:34 +02:00 committed by GitHub
parent 6beb92278f
commit 3457b8ed3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 110 additions and 73 deletions

View File

@ -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",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0))
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)),
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);

View File

@ -28,16 +28,16 @@
#include "gnss_sdr_make_unique.h" // for std::make:unique in C++11
#include "osnma_data.h" // for OSNMA_data structures
#include "osnma_nav_data_manager.h"
#include <gnuradio/block.h> // for gr::block
#include <pmt/pmt.h> // for pmt::pmt_t
#include <array> // for std::array
#include <cstdint> // for uint8_t
#include <ctime> // for std::time_t
#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 <gnuradio/block.h> // for gr::block
#include <pmt/pmt.h> // for pmt::pmt_t
#include <array> // for std::array
#include <cstdint> // for uint8_t
#include <ctime> // for std::time_t
#include <map> // for std::map, std::multimap
#include <memory> // for std::shared_ptr
#include <string> // for std::string
#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;
@ -111,8 +112,8 @@ private:
std::array<uint16_t, 16> d_number_of_blocks{};
std::array<uint8_t, 60> d_mack_message{}; // C: 480 b
std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader; // osnma parameters parser
std::unique_ptr<Osnma_Helper> d_helper; // helper class with auxiliary functions
std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader; // osnma parameters parser
std::unique_ptr<Osnma_Helper> d_helper; // helper class with auxiliary functions
std::unique_ptr<OSNMA_nav_data_Manager> d_nav_data_manager; // refactor for holding and processing navigation data
OSNMA_data d_osnma_data{};
@ -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);

View File

@ -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
{

View File

@ -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;
}

View File

@ -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