1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-02-07 14:40:12 +00:00

Code cleaning

This commit is contained in:
Carles Fernandez 2024-07-23 11:16:45 +02:00
parent 6c9f999583
commit 39f94dcbe6
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
10 changed files with 360 additions and 482 deletions

View File

@ -369,6 +369,8 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
// 1. De-interleave // 1. De-interleave
std::vector<float> page_part_symbols_soft_value(frame_length); std::vector<float> page_part_symbols_soft_value(frame_length);
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_soft_value.data()); deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_soft_value.data());
bool flag_osnma_adkd_4_gst = false;
bool flag_osnma_adkd_4_utc = false;
// 2. Viterbi decoder // 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
@ -441,33 +443,31 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
// 4. Push the new navigation data to the queues // 4. Push the new navigation data to the queues
// extract OSNMA bits, reset container. // extract OSNMA bits, reset container.
bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549; bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549;
if(check_size_is_ok) if (check_size_is_ok)
{ {
std::cout << "Galileo OSNMA: new ADKD=0/12 navData from " << d_satellite << " at TOW_sf=" << d_inav_nav.get_TOW5() - 25 <<std::endl; DLOG(INFO) << "Galileo OSNMA: new ADKD=0/12 navData from " << d_satellite << " at TOW_sf=" << d_inav_nav.get_TOW5() - 25;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
d_satellite.get_PRN(), d_satellite.get_PRN(),
d_inav_nav.get_osnma_adkd_0_12_nav_bits(), d_inav_nav.get_osnma_adkd_0_12_nav_bits(),
d_inav_nav.get_TOW5() - 25); d_inav_nav.get_TOW5() - 25);
this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma)); this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma));
LOG(INFO) << "|---> Galileo OSNMA :: Sending Telemetry Decoder NavData (PRN_d="<< static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW5() - 25) <<")";//: 0b" << d_inav_nav.get_osnma_adkd_0_12_nav_bits(); DLOG(INFO) << "|---> Galileo OSNMA :: Sending Telemetry Decoder NavData (PRN_d=" << static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW5() - 25) << ")"; //: 0b" << d_inav_nav.get_osnma_adkd_0_12_nav_bits();
d_inav_nav.reset_osnma_nav_bits_adkd0_12(); d_inav_nav.reset_osnma_nav_bits_adkd0_12();
} }
check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141;
if(check_size_is_ok) if (check_size_is_ok)
{ {
std::cout << "Galileo OSNMA: new ADKD=4 navData from " << d_satellite <<" at TOW_sf=" << d_inav_nav.get_TOW6() - 5 <<std::endl; DLOG(INFO) << "Galileo OSNMA: new ADKD=4 navData from " << d_satellite << " at TOW_sf=" << d_inav_nav.get_TOW6() - 5;
const auto tmp_obj = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> // TODO conversion from W6 to W_Start_of_subframe
const auto tmp_obj = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> // TODO conversion from W6 to W_Start_of_subframe
d_satellite.get_PRN(), d_satellite.get_PRN(),
d_inav_nav.get_osnma_adkd_4_nav_bits(), d_inav_nav.get_osnma_adkd_4_nav_bits(),
d_inav_nav.get_TOW6() - 5); d_inav_nav.get_TOW6() - 5);
this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj)); this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj));
LOG(INFO) << "|---> Galileo OSNMA :: Sending Telemetry Decoder NavData (PRN_d="<< static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW6() - 5) <<")";//: 0b" << d_inav_nav.get_osnma_adkd_4_nav_bits(); DLOG(INFO) << "|---> Galileo OSNMA :: Sending Telemetry Decoder NavData (PRN_d=" << static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW6() - 5) << ")"; //: 0b" << d_inav_nav.get_osnma_adkd_4_nav_bits();
d_inav_nav.reset_osnma_nav_bits_adkd4(); d_inav_nav.reset_osnma_nav_bits_adkd4();
} }
if (d_inav_nav.have_new_ephemeris() == true) // C: tells if W1-->W4 available from same blcok (and W5!) if (d_inav_nav.have_new_ephemeris() == true) // C: tells if W1-->W4 available from same blcok (and W5!)
{ {
// get object for this SV (mandatory) // get object for this SV (mandatory)
@ -499,8 +499,6 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
} }
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj)); this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
d_first_eph_sent = true; // do not send reduced CED anymore, since we have the full ephemeris set d_first_eph_sent = true; // do not send reduced CED anymore, since we have the full ephemeris set
// d_flag_osnma_adkd_0_12 = true; // W1-> W5 available
} }
else else
{ {
@ -586,7 +584,7 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
d_delta_t = tmp_obj->A_0G + tmp_obj->A_1G * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - tmp_obj->t_0G + 604800 * (std::fmod(static_cast<float>(d_inav_nav.get_Galileo_week() - tmp_obj->WN_0G), 64.0))); d_delta_t = tmp_obj->A_0G + tmp_obj->A_1G * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - tmp_obj->t_0G + 604800 * (std::fmod(static_cast<float>(d_inav_nav.get_Galileo_week() - tmp_obj->WN_0G), 64.0)));
DLOG(INFO) << "delta_t=" << d_delta_t << "[s]"; DLOG(INFO) << "delta_t=" << d_delta_t << "[s]";
d_flag_osnma_adkd_4_utc = true; flag_osnma_adkd_4_utc = true;
} }
if (d_inav_nav.have_new_almanac() == true) // flag_almanac_4 tells if W10 available. if (d_inav_nav.have_new_almanac() == true) // flag_almanac_4 tells if W10 available.
@ -621,11 +619,11 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
DLOG(INFO) << "d_TOW_at_current_symbol_ms=" << d_TOW_at_current_symbol_ms; DLOG(INFO) << "d_TOW_at_current_symbol_ms=" << d_TOW_at_current_symbol_ms;
DLOG(INFO) << "d_nav.WN_0=" << d_inav_nav.get_Galileo_week(); DLOG(INFO) << "d_nav.WN_0=" << d_inav_nav.get_Galileo_week();
d_flag_osnma_adkd_4_gst = true; flag_osnma_adkd_4_gst = true;
} }
// get osnma message if the needed nav data is available // get osnma message if the needed nav data is available
bool adkd_4_nav_data_available = d_flag_osnma_adkd_4_utc && d_flag_osnma_adkd_4_gst; // supposition: data did not change bt. flags reset and now. bool adkd_4_nav_data_available = flag_osnma_adkd_4_utc && flag_osnma_adkd_4_gst; // supposition: data did not change bt. flags reset and now.
// bool adkd_4_nav_data_available = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; // newApproach: let decoder decide when block starts and let it fill the data, and just check for length // bool adkd_4_nav_data_available = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; // newApproach: let decoder decide when block starts and let it fill the data, and just check for length
if(adkd_4_nav_data_available /*&& d_inav_nav.is_TOW5_set() not needed cause W6 has TOW also.*/) if(adkd_4_nav_data_available /*&& d_inav_nav.is_TOW5_set() not needed cause W6 has TOW also.*/)

View File

@ -155,9 +155,6 @@ private:
bool d_there_are_e1_channels; bool d_there_are_e1_channels;
bool d_there_are_e6_channels; bool d_there_are_e6_channels;
bool d_use_ced; bool d_use_ced;
bool d_flag_osnma_adkd_0_12; // flag to indicate if the ephemeris is complete for OSNMA processing
bool d_flag_osnma_adkd_4_gst; // flag to indicate if the GST conversion parameters are complete for OSNMA processing
bool d_flag_osnma_adkd_4_utc; // flag to indicate if the iono correction and time is complete for OSNMA processing
}; };

View File

