mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 09:13:05 +00:00 
			
		
		
		
	[TAS-227] [BUG] Tag verification fails for .dat files (WIP)
WIP
This commit is contained in:
		@@ -439,6 +439,35 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // 4. Push the new navigation data to the queues
 | 
			
		||||
    // extract OSNMA bits, reset container.
 | 
			
		||||
    bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549;
 | 
			
		||||
    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;
 | 
			
		||||
            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_inav_nav.get_osnma_adkd_0_12_nav_bits(),
 | 
			
		||||
                d_inav_nav.get_TOW5() - 25);
 | 
			
		||||
            this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma));
 | 
			
		||||
            LOG(INFO) << "|---> Galileo OSNMA :: 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();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141;
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
            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_inav_nav.get_osnma_adkd_4_nav_bits(),
 | 
			
		||||
                d_inav_nav.get_TOW6() - 5);
 | 
			
		||||
            this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj));
 | 
			
		||||
            LOG(INFO) << "|---> Galileo OSNMA :: 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();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
@@ -472,20 +501,6 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
 | 
			
		||||
            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
 | 
			
		||||
            // extract bits, reset container.
 | 
			
		||||
            bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549;
 | 
			
		||||
            if(check_size_is_ok)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << d_satellite.get_PRN() << ") " << "TOW_sf=" << d_inav_nav.get_TOW5() - 24 <<std::endl;
 | 
			
		||||
                    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_inav_nav.get_osnma_adkd_0_12_nav_bits(),
 | 
			
		||||
                        d_inav_nav.get_TOW5() - 24);
 | 
			
		||||
                    this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma));
 | 
			
		||||
                    d_inav_nav.reset_osnma_nav_bits_adkd0_12();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    else
 | 
			
		||||
        {
 | 
			
		||||
@@ -615,19 +630,6 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in
 | 
			
		||||
    //    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.*/)
 | 
			
		||||
        {
 | 
			
		||||
            bool check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141;
 | 
			
		||||
            if(check_size_is_ok)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cout << "Galileo OSNMA: sending ADKD=4 navData, PRN_d (" << d_satellite.get_PRN() << ") " << "TOW_sf=" << d_inav_nav.get_TOW6() - 4 <<std::endl;
 | 
			
		||||
 | 
			
		||||
                    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_inav_nav.get_osnma_adkd_4_nav_bits(),
 | 
			
		||||
                        d_inav_nav.get_TOW6() - 4);
 | 
			
		||||
                    this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj));
 | 
			
		||||
                    d_inav_nav.reset_osnma_nav_bits_adkd4();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    auto newOSNMA = d_inav_nav.have_new_nma();
 | 
			
		||||
    if (d_band == '1' && newOSNMA)
 | 
			
		||||
 
 | 
			
		||||
@@ -62,13 +62,13 @@ osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath,
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
osnma_msg_receiver::osnma_msg_receiver(
 | 
			
		||||
    const std::string& pemFilePath,
 | 
			
		||||
    const std::string& crtFilePath,
 | 
			
		||||
    const std::string& merkleFilePath) : gr::block("osnma_msg_receiver",
 | 
			
		||||
                                             gr::io_signature::make(0, 0, 0),
 | 
			
		||||
                                             gr::io_signature::make(0, 0, 0))
 | 
			
		||||
{
 | 
			
		||||
    d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>();
 | 
			
		||||
    d_crypto = std::make_unique<Gnss_Crypto>(pemFilePath, merkleFilePath);
 | 
			
		||||
    d_crypto = std::make_unique<Gnss_Crypto>(crtFilePath, merkleFilePath);
 | 
			
		||||
    d_helper = std::make_unique<Osnma_Helper>();
 | 
			
		||||
    //  register OSNMA input message port from telemetry blocks
 | 
			
		||||
    this->message_port_register_in(pmt::mp("OSNMA_from_TLM"));
 | 
			
		||||
@@ -101,13 +101,13 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
 | 
			
		||||
                    const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN);  // TODO remove if unneeded
 | 
			
		||||
 | 
			
		||||
                    std::ostringstream output_message;
 | 
			
		||||
                    output_message << "Galileo OSNMA: Subframe received starting at "
 | 
			
		||||
                                   << "WN="
 | 
			
		||||
                                   << nma_msg->WN_sf0
 | 
			
		||||
                                   << ", TOW="
 | 
			
		||||
                                   << nma_msg->TOW_sf0
 | 
			
		||||
                                   << ", from satellite "
 | 
			
		||||
                                   << sat;
 | 
			
		||||
                    output_message << "Galileo OSNMA: complete OSNMA message received starting at "
 | 
			
		||||
                        << "WN="
 | 
			
		||||
                        << nma_msg->WN_sf0
 | 
			
		||||
                        << ", TOW="
 | 
			
		||||
                        << nma_msg->TOW_sf0
 | 
			
		||||
                        << ", from satellite "
 | 
			
		||||
                        << sat;
 | 
			
		||||
                    LOG(WARNING) << output_message.str();
 | 
			
		||||
                    std::cout << output_message.str() << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -125,14 +125,14 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
 | 
			
		||||
                    // iono data => 549 bits, utc data, 141 bits.
 | 
			
		||||
                    if (nav_data.size() == 549)
 | 
			
		||||
                        {
 | 
			
		||||
                            LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") "
 | 
			
		||||
                                      << "TOW_sf=" << TOW;
 | 
			
		||||
//                            LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") "
 | 
			
		||||
//                                      << "TOW_sf=" << TOW;
 | 
			
		||||
                            d_satellite_nav_data[PRNa][TOW].ephemeris_iono_vector_2 = nav_data;
 | 
			
		||||
                        }
 | 
			
		||||
                    else if (nav_data.size() == 141)
 | 
			
		||||
                        {
 | 
			
		||||
                            LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") "
 | 
			
		||||
                                      << "TOW_sf=" << TOW;
 | 
			
		||||
//                            LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") "
 | 
			
		||||
//                                      << "TOW_sf=" << TOW;
 | 
			
		||||
                            d_satellite_nav_data[PRNa][TOW].utc_vector_2 = nav_data;
 | 
			
		||||
                        }
 | 
			
		||||
                    else
 | 
			
		||||
