mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-18 21:23:02 +00:00
[TAS-177] implement OsnmaTestVectorsSimulation
This commit introduces two new unit tests for the osnma_msg_receiver class: 'TeslaKeyVerification' and 'OsnmaTestVectorsSimulation'. The first test verifies the Tesla key handling within the class. The second test uses real-world test vectors to simulate osnma message receiving and verifies correct parsing and processing of messages.
This commit is contained in:
parent
881bb5c58a
commit
e13fc39214
@ -149,6 +149,7 @@ void osnma_msg_receiver::read_nma_header(uint8_t nma_header)
|
||||
d_osnma_data.d_nma_header.cid = d_dsm_reader->get_cid(nma_header);
|
||||
d_osnma_data.d_nma_header.cpks = d_dsm_reader->get_cpks(nma_header);
|
||||
d_osnma_data.d_nma_header.reserved = d_dsm_reader->get_nma_header_reserved(nma_header);
|
||||
std::cout<< "NMAS: " << static_cast<int>(d_osnma_data.d_nma_header.nmas) << " CPKS: " << static_cast<int>(d_osnma_data.d_nma_header.cpks) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@ -438,7 +439,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector<uint8_t>& dsm_msg
|
||||
// Check that the padding bits received match the computed values
|
||||
if (d_osnma_data.d_dsm_kroot_message.p_dk == p_dk_truncated)
|
||||
{
|
||||
LOG(WARNING) << "OSNMA: DSM-KROOT message received ok.";
|
||||
LOG(WARNING) << "Galileo OSNMA: DSM-KROOT message received ok.";
|
||||
std::cout << "Galileo OSNMA: KROOT with CID=" << static_cast<uint32_t>(d_osnma_data.d_nma_header.cid)
|
||||
<< ", PKID=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.pkid)
|
||||
<< ", WN=" << static_cast<uint32_t>(d_osnma_data.d_dsm_kroot_message.wn_k)
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#ifndef GNSS_SDR_OSNMA_MSG_RECEIVER_H
|
||||
#define GNSS_SDR_OSNMA_MSG_RECEIVER_H
|
||||
#define FRIEND_TEST(test_case_name, test_name)\
|
||||
friend class test_case_name##_##test_name##_Test
|
||||
|
||||
#include "galileo_inav_message.h" // for OSNMA_msg
|
||||
#include "gnss_block_interface.h" // for gnss_shared_ptr
|
||||
@ -54,7 +56,6 @@ class osnma_msg_receiver : public gr::block
|
||||
{
|
||||
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);
|
||||
@ -115,6 +116,9 @@ private:
|
||||
void remove_verified_tags();
|
||||
void control_tags_awaiting_verify_size();
|
||||
bool verify_macseq(const MACK_message& mack);
|
||||
|
||||
FRIEND_TEST(OsnmaMsgReceiverTest, TeslaKeyVerification);
|
||||
FRIEND_TEST(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1302,3 +1302,37 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
|
||||
#${GNSSSDR_SOURCE_DIR}/src/core/receiver,
|
||||
${GNSSSDR_SOURCE_DIR}/src/core/system_parameters)
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA)
|
||||
set(OSNMA_MSG_RECEIVER_TEST_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc)
|
||||
|
||||
# Configure the test executable:
|
||||
if(USE_CMAKE_TARGET_SOURCES)
|
||||
add_executable(osnma_msg_receiver_test)
|
||||
target_sources(osnma_msg_receiver_test PRIVATE ${OSNMA_MSG_RECEIVER_TEST_SOURCES})
|
||||
else()
|
||||
add_executable(osnma_msg_receiver_test ${OSNMA_MSG_RECEIVER_TEST_SOURCES})
|
||||
endif()
|
||||
|
||||
# Link libraries that gnss_crypto_test requires:
|
||||
target_link_libraries(osnma_msg_receiver_test
|
||||
PRIVATE
|
||||
Boost::thread
|
||||
Gflags::gflags
|
||||
Glog::glog
|
||||
GTest::GTest
|
||||
GTest::Main
|
||||
core_libs
|
||||
)
|
||||
|
||||
# Include any directories your test needs for header files:
|
||||
target_include_directories(osnma_msg_receiver_test
|
||||
PRIVATE
|
||||
#${GNSSSDR_SOURCE_DIR}/src/algorithms,
|
||||
#${GNSSSDR_SOURCE_DIR}/src/core,
|
||||
#${GNSSSDR_SOURCE_DIR}/src/core/receiver,
|
||||
${GNSSSDR_SOURCE_DIR}/src/core/system_parameters)
|
||||
endif()
|
@ -73,6 +73,7 @@ DECLARE_string(log_dir);
|
||||
#include "unit-tests/signal-processing-blocks/adapter/pass_through_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/libs/item_type_helpers_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/pvt/geohash_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc"
|
||||
|
@ -8,21 +8,21 @@ TEST(GnssCryptoTest, VerifySignature) {
|
||||
// "../data/OSNMA_PublicKey_20240115100000_newPKID_1.pem"
|
||||
std::unique_ptr<Gnss_Crypto> d_crypto = std::make_unique<Gnss_Crypto>();
|
||||
|
||||
// RG example - import crt certificate
|
||||
// std::vector<uint8_t> message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF};
|
||||
// std::vector<uint8_t> signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB};
|
||||
// std::vector<uint8_t> publicKey { // PEM format - 1000 bits
|
||||
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
|
||||
//
|
||||
// 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
|
||||
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
|
||||
// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D,
|
||||
//
|
||||
// 0x0A,
|
||||
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ;
|
||||
// RG example - import crt certificate - result: FAIL
|
||||
//std::vector<uint8_t> message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF};
|
||||
//std::vector<uint8_t> signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB};
|
||||
//std::vector<uint8_t> publicKey { // PEM format - 1000 bits
|
||||
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A,
|
||||
//
|
||||
// 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49,
|
||||
// 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37,
|
||||
// 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D,
|
||||
//
|
||||
// 0x0A,
|
||||
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A } ;
|
||||
|
||||
// own ECDSA-P256 key and message generated and signed and verified successfully with openssl
|
||||
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A al final. Raw message
|
||||
std::vector<uint8_t> message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A }; // Hello world con 0x0A al final. Raw message (unhashed)
|
||||
std::vector<uint8_t> signature{0x30, 0x45, 0x02, 0x21, 0x00, 0xFB, 0xE6, 0x09, 0x74, 0x5C, 0x12, 0xE8, 0x2C, 0x0C, 0xC9, 0x7A, 0x8E, 0x13, 0x88, 0x87, 0xDA, 0xBF, 0x08, 0x43, 0xF8, 0xC8, 0x93, 0x16, 0x5A,
|
||||
0x0F, 0x7A, 0xA4, 0xBF, 0x4A, 0xE1, 0xE1, 0xDB, 0x02, 0x20, 0x6B, 0xCB, 0x2F, 0x80, 0x69, 0xBB, 0xDE, 0xC9, 0x11, 0x1D, 0x51, 0x2B, 0x9F, 0x61, 0xA0, 0xC1, 0x29, 0xD1, 0x0B,
|
||||
0x58, 0x09, 0x82, 0x58, 0xFC, 0x9E, 0x00, 0xC7, 0xEE, 0xA5, 0xB9, 0xB2, 0x56}; // Hello world hashed and then encrypted with PrK
|
||||
@ -56,6 +56,8 @@ TEST(GnssCryptoTest, VerifySignature) {
|
||||
// 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6B, 0x6A, 0x4F, 0x50, 0x51, 0x4D, 0x42, 0x41, 0x67, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D,
|
||||
// 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A };
|
||||
|
||||
|
||||
|
||||
d_crypto->set_public_key(publicKey);
|
||||
bool result = d_crypto->verify_signature(message, signature);
|
||||
|
||||
|
@ -0,0 +1,265 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <fstream>
|
||||
#include <osnma_msg_receiver.h>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
|
||||
struct TestVector
|
||||
{
|
||||
int svId;
|
||||
int numNavBits;
|
||||
std::vector<uint8_t> navBits;
|
||||
};
|
||||
|
||||
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
|
||||
int T {};
|
||||
uint32_t TOW{};
|
||||
uint32_t WN{};
|
||||
void set_time(std::tm& input);
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
flag_CRC_test = false;
|
||||
page_even = "";
|
||||
|
||||
std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0};
|
||||
set_time(input_time);
|
||||
std::string pemFilePath = "OSNMA_PublicKey_20230803105952_newPKID_1.pem";
|
||||
std::string merkleFilePath = "OSNMA_MerkleTree_20230803105953_newPKID_1.xml";
|
||||
osnma = osnma_msg_receiver_make(pemFilePath, merkleFilePath);
|
||||
}
|
||||
|
||||
public:
|
||||
static std::vector<uint8_t> parseNavBits(const std::string& hex);
|
||||
static std::vector<TestVector> readTestVectorsFromFile(const std::string& filename);
|
||||
std::string bytes_to_str(const std::vector<uint8_t>& bytes);
|
||||
std::vector<uint8_t> extract_page_bytes(const TestVector& tv, const int byte_index, const int num_bytes);
|
||||
};
|
||||
|
||||
|
||||
TEST_F(OsnmaMsgReceiverTest, 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};
|
||||
osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits
|
||||
osnma->d_receiver_time = 345630;
|
||||
osnma->d_GST_0 = 345600;
|
||||
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})));
|
||||
std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB};
|
||||
uint32_t TOW = 345630;
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
bool result = osnma->verify_tesla_key(key, TOW);
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result); // Adjust this according to what you expect
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
||||
{
|
||||
// Arrange
|
||||
std::vector<TestVector> testVectors = readTestVectorsFromFile(/*"/home/cgm/CLionProjects/osnma/src/tests/data/*/"16_AUG_2023_GST_05_00_01.csv");
|
||||
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};
|
||||
const int SIZE_SUBFRAME_PAGES{15};
|
||||
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES};
|
||||
const int DURATION_SUBFRAME{30};
|
||||
|
||||
std::cout << "OsnmaTestVectorsSimulation:" << std::endl;
|
||||
std::cout << "d_GST_SIS: " << d_GST_SIS << std::endl;
|
||||
std::cout << "T: " << T << std::endl;
|
||||
std::cout << "TOW: " << TOW << std::endl;
|
||||
std::cout << "WN: " << WN << std::endl;
|
||||
|
||||
|
||||
// Act
|
||||
while (end_of_hex_stream == false){ // loop over all bytes of data. Note all TestVectors have same amount of data.
|
||||
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe
|
||||
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)
|
||||
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;
|
||||
end_of_hex_stream = true;
|
||||
break;
|
||||
}
|
||||
// convert them to bitset representation using bytes_to_string
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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));
|
||||
hkroot[idx] = static_cast<uint8_t>(hkrootBits.to_ulong());
|
||||
mack[idx] = static_cast<uint32_t>(mackBits.to_ulong());
|
||||
|
||||
byte_index += SIZE_PAGE_BYTES;
|
||||
}
|
||||
if(end_of_hex_stream)
|
||||
break;
|
||||
osnmaMsg_sptr->hkroot = hkroot;
|
||||
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;
|
||||
|
||||
auto temp_obj = pmt::make_any(osnmaMsg_sptr);
|
||||
|
||||
osnma->msg_handler_osnma(temp_obj); // osnma entry point
|
||||
}
|
||||
|
||||
|
||||
if(!end_of_hex_stream){
|
||||
offset_byte = byte_index; // update offset for the next subframe
|
||||
d_GST_SIS += DURATION_SUBFRAME;
|
||||
T = d_GST_SIS % 30;
|
||||
TOW = d_GST_SIS & 0x000FFFFF;
|
||||
WN = (d_GST_SIS & 0xFFF00000) >> 20 ;
|
||||
std::cout << "OsnmaTestVectorsSimulation:" << std::endl;
|
||||
std::cout << "d_GST_SIS: " << d_GST_SIS << std::endl;
|
||||
std::cout << "T: " << T << std::endl;
|
||||
std::cout << "TOW: " << TOW << std::endl;
|
||||
std::cout << "WN: " << WN << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Assert
|
||||
// TODO
|
||||
}
|
||||
|
||||
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";
|
||||
return testVectors;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
std::getline(file, line);
|
||||
if (line != "SVID,NumNavBits,NavBitsHEX\r" ){
|
||||
std::cerr<<"Error parsing first line" <<"\n";
|
||||
}
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
std::stringstream ss(line);
|
||||
TestVector tv;
|
||||
|
||||
std::string val;
|
||||
|
||||
std::getline(ss, val, ',');
|
||||
tv.svId = std::stoi(val);
|
||||
|
||||
std::getline(ss, val, ',');
|
||||
tv.numNavBits = std::stoi(val);
|
||||
|
||||
std::getline(ss, val, ',');
|
||||
tv.navBits = OsnmaMsgReceiverTest::parseNavBits(val);
|
||||
|
||||
testVectors.push_back(tv);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::string byteString = hex.substr(i, 2);
|
||||
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)
|
||||
{
|
||||
std::bitset<8> bits(byte);
|
||||
bit_string += bits.to_string();
|
||||
}
|
||||
return bit_string;
|
||||
}
|
||||
std::vector<uint8_t> OsnmaMsgReceiverTest::extract_page_bytes(const TestVector& tv, const int byte_index, const int num_bytes)
|
||||
{
|
||||
// Ensure we don't go beyond the end of tv.navBits
|
||||
int num_bytes_to_extract = std::min(num_bytes, static_cast<int>(tv.navBits.size() - byte_index));
|
||||
|
||||
// If byte_index is beyond the end of tv.navBits, return an empty vector
|
||||
if (num_bytes_to_extract <= 0)
|
||||
{
|
||||
return std::vector<uint8_t>();
|
||||
}
|
||||
|
||||
// Use std::next to get an iterator to the range to extract
|
||||
std::vector<uint8_t> extracted_bytes(tv.navBits.begin() + byte_index, tv.navBits.begin() + byte_index + num_bytes_to_extract);
|
||||
|
||||
return extracted_bytes;
|
||||
}
|
||||
|
||||
void OsnmaMsgReceiverTest::set_time(std::tm& input)
|
||||
{
|
||||
// GST epoch (start of GST time)
|
||||
std::tm tm_epoch = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0};
|
||||
|
||||
auto epoch_time_point = std::chrono::system_clock::from_time_t(mktime(&tm_epoch));
|
||||
auto input_time_point = std::chrono::system_clock::from_time_t(mktime(&input));
|
||||
|
||||
// Get the duration from epoch in seconds
|
||||
auto duration_sec = std::chrono::duration_cast<std::chrono::seconds>(input_time_point - epoch_time_point);
|
||||
|
||||
// Calculate the week number (WN) and time of week (TOW)
|
||||
uint32_t sec_in_week = 7 * 24 * 60 * 60;
|
||||
uint32_t week_number = duration_sec.count() / sec_in_week;
|
||||
uint32_t time_of_week = duration_sec.count() % sec_in_week;
|
||||
this->WN = week_number;
|
||||
this->TOW = time_of_week;
|
||||
// Return the week number and time of week as a pair
|
||||
|
||||
this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF);
|
||||
this->T = d_GST_SIS % 30;
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user