diff --git a/src/fsfw/osal/host/Clock.cpp b/src/fsfw/osal/host/Clock.cpp index 62f9d9d5f..d0acdfdf0 100644 --- a/src/fsfw/osal/host/Clock.cpp +++ b/src/fsfw/osal/host/Clock.cpp @@ -150,17 +150,14 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* time_tm.tm_hour = from->hour; time_tm.tm_min = from->minute; time_tm.tm_sec = from->second; + time_tm.tm_isdst = 0; - time_t seconds = mktime(&time_tm); + time_t seconds = timegm(&time_tm); to->tv_sec = seconds; to->tv_usec = from->usecond; // Fails in 2038.. return HasReturnvaluesIF::RETURN_OK; -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; -#endif - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index 7092e6b2b..61eb970ff 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -140,8 +140,9 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* fromTm.tm_hour = from->hour; fromTm.tm_min = from->minute; fromTm.tm_sec = from->second; + fromTm.tm_isdst = 0; - to->tv_sec = mktime(&fromTm); + to->tv_sec = timegm(&fromTm); to->tv_usec = from->usecond; return HasReturnvaluesIF::RETURN_OK; } diff --git a/src/fsfw/timemanager/CCSDSTime.cpp b/src/fsfw/timemanager/CCSDSTime.cpp index 290d58dce..c5132cbb0 100644 --- a/src/fsfw/timemanager/CCSDSTime.cpp +++ b/src/fsfw/timemanager/CCSDSTime.cpp @@ -557,6 +557,35 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t return RETURN_OK; } +ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short* from) { + if (to == nullptr or from == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + uint16_t days = (from->dayMSB << 8) + from->dayLSB; + if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) { + return INVALID_TIME_FORMAT; + } + days -= DAYS_CCSDS_TO_UNIX_EPOCH; + to->tv_sec = days * SECONDS_PER_DAY; + uint32_t msDay = + (from->msDay_hh << 24) + (from->msDay_h << 16) + (from->msDay_l << 8) + from->msDay_ll; + to->tv_sec += (msDay / 1000); + to->tv_usec = (msDay % 1000) * 1000; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime::CDS_short* from) { + if (to == nullptr or from == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeval tempTimeval; + ReturnValue_t result = convertFromCDS(&tempTimeval, from); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CCSDSTime::convertTimevalToTimeOfDay(to, &tempTimeval); +} + ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from, size_t* foundLength, size_t maxLength) { uint32_t secs = 0; diff --git a/src/fsfw/timemanager/CCSDSTime.h b/src/fsfw/timemanager/CCSDSTime.h index 4a0e1bfc4..9de41e097 100644 --- a/src/fsfw/timemanager/CCSDSTime.h +++ b/src/fsfw/timemanager/CCSDSTime.h @@ -180,6 +180,8 @@ class CCSDSTime : public HasReturnvaluesIF { static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from, size_t *foundLength, size_t maxLength); + static ReturnValue_t convertFromCDS(timeval *to, const CCSDSTime::CDS_short *from); + static ReturnValue_t convertFromCDS(Clock::TimeOfDay_t *to, const CCSDSTime::CDS_short *from); static ReturnValue_t convertFromCCS(Clock::TimeOfDay_t *to, uint8_t const *from, size_t *foundLength, size_t maxLength); diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp index fb22972e3..077625959 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -93,10 +94,8 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { poolOwner->dataset.setChanged(true); /* Store current time, we are going to check the (approximate) time equality later */ - CCSDSTime::CDS_short timeCdsNow; timeval now; Clock::getClock_timeval(&now); - CCSDSTime::convertToCcsds(&timeCdsNow, &now); /* Trigger generation of snapshot */ REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); @@ -131,13 +130,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { CHECK(newSet.localPoolUint16Vec.value[2] == 42932); /* Now we check that both times are equal */ - CHECK(cdsShort.pField == timeCdsNow.pField); - CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1)); - CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1)); - CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1)); - CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1)); - CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1)); - CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5)); + timeval timeFromHK; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); } SECTION("VariableSnapshotTest") { @@ -158,13 +155,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { } poolVar->setChanged(true); - /* Store current time, we are going to check the (approximate) time equality later */ CCSDSTime::CDS_short timeCdsNow; timeval now; Clock::getClock_timeval(&now); - CCSDSTime::convertToCcsds(&timeCdsNow, &now); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); /* Check update snapshot was sent. */ @@ -193,13 +187,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { CHECK(varCopy.value == 25); /* Now we check that both times are equal */ - CHECK(cdsShort.pField == timeCdsNow.pField); - CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1)); - CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1)); - CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1)); - CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1)); - CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1)); - CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5)); + timeval timeFromHK; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); } SECTION("VariableNotificationTest") { diff --git a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp index 89713488b..2e80487aa 100644 --- a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp +++ b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -89,4 +90,43 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { REQUIRE(timeTo.second == 59); REQUIRE(timeTo.usecond == Catch::Approx(123000)); } + + SECTION("CDS Conversions") { + // Preperation + Clock::TimeOfDay_t time; + time.year = 2020; + time.month = 2; + time.day = 29; + time.hour = 13; + time.minute = 24; + time.second = 45; + time.usecond = 123456; + timeval timeAsTimeval; + auto result = Clock::convertTimeOfDayToTimeval(&time, &timeAsTimeval); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(timeAsTimeval.tv_sec == 1582982685); + CHECK(timeAsTimeval.tv_usec == 123456); + + // Conversion to CDS Short + CCSDSTime::CDS_short cdsTime; + result = CCSDSTime::convertToCcsds(&cdsTime, &timeAsTimeval); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + // Days in CCSDS Epoch 22704 (0x58B0) + CHECK(cdsTime.dayMSB == 0x58); + CHECK(cdsTime.dayLSB == 0xB0); + // MS of day 48285123.456 (floored here) + CHECK(cdsTime.msDay_hh == 0x2); + CHECK(cdsTime.msDay_h == 0xE0); + CHECK(cdsTime.msDay_l == 0xC5); + CHECK(cdsTime.msDay_ll == 0xC3); + + // Conversion back to timeval + timeval timeReturnAsTimeval; + result = CCSDSTime::convertFromCDS(&timeReturnAsTimeval, &cdsTime); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + // micro seconds precision is lost + timeval difference = timeAsTimeval - timeReturnAsTimeval; + CHECK(difference.tv_usec == 456); + CHECK(difference.tv_sec == 0); + } } \ No newline at end of file