@@ -322,8 +322,8 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr<OSNMA_msg
 | 
			
		||||
        {
 | 
			
		||||
            d_tags_allowed = tags_to_verify::all;
 | 
			
		||||
            d_tags_to_verify = {0, 4, 12};
 | 
			
		||||
            LOG(INFO) << "Galileo OSNMA: time constraint OK (" << delta_T;
 | 
			
		||||
            LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS;
 | 
			
		||||
            LOG(INFO) << "Galileo OSNMA: time constraint OK ( delta_T=" << delta_T << " s)";
 | 
			
		||||
//            LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS;
 | 
			
		||||
            // std::cout << "( |local_t - GST_SIS| < T_L ) [ |" << static_cast<int>(d_receiver_time - d_GST_SIS)<< " | < " << static_cast<int>(d_T_L) << " ]" << std::endl;
 | 
			
		||||
 | 
			
		||||
            // TODO set flag to false to avoid processing dsm and MACK messages
 | 
			
		||||
@@ -914,13 +914,25 @@ void osnma_msg_receiver::process_mack_message()
 | 
			
		||||
                    bool ret = verify_macseq(*mack);
 | 
			
		||||
                    if (ret || d_flag_debug)
 | 
			
		||||
                        {
 | 
			
		||||
                            LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa;
 | 
			
		||||
                            for (std::size_t i = 0; i < mack->tag_and_info.size(); ++i)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // add tags of current mack to the verification queue
 | 
			
		||||
                                    auto& tag = mack->tag_and_info[i];
 | 
			
		||||
                                    Tag t(tag, mack->TOW, mack->WN, mack->PRNa, i + 2);  // tag0 (mack header) has CTR1, so first tag of MTI has CTR = 2.
 | 
			
		||||
                                    d_tags_awaiting_verify.insert(std::pair<uint32_t, Tag>(mack->TOW, t));
 | 
			
		||||
                                    LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa;
 | 
			
		||||
                                    LOG(INFO) << "Galileo OSNMA: Add Tag Id= "
 | 
			
		||||
                                              << t.tag_id
 | 
			
		||||
                                              << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase
 | 
			
		||||
                                              << t.received_tag << std::dec
 | 
			
		||||
                                              << ", TOW="
 | 
			
		||||
                                              << t.TOW
 | 
			
		||||
                                              << ", ADKD="
 | 
			
		||||
                                              << static_cast<unsigned>(t.ADKD)
 | 
			
		||||
                                              << ", PRNa="
 | 
			
		||||
                                              << static_cast<unsigned>(t.PRNa)
 | 
			
		||||
                                              << ", PRNd="
 | 
			
		||||
                                              << static_cast<unsigned>(t.PRN_d);
 | 
			
		||||
                                }
 | 
			
		||||
                            std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl;
 | 
			
		||||
                            mack = d_macks_awaiting_MACSEQ_verification.erase(mack);
 | 
			
		||||
@@ -1070,6 +1082,11 @@ bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message)
 | 
			
		||||
 | 
			
		||||
bool osnma_msg_receiver::verify_tag(Tag& tag)
 | 
			
		||||
{
 | 
			
		||||
    // Debug
 | 
			
		||||
    LOG(INFO) << "Galileo OSNMA: Tag verification :: Start for tag Id= "
 | 
			
		||||
              << tag.tag_id
 | 
			
		||||
              << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase
 | 
			
		||||
              << tag.received_tag << std::dec;
 | 
			
		||||
    // TODO case tag0, to be verified here?, PRNd not needed for it
 | 
			
		||||
    // build message
 | 
			
		||||
    std::vector<uint8_t> m = build_message(tag);
 | 
			
		||||
@@ -1077,9 +1094,16 @@ bool osnma_msg_receiver::verify_tag(Tag& tag)
 | 
			
		||||
    std::vector<uint8_t> mac;
 | 
			
		||||
    std::vector<uint8_t> applicable_key;
 | 
			
		||||
    if (tag.ADKD == 0 || tag.ADKD == 4)
 | 
			
		||||
        applicable_key = d_tesla_keys[tag.TOW + 30];
 | 
			
		||||
    else  // ADKD 12
 | 
			
		||||
        applicable_key = d_tesla_keys[tag.TOW + 330];
 | 
			
		||||
        {
 | 
			
		||||
            applicable_key = d_tesla_keys[tag.TOW + 30];
 | 
			
		||||
            LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<<static_cast<int>(tag.TOW + 30);
 | 
			
		||||
        }
 | 
			
		||||
        else  // ADKD 12
 | 
			
		||||
            {
 | 
			
		||||
                applicable_key = d_tesla_keys[tag.TOW + 330];
 | 
			
		||||
                LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<<static_cast<int>(tag.TOW + 330);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (d_osnma_data.d_dsm_kroot_message.mf == 0)  // C: HMAC-SHA-256
 | 
			
		||||
        {
 | 
			
		||||
@@ -1142,7 +1166,7 @@ bool osnma_msg_receiver::verify_tag(Tag& tag)
 | 
			
		||||
                      << ", PRNa="
 | 
			
		||||
                      << static_cast<unsigned>(tag.PRNa)
 | 
			
		||||
                      << ", PRNd="
 | 
			
		||||
                      << static_cast<unsigned>(tag.PRN_d);
 | 
			
		||||
                      << static_cast<unsigned>(tag.PRN_d) << std::endl;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    return false;
 | 
			
		||||
@@ -1171,10 +1195,12 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag)
 | 
			
		||||
    if (tag.ADKD == 0 || tag.ADKD == 12)  // note: for ADKD=12 still the same logic applies. Only the Key selection is shifted 10 Subframes into the future.
 | 
			
		||||
        {
 | 
			
		||||
            applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].ephemeris_iono_vector_2;
 | 
			
		||||
            LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data;
 | 
			
		||||
        }
 | 
			
		||||
    else if (tag.ADKD == 4)
 | 
			
		||||
        {
 | 
			
		||||
            applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].utc_vector_2;
 | 
			
		||||
            LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast<int>(tag.PRN_d)  << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data;
 | 
			
		||||
        }
 | 
			
		||||
    else
 | 
			
		||||
        LOG(WARNING) << "Galileo OSNMA :: Tag verification :: unknown ADKD";
 | 
			
		||||