@ -25,13 +25,15 @@
#include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader #include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader
#include "osnma_helper.h" #include "osnma_helper.h"
#include <gnuradio/io_signature.h> // for gr::io_signature::make #include <gnuradio/io_signature.h> // for gr::io_signature::make
#include <algorithm>
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
#include <iomanip> // for std::setfill #include <iomanip> // for std::setfill
#include <ios> // for std::hex, std::uppercase #include <ios> // for std::hex, std::uppercase
#include <iostream> #include <iostream>
#include <numeric> // for std::accumulate #include <numeric> // for std::accumulate
#include <sstream> // std::stringstream #include <sstream> // std::stringstream
#include <tuple>
#include <typeinfo> // for typeid #include <typeinfo> // for typeid
#include <utility> #include <utility>
@ -104,12 +106,12 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
std::ostringstream output_message; std::ostringstream output_message;
output_message << "Galileo OSNMA: data received starting at " output_message << "Galileo OSNMA: data received starting at "
<< "WN=" << "WN="
<< nma_msg->WN_sf0 << nma_msg->WN_sf0
<< ", TOW=" << ", TOW="
<< nma_msg->TOW_sf0 << nma_msg->TOW_sf0
<< ", from satellite " << ", from satellite "
<< sat; << sat;
LOG(INFO) << output_message.str(); LOG(INFO) << output_message.str();
std::cout << output_message.str() << std::endl; std::cout << output_message.str() << std::endl;
@ -126,15 +128,15 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
// iono data => 549 bits, utc data, 141 bits. // iono data => 549 bits, utc data, 141 bits.
if (nav_data.size() == 549) if (nav_data.size() == 549)
{ {
// LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " // LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 OSNMA_NavData, PRN_d (" << PRNa << ") "
// << "TOW_sf=" << TOW; // << "TOW_sf=" << TOW;
d_satellite_nav_data[PRNa][TOW].ephemeris_iono_vector_2 = nav_data; d_satellite_nav_data[PRNa][TOW].set_ephemeris_iono_data(nav_data);
} }
else if (nav_data.size() == 141) else if (nav_data.size() == 141)
{ {
// LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") " // LOG(INFO) << "Galileo OSNMA: received ADKD=4 OSNMA_NavData, PRN_d (" << PRNa << ") "
// << "TOW_sf=" << TOW; // << "TOW_sf=" << TOW;
d_satellite_nav_data[PRNa][TOW].utc_vector_2 = nav_data; d_satellite_nav_data[PRNa][TOW].set_utc_data(nav_data);
} }
else else
{ {
@ -488,11 +490,11 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
<< ", WN=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.wn_k) << ", WN=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.wn_k)
<< ", TOW=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.towh_k) * 3600; << ", TOW=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.towh_k) * 3600;
local_time_verification(osnma_msg); local_time_verification(osnma_msg);
if(l_ds_bits == 512) if (l_ds_bits == 512)
{ {
d_kroot_verified = d_crypto->verify_signature_ecdsa_p256(message, d_osnma_data.d_dsm_kroot_message.ds); d_kroot_verified = d_crypto->verify_signature_ecdsa_p256(message, d_osnma_data.d_dsm_kroot_message.ds);
} }
else if(l_ds_bits == 1056) else if (l_ds_bits == 1056)
{ {
d_kroot_verified = d_crypto->verify_signature_ecdsa_p521(message, d_osnma_data.d_dsm_kroot_message.ds); d_kroot_verified = d_crypto->verify_signature_ecdsa_p521(message, d_osnma_data.d_dsm_kroot_message.ds);
} }
@ -614,11 +616,11 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptr<OSNMA
index = index + 4; index = index + 4;
} }
// update the structure with newly coming NavData // update the structure with newly coming OSNMA_NavData
d_osnma_data.d_nav_data.init(osnma_msg); d_osnma_data.d_nav_data.init(osnma_msg);
if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10 if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10
{// TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future { // TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future
read_mack_header(); read_mack_header();
d_osnma_data.d_mack_message.PRNa = osnma_msg->PRN; // FIXME this is ugly. d_osnma_data.d_mack_message.PRNa = osnma_msg->PRN; // FIXME this is ugly.
d_osnma_data.d_mack_message.TOW = osnma_msg->TOW_sf0; d_osnma_data.d_mack_message.TOW = osnma_msg->TOW_sf0;
@ -626,7 +628,7 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptr<OSNMA
read_mack_body(); read_mack_body();
process_mack_message(); process_mack_message();
// TODO - shorten the MACK processing for the cases where no TK verified or no Kroot verified (warm and cold start) // TODO - shorten the MACK processing for the cases where no TK verified or no Kroot verified (warm and cold start)
// still, for instance the NAvData and Mack storage (within process_mack_message) makes sense. // still, for instance the OSNMA_NavData and Mack storage (within process_mack_message) makes sense.
} }
} }
@ -651,7 +653,7 @@ void osnma_msg_receiver::read_mack_header()
} }
if (lt_bits == 0) if (lt_bits == 0)
{ {
return; // C: TODO if Tag length is 0, what is the action? no verification possible of NavData for sure. return; // C: TODO if Tag length is 0, what is the action? no verification possible of OSNMA_NavData for sure.
} }
uint16_t macseq = 0; uint16_t macseq = 0;
uint8_t cop = 0; uint8_t cop = 0;
@ -869,7 +871,7 @@ void osnma_msg_receiver::read_mack_body()
} }
} }
d_osnma_data.d_mack_message.tag_and_info[k].tag = tag; d_osnma_data.d_mack_message.tag_and_info[k].tag = tag;
d_osnma_data.d_mack_message.tag_and_info[k].counter = k + 2; // CTR==1 for Tag0, increases subsequently for all other tags. d_osnma_data.d_mack_message.tag_and_info[k].counter = k + 2; // CTR==1 for Tag0, increases subsequently for all other tags.
d_osnma_data.d_mack_message.tag_and_info[k].tag_info.PRN_d = PRN_d; d_osnma_data.d_mack_message.tag_and_info[k].tag_info.PRN_d = PRN_d;
d_osnma_data.d_mack_message.tag_and_info[k].tag_info.ADKD = ADKD; d_osnma_data.d_mack_message.tag_and_info[k].tag_info.ADKD = ADKD;
d_osnma_data.d_mack_message.tag_and_info[k].tag_info.cop = cop; d_osnma_data.d_mack_message.tag_and_info[k].tag_info.cop = cop;
@ -882,13 +884,13 @@ void osnma_msg_receiver::read_mack_body()
* @brief Verifies the tags transmitted in the past. * @brief Verifies the tags transmitted in the past.
* *
* \details This function is responsible for processing the MACK message received (480 bits) at time SF(i). * \details This function is responsible for processing the MACK message received (480 bits) at time SF(i).
* It stores the last 10 MACK messages and the last 11 NavData messages. * It stores the last 10 MACK messages and the last 11 OSNMA_NavData messages.
* Then attempts to verify the Tesla Key by computing the number of hashes of distance between the key-to-verify and the * Then attempts to verify the Tesla Key by computing the number of hashes of distance between the key-to-verify and the
* Kroot and iteratively hashing the result, until the required number of hashes is achieved. * Kroot and iteratively hashing the result, until the required number of hashes is achieved.
* The result is then compared with the Kroot. If the two values match, the Tesla key is verified. * The result is then compared with the Kroot. If the two values match, the Tesla key is verified.
* It also performs MACSEQ validation and compares the ADKD of Mack tags with MACLT defined ADKDs. * It also performs MACSEQ validation and compares the ADKD of Mack tags with MACLT defined ADKDs.
* Finally, it verifies the tags. * Finally, it verifies the tags.
* \pre Kroot or already a TESLA key shall be available. Depending on the ADKD of the tag, NavData of SF(i-2)...SF(i-11) * \pre Kroot or already a TESLA key shall be available. Depending on the ADKD of the tag, OSNMA_NavData of SF(i-2)...SF(i-11)
* \post Number of tags bits verified for each ADKD. MACSEQ verification success * \post Number of tags bits verified for each ADKD. MACSEQ verification success
* @param osnma_msg A reference to OSNMA_msg containing the MACK message to be processed. * @param osnma_msg A reference to OSNMA_msg containing the MACK message to be processed.
*/ */
@ -908,12 +910,12 @@ void osnma_msg_receiver::process_mack_message()
} }
} }
// verify tesla key and add it to the container of verified keys if successful // verify tesla key and add it to the container of verified keys if successful
if (d_tesla_keys.find(d_osnma_data.d_nav_data.TOW_sf0) == d_tesla_keys.end()) // check if already available => no need to verify if (d_tesla_keys.find(d_osnma_data.d_nav_data.get_tow_sf0()) == d_tesla_keys.end()) // check if already available => no need to verify
{ {
bool retV = verify_tesla_key(d_osnma_data.d_mack_message.key, d_osnma_data.d_nav_data.TOW_sf0); bool retV = verify_tesla_key(d_osnma_data.d_mack_message.key, d_osnma_data.d_nav_data.get_tow_sf0());
if (retV) if (retV)
{ {
d_tesla_keys.insert(std::pair<uint32_t, std::vector<uint8_t>>(d_osnma_data.d_nav_data.TOW_sf0, d_osnma_data.d_mack_message.key)); d_tesla_keys.insert(std::pair<uint32_t, std::vector<uint8_t>>(d_osnma_data.d_nav_data.get_tow_sf0(), d_osnma_data.d_mack_message.key));
} }
} }
@ -924,11 +926,11 @@ void osnma_msg_receiver::process_mack_message()
if (d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end()) if (d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end())
{ {
// add tag0 first // add tag0 first
Tag tag0 (*mack); Tag tag0(*mack);
d_tags_awaiting_verify.insert(std::pair<uint32_t, Tag>(mack->TOW, tag0)); d_tags_awaiting_verify.insert(std::pair<uint32_t, Tag>(mack->TOW, tag0));
// bool ret = verify_macseq(*mack); // bool ret = verify_macseq(*mack);
std::vector<MACK_tag_and_info> macseq_verified_tags = verify_macseq_new(*mack); std::vector<MACK_tag_and_info> macseq_verified_tags = verify_macseq_new(*mack);
for (auto & tag_and_info : macseq_verified_tags) for (auto& tag_and_info : macseq_verified_tags)
{ {
// add tags of current mack to the verification queue // add tags of current mack to the verification queue
Tag t(tag_and_info, mack->TOW, mack->WN, mack->PRNa, tag_and_info.counter); Tag t(tag_and_info, mack->TOW, mack->WN, mack->PRNa, tag_and_info.counter);
@ -948,7 +950,6 @@ void osnma_msg_receiver::process_mack_message()
} }
LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size(); LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size();
mack = d_macks_awaiting_MACSEQ_verification.erase(mack); mack = d_macks_awaiting_MACSEQ_verification.erase(mack);
} }
else else
{ {
@ -969,7 +970,7 @@ void osnma_msg_receiver::process_mack_message()
/* TODO - take into account: /* TODO - take into account:
* - COP: if * - COP: if
* - ADKD type * - ADKD type
* - NavData the tag verifies (min. number of bits verified to consider NavData OK) * - OSNMA_NavData the tag verifies (min. number of bits verified to consider OSNMA_NavData OK)
* */ * */
if (ret) if (ret)
{ {
@ -1020,7 +1021,7 @@ void osnma_msg_receiver::process_mack_message()
<< static_cast<unsigned>(it.second.PRN_d) << std::endl; << static_cast<unsigned>(it.second.PRN_d) << std::endl;
} }
} }
else if (it.second.TOW > d_osnma_data.d_nav_data.TOW_sf0) else if (it.second.TOW > d_osnma_data.d_nav_data.get_tow_sf0())
{ {
// TODO - I dont understand logic. This needs to be reviewed. // TODO - I dont understand logic. This needs to be reviewed.
// case 1: adkd=12 and t.Tow + 300 < current TOW // case 1: adkd=12 and t.Tow + 300 < current TOW
@ -1059,7 +1060,7 @@ void osnma_msg_receiver::process_mack_message()
*/ */
bool osnma_msg_receiver::verify_dsm_pkr(const DSM_PKR_message& message) const bool osnma_msg_receiver::verify_dsm_pkr(const DSM_PKR_message& message) const
{ {
const auto base_leaf = get_merkle_tree_leaves(message); // m_i const auto base_leaf = get_merkle_tree_leaves(message); // m_i
const auto computed_merkle_root = compute_merkle_root(message, base_leaf); // x_4_0 const auto computed_merkle_root = compute_merkle_root(message, base_leaf); // x_4_0
const auto msg_id = static_cast<int>(message.mid); const auto msg_id = static_cast<int>(message.mid);
LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: leaf provided for Message ID " << msg_id; LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: leaf provided for Message ID " << msg_id;
@ -1110,7 +1111,7 @@ std::vector<uint8_t> osnma_msg_receiver::compute_merkle_root(const DSM_PKR_messa
std::vector<uint8_t> osnma_msg_receiver::get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const std::vector<uint8_t> osnma_msg_receiver::get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const
{ {
// build base leaf m_i according to OSNMA SIS ICD v1.1, section 6.2 DSM-PKR Verification // build base leaf m_i according to OSNMA SIS ICD v1.1, section 6.2 DSM-PKR Verification
std::vector<uint8_t> m_i; std::vector<uint8_t> m_i;
const size_t size_npk = dsm_pkr_message.npk.size(); const size_t size_npk = dsm_pkr_message.npk.size();
m_i.reserve(1 + size_npk); m_i.reserve(1 + size_npk);
@ -1138,7 +1139,7 @@ bool osnma_msg_receiver::verify_tag(const Tag& tag) const
if (tag.ADKD == 0 || tag.ADKD == 4) if (tag.ADKD == 0 || tag.ADKD == 4)
{ {
const auto it = d_tesla_keys.find(tag.TOW + 30); const auto it = d_tesla_keys.find(tag.TOW + 30);
if(it != d_tesla_keys.cend()) if (it != d_tesla_keys.cend())
{ {
applicable_key = it->second; applicable_key = it->second;
} }
@ -1151,7 +1152,7 @@ bool osnma_msg_receiver::verify_tag(const Tag& tag) const
else // ADKD 12 else // ADKD 12
{ {
const auto it = d_tesla_keys.find(tag.TOW + 330); const auto it = d_tesla_keys.find(tag.TOW + 330);
if(it != d_tesla_keys.cend()) if (it != d_tesla_keys.cend())
{ {
applicable_key = it->second; applicable_key = it->second;
} }
@ -1212,26 +1213,6 @@ bool osnma_msg_receiver::verify_tag(const Tag& tag) const
// Compare computed tag with received one truncated // Compare computed tag with received one truncated
if (tag.received_tag == computed_mac) if (tag.received_tag == computed_mac)
{ {
LOG(INFO) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id="
<< tag.tag_id
<< ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase
<< tag.received_tag << std::dec
<< ", TOW="
<< tag.TOW
<< ", ADKD="
<< static_cast<unsigned>(tag.ADKD)
<< ", PRNa="
<< static_cast<unsigned>(tag.PRNa)
<< ", PRNd="
<< static_cast<unsigned>(tag.PRN_d);
std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id="
<< tag.tag_id
<< ", ADKD="
<< static_cast<unsigned>(tag.ADKD)
<< ", PRNa="
<< static_cast<unsigned>(tag.PRNa)
<< ", PRNd="
<< static_cast<unsigned>(tag.PRN_d) << std::endl;
return true; return true;
} }
return false; return false;
@ -1267,7 +1248,7 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag) const
const auto it2 = it->second.find(tag.TOW - 30); const auto it2 = it->second.find(tag.TOW - 30);
if (it2 != it->second.cend()) if (it2 != it->second.cend())
{ {
applicable_nav_data = it2->second.ephemeris_iono_vector_2; applicable_nav_data = it2->second.get_ephemeris_iono_data();
} }
} }
// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; // LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data;
@ -1280,10 +1261,10 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag) const
const auto it2 = it->second.find(tag.TOW - 30); const auto it2 = it->second.find(tag.TOW - 30);
if (it2 != it->second.cend()) if (it2 != it->second.cend())
{ {
applicable_nav_data = it2->second.utc_vector_2; applicable_nav_data = it2->second.get_utc_data();
} }
} }
// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; // LOG(INFO) << "|---> Galileo OSNMA :: applicable OSNMA_NavData (PRN_d="<< static_cast<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data;
} }
else else
{ {
@ -1292,7 +1273,7 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag) const
// convert std::string to vector<uint8_t> // convert std::string to vector<uint8_t>
applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data); applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data);
// Convert and add NavData bytes into the message, taking care of that NMAS has only 2 bits // Convert and add OSNMA_NavData bytes into the message, taking care of that NMAS has only 2 bits
for (uint8_t byte : applicable_nav_data_bytes) for (uint8_t byte : applicable_nav_data_bytes)
{ {
m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m
@ -1322,7 +1303,7 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag) const
} }
void osnma_msg_receiver::add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data) void osnma_msg_receiver::add_satellite_data(uint32_t SV_ID, uint32_t TOW, const OSNMA_NavData& data)
{ {
// control size of container // control size of container
while (d_satellite_nav_data[SV_ID].size() >= 25) while (d_satellite_nav_data[SV_ID].size() >= 25)
@ -1596,8 +1577,8 @@ bool osnma_msg_receiver::tag_has_nav_data_available(const Tag& t) const
if (prn_it != d_satellite_nav_data.end()) if (prn_it != d_satellite_nav_data.end())
{ {
// PRN was found, check if TOW exists in inner map // PRN was found, check if TOW exists in inner map
//LOG(INFO) << "Galileo OSNMA: hasData = true " << std::endl; // LOG(INFO) << "Galileo OSNMA: hasData = true " << std::endl;
std::map<uint32_t, NavData> tow_map = prn_it->second; std::map<uint32_t, OSNMA_NavData> tow_map = prn_it->second;
auto tow_it = tow_map.find(t.TOW - 30); auto tow_it = tow_map.find(t.TOW - 30);
if (tow_it != tow_map.end()) if (tow_it != tow_map.end())
{ {
@ -1612,7 +1593,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(const Tag& t) const
else else
{ {
// PRN was not found // PRN was not found
//LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl; // LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl;
return false; return false;
} }
return false; return false;
@ -1631,7 +1612,7 @@ bool osnma_msg_receiver::tag_has_key_available(const Tag& t) const
auto it = d_tesla_keys.find(t.TOW + 30); auto it = d_tesla_keys.find(t.TOW + 30);
if (it != d_tesla_keys.end()) if (it != d_tesla_keys.end())
{ {
//LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; // LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
return true; return true;
} }
} }
@ -1640,11 +1621,11 @@ bool osnma_msg_receiver::tag_has_key_available(const Tag& t) const
auto it = d_tesla_keys.find(t.TOW + 330); auto it = d_tesla_keys.find(t.TOW + 330);
if (it != d_tesla_keys.end()) if (it != d_tesla_keys.end())
{ {
//LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; // LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
return true; return true;
} }
} }
//LOG(INFO) << "Galileo OSNMA: hasKey = false "; // LOG(INFO) << "Galileo OSNMA: hasKey = false ";
return false; return false;
} }

