2021-07-13 20:58:45 +02:00
|
|
|
#include "fsfw/timemanager/Clock.h"
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
#include <linux/sysinfo.h>
|
2022-02-02 10:29:30 +01:00
|
|
|
#include <sys/sysinfo.h>
|
2018-07-12 16:29:32 +02:00
|
|
|
#include <unistd.h>
|
2022-02-02 10:29:30 +01:00
|
|
|
|
2022-07-25 19:36:56 +02:00
|
|
|
#include <ctime>
|
2020-09-22 15:57:26 +02:00
|
|
|
#include <fstream>
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2022-03-25 18:47:31 +01:00
|
|
|
#include "fsfw/ipc/MutexGuard.h"
|
2022-03-25 18:48:53 +01:00
|
|
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2022-07-25 10:56:19 +02:00
|
|
|
uint32_t Clock::getTicksPerSecond() {
|
2022-02-02 10:29:30 +01:00
|
|
|
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
|
|
|
return ticks;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timespec timeUnix{};
|
|
|
|
timeval timeTimeval{};
|
2022-02-02 10:29:30 +01:00
|
|
|
convertTimeOfDayToTimeval(time, &timeTimeval);
|
|
|
|
timeUnix.tv_sec = timeTimeval.tv_sec;
|
|
|
|
timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000;
|
|
|
|
|
|
|
|
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
|
|
|
|
if (status != 0) {
|
|
|
|
// TODO errno
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::setClock(const timeval* time) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timespec timeUnix{};
|
2022-02-02 10:29:30 +01:00
|
|
|
timeUnix.tv_sec = time->tv_sec;
|
|
|
|
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
|
|
|
|
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
|
|
|
|
if (status != 0) {
|
|
|
|
// TODO errno
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timespec timeUnix{};
|
2022-02-02 10:29:30 +01:00
|
|
|
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
|
|
|
if (status != 0) {
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
time->tv_sec = timeUnix.tv_sec;
|
|
|
|
time->tv_usec = timeUnix.tv_nsec / 1000.0;
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timeval timeVal{};
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t result = getClock_timeval(&timeVal);
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
2022-07-25 10:56:19 +02:00
|
|
|
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
|
2022-02-02 10:29:30 +01:00
|
|
|
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-05-29 17:47:55 +02:00
|
|
|
timeval Clock::getUptime() {
|
2022-07-25 10:56:19 +02:00
|
|
|
timeval uptime{};
|
2022-02-02 10:29:30 +01:00
|
|
|
auto result = getUptime(&uptime);
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "Clock::getUptime: Error getting uptime" << std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
return uptime;
|
2020-05-29 17:47:55 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
2022-02-02 10:29:30 +01:00
|
|
|
double uptimeSeconds;
|
2023-03-15 12:21:50 +01:00
|
|
|
std::ifstream ifile("/proc/uptime");
|
|
|
|
if (ifile.bad()) {
|
|
|
|
return returnvalue::FAILED;
|
|
|
|
}
|
|
|
|
if (ifile >> uptimeSeconds) {
|
2022-02-02 10:29:30 +01:00
|
|
|
uptime->tv_sec = uptimeSeconds;
|
|
|
|
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
2023-03-15 12:21:50 +01:00
|
|
|
return returnvalue::OK;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2023-03-15 12:21:50 +01:00
|
|
|
return returnvalue::FAILED;
|
2020-12-14 21:46:33 +01:00
|
|
|
}
|
2020-09-18 12:58:38 +02:00
|
|
|
|
2020-12-14 21:46:33 +01:00
|
|
|
// Wait for new FSFW Clock function delivering seconds uptime.
|
2022-02-02 10:29:30 +01:00
|
|
|
// uint32_t Clock::getUptimeSeconds() {
|
2020-12-14 21:46:33 +01:00
|
|
|
// //TODO This is not posix compatible and delivers only seconds precision
|
2020-09-18 12:58:38 +02:00
|
|
|
// struct sysinfo sysInfo;
|
|
|
|
// int result = sysinfo(&sysInfo);
|
|
|
|
// if(result != 0){
|
2022-08-16 12:29:53 +02:00
|
|
|
// return returnvalue::FAILED;
|
2020-09-18 12:58:38 +02:00
|
|
|
// }
|
|
|
|
// return sysInfo.uptime;
|
2020-12-14 21:46:33 +01:00
|
|
|
//}
|
2018-07-12 16:29:32 +02:00
|
|
|
|
|
|
|
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timeval uptime{};
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t result = getUptime(&uptime);
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
*uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
2022-07-25 10:56:19 +02:00
|
|
|
timespec timeUnix{};
|
2022-02-02 10:29:30 +01:00
|
|
|
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
|
|
|
if (status != 0) {
|
|
|
|
// TODO errno
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2022-03-25 18:47:31 +01:00
|
|
|
ReturnValue_t result = checkOrCreateClockMutex();
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-03-25 18:47:31 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
MutexGuard helper(timeMutex);
|
|
|
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
|
|
|
// Therefore we have to use a Mutex here
|
2022-07-25 10:56:19 +02:00
|
|
|
struct std::tm* timeInfo;
|
2022-02-02 10:29:30 +01:00
|
|
|
timeInfo = gmtime(&timeUnix.tv_sec);
|
|
|
|
time->year = timeInfo->tm_year + 1900;
|
|
|
|
time->month = timeInfo->tm_mon + 1;
|
|
|
|
time->day = timeInfo->tm_mday;
|
|
|
|
time->hour = timeInfo->tm_hour;
|
|
|
|
time->minute = timeInfo->tm_min;
|
|
|
|
time->second = timeInfo->tm_sec;
|
|
|
|
time->usecond = timeUnix.tv_nsec / 1000.0;
|
|
|
|
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
|
2022-07-25 10:56:19 +02:00
|
|
|
std::tm fromTm{};
|
2022-02-02 10:29:30 +01:00
|
|
|
// Note: Fails for years before AD
|
|
|
|
fromTm.tm_year = from->year - 1900;
|
|
|
|
fromTm.tm_mon = from->month - 1;
|
|
|
|
fromTm.tm_mday = from->day;
|
|
|
|
fromTm.tm_hour = from->hour;
|
|
|
|
fromTm.tm_min = from->minute;
|
|
|
|
fromTm.tm_sec = from->second;
|
2022-03-07 18:22:10 +01:00
|
|
|
fromTm.tm_isdst = 0;
|
2022-02-02 10:29:30 +01:00
|
|
|
|
2022-03-07 18:22:10 +01:00
|
|
|
to->tv_sec = timegm(&fromTm);
|
2022-02-02 10:29:30 +01:00
|
|
|
to->tv_usec = from->usecond;
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
2022-02-02 10:29:30 +01:00
|
|
|
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|