@@ -1484,7 +1510,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t)
 | 
			
		||||
    if (prn_it != d_satellite_nav_data.end())
 | 
			
		||||
        {
 | 
			
		||||
            // 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;
 | 
			
		||||
            auto tow_it = tow_map.find(t.TOW - 30);
 | 
			
		||||
            if (tow_it != tow_map.end())
 | 
			
		||||
@@ -1500,7 +1526,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t)
 | 
			
		||||
    else
 | 
			
		||||
        {
 | 
			
		||||
            // PRN was not found
 | 
			
		||||
            LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl;
 | 
			
		||||
            //LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    return false;
 | 
			
		||||
@@ -1519,7 +1545,7 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t)
 | 
			
		||||
            auto it = d_tesla_keys.find(t.TOW + 30);
 | 
			
		||||
            if (it != d_tesla_keys.end())
 | 
			
		||||
                {
 | 
			
		||||
                    LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
 | 
			
		||||
                    //LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
@@ -1528,11 +1554,11 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t)
 | 
			
		||||
            auto it = d_tesla_keys.find(t.TOW + 330);
 | 
			
		||||
            if (it != d_tesla_keys.end())
 | 
			
		||||
                {
 | 
			
		||||
                    LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
 | 
			
		||||
                    //LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl;
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    LOG(INFO) << "Galileo OSNMA: hasKey = false ";
 | 
			
		||||
    //LOG(INFO) << "Galileo OSNMA: hasKey = false ";
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1601,6 +1627,6 @@ std::vector<uint8_t> osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede
 | 
			
		||||
    // compare computed current key against received key
 | 
			
		||||
    auto end = std::chrono::high_resolution_clock::now();
 | 
			
		||||
    std::chrono::duration<double> elapsed = end - start;
 | 
			
		||||
    LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds.";
 | 
			
		||||
//    LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds.";
 | 
			
		||||
    return K_II;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ public:
 | 
			
		||||
    ~osnma_msg_receiver() = default;  //!< Default destructor
 | 
			
		||||
private:
 | 
			
		||||
    friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath);
 | 
			
		||||
    osnma_msg_receiver(const std::string& pemFilePath, const std::string& merkleFilePath);
 | 
			
		||||
    osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath);
 | 
			
		||||
 | 
			
		||||
    void msg_handler_osnma(const pmt::pmt_t& msg);
 | 
			
		||||
    void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg);
 | 
			
		||||
 
 | 
			
		||||
@@ -1417,7 +1417,7 @@ OSNMA_msg Galileo_Inav_Message::get_osnma_msg()
 | 
			
		||||
    nma_position_filled = std::array<int8_t, 15>{};
 | 
			
		||||
    // Fill TOW and WN
 | 
			
		||||
    nma_msg.WN_sf0 = WN_0;
 | 
			
		||||
    int32_t TOW_sf0 = TOW_5 - 24; // according to OS SIS ICD, TOW of word 5 is 25 seconds after Sf start
 | 
			
		||||
    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)
 | 
			
		||||
        {
 | 
			
		||||
            TOW_sf0 += 604800;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@
 | 
			
		||||
 | 
			
		||||
#include "osnma_helper.h"
 | 
			
		||||
#include <bitset>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#include <ios>
 | 
			
		||||
 | 
			
		||||
uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const
 | 
			
		||||
{
 | 
			
		||||
@@ -74,3 +76,12 @@ std::string Osnma_Helper::verification_status_str(int status)
 | 
			
		||||
            default: return "UNKNOWN";
 | 
			
		||||
            }
 | 
			
		||||
}
 | 
			
		||||