View File

@ -77,7 +77,7 @@ private:
void read_mack_header(); void read_mack_header();
void read_mack_body(); void read_mack_body();
void process_mack_message(); void process_mack_message();
void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data); void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const OSNMA_NavData& data);
void remove_verified_tags(); void remove_verified_tags();
void control_tags_awaiting_verify_size(); void control_tags_awaiting_verify_size();
void display_data(); void display_data();
@ -95,7 +95,7 @@ private:
std::vector<uint8_t> hash_chain(uint32_t num_of_hashes_needed, const std::vector<uint8_t>& key, uint32_t GST_SFi, const uint8_t lk_bytes) const; std::vector<uint8_t> hash_chain(uint32_t num_of_hashes_needed, const std::vector<uint8_t>& key, uint32_t GST_SFi, const uint8_t lk_bytes) const;
std::vector<MACK_tag_and_info> verify_macseq_new(const MACK_message& mack); std::vector<MACK_tag_and_info> verify_macseq_new(const MACK_message& mack);
std::map<uint32_t, std::map<uint32_t, NavData>> d_satellite_nav_data; // map holding NavData sorted by SVID (first key) and TOW (second key). std::map<uint32_t, std::map<uint32_t, OSNMA_NavData>> d_satellite_nav_data; // map holding OSNMA_NavData sorted by SVID (first key) and TOW (second key).
std::map<uint32_t, std::vector<uint8_t>> d_tesla_keys; // tesla keys over time, sorted by TOW 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::multimap<uint32_t, Tag> d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW

View File

