1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-12 19:20:32 +00:00

[TAS-227] [BUG] Tag verification fails for .dat files (WIP)

WIP
This commit is contained in:
cesaaargm 2024-06-26 15:01:05 +02:00
parent 82ef50f8dd
commit 1d815f0bbf
7 changed files with 369 additions and 294 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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