std::string Osnma_Helper::convert_to_hex_string(const std::vector<uint8_t>& vector)
 | 
			
		||||
{
 | 
			
		||||
    std::stringstream ss;
 | 
			
		||||
    ss << std::hex << std::setfill('0');
 | 
			
		||||
    for (auto byte : vector) {
 | 
			
		||||
            ss << std::setw(2) << static_cast<int>(byte);
 | 
			
		||||
        }
 | 
			
		||||
    return ss.str();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ public:
 | 
			
		||||
    std::vector<uint8_t> gst_to_uint8(uint32_t GST) const;
 | 
			
		||||
    std::vector<uint8_t> bytes(const std::string& binaryString);
 | 
			
		||||
    std::string verification_status_str(int status);
 | 
			
		||||
    std::string convert_to_hex_string(const std::vector<uint8_t>& vector);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // GNSS_SDR_OSNMA_HELPER_H
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
#include <bitset>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <logging.h>
 | 
			
		||||
#include <osnma_msg_receiver.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
@@ -14,42 +15,39 @@ struct TestVector
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
// log_name, input_time, crtFilePath, merkleFilePath, testVectors
 | 
			
		||||
class OsnmaMsgReceiverTest : public ::testing::Test
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
    osnma_msg_receiver_sptr osnma;
 | 
			
		||||
    Galileo_Inav_Message galileo_message;
 | 
			
		||||
    uint8_t page_position_in_inav_subframe;
 | 
			
		||||
    bool flag_CRC_test;
 | 
			
		||||
    std::string page_even;
 | 
			
		||||
    OSNMA_msg osnma_msg{};
 | 
			
		||||
    std::array<int8_t, 15> nma_position_filled;
 | 
			
		||||
    uint32_t d_GST_SIS{};  // 16 AUG 2023 05 00 01
 | 
			
		||||
    uint32_t d_GST_SIS{};
 | 
			
		||||
    uint32_t TOW{};
 | 
			
		||||
    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
 | 
			
		||||
    const uint32_t LEAP_SECONDS = 0;                                 // 13 + 5;
 | 
			
		||||
    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;
 | 
			
		||||
    void set_time(std::tm& input);
 | 
			
		||||
    //    std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"};
 | 
			
		||||
    std::string log_name{"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
 | 
			
		||||
    // void initializeGoogleLog();
 | 
			
		||||
//    std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"};
 | 
			
		||||
    std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"};
 | 
			
		||||
    void initializeGoogleLog();
 | 
			
		||||
 | 
			
		||||
    void SetUp() override
 | 
			
		||||
    {
 | 
			
		||||
        flag_CRC_test = false;  // TODO what for?
 | 
			
		||||
        page_even = "";
 | 
			
		||||
 | 
			
		||||
        //        std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0};
 | 
			
		||||
        std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0};
 | 
			
		||||
        initializeGoogleLog();
 | 
			
		||||
//        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
 | 
			
		||||
        set_time(input_time);
 | 
			
		||||
        //        std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem";
 | 
			
		||||
        //        std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
 | 
			
		||||
        std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.pem";
 | 
			
		||||
//        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 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";
 | 
			
		||||
        osnma = osnma_msg_receiver_make(pemFilePath, 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);
 | 
			
		||||
@@ -57,85 +55,199 @@ public:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification)
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0)
 | 
			
		||||
{
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    // m0
 | 
			
		||||
    std::vector<uint8_t> expected_message =  {
 | 
			
		||||
        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,
 | 
			
		||||
        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,
 | 
			
		||||
        0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    uint32_t TOW_Tag0 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData = TOW_Tag0 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
 | 
			
		||||
    uint32_t WN = 1248;
 | 
			
		||||
    uint32_t PRNa = 2;
 | 
			
		||||
    uint8_t CTR = 1;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MACK_tag_and_info MTI;
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x00;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
    auto computed_message = osnma->build_message(t0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    // ----------
 | 
			
		||||
    ASSERT_TRUE(computed_message == expected_message);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, TagVerification) {
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    // Tag0
 | 
			
		||||
    uint32_t TOW_Tag0 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData = TOW_Tag0 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ;
 | 
			
		||||
    uint32_t WN = 1248;
 | 
			
		||||
    uint32_t PRNa = 2;
 | 
			
		||||
    uint8_t CTR = 1;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MACK_tag_and_info MTI;
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x00;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
    bool result_tag0 = osnma->verify_tag(t0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    // ----------
 | 
			
		||||
    //ASSERT_TRUE(result_tag0);
 | 
			
		||||
 | 
			
		||||
    // Tag3
 | 
			
		||||
    uint32_t TOW_Tag3 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ;
 | 
			
		||||
    WN = 1248;
 | 
			
		||||
    PRNa = 2;
 | 
			
		||||
    CTR = 3;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 =
 | 
			
		||||
        "111111111111111111111111111111110000000000000000000000010001001001001000"
 | 
			
		||||
        "111000001000100111100010010111111111011110111111111001001100000100000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0x7BB238C883);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x04;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t3(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
    bool result_tag3 = osnma->verify_tag(t3);
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(result_tag0 && result_tag3);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) {
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    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.ks = 4;                                                                                                    // TABLE 10 --> 128 bits
 | 
			
		||||
    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.alpha = 0x610BDF26D77B;
 | 
			
		||||
    // local_time_verification would do this operation. TODO - eliminate duplication.
 | 
			
		||||
    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_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_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_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
 | 
			
		||||
    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
 | 
			
		||||
    uint32_t TOW = 345630;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
    bool result = osnma->verify_tesla_key(key, TOW);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    // ----------
 | 
			
		||||
    ASSERT_TRUE(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
{
 | 
			
		||||
    // initializeGoogleLog();
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    //    std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv");
 | 
			
		||||
    std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv");
 | 
			
		||||
    if (testVectors.empty())
 | 
			
		||||
        {
 | 
			
		||||
//    std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); // conf. 1
 | 
			
		||||
    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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    bool end_of_hex_stream{false};
 | 
			
		||||
    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
 | 
			
		||||
    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_BYTES{SIZE_PAGE_BYTES * SIZE_SUBFRAME_PAGES};  // total bytes of a subframe
 | 
			
		||||
    const int DURATION_SUBFRAME{30};                                       // duration of a subframe, in seconds
 | 
			
		||||
    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_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 DUMMY_PAGE{63};
 | 
			
		||||
    bool flag_dummy_page{false};
 | 
			
		||||
    std::cout << "OsnmaTestVectorsSimulation:"
 | 
			
		||||
              << " d_GST_SIS= " << d_GST_SIS
 | 
			
		||||
              << ", TOW=" << TOW
 | 
			
		||||
              << ", WN=" << WN << std::endl;
 | 
			
		||||
    std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
 | 
			
		||||
    << ", TOW=" << TOW
 | 
			
		||||
    << ", WN=" << WN << std::endl;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
            for (const TestVector& tv : testVectors)
 | 
			
		||||
                {  // loop over all SVs, extract a subframe
 | 
			
		||||
                    std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) " << tv.svId << std::endl;
 | 
			
		||||
            for(const TestVector& tv : testVectors) { // 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>();
 | 
			
		||||
                    std::array<uint8_t, 15> hkroot{};
 | 
			
		||||
                    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)
 | 
			
		||||
                    std::map<uint8_t, std::bitset<128>> words;  // structure containing <WORD_NUMBER> and <EXTRACTED_BITS>
 | 
			
		||||
                    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>
 | 
			
		||||
 | 
			
		||||
                    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
 | 
			
		||||
                            std::vector<uint8_t> page_bytes = extract_page_bytes(tv, byte_index, SIZE_PAGE_BYTES);
 | 
			
		||||
                            if (page_bytes.empty())
 | 
			
		||||
                                {
 | 
			
		||||
                                    std::cout << "OsnmaTestVectorsSimulation: end of TestVectors \n"
 | 
			
		||||
                                              << "byte_index=" << byte_index << " expected= " << 432000 / 8 << std::endl;
 | 
			
		||||
                            std::vector<uint8_t> page_bytes = extract_page_bytes(tv,byte_index,SIZE_PAGE_BYTES);
 | 
			
		||||
                            if(page_bytes.empty()){
 | 
			
		||||
                                    std::cout<< "OsnmaTestVectorsSimulation: end of TestVectors \n" << "byte_index="<<byte_index<< " expected= " << 432000/8 << std::endl;
 | 
			
		||||
                                    end_of_hex_stream = true;
 | 
			
		||||
                                    break;
 | 
			
		||||
                                }
 | 
			
		||||
@@ -143,37 +255,33 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
                            std::string page_bits = bytes_to_str(page_bytes);
 | 
			
		||||
                            // Extract the 40 OSNMA bits starting from the 18th bit
 | 
			
		||||
                            std::string even_page = page_bits.substr(0, page_bits.size() / 2);
 | 
			
		||||
                            ;
 | 
			
		||||
                            std::string odd_page = page_bits.substr(page_bits.size() / 2);
 | 
			
		||||
                            if (even_page.size() < 120 || odd_page.size() < 120)
 | 
			
		||||
                                {
 | 
			
		||||
                                    std::cout << "OsnmaTestVectorsSimulation: error parsing pages" << std::endl;
 | 
			
		||||
                            std::string odd_page = page_bits.substr( page_bits.size() / 2);
 | 
			
		||||
                            if(even_page.size() < 120 || odd_page.size() < 120 ){
 | 
			
		||||
                                    std::cout<< "OsnmaTestVectorsSimulation: error parsing pages" << std::endl;
 | 
			
		||||
                                }
 | 
			
		||||
                            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 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)
 | 
			
		||||
                                std::cerr << "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
 | 
			
		||||
                            if(!even_odd_OK || !page_type_OK || !tail_bits_OK)
 | 
			
		||||
                                std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
 | 
			
		||||
 | 
			
		||||
                            std::bitset<112> data_k(even_page.substr(2, 112));
 | 
			
		||||
                            std::bitset<16> data_j(odd_page.substr(2, 16));
 | 
			
		||||
                            std::bitset<112> data_k(even_page.substr(2,112));
 | 
			
		||||
                            std::bitset<16> data_j(odd_page.substr(2,16));
 | 
			
		||||
                            std::bitset<112> shifted_data_k = data_k;
 | 
			
		||||
                            //                            uint8_t word_type = 0;
 | 
			
		||||
                            //                            for(int i = 0; i < 6; ++i) {
 | 
			
		||||
                            //                                    word_type |= (data_k[104 + i] << i);
 | 
			
		||||
                            //                                }
 | 
			
		||||
                            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;
 | 
			
		||||
                            if ((word_type >= 1 && word_type <= 5) || word_type == 6 || word_type == 10)
 | 
			
		||||
                            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;
 | 
			
		||||
                            if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // store raw word
 | 
			
		||||
                                    std::bitset<128> data_combined(data_k.to_string() + data_j.to_string());
 | 
			
		||||
                                    words[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;
 | 
			
		||||
 | 
			
		||||
                            // place it into osnma object.
 | 
			
		||||
                            std::bitset<40> osnmaBits(odd_page.substr(18, 40));
 | 
			
		||||
 | 
			
		||||
                            // Extract bits for hkroot and mack
 | 
			
		||||
                            std::bitset<8> hkrootBits(osnmaBits.to_string().substr(0, 8));
 | 
			
		||||
                            std::bitset<32> mackBits(osnmaBits.to_string().substr(8, 32));
 | 
			
		||||
@@ -183,13 +291,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
                            byte_index += SIZE_PAGE_BYTES;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    std::cout << "----------" << std::endl;
 | 
			
		||||
                    if (end_of_hex_stream)
 | 
			
		||||
                    std::cout<< "----------" << std::endl;
 | 
			
		||||
                    if(end_of_hex_stream)
 | 
			
		||||
                        break;
 | 
			
		||||
                    if (flag_dummy_page)
 | 
			
		||||
                        {
 | 
			
		||||
                    if(flag_dummy_page){
 | 
			
		||||
                            flag_dummy_page = false;
 | 
			
		||||
                            continue;  // skip this SV
 | 
			
		||||
                            continue; // skip this SV
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    // Fill osnma object
 | 
			
		||||
@@ -197,26 +304,26 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
                    osnmaMsg_sptr->mack = mack;
 | 
			
		||||
 | 
			
		||||
                    osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF;
 | 
			
		||||
                    osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20;
 | 
			
		||||
                    osnmaMsg_sptr->PRN = tv.svId;  // PRNa
 | 
			
		||||
                    osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ;
 | 
			
		||||
                    osnmaMsg_sptr->PRN = tv.svId; // PRNa
 | 
			
		||||
 | 
			
		||||
                    // TODO - refactor this logic, currently it is split
 | 
			
		||||
 | 
			
		||||
                    // check if words 1--> 5 words are received => fill EphClockStatus data vector
 | 
			
		||||
                    // check if words_for_OSNMA 1--> 5 words_for_OSNMA are received => fill EphClockStatus data vector
 | 
			
		||||
                    bool ephClockStatusWordsReceived = true;
 | 
			
		||||
                    for (int i = 1; i <= 5; ++i)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (words.find(i) == words.end())
 | 
			
		||||
                            if (words_for_OSNMA.find(i) == words_for_OSNMA.end())
 | 
			
		||||
                                {
 | 
			
		||||
                                    ephClockStatusWordsReceived = false;
 | 
			
		||||
                                    std::cerr << "OsnmaTestVectorsSimulation: error parsing words 1->5. "
 | 
			
		||||
                                                 "Word "
 | 
			
		||||
                                              << i << " should be received for each subframe but was not." << std::endl;
 | 
			
		||||
                                    std::cerr<< "OsnmaTestVectorsSimulation: error parsing words_for_OSNMA 1->5. "
 | 
			
		||||
                                                 "Word "<< i << " should be received for each subframe but was not." << std::endl;
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                    // extract bits as needed by osnma block
 | 
			
		||||
                    if (ephClockStatusWordsReceived)
 | 
			
		||||
                    if(ephClockStatusWordsReceived)
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
                            // Define the starting position and length of bits to extract for each word
 | 
			
		||||
                            std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
 | 
			
		||||
                                {1, {6, 120}},
 | 
			
		||||
@@ -226,41 +333,41 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
                                {5, {6, 67}},
 | 
			
		||||
                            };
 | 
			
		||||
 | 
			
		||||
                            // Fill NavData bits -- Iterate over the extraction parameters                            // Fill NavData bits -- Iterate over the extraction parameters
 | 
			
		||||
                            // Fill NavData bits -- Iterate over the extraction parameters
 | 
			
		||||
                            std::string nav_data_ADKD_0_12 = "";
 | 
			
		||||
                            for (const auto& param : extractionParams)
 | 
			
		||||
                                {
 | 
			
		||||
                            for (const auto& param : extractionParams) {
 | 
			
		||||
                                    uint8_t wordKey = param.first;
 | 
			
		||||
                                    uint8_t start = param.second.first;
 | 
			
		||||
                                    uint8_t length = param.second.second;
 | 
			
		||||
 | 
			
		||||
                                    // Extract the required bits and fill osnma block
 | 
			
		||||
                                    nav_data_ADKD_0_12 += words[wordKey].to_string().substr(start, length);
 | 
			
		||||
                                    nav_data_ADKD_0_12 += words_for_OSNMA[wordKey].to_string().substr(start, length);
 | 
			
		||||
                                }
 | 
			
		||||
                            // send to osnma block
 | 
			
		||||
                            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;
 | 
			
		||||
                                    const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>(  // < PRNd , navDataBits, TOW_Sosf>
 | 
			
		||||
                                    std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " << "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,
 | 
			
		||||
                                        nav_data_ADKD_0_12,
 | 
			
		||||
                                        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;
 | 
			
		||||
                                    osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
 | 
			
		||||
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    // check w6 && w10 is received => fill TimingData data vector
 | 
			
		||||
                    bool timingWordsReceived = words.find(6) != words.end() &&
 | 
			
		||||
                                               words.find(10) != words.end();
 | 
			
		||||
                    bool timingWordsReceived = words_for_OSNMA.find(6) != words_for_OSNMA.end() &&
 | 
			
		||||
                                               words_for_OSNMA.find(10) != words_for_OSNMA.end();
 | 
			
		||||
                    // extract bits as needed by osnma block
 | 
			
		||||
                    if (timingWordsReceived)
 | 
			
		||||
                        {
 | 
			
		||||
                    if(timingWordsReceived){
 | 
			
		||||
                            // Define the starting position and length of bits to extract for each word
 | 
			
		||||
                            std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
 | 
			
		||||
                                {6, {6, 99}},
 | 
			
		||||
                                {10, {86, 42}}};
 | 
			
		||||
                                {10, {86, 42}}
 | 
			
		||||
                            };
 | 
			
		||||
 | 
			
		||||
                            std::string nav_data_ADKD_4 = "";
 | 
			
		||||
                            // Fill NavData bits -- Iterate over the extraction parameters
 | 
			
		||||
@@ -271,42 +378,42 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
                                    uint8_t length = param.second.second;
 | 
			
		||||
 | 
			
		||||
                                    // Extract the required bits and fill osnma block
 | 
			
		||||
                                    nav_data_ADKD_4 += words[wordKey].to_string().substr(
 | 
			
		||||
                                        start, length);
 | 
			
		||||
                                    nav_data_ADKD_4 += words_for_OSNMA[wordKey].to_string().substr(start, length);
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                            // send to osnma block
 | 
			
		||||
                            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;
 | 
			
		||||
                                    const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>(  // < PRNd , navDataBits, TOW_Sosf>
 | 
			
		||||
                                    std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " << "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,
 | 
			
		||||
                                        nav_data_ADKD_4,
 | 
			
		||||
                                        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;
 | 
			
		||||
                                    osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma));
 | 
			
		||||
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    // Call the handler, as if it came from telemetry decoder block
 | 
			
		||||
                    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)
 | 
			
		||||
                {
 | 
			
		||||
                    offset_byte = byte_index;  // update offset for the next subframe
 | 
			
		||||
            if(!end_of_hex_stream){
 | 
			
		||||
                    offset_byte = byte_index; // update offset for the next subframe
 | 
			
		||||
                    d_GST_SIS += DURATION_SUBFRAME;
 | 
			
		||||
                    TOW = d_GST_SIS & 0x000FFFFF;
 | 
			
		||||
                    WN = (d_GST_SIS & 0xFFF00000) >> 20;
 | 
			
		||||
                    std::cout << "OsnmaTestVectorsSimulation:"
 | 
			
		||||
                              << " d_GST_SIS= " << d_GST_SIS
 | 
			
		||||
                    WN = (d_GST_SIS & 0xFFF00000) >> 20 ;
 | 
			
		||||
                    std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
 | 
			
		||||
                              << ", TOW=" << TOW
 | 
			
		||||
                              << ", WN=" << WN << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -316,24 +423,22 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
 | 
			
		||||
    // TODO - create global vars with failed tags and compare to total tags (Tag Id for example)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename)
 | 
			
		||||
{
 | 
			
		||||
    std::ifstream file(filename);
 | 
			
		||||
    std::vector<TestVector> testVectors;
 | 
			
		||||
    if (!file.is_open())
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << "Error reading the file \"" << filename << "\" \n";
 | 
			
		||||
    if (!file.is_open()) {
 | 
			
		||||
            std::cerr<<"Error reading the file \"" << filename <<"\" \n";
 | 
			
		||||
            return testVectors;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    std::string line;
 | 
			
		||||
    std::getline(file, line);
 | 
			
		||||
    if (line != "SVID,NumNavBits,NavBitsHEX\r")
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << "Error parsing first line"
 | 
			
		||||
                      << "\n";
 | 
			
		||||
        }
 | 
			
		||||
        if (line != "SVID,NumNavBits,NavBitsHEX\r" ){
 | 
			
		||||
                std::cerr<<"Error parsing first line" <<"\n";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
    while (std::getline(file, line))
 | 
			
		||||
        {
 | 
			
		||||
@@ -356,35 +461,29 @@ std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std:
 | 
			
		||||
 | 
			
		||||
    return testVectors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::vector<uint8_t> OsnmaMsgReceiverTest::parseNavBits(const std::string& hex)
 | 
			
		||||
{
 | 
			
		||||
    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);
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
    return bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes)
 | 
			
		||||
{
 | 
			
		||||
    std::string bit_string;
 | 
			
		||||
    bit_string.reserve(bytes.size() * 8);
 | 
			
		||||
    for (const auto& byte : bytes)
 | 
			
		||||
    for(const auto& byte : bytes)
 | 
			
		||||
        {
 | 
			
		||||
            std::bitset<8> bits(byte);
 | 
			
		||||
            bit_string += bits.to_string();
 | 
			
		||||
        }
 | 
			
		||||
    return bit_string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Extracts a range of bytes from a TestVector's navBits vector.
 | 
			
		||||
 *
 | 
			
		||||
@@ -413,8 +512,6 @@ std::vector<uint8_t> OsnmaMsgReceiverTest::extract_page_bytes(const TestVector&
 | 
			
		||||
 | 
			
		||||
    return extracted_bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sets the time based on the given input.
 | 
			
		||||
 *
 | 
			
		||||
@@ -438,118 +535,56 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input)
 | 
			
		||||
    uint32_t sec_in_week = 7 * 24 * 60 * 60;
 | 
			
		||||
    uint32_t week_number = duration_sec.count() / sec_in_week;
 | 
			
		||||
    uint32_t time_of_week = duration_sec.count() % sec_in_week;
 | 
			
		||||
    this->WN = week_number;
 | 
			
		||||
    this->TOW = time_of_week + LEAP_SECONDS;
 | 
			
		||||
    this->WN =  week_number;
 | 
			
		||||
    this->TOW =  time_of_week + LEAP_SECONDS;
 | 
			
		||||
    // Return the week number and time of week as a pair
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
    this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
 | 
			
		||||
    this->d_GST_SIS =  (this->WN  & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0)
 | 
			
		||||
void OsnmaMsgReceiverTest::initializeGoogleLog()
 | 
			
		||||
{
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    // m0
 | 
			
		||||
    std::vector<uint8_t> expected_message = {
 | 
			
		||||
        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,
 | 
			
		||||
        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,
 | 
			
		||||
        0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00};
 | 
			
		||||
 | 
			
		||||
    uint32_t TOW_Tag0 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData = TOW_Tag0 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
 | 
			
		||||
    uint32_t WN = 1248;
 | 
			
		||||
    uint32_t PRNa = 2;
 | 
			
		||||
    uint8_t CTR = 1;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MACK_tag_and_info MTI;
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x00;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
    auto computed_message = osnma->build_message(t0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    // ----------
 | 
			
		||||
    ASSERT_TRUE(computed_message == expected_message);
 | 
			
		||||
    google::InitGoogleLogging(log_name.c_str());
 | 
			
		||||
    FLAGS_minloglevel = 0; // INFO
 | 
			
		||||
    FLAGS_logtostderr = 0;  // add this line
 | 
			
		||||
    FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/build/src/tests/logs";
 | 
			
		||||
    if (FLAGS_log_dir.empty())
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << "Logging will be written at "
 | 
			
		||||
                      << std::filesystem::temp_directory_path()
 | 
			
		||||
                      << '\n'
 | 
			
		||||
                      << "Use gnss-sdr --log_dir=/path/to/log to change that.\n";
 | 
			
		||||
        }
 | 
			
		||||
    else
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
                {
 | 
			
		||||
                    const std::filesystem::path p(FLAGS_log_dir);
 | 
			
		||||
                    if (!std::filesystem::exists(p))
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cout << "The path "
 | 
			
		||||
                                      << FLAGS_log_dir
 | 
			
		||||
                                      << " does not exist, attempting to create it.\n";
 | 
			
		||||
                            std::error_code ec;
 | 
			
		||||
                            if (!std::filesystem::create_directory(p, ec))
 | 
			
		||||
                                {
 | 
			
		||||
                                    std::cout << "Could not create the " << FLAGS_log_dir << " folder.\n";
 | 
			
		||||
                                    gflags::ShutDownCommandLineFlags();
 | 
			
		||||
                                    throw std::runtime_error("Could not create folder for logs");
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                    std::cout << "Logging will be written at " << FLAGS_log_dir << '\n';
 | 
			
		||||
                }
 | 
			
		||||
            catch (const std::exception& e)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << e.what() << '\n';
 | 
			
		||||
                    std::cerr << "Could not create the " << FLAGS_log_dir << " folder.\n";
 | 
			
		||||
                    gflags::ShutDownCommandLineFlags();
 | 
			
		||||
                    throw;
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(OsnmaMsgReceiverTest, TagVerification)
 | 
			
		||||
{
 | 
			
		||||
    // Arrange
 | 
			
		||||
    // ----------
 | 
			
		||||
    // Tag0
 | 
			
		||||
    uint32_t TOW_Tag0 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData = TOW_Tag0 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30;
 | 
			
		||||
    uint32_t WN = 1248;
 | 
			
		||||
    uint32_t PRNa = 2;
 | 
			
		||||
    uint8_t CTR = 1;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MACK_tag_and_info MTI;
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0xE37BC4F858);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x00;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Act
 | 
			
		||||
    // ----------
 | 
			
		||||
    bool result_tag0 = osnma->verify_tag(t0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Assert
 | 
			
		||||
    // ----------
 | 
			
		||||
    // ASSERT_TRUE(result_tag0);
 | 
			
		||||
 | 
			
		||||
    // Tag3
 | 
			
		||||
    uint32_t TOW_Tag3 = 345660;
 | 
			
		||||
    uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30;
 | 
			
		||||
    uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30;
 | 
			
		||||
    WN = 1248;
 | 
			
		||||
    PRNa = 2;
 | 
			
		||||
    CTR = 3;
 | 
			
		||||
 | 
			
		||||
    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_osnma_data.d_dsm_kroot_message.mf = 0;
 | 
			
		||||
    osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 =
 | 
			
		||||
        "111111111111111111111111111111110000000000000000000000010001001001001000"
 | 
			
		||||
        "111000001000100111100010010111111111011110111111111001001100000100000000";
 | 
			
		||||
    osnma->d_osnma_data.d_nma_header.nmas = 0b10;
 | 
			
		||||
 | 
			
		||||
    MTI.tag = static_cast<uint64_t>(0x7BB238C883);
 | 
			
		||||
    MTI.tag_info.PRN_d = 0x02;
 | 
			
		||||
    MTI.tag_info.ADKD = 0x04;
 | 
			
		||||
    MTI.tag_info.cop = 0x0F;
 | 
			
		||||
    Tag t3(MTI, TOW_Tag0, WN, PRNa, CTR);
 | 
			
		||||
 | 
			
		||||
    bool result_tag3 = osnma->verify_tag(t3);
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(result_tag0 && result_tag3);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user