@ -185,7 +185,7 @@ void Galileo_Inav_Message::split_page(std::string page_string, int32_t flag_even
if (page_position_in_inav_subframe != 255) if (page_position_in_inav_subframe != 255)
{ {
if (page_position_in_inav_subframe == 0) if (page_position_in_inav_subframe == 0)
{ // TODO - is it redundant? receiving Word 2 already resets this { // TODO - is it redundant? receiving Word 2 already resets this
nma_position_filled = std::array<int8_t, 15>{}; nma_position_filled = std::array<int8_t, 15>{};
nma_msg.mack = std::array<uint32_t, 15>{}; nma_msg.mack = std::array<uint32_t, 15>{};
nma_msg.hkroot = std::array<uint8_t, 15>{}; nma_msg.hkroot = std::array<uint8_t, 15>{};
@ -215,6 +215,7 @@ void Galileo_Inav_Message::split_page(std::string page_string, int32_t flag_even
} }
} }
// C: tells if W1-->W4 available from same blcok // C: tells if W1-->W4 available from same blcok
bool Galileo_Inav_Message::have_new_ephemeris() // Check if we have a new ephemeris stored in the galileo navigation class bool Galileo_Inav_Message::have_new_ephemeris() // Check if we have a new ephemeris stored in the galileo navigation class
{ {
@ -349,6 +350,7 @@ bool Galileo_Inav_Message::have_new_ephemeris() // Check if we have a new ephem
return false; return false;
} }
// C: tells if W5 is available // C: tells if W5 is available
bool Galileo_Inav_Message::have_new_iono_and_GST() // Check if we have a new iono data set stored in the galileo navigation class bool Galileo_Inav_Message::have_new_iono_and_GST() // Check if we have a new iono data set stored in the galileo navigation class
{ {
@ -361,6 +363,7 @@ bool Galileo_Inav_Message::have_new_iono_and_GST() // Check if we have a new io
return false; return false;
} }
// C: tells if W6 is available // C: tells if W6 is available
bool Galileo_Inav_Message::have_new_utc_model() // Check if we have a new utc data set stored in the galileo navigation class bool Galileo_Inav_Message::have_new_utc_model() // Check if we have a new utc data set stored in the galileo navigation class
{ {
@ -373,13 +376,14 @@ bool Galileo_Inav_Message::have_new_utc_model() // Check if we have a new utc d
return false; return false;
} }
// flag_almanac_4 tells if W10 available. // flag_almanac_4 tells if W10 available.
bool Galileo_Inav_Message::have_new_almanac() // Check if we have a new almanac data set stored in the galileo navigation class bool Galileo_Inav_Message::have_new_almanac() // Check if we have a new almanac data set stored in the galileo navigation class
{ {
// if(flag_almanac_4) // if(flag_almanac_4)
// { // {
// flag_adkd_4_complete = true; // flag_adkd_4_complete = true;
// } // }
if ((flag_almanac_1 == true) and (flag_almanac_2 == true) and (flag_almanac_3 == true) and (flag_almanac_4 == true)) if ((flag_almanac_1 == true) and (flag_almanac_2 == true) and (flag_almanac_3 == true) and (flag_almanac_4 == true))
{ {
// All Almanac data have been received // All Almanac data have been received
@ -618,7 +622,7 @@ void Galileo_Inav_Message::read_page_1(const std::bitset<GALILEO_DATA_JK_BITS>&
DLOG(INFO) << "A_1= " << A_1; DLOG(INFO) << "A_1= " << A_1;
flag_ephemeris_1 = true; flag_ephemeris_1 = true;
DLOG(INFO) << "flag_tow_set" << flag_TOW_set; DLOG(INFO) << "flag_tow_set" << flag_TOW_set;
nav_bits_word_1 = data_bits.to_string().substr(6,120); nav_bits_word_1 = data_bits.to_string().substr(6, 120);
} }
@ -640,7 +644,7 @@ void Galileo_Inav_Message::read_page_2(const std::bitset<GALILEO_DATA_JK_BITS>&
DLOG(INFO) << "iDot_2= " << iDot_2; DLOG(INFO) << "iDot_2= " << iDot_2;
flag_ephemeris_2 = true; flag_ephemeris_2 = true;
DLOG(INFO) << "flag_tow_set" << flag_TOW_set; DLOG(INFO) << "flag_tow_set" << flag_TOW_set;
nav_bits_word_2 = data_bits.to_string().substr(6,120); nav_bits_word_2 = data_bits.to_string().substr(6, 120);
} }
@ -1058,7 +1062,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
flag_utc_model = true; // set to false externally flag_utc_model = true; // set to false externally
flag_TOW_set = true; // set to false externally flag_TOW_set = true; // set to false externally
DLOG(INFO) << "flag_tow_set" << flag_TOW_set; DLOG(INFO) << "flag_tow_set" << flag_TOW_set;
nav_bits_word_6 = data_jk_bits.to_string().substr(6, 99); nav_bits_word_6 = data_jk_bits.to_string().substr(6, 99);
break; break;
case 7: // Word type 7: Almanac for SVID1 (1/2), almanac reference time and almanac reference week number case 7: // Word type 7: Almanac for SVID1 (1/2), almanac reference time and almanac reference week number
@ -1417,7 +1421,7 @@ OSNMA_msg Galileo_Inav_Message::get_osnma_msg()
nma_position_filled = std::array<int8_t, 15>{}; nma_position_filled = std::array<int8_t, 15>{};
// Fill TOW and WN // Fill TOW and WN
nma_msg.WN_sf0 = WN_0; nma_msg.WN_sf0 = WN_0;
int32_t TOW_sf0 = TOW_5 - 25;//- 24; // according to OS SIS ICD, TOW of word 5 is 25 seconds after Sf start TODO review int32_t TOW_sf0 = TOW_5 - 25; //- 24; // according to OS SIS ICD, TOW of word 5 is 25 seconds after Sf start TODO review
if (TOW_sf0 < 0) if (TOW_sf0 < 0)
{ {
TOW_sf0 += 604800; TOW_sf0 += 604800;
@ -1442,17 +1446,23 @@ bool Galileo_Inav_Message::have_new_nma()
return false; return false;
} }
} }
std::string Galileo_Inav_Message::get_osnma_adkd_4_nav_bits() std::string Galileo_Inav_Message::get_osnma_adkd_4_nav_bits()
{ {
nav_bits_adkd_4 = nav_bits_word_6 + nav_bits_word_10; nav_bits_adkd_4 = nav_bits_word_6 + nav_bits_word_10;
return nav_bits_adkd_4; return nav_bits_adkd_4;
} }
std::string Galileo_Inav_Message::get_osnma_adkd_0_12_nav_bits() std::string Galileo_Inav_Message::get_osnma_adkd_0_12_nav_bits()
{ {
nav_bits_adkd_0_12 = nav_bits_word_1 + nav_bits_word_2 + nav_bits_word_3 + nav_bits_word_4 + nav_bits_word_5; nav_bits_adkd_0_12 = nav_bits_word_1 + nav_bits_word_2 + nav_bits_word_3 + nav_bits_word_4 + nav_bits_word_5;
return nav_bits_adkd_0_12; return nav_bits_adkd_0_12;
} }
void Galileo_Inav_Message::reset_osnma_nav_bits_adkd0_12() void Galileo_Inav_Message::reset_osnma_nav_bits_adkd0_12()
{ {
nav_bits_word_1 = ""; nav_bits_word_1 = "";
@ -1461,6 +1471,8 @@ void Galileo_Inav_Message::reset_osnma_nav_bits_adkd0_12()
nav_bits_word_4 = ""; nav_bits_word_4 = "";
nav_bits_word_5 = ""; nav_bits_word_5 = "";
} }
void Galileo_Inav_Message::reset_osnma_nav_bits_adkd4() void Galileo_Inav_Message::reset_osnma_nav_bits_adkd4()
{ {
nav_bits_word_6 = ""; nav_bits_word_6 = "";

View File

@ -49,17 +49,15 @@ public:
std::array<uint32_t, 15> mack{}; std::array<uint32_t, 15> mack{};
std::array<uint8_t, 15> hkroot{}; std::array<uint8_t, 15> hkroot{};
uint32_t PRN{}; uint32_t PRN{};
uint32_t WN_sf0{}; // TODO - this is present in UtcModelData already uint32_t WN_sf0{}; // TODO - this is present in UtcModelData already
uint32_t TOW_sf0{}; uint32_t TOW_sf0{};
std::vector<uint8_t> EphemerisClockAndStatusData {}; // TODO _2 rename and substitute this std::vector<uint8_t> EphemerisClockAndStatusData{}; // TODO _2 rename and substitute this
std::string EphemerisClockAndStatusData_2{}; std::string EphemerisClockAndStatusData_2{};
std::vector<uint8_t> TimingData {}; std::vector<uint8_t> TimingData{};
std::string TimingData_2{}; std::string TimingData_2{};
Galileo_Ephemeris EphemerisData {}; Galileo_Ephemeris EphemerisData{};
Galileo_Iono IonoData {}; Galileo_Iono IonoData{};
Galileo_Utc_Model UtcModelData {}; Galileo_Utc_Model UtcModelData{};
}; };
/*! /*!

View File

@ -1,172 +1,55 @@
/*! /*!
* \file osnma_data.cc * \file osnma_data.cc
* \brief Class for Galileo OSNMA data storage * \brief Class for Galileo OSNMA data storage
* \author Carles Fernandez-Prades, 2020-2023 cfernandez(at)cttc.es * \author Carles Fernandez-Prades, 2020-2023 cfernandez(at)cttc.es
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* *
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * This file is part of GNSS-SDR.
* *
* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/
#include "osnma_data.h"
#include <cstring>
#include <iostream>
/**
* @brief Constructs a NavData object with the given osnma_msg.
* \details Packs the ephemeris, iono and utc data from the current subframe into the NavData structure. It also gets the PRNa and the GST.
* @param osnma_msg The shared pointer to the OSNMA_msg object.
*/ */
#include "osnma_data.h"
uint32_t Tag::id_counter = 0; uint32_t Tag::id_counter = 0;
void NavData::init(const std::shared_ptr<OSNMA_msg> &osnma_msg)
void OSNMA_NavData::init(const std::shared_ptr<OSNMA_msg>& osnma_msg)
{ {
EphemerisData = osnma_msg->EphemerisData; d_TOW_sf0 = osnma_msg->TOW_sf0;
IonoData = osnma_msg->IonoData;
UtcData = osnma_msg->UtcModelData;
generate_eph_iono_vector();
generate_utc_vector();
PRNa = osnma_msg->PRN;
WN_sf0 = osnma_msg->WN_sf0;
TOW_sf0 = osnma_msg->TOW_sf0;
// new parsing, directly parsing bits
// ephemeris_iono_vector_2 = osnma_msg->EphemerisClockAndStatusData_2;
// utc_vector_2 = osnma_msg->TimingData_2;
};
void NavData::generate_eph_iono_vector()
{
ephemeris_iono_vector.clear();
uint64_t bit_buffer = 0; // variable to store the bits to be extracted, it can contain bits from different variables
int bit_count = 0; // Number of bits in the buffer, i.e. to be extracted
// create structure to hold the variables to store into the vector along with their bit size
std::vector<std::pair<void*, int>> variables = {
// data from word type 1
{static_cast<void*>(&EphemerisData.IOD_nav), sizeof(EphemerisData.IOD_nav) * 8},
{static_cast<void*>(&EphemerisData.toe), sizeof(EphemerisData.toe) * 8},
{static_cast<void*>(&EphemerisData.M_0), sizeof(EphemerisData.M_0) * 8},
{static_cast<void*>(&EphemerisData.ecc), sizeof(EphemerisData.ecc) * 8},
{static_cast<void*>(&EphemerisData.sqrtA), sizeof(EphemerisData.sqrtA) * 8},
// data from word type 2
{static_cast<void*>(&EphemerisData.IOD_nav), sizeof(EphemerisData.IOD_nav) * 8},
{static_cast<void*>(&EphemerisData.OMEGA_0), sizeof(EphemerisData.OMEGA_0) * 8},
{static_cast<void*>(&EphemerisData.i_0), sizeof(EphemerisData.i_0) * 8},
{static_cast<void*>(&EphemerisData.omega), sizeof(EphemerisData.omega) * 8},
{static_cast<void*>(&EphemerisData.idot), sizeof(EphemerisData.idot) * 8},
{static_cast<void*>(&EphemerisData.IOD_nav), sizeof(EphemerisData.IOD_nav) * 8},
// data from word type 3
{static_cast<void*>(&EphemerisData.OMEGAdot), sizeof(EphemerisData.OMEGAdot) * 8},
{static_cast<void*>(&EphemerisData.delta_n), sizeof(EphemerisData.delta_n) * 8},
{static_cast<void*>(&EphemerisData.Cuc), sizeof(EphemerisData.Cuc) * 8},
{static_cast<void*>(&EphemerisData.Cus), sizeof(EphemerisData.Cus) * 8},
{static_cast<void*>(&EphemerisData.Crc), sizeof(EphemerisData.Crc) * 8},
{static_cast<void*>(&EphemerisData.Crs), sizeof(EphemerisData.Crs) * 8},
{static_cast<void*>(&EphemerisData.SISA), sizeof(EphemerisData.SISA) * 8},
// data from word type 4
{static_cast<void*>(&EphemerisData.IOD_nav), sizeof(EphemerisData.IOD_nav) * 8},
{static_cast<void*>(&EphemerisData.PRN), sizeof(EphemerisData.PRN) * 8},
{static_cast<void*>(&EphemerisData.Cic), sizeof(EphemerisData.Cic) * 8},
{static_cast<void*>(&EphemerisData.Cis), sizeof(EphemerisData.Cis) * 8},
{static_cast<void*>(&EphemerisData.toe), sizeof(EphemerisData.toe) * 8},
{static_cast<void*>(&EphemerisData.af0), sizeof(EphemerisData.af0) * 8},
{static_cast<void*>(&EphemerisData.af1), sizeof(EphemerisData.af1) * 8},
{static_cast<void*>(&EphemerisData.af2), sizeof(EphemerisData.af2) * 8},
// data from word type 5
{static_cast<void*>(&IonoData.ai0), sizeof(IonoData.ai0) * 8},
{static_cast<void*>(&IonoData.ai1), sizeof(IonoData.ai1) * 8},
{static_cast<void*>(&IonoData.ai2), sizeof(IonoData.ai2) * 8},
{static_cast<void*>(&IonoData.Region1_flag), sizeof(IonoData.Region1_flag) * 8},
{static_cast<void*>(&IonoData.Region2_flag), sizeof(IonoData.Region2_flag) * 8},
{static_cast<void*>(&IonoData.Region3_flag), sizeof(IonoData.Region3_flag) * 8},
{static_cast<void*>(&IonoData.Region4_flag), sizeof(IonoData.Region4_flag) * 8},
{static_cast<void*>(&IonoData.Region5_flag), sizeof(IonoData.Region5_flag) * 8},
{static_cast<void*>(&EphemerisData.BGD_E1E5a), sizeof(EphemerisData.BGD_E1E5a) * 8},
{static_cast<void*>(&EphemerisData.BGD_E1E5b), sizeof(EphemerisData.BGD_E1E5b) * 8},
{static_cast<void*>(&EphemerisData.E5b_HS), sizeof(EphemerisData.E5b_HS) * 8},
{static_cast<void*>(&EphemerisData.E1B_HS), sizeof(EphemerisData.E1B_HS) * 8},
{static_cast<void*>(&EphemerisData.E5b_DVS), sizeof(EphemerisData.E5b_DVS) * 8},
{static_cast<void*>(&EphemerisData.E1B_DVS), sizeof(EphemerisData.E1B_DVS) * 8},
};
for (auto& var : variables)
{
// extract the bits from the variable
uint64_t binary_representation;
memcpy(&binary_representation, var.first, var.second / 8);
// Append the bits to the buffer and update the bit count
bit_buffer = (bit_buffer << var.second) | binary_representation;
bit_count += var.second;
// While there are 8 or more bits in the buffer
while (bit_count >= 8)
{
// Extract the 8 bits starting from last bit position and add them to the vector
uint8_t extracted_bits = (bit_buffer >> (bit_count - 8)) & 0xFF;
ephemeris_iono_vector.push_back(extracted_bits);
// Remove the extracted bits from the buffer
bit_count -= 8;
bit_buffer = bit_buffer & ~(0xFF << bit_count);
}
}
// If there are any bits left in the buffer, add them to the vector
if (bit_count > 0)
{
ephemeris_iono_vector.push_back(static_cast<uint8_t>(bit_buffer));
}
} }
void NavData::generate_utc_vector()
std::string OSNMA_NavData::get_ephemeris_iono_data() const
{ {
utc_vector.clear(); return d_ephemeris_iono;
uint64_t bit_buffer = 0;
int bit_count = 0;
std::vector<std::pair<void*, int>> variables = {
{static_cast<void*>(&UtcData.A0), sizeof(UtcData.A0) * 8},
{static_cast<void*>(&UtcData.A1), sizeof(UtcData.A1) * 8},
{static_cast<void*>(&UtcData.Delta_tLS), sizeof(UtcData.Delta_tLS) * 8},
{static_cast<void*>(&UtcData.tot), sizeof(UtcData.tot) * 8},
{static_cast<void*>(&UtcData.WNot), sizeof(UtcData.WNot) * 8},
{static_cast<void*>(&UtcData.WN_LSF), sizeof(UtcData.WN_LSF) * 8},
{static_cast<void*>(&UtcData.DN), sizeof(UtcData.DN) * 8},
{static_cast<void*>(&UtcData.Delta_tLSF), sizeof(UtcData.Delta_tLSF) * 8},
{static_cast<void*>(&UtcData.A_0G), sizeof(UtcData.A_0G) * 8},
{static_cast<void*>(&UtcData.A_1G), sizeof(UtcData.A_1G) * 8},
{static_cast<void*>(&UtcData.t_0G), sizeof(UtcData.t_0G) * 8},
{static_cast<void*>(&UtcData.WN_0G), sizeof(UtcData.WN_0G) * 8},
};
for (auto& var : variables)
{
uint64_t binary_representation;
memcpy(&binary_representation, var.first, var.second / 8);
bit_buffer = (bit_buffer << var.second) | binary_representation;
bit_count += var.second;
while (bit_count >= 8)
{
uint8_t extracted_bits = (bit_buffer >> (bit_count - 8)) & 0xFF;
utc_vector.push_back(extracted_bits);
bit_count -= 8;
bit_buffer = bit_buffer & ~(0xFF << bit_count);
}
}
if (bit_count > 0)
{
utc_vector.push_back(static_cast<uint8_t>(bit_buffer));
}
} }
std::string OSNMA_NavData::get_utc_data() const
{
return d_utc;
}
uint32_t OSNMA_NavData::get_tow_sf0() const
{
return d_TOW_sf0;
}
void OSNMA_NavData::set_ephemeris_iono_data(const std::string& iono_data)
{
d_ephemeris_iono = iono_data;
}
void OSNMA_NavData::set_utc_data(const std::string& utc_data)
{
d_utc = utc_data;
}

View File

@ -18,12 +18,10 @@
#ifndef GNSS_SDR_OSNMA_DATA_H #ifndef GNSS_SDR_OSNMA_DATA_H
#define GNSS_SDR_OSNMA_DATA_H #define GNSS_SDR_OSNMA_DATA_H
#include "galileo_ephemeris.h" #include "galileo_inav_message.h" // for OSNMA_msg
#include "galileo_inav_message.h"
#include "galileo_iono.h"
#include "galileo_utc_model.h"
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -72,9 +70,9 @@ class MACK_tag_and_info
{ {
public: public:
MACK_tag_and_info() = default; MACK_tag_and_info() = default;
uint64_t tag; // C: 20-40 bits uint64_t tag; // C: 20-40 bits
MACK_tag_info tag_info; MACK_tag_info tag_info;
uint32_t counter; // CTR uint32_t counter; // CTR
}; };
class DSM_PKR_message class DSM_PKR_message
@ -107,7 +105,7 @@ public:
uint8_t reserved1{}; uint8_t reserved1{};
uint8_t hf{}; uint8_t hf{};
uint8_t mf{}; uint8_t mf{};
uint8_t ks{}; // key size, in bits uint8_t ks{}; // key size, in bits
uint8_t ts{}; uint8_t ts{};
uint8_t maclt{}; uint8_t maclt{};
uint8_t reserved{}; uint8_t reserved{};
@ -121,31 +119,26 @@ public:
MACK_header header; MACK_header header;
std::vector<MACK_tag_and_info> tag_and_info; std::vector<MACK_tag_and_info> tag_and_info;
std::vector<uint8_t> key; std::vector<uint8_t> key;
uint32_t TOW; // TODO duplicated variable, also in NavData uint32_t TOW; // TODO duplicated variable, also in OSNMA_NavData
uint32_t WN; uint32_t WN;
uint32_t PRNa; uint32_t PRNa;
}; };
class NavData class OSNMA_NavData
{ {
public: public:
NavData()=default; OSNMA_NavData() = default;
void init(const std::shared_ptr<OSNMA_msg> &osnma_msg); void init(const std::shared_ptr<OSNMA_msg>& osnma_msg);
std::vector<uint8_t> ephemeris_iono_vector{}; std::string get_ephemeris_iono_data() const;
std::string ephemeris_iono_vector_2{}; std::string get_utc_data() const;
std::vector<uint8_t> utc_vector{}; uint32_t get_tow_sf0() const;
std::string utc_vector_2{}; void set_ephemeris_iono_data(const std::string& iono_data);
uint32_t PRNa{}; void set_utc_data(const std::string& utc_data);
uint32_t WN_sf0{};
uint32_t TOW_sf0{};
private: private:
Galileo_Ephemeris EphemerisData; std::string d_ephemeris_iono;
Galileo_Iono IonoData; std::string d_utc;
Galileo_Utc_Model UtcData; uint32_t d_TOW_sf0{};
void generate_eph_iono_vector(); // TODO pass data directly fro Telemetry Decoder (if bits are in the needed order)
void generate_utc_vector(); // TODO
}; };
/*! /*!
@ -161,19 +154,22 @@ public:
DSM_PKR_message d_dsm_pkr_message; DSM_PKR_message d_dsm_pkr_message;
DSM_KROOT_message d_dsm_kroot_message; DSM_KROOT_message d_dsm_kroot_message;
MACK_message d_mack_message; MACK_message d_mack_message;
NavData d_nav_data; OSNMA_NavData d_nav_data;
}; };
class Tag class Tag
{ {
public: public:
enum e_verification_status{ enum e_verification_status
{
SUCCESS, SUCCESS,
FAIL, FAIL,
UNVERIFIED}; UNVERIFIED
Tag(const MACK_tag_and_info& MTI, uint32_t TOW,uint32_t WN, uint32_t PRNa,uint8_t CTR) // standard tag constructor, for tags within Tag&Info field };
Tag(const MACK_tag_and_info& MTI, uint32_t TOW, uint32_t WN, uint32_t PRNa, uint8_t CTR) // standard tag constructor, for tags within Tag&Info field
: tag_id(id_counter++), : tag_id(id_counter++),
TOW(TOW), // TODO missing for build_message WN for GST computation, CTR, NMAS, NavData missing TOW(TOW), // TODO missing for build_message WN for GST computation, CTR, NMAS, OSNMA_NavData missing
WN(WN), WN(WN),
PRNa(PRNa), PRNa(PRNa),
CTR(CTR), CTR(CTR),
@ -186,16 +182,16 @@ public:
skipped(0) skipped(0)
{ {
} }
Tag(const MACK_message& mack) // constructor for Tag0 Tag(const MACK_message& mack) // constructor for Tag0
: tag_id(id_counter++), : tag_id(id_counter++),
TOW(mack.TOW), // TODO missing for build_message WN for GST computation, CTR, NMAS, NavData missing TOW(mack.TOW), // TODO missing for build_message WN for GST computation, CTR, NMAS, OSNMA_NavData missing
WN(mack.WN), WN(mack.WN),
PRNa(mack.PRNa), PRNa(mack.PRNa),
CTR(1), CTR(1),
status(UNVERIFIED), status(UNVERIFIED),
received_tag(mack.header.tag0), received_tag(mack.header.tag0),
computed_tag(0), computed_tag(0),
PRN_d(mack.PRNa), // Tag0 are self-authenticating PRN_d(mack.PRNa), // Tag0 are self-authenticating
ADKD(0), ADKD(0),
cop(mack.header.cop), cop(mack.header.cop),
skipped(0) skipped(0)

View File

@ -30,8 +30,8 @@ public:
std::vector<uint8_t> gst_to_uint8(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::vector<uint8_t> bytes(const std::string& binaryString) const;
std::string verification_status_str(int status) const; std::string verification_status_str(int status) const;
std::string convert_to_hex_string(const std::vector<uint8_t>& vector) 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::vector<uint8_t> convert_from_hex_string(const std::string& hex_string) const; // TODO remove similar function in gnss_crypto
}; };
#endif // GNSS_SDR_OSNMA_HELPER_H #endif // GNSS_SDR_OSNMA_HELPER_H

View File

@ -1,13 +1,31 @@
/*!
* \file osmna_msg_receiver_testt.cc
* \brief Tests for the osnma_msg_receiver class.
* \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es
* Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de
*
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "gnss_crypto.h"
#include "osnma_helper.h"
#include "osnma_msg_receiver.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <bitset> #include <bitset>
#include <chrono> #include <chrono>
#include <fstream> #include <fstream>
#include <osnma_msg_receiver.h>
#include <vector> #include <vector>
#if USE_GLOG_AND_GFLAGS #if USE_GLOG_AND_GFLAGS
#include "osnma_helper.h"
#include "gnss_crypto.h"
#include <glog/logging.h> // for LOG #include <glog/logging.h> // for LOG
#include <filesystem> #include <filesystem>
#else #else
@ -21,11 +39,18 @@ struct TestVector
std::vector<uint8_t> navBits; std::vector<uint8_t> navBits;
}; };
// TODO - parametrize class for different configurations (config_1, config_2, etc.. potentially 5 or 6 more) an make sure wont affect current TEST_F // TODO - parametrize class for different configurations (config_1, config_2, etc.. potentially 5 or 6 more) an make sure wont affect current TEST_F
// note: until the test is parametrized for configuration 1 and 2, in order to change between them you have to comment/uncomment the respective calls in this test, identified with comments // conf. 1/2 // note: until the test is parametrized for configuration 1 and 2, in order to change between them you have to comment/uncomment the respective calls in this test, identified with comments // conf. 1/2
// log_name, input_time, crtFilePath, merkleFilePath, testVectors // log_name, input_time, crtFilePath, merkleFilePath, testVectors
class OsnmaMsgReceiverTest : public ::testing::Test class OsnmaMsgReceiverTest : public ::testing::Test
{ {
public:
static std::vector<uint8_t> parseNavBits(const std::string& hex);
static std::vector<TestVector> readTestVectorsFromFile(const std::string& filename);
std::string bytes_to_str(const std::vector<uint8_t>& bytes);
std::vector<uint8_t> extract_page_bytes(const TestVector& tv, const int byte_index, const int num_bytes);
protected: protected:
Osnma_Helper helper; Osnma_Helper helper;
osnma_msg_receiver_sptr osnma; osnma_msg_receiver_sptr osnma;
@ -34,38 +59,31 @@ protected:
uint32_t d_GST_SIS{}; uint32_t d_GST_SIS{};
uint32_t TOW{}; uint32_t TOW{};
uint32_t WN{}; uint32_t WN{};
std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm
const uint32_t LEAP_SECONDS = 0; //13 + 5; const uint32_t LEAP_SECONDS = 0; // 13 + 5;
void set_time(std::tm& input); void set_time(std::tm& input);
// std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"}; // std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"};
std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; std::string log_name{"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
void initializeGoogleLog(); void initializeGoogleLog();
void SetUp() override void SetUp() override
{ {
initializeGoogleLog(); initializeGoogleLog();
// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; // conf. 1 // std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; // conf. 1
std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; // conf. 2 std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; // conf. 2
set_time(input_time); set_time(input_time);
// std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.crt"; // conf. 1 // std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.crt"; // conf. 1
// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml"; // std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.crt"; // conf. 2 std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.crt"; // conf. 2
std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml"; std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml";
osnma = osnma_msg_receiver_make(crtFilePath, merkleFilePath); osnma = osnma_msg_receiver_make(crtFilePath, merkleFilePath);
} }
public:
static std::vector<uint8_t> parseNavBits(const std::string& hex);
static std::vector<TestVector> readTestVectorsFromFile(const std::string& filename);
std::string bytes_to_str(const std::vector<uint8_t>& bytes);
std::vector<uint8_t> extract_page_bytes(const TestVector& tv, const int byte_index, const int num_bytes);
}; };
TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot) TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot)
{ {
// Arrange // Arrange
// ----------
std::vector<uint8_t> computed_merkle_root; std::vector<uint8_t> computed_merkle_root;
std::vector<uint8_t> expected_merkle_root = helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D"); std::vector<uint8_t> expected_merkle_root = helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D");
DSM_PKR_message dsm_pkr_message; DSM_PKR_message dsm_pkr_message;
@ -73,8 +91,8 @@ TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot)
dsm_pkr_message.npktid = 0x2; dsm_pkr_message.npktid = 0x2;
dsm_pkr_message.mid = 0x01; dsm_pkr_message.mid = 0x01;
std::vector<uint8_t> base_leaf = helper.convert_from_hex_string("120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA"); std::vector<uint8_t> base_leaf = helper.convert_from_hex_string("120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA");
std::vector<uint8_t> vec = helper.convert_from_hex_string(
std::vector<uint8_t> vec = helper.convert_from_hex_string("7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06" "7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06"
"956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7" "956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7"
"407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1" "407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1"
"24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87"); "24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87");
@ -82,18 +100,16 @@ TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot)
dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA"); dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA");
// Act // Act
// ----------
computed_merkle_root = osnma->compute_merkle_root(dsm_pkr_message, base_leaf); computed_merkle_root = osnma->compute_merkle_root(dsm_pkr_message, base_leaf);
// Assert // Assert
// ----------
ASSERT_EQ(computed_merkle_root, expected_merkle_root); ASSERT_EQ(computed_merkle_root, expected_merkle_root);
} }
TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf) TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf)
{ {
// Arrange // Arrange
// ----------
std::vector<uint8_t> expected_base_leaf = helper.convert_from_hex_string("120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA"); std::vector<uint8_t> expected_base_leaf = helper.convert_from_hex_string("120303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA");
DSM_PKR_message dsm_pkr_message; DSM_PKR_message dsm_pkr_message;
dsm_pkr_message.npkt = 0x01; dsm_pkr_message.npkt = 0x01;
@ -101,63 +117,68 @@ TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf)
dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA"); dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA");
// Act // Act
// ----------
std::vector<uint8_t> computed_base_leaf = osnma->get_merkle_tree_leaves(dsm_pkr_message); std::vector<uint8_t> computed_base_leaf = osnma->get_merkle_tree_leaves(dsm_pkr_message);
// Assert // Assert
// ---------- ASSERT_EQ(computed_base_leaf, expected_base_leaf);
ASSERT_EQ(computed_base_leaf,expected_base_leaf);
} }
TEST_F(OsnmaMsgReceiverTest, VerifyPublicKey){ // values taken from RG A.7
TEST_F(OsnmaMsgReceiverTest, VerifyPublicKey)
{
// values taken from RG A.7
// Arrange // Arrange
// ----------
osnma->d_crypto->set_merkle_root(helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D")); osnma->d_crypto->set_merkle_root(helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D"));
DSM_PKR_message dsm_pkr_message; DSM_PKR_message dsm_pkr_message;
dsm_pkr_message.npkt = 0x01; dsm_pkr_message.npkt = 0x01;
dsm_pkr_message.npktid = 0x2; dsm_pkr_message.npktid = 0x2;
dsm_pkr_message.mid = 0x01; dsm_pkr_message.mid = 0x01;
std::vector<uint8_t> vec = helper.convert_from_hex_string("7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06" std::vector<uint8_t> vec = helper.convert_from_hex_string(
"956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7" "7CBE05D9970CFC9E22D0A43A340EF557624453A2E821AADEAC989C405D78BA06"
"407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1" "956380BAB0D2C939EC6208151040CCFFCF1FB7156178FD1255BA0AECAAA253F7"
"24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87"); "407B6C5DD4DF059FF8789474061301E1C34881DB7A367A913A3674300E21EAB1"
"24EF508389B7D446C3E2ECE8D459FBBD3239A794906F5B1F92469C640164FD87");
std::copy(vec.begin(), vec.end(), dsm_pkr_message.itn.begin()); std::copy(vec.begin(), vec.end(), dsm_pkr_message.itn.begin());
dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA"); dsm_pkr_message.npk = helper.convert_from_hex_string("0303B2CE64BC207BDD8BC4DF859187FCB686320D63FFA091410FC158FBB77980EA");
// Act // Act
// ----------
bool result = osnma->verify_dsm_pkr(dsm_pkr_message); bool result = osnma->verify_dsm_pkr(dsm_pkr_message);
// Assert // Assert
// ----------
ASSERT_TRUE(result); ASSERT_TRUE(result);
} }
TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0) TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0)
{ {
// Arrange // Arrange
// ---------- std::vector<uint8_t> expected_message = {
// m0
std::vector<uint8_t> expected_message = {
0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B, 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B,
0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21, 0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21,
0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D, 0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D,
0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00, 0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00,
0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00 0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00};
};
uint32_t TOW_Tag0 = 345660; uint32_t TOW_Tag0 = 345660;
uint32_t TOW_NavData = TOW_Tag0 - 30; uint32_t TOW_NavData = TOW_Tag0 - 30;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
uint32_t WN = 1248; uint32_t WN = 1248;
uint32_t PRNa = 2; uint32_t PRNa = 2;
uint8_t CTR = 1; uint8_t CTR = 1;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4 osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; osnma->d_satellite_nav_data[PRNa][TOW_NavData].set_ephemeris_iono_data(
"000011101001011001000100000101000111010110100100100101100000000000"
"011101101011001111101110101010000001010000011011111100000011101011"
"011100101101011010101011011011001001110111101011110110111111001111"
"001000011111101110011000111111110111111010000011101011111111110000"
"110111000000100000001110110000110110001110000100001110101100010100"
"110100010001000110001110011010110000111010000010000000000001101000"
"000000000011100101100100010000000000000110110100110001111100000000"
"000000100110100000000101010010100000001011000010001001100000011111"
"110111111111000000000");
osnma->d_osnma_data.d_nma_header.nmas = 0b10; osnma->d_osnma_data.d_nma_header.nmas = 0b10;
MACK_tag_and_info MTI; MACK_tag_and_info MTI;
@ -167,34 +188,39 @@ TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0)
MTI.tag_info.cop = 0x0F; MTI.tag_info.cop = 0x0F;
Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
// Act // Act
// ----------
auto computed_message = osnma->build_message(t0); auto computed_message = osnma->build_message(t0);
// Assert // Assert
// ----------
ASSERT_TRUE(computed_message == expected_message); ASSERT_TRUE(computed_message == expected_message);
} }
TEST_F(OsnmaMsgReceiverTest, TagVerification) {
TEST_F(OsnmaMsgReceiverTest, TagVerification)
{
// Arrange // Arrange
// ----------
// Tag0 // Tag0
uint32_t TOW_Tag0 = 345660; uint32_t TOW_Tag0 = 345660;
uint32_t TOW_NavData = TOW_Tag0 - 30; uint32_t TOW_NavData = TOW_Tag0 - 30;
uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
uint32_t WN = 1248; uint32_t WN = 1248;
uint32_t PRNa = 2; uint32_t PRNa = 2;
uint8_t CTR = 1; uint8_t CTR = 1;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; osnma->d_satellite_nav_data[PRNa][TOW_NavData].set_ephemeris_iono_data("");
osnma->d_satellite_nav_data[PRNa][TOW_NavData].set_ephemeris_iono_data(
"000011101001011001000100000101000111010110100100100101100000000000"
"011101101011001111101110101010000001010000011011111100000011101011"
"011100101101011010101011011011001001110111101011110110111111001111"
"001000011111101110011000111111110111111010000011101011111111110000"
"110111000000100000001110110000110110001110000100001110101100010100"
"110100010001000110001110011010110000111010000010000000000001101000"
"000000000011100101100100010000000000000110110100110001111100000000"
"000000100110100000000101010010100000001011000010001001100000011111"
"110111111111000000000");
osnma->d_osnma_data.d_nma_header.nmas = 0b10; osnma->d_osnma_data.d_nma_header.nmas = 0b10;
MACK_tag_and_info MTI; MACK_tag_and_info MTI;
@ -204,34 +230,25 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) {
MTI.tag_info.cop = 0x0F; MTI.tag_info.cop = 0x0F;
Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
// Act // Act
// ----------
bool result_tag0 = osnma->verify_tag(t0); bool result_tag0 = osnma->verify_tag(t0);
// Assert // Assert
// ----------
//ASSERT_TRUE(result_tag0);
// Tag3 // Tag3
uint32_t TOW_Tag3 = 345660; uint32_t TOW_Tag3 = 345660;
uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30; uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30;
uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ; uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30;
WN = 1248; WN = 1248;
PRNa = 2; PRNa = 2;
CTR = 3; CTR = 3;
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 = osnma->d_satellite_nav_data[PRNa][TOW_NavData].set_utc_data(
"111111111111111111111111111111110000000000000000000000010001001001001000" "111111111111111111111111111111110000000000000000000000010001001001001000"
"111000001000100111100010010111111111011110111111111001001100000100000000"; "111000001000100111100010010111111111011110111111111001001100000100000000");
osnma->d_osnma_data.d_nma_header.nmas = 0b10; osnma->d_osnma_data.d_nma_header.nmas = 0b10;
MTI.tag = static_cast<uint64_t>(0x7BB238C883); MTI.tag = static_cast<uint64_t>(0x7BB238C883);
@ -243,90 +260,78 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) {
bool result_tag3 = osnma->verify_tag(t3); bool result_tag3 = osnma->verify_tag(t3);
ASSERT_TRUE(result_tag0 && result_tag3); ASSERT_TRUE(result_tag0 && result_tag3);
} }
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) {
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification)
{
// Arrange // Arrange
// ----------
osnma->d_tesla_key_verified = false; osnma->d_tesla_key_verified = false;
osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30 osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30
osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits
osnma->d_osnma_data.d_dsm_kroot_message.alpha = 0x610BDF26D77B; osnma->d_osnma_data.d_dsm_kroot_message.alpha = 0x610BDF26D77B;
// local_time_verification would do this operation. TODO - eliminate duplication. // local_time_verification would do this operation. TODO - eliminate duplication.
osnma->d_GST_SIS = (1248 & 0x00000FFF) << 20 | (345630 & 0x000FFFFF); osnma->d_GST_SIS = (1248 & 0x00000FFF) << 20 | (345630 & 0x000FFFFF);
osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30)
osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630; osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630;
osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600,{0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference. osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600, {0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference.
std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2 std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2
uint32_t TOW = 345630; uint32_t TOW = 345630;
// Act // Act
// ----------
bool result = osnma->verify_tesla_key(key, TOW); bool result = osnma->verify_tesla_key(key, TOW);
// Assert // Assert
// ----------
ASSERT_TRUE(result); ASSERT_TRUE(result);
} }
TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
{ {
// Arrange // Arrange
// ---------- std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv"); // conf. 2
// std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); // conf. 1 if (testVectors.empty())
std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv"); // conf. 2 {
if (testVectors.empty()){
ASSERT_TRUE(false); ASSERT_TRUE(false);
} }
bool end_of_hex_stream{false}; bool end_of_hex_stream{false};
int offset_byte{0}; int offset_byte{0};
int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size
const int SIZE_PAGE_BYTES{240/8}; // total bytes of a page const int SIZE_PAGE_BYTES{240 / 8}; // total bytes of a page
const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; // total bytes of a subframe const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds
const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds
const int DUMMY_PAGE{63}; const int DUMMY_PAGE{63};
bool flag_dummy_page{false}; bool flag_dummy_page{false};
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS std::cout << "OsnmaTestVectorsSimulation:"
<< ", TOW=" << TOW << " d_GST_SIS= " << d_GST_SIS
<< ", WN=" << WN << std::endl; << ", TOW=" << TOW
<< ", WN=" << WN << std::endl;
// Act // Act
// ----------
// loop over all bytes of data. Note: all TestVectors have same amount of data. // loop over all bytes of data. Note: all TestVectors have same amount of data.
while (end_of_hex_stream == false){ while (end_of_hex_stream == false)
{
// loop over all SVs, extract a subframe // loop over all SVs, extract a subframe
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe for (const TestVector& tv : testVectors)
std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl; { // loop over all SVs, extract a subframe
std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) " << tv.svId << std::endl;
auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>(); auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>();
std::array<uint8_t, 15> hkroot{}; std::array<uint8_t, 15> hkroot{};
std::array<uint32_t, 15> mack{}; std::array<uint32_t, 15> mack{};
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
std::map<uint8_t, std::bitset<128>> words_for_OSNMA; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS> std::map<uint8_t, std::bitset<128>> words_for_OSNMA; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS>
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
{ {
// extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index // extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index
std::vector<uint8_t> page_bytes = extract_page_bytes(tv,byte_index,SIZE_PAGE_BYTES); std::vector<uint8_t> page_bytes = extract_page_bytes(tv, byte_index, SIZE_PAGE_BYTES);
if(page_bytes.empty()){ if (page_bytes.empty())
std::cout<< "OsnmaTestVectorsSimulation: end of TestVectors \n" << "byte_index="<<byte_index<< " expected= " << 432000/8 << std::endl; {
std::cout << "OsnmaTestVectorsSimulation: end of TestVectors \n"
<< "byte_index=" << byte_index << " expected= " << 432000 / 8 << std::endl;
end_of_hex_stream = true; end_of_hex_stream = true;
break; break;
} }
@ -334,28 +339,29 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
std::string page_bits = bytes_to_str(page_bytes); std::string page_bits = bytes_to_str(page_bytes);
// Extract the 40 OSNMA bits starting from the 18th bit // Extract the 40 OSNMA bits starting from the 18th bit
std::string even_page = page_bits.substr(0, page_bits.size() / 2); std::string even_page = page_bits.substr(0, page_bits.size() / 2);
std::string odd_page = page_bits.substr( page_bits.size() / 2); std::string odd_page = page_bits.substr(page_bits.size() / 2);
if(even_page.size() < 120 || odd_page.size() < 120 ){ if (even_page.size() < 120 || odd_page.size() < 120)
std::cout<< "OsnmaTestVectorsSimulation: error parsing pages" << std::endl; {
std::cout << "OsnmaTestVectorsSimulation: error parsing pages" << std::endl;
} }
bool even_odd_OK = even_page[0] == '0' && odd_page[0] == '1'; bool even_odd_OK = even_page[0] == '0' && odd_page[0] == '1';
bool page_type_OK = even_page[1] == '0' && odd_page[1] == '0'; bool page_type_OK = even_page[1] == '0' && odd_page[1] == '0';
bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000"; bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000";
if(!even_odd_OK || !page_type_OK || !tail_bits_OK) if (!even_odd_OK || !page_type_OK || !tail_bits_OK)
std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl; std::cerr << "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
std::bitset<112> data_k(even_page.substr(2,112)); std::bitset<112> data_k(even_page.substr(2, 112));
std::bitset<16> data_j(odd_page.substr(2,16)); std::bitset<16> data_j(odd_page.substr(2, 16));
std::bitset<112> shifted_data_k = data_k; std::bitset<112> shifted_data_k = data_k;
uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word
std::cout<< "OsnmaTestVectorsSimulation: received Word "<< static_cast<int>(word_type) << std::endl; std::cout << "OsnmaTestVectorsSimulation: received Word " << static_cast<int>(word_type) << std::endl;
if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10) if ((word_type >= 1 && word_type <= 5) || word_type == 6 || word_type == 10)
{ {
// store raw word // store raw word
std::bitset<128> data_combined(data_k.to_string() + data_j.to_string()); std::bitset<128> data_combined(data_k.to_string() + data_j.to_string());
words_for_OSNMA[word_type] = data_combined; words_for_OSNMA[word_type] = data_combined;
} }
if(word_type == DUMMY_PAGE) if (word_type == DUMMY_PAGE)
flag_dummy_page = true; flag_dummy_page = true;
// place it into osnma object. // place it into osnma object.
@ -370,12 +376,13 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
byte_index += SIZE_PAGE_BYTES; byte_index += SIZE_PAGE_BYTES;
} }
std::cout<< "----------" << std::endl; std::cout << "----------" << std::endl;
if(end_of_hex_stream) if (end_of_hex_stream)
break; break;
if(flag_dummy_page){ if (flag_dummy_page)
{
flag_dummy_page = false; flag_dummy_page = false;
continue; // skip this SV continue; // skip this SV
} }
// Fill osnma object // Fill osnma object
@ -383,8 +390,8 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
osnmaMsg_sptr->mack = mack; osnmaMsg_sptr->mack = mack;
osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF; osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF;
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ; osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20;
osnmaMsg_sptr->PRN = tv.svId; // PRNa osnmaMsg_sptr->PRN = tv.svId; // PRNa
// TODO - refactor this logic, currently it is split // TODO - refactor this logic, currently it is split
@ -395,14 +402,14 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
if (words_for_OSNMA.find(i) == words_for_OSNMA.end()) if (words_for_OSNMA.find(i) == words_for_OSNMA.end())
{ {
ephClockStatusWordsReceived = false; ephClockStatusWordsReceived = false;
std::cerr<< "OsnmaTestVectorsSimulation: error parsing words_for_OSNMA 1->5. " std::cerr << "OsnmaTestVectorsSimulation: error parsing words_for_OSNMA 1->5. "
"Word "<< i << " should be received for each subframe but was not." << std::endl; "Word "
<< i << " should be received for each subframe but was not." << std::endl;
} }
} }
// extract bits as needed by osnma block // extract bits as needed by osnma block
if(ephClockStatusWordsReceived) if (ephClockStatusWordsReceived)
{ {
// Define the starting position and length of bits to extract for each word // Define the starting position and length of bits to extract for each word
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = { std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
{1, {6, 120}}, {1, {6, 120}},
@ -414,7 +421,8 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
// Fill NavData bits -- Iterate over the extraction parameters // Fill NavData bits -- Iterate over the extraction parameters
std::string nav_data_ADKD_0_12 = ""; std::string nav_data_ADKD_0_12 = "";
for (const auto& param : extractionParams) { for (const auto& param : extractionParams)
{
uint8_t wordKey = param.first; uint8_t wordKey = param.first;
uint8_t start = param.second.first; uint8_t start = param.second.first;
uint8_t length = param.second.second; uint8_t length = param.second.second;
@ -424,16 +432,16 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
} }
// send to osnma block // send to osnma block
bool check_size_is_ok = nav_data_ADKD_0_12.size() == 549; bool check_size_is_ok = nav_data_ADKD_0_12.size() == 549;
if(check_size_is_ok) if (check_size_is_ok)
{ {
std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl; std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") "
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
tv.svId, tv.svId,
nav_data_ADKD_0_12, nav_data_ADKD_0_12,
osnmaMsg_sptr->TOW_sf0); osnmaMsg_sptr->TOW_sf0);
LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) <<"): 0b" << nav_data_ADKD_0_12; LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d=" << static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) << "): 0b" << nav_data_ADKD_0_12;
osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
} }
} }
@ -441,12 +449,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
bool timingWordsReceived = words_for_OSNMA.find(6) != words_for_OSNMA.end() && bool timingWordsReceived = words_for_OSNMA.find(6) != words_for_OSNMA.end() &&
words_for_OSNMA.find(10) != words_for_OSNMA.end(); words_for_OSNMA.find(10) != words_for_OSNMA.end();
// extract bits as needed by osnma block // extract bits as needed by osnma block
if(timingWordsReceived){ if (timingWordsReceived)
{
// Define the starting position and length of bits to extract for each word // Define the starting position and length of bits to extract for each word
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = { std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
{6, {6, 99}}, {6, {6, 99}},
{10, {86, 42}} {10, {86, 42}}};
};
std::string nav_data_ADKD_4 = ""; std::string nav_data_ADKD_4 = "";
// Fill NavData bits -- Iterate over the extraction parameters // Fill NavData bits -- Iterate over the extraction parameters
@ -461,63 +469,62 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
} }
// send to osnma block // send to osnma block
bool check_size_is_ok = nav_data_ADKD_4.size() == 141; bool check_size_is_ok = nav_data_ADKD_4.size() == 141;
if(check_size_is_ok) if (check_size_is_ok)
{ {
std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl; std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") "
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl;
const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf>
tv.svId, tv.svId,
nav_data_ADKD_4, nav_data_ADKD_4,
osnmaMsg_sptr->TOW_sf0); osnmaMsg_sptr->TOW_sf0);
LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) <<"): 0b" << nav_data_ADKD_4; LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d=" << static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) << "): 0b" << nav_data_ADKD_4;
osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
} }
} }
// Call the handler, as if it came from telemetry decoder block // Call the handler, as if it came from telemetry decoder block
auto temp_obj = pmt::make_any(osnmaMsg_sptr); auto temp_obj = pmt::make_any(osnmaMsg_sptr);
osnma->msg_handler_osnma(temp_obj); // osnma entry point osnma->msg_handler_osnma(temp_obj); // osnma entry point
} }
if (!end_of_hex_stream)
if(!end_of_hex_stream){ {
offset_byte = byte_index; // update offset for the next subframe offset_byte = byte_index; // update offset for the next subframe
d_GST_SIS += DURATION_SUBFRAME; d_GST_SIS += DURATION_SUBFRAME;
TOW = d_GST_SIS & 0x000FFFFF; TOW = d_GST_SIS & 0x000FFFFF;
WN = (d_GST_SIS & 0xFFF00000) >> 20 ; WN = (d_GST_SIS & 0xFFF00000) >> 20;
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS std::cout << "OsnmaTestVectorsSimulation:"
<< " d_GST_SIS= " << d_GST_SIS
<< ", TOW=" << TOW << ", TOW=" << TOW
<< ", WN=" << WN << std::endl; << ", WN=" << WN << std::endl;
} }
} }
// Assert // Assert
// ----------
// TODO - create global vars with failed tags and compare to total tags (Tag Id for example) // TODO - create global vars with failed tags and compare to total tags (Tag Id for example)
} }
// Auxiliary functions for the OsnmaTestVectorsSimulation test fixture. // Auxiliary functions for the OsnmaTestVectorsSimulation test fixture.
// Essentially, they perform same work as the telemetry decoder block, but adapted to the osnma-test-vector files. // Essentially, they perform same work as the telemetry decoder block, but adapted to the osnma-test-vector files.
std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename) std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename)
{ {
std::ifstream file(filename); std::ifstream file(filename);
std::vector<TestVector> testVectors; std::vector<TestVector> testVectors;
if (!file.is_open()) { if (!file.is_open())
std::cerr<<"Error reading the file \"" << filename <<"\" \n"; {
std::cerr << "Error reading the file \"" << filename << "\" \n";
return testVectors; return testVectors;
} }
std::string line; std::string line;
std::getline(file, line); std::getline(file, line);
if (line != "SVID,NumNavBits,NavBitsHEX\r" ){ if (line != "SVID,NumNavBits,NavBitsHEX\r")
std::cerr<<"Error parsing first line" <<"\n"; {
} std::cerr << "Error parsing first line"
<< "\n";
}
while (std::getline(file, line)) while (std::getline(file, line))
{ {
@ -540,29 +547,35 @@ std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std:
return testVectors; return testVectors;
} }
std::vector<uint8_t> OsnmaMsgReceiverTest::parseNavBits(const std::string& hex) std::vector<uint8_t> OsnmaMsgReceiverTest::parseNavBits(const std::string& hex)
{ {
std::vector<uint8_t> bytes; std::vector<uint8_t> bytes;
for (unsigned int i = 0; i < hex.length()-1; i += 2) for (unsigned int i = 0; i < hex.length() - 1; i += 2)
{ {
std::string byteString = hex.substr(i, 2); std::string byteString = hex.substr(i, 2);
uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16); uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16);
bytes.push_back(byte); bytes.push_back(byte);
} }
return bytes; return bytes;
} }
std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes) std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes)
{ {
std::string bit_string; std::string bit_string;
bit_string.reserve(bytes.size() * 8); bit_string.reserve(bytes.size() * 8);
for(const auto& byte : bytes) for (const auto& byte : bytes)
{ {
std::bitset<8> bits(byte); std::bitset<8> bits(byte);
bit_string += bits.to_string(); bit_string += bits.to_string();
} }
return bit_string; return bit_string;
} }
/** /**
* @brief Extracts a range of bytes from a TestVector's navBits vector. * @brief Extracts a range of bytes from a TestVector's navBits vector.
* *
@ -591,6 +604,8 @@ std::vector<uint8_t> OsnmaMsgReceiverTest::extract_page_bytes(const TestVector&
return extracted_bytes; return extracted_bytes;
} }
/** /**
* @brief Sets the time based on the given input. * @brief Sets the time based on the given input.
* *
@ -614,25 +629,24 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input)
uint32_t sec_in_week = 7 * 24 * 60 * 60; uint32_t sec_in_week = 7 * 24 * 60 * 60;
uint32_t week_number = duration_sec.count() / sec_in_week; uint32_t week_number = duration_sec.count() / sec_in_week;
uint32_t time_of_week = duration_sec.count() % sec_in_week; uint32_t time_of_week = duration_sec.count() % sec_in_week;
this->WN = week_number; this->WN = week_number;
this->TOW = time_of_week + LEAP_SECONDS; this->TOW = time_of_week + LEAP_SECONDS;
// Return the week number and time of week as a pair // Return the week number and time of week as a pair
// TODO: d_GST_SIS or d_receiver_time? doubt // TODO: d_GST_SIS or d_receiver_time? doubt
// I am assuming that local realisation of receiver is identical to SIS GST time coming from W5 or W0 // I am assuming that local realisation of receiver is identical to SIS GST time coming from W5 or W0
this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF); this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
} }
void OsnmaMsgReceiverTest::initializeGoogleLog() void OsnmaMsgReceiverTest::initializeGoogleLog()
{ {
google::InitGoogleLogging(log_name.c_str()); // TODO - running all tests causes conflict due to being called twice google::InitGoogleLogging(log_name.c_str()); // TODO - running all tests causes conflict due to being called twice
FLAGS_minloglevel = 0; // INFO FLAGS_minloglevel = 0; // INFO
FLAGS_logtostderr = 0; // add this line FLAGS_logtostderr = 0; // add this line
FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/data/build/src/tests/logs"; FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/data/build/src/tests/logs";
if (FLAGS_log_dir.empty()) if (FLAGS_log_dir.empty())
{ {
std::cout << "Logging will be written at " std::cout << "Logging will be written at "
<< std::filesystem::temp_directory_path() << std::filesystem::temp_directory_path()
<< '\n' << '\n'
@ -667,4 +681,3 @@ void OsnmaMsgReceiverTest::initializeGoogleLog()
} }
} }
} }