Установка системного времени с помощью структуры gps timestamp_t в Linux

Установка системного времени с помощью структуры gps timestamp_t в Linux

Всем привет,

Я пытаюсь написать код, который, как только я получаю успешную блокировку GPS (Adafruit Ultimate GPS с GPSD), устанавливаю системное время. Прямо сейчас я вижу, что 'timestamp_t':

typedef double timestamp_t; /* Unix time in seconds with fractional part */

является частью моей структуры "gps_data_t*". Это хорошее начало, однако функция, которую я планировал использовать для установки системного времени в Linux, такова:

int settimeofday(const struct timeval *tv, const struct timezone *tz);

Я нашел информацию о том, как преобразовать time_t в *timeval, но как мне обработать этот двойной код, чтобы преобразовать его в *timeval?

Код:

gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);

if (gps_rec.stream(WATCH_ENABLE|WATCH_JSON) == NULL) {
    std::cout << "No GPSD running. exiting GPS thread." << std::endl;
    return;
}

//Data structure
struct gps_data_t* newdata;

//Loop until first GPS lock to set system time
while ((newdata = gps_rec.read()) == NULL) {
    //Wait for a valid read
}

//Set system time - timestamp_t vs timeval?
timeval *tv{?? newdata->time ??};
timezone *tz{ timezone(300, DST_USA)};
settimeofday(tv, tz);

Некоторые комментарии и ссылки помогли мне. Путаница заключается в различии между timeval, time_t и timestamp_t. Насколько я понял вот отличия, поправьте если не так:

Все время в секундах после 1 января 1970 года, но...

timeval — это структура из (2) длинных значений, tv_sec — это секунды после 01.01.1970, tv_usec — микросекунды после этого.

time_t длинный? это также секунды после 01.01.1970

timestamp_t — это двойное число, которое равно секундам после 01.01.1970, поэтому десятичная часть может вычислять микросекунды, чтобы получить «примерно» ту же точность timeval.

Таким образом, преобразование между всеми из них может быть таким:

timeval time;
time_t timet;
timestamp_t timestampt;

timet = time.tv_sec;   //usec dropped
timet = timestampt;    //usec dropped
timestampt = timet;    //usec not given
timestampt = time.tv_sec;
timestampt += (time.tv_usec / 1000000)  //Denominator may be off by a few 0's

Является ли эта картина более четкой картиной?


Чтобы пойти в обратном направлении, что и нужно для моего приложения:

//Convert gps_data_t* member 'time' to timeval
timeval tv;
double wholeseconds, decimalseconds;
decimalseconds = modf(newdata->time, &wholeseconds);
tv.sec = static_cast<int32_t>(wholeseconds);
tv.usec = static_cast<int32_t>(decimalseconds * 1000000.0);

//Create timezone
timezone tz{ timezone(300, DST_USA)};

//Set system time
settimeofday(&tv, &tz);

person DrTarr    schedule 08.11.2016    source источник
comment
Прежде всего, только потому, что функция ожидает указатель на структуру, не означает, что вы должны объявить переменную указателем. Вы, должно быть, где-то читали об операторе адреса &.   -  person Some programmer dude    schedule 08.11.2016
comment
Да, я не думаю, что путаница связана с тем, что требует функция settimeofday, структура timeval довольно ясна. Это структура timestamp_t из данных GPS, которую я не совсем понимаю. Однако я только что нашел эту ссылку, которая очень полезно, и я должен буду попробовать. Я предполагаю, что timestamp_t похож на time_t, однако в качестве двойника он имеет дробную составляющую, которая соответствует долям секунд, что не критично в этом приложении. Это может быть недостающая часть.   -  person DrTarr    schedule 08.11.2016
comment
Взгляните на этот пост настройка системного времени с использованием функции библиотеки c   -  person J. Piquard    schedule 08.11.2016
comment
Вы должны преобразовать time.tv_usec как двойное число перед вычислением десятичной части, такой как timestampt += ((double)time.tv_usec / 1000000.0L);. Но, насколько я понимаю вашу проблему, вы хотите преобразовать значение timestamp_t timestampt в значение timeval time.   -  person J. Piquard    schedule 08.11.2016
comment
Вы правы, я написал код выше (не могу опубликовать его в комментарии), который, я думаю, будет делать то, что я хочу. Спасибо   -  person DrTarr    schedule 08.11.2016
comment
Почему вы не написали свой собственный ответ, чтобы стать Explainer? Вы уверены, что struct gps_data_t* newdata; дает вам значение time? В этом Github gps.h timestamp_t time; находится в struct gps_fix_t и timestamp_t online; находится в struct gps_data_t.   -  person J. Piquard    schedule 08.11.2016
comment
Еще не проверял, я не занимаюсь разработкой на этом компьютере. Вы правы, это не напрямую в структуре gps_data_t*, тогда это будет newdata-›fix.time. Когда я скомпилирую и протестирую его, я опубликую его как ответ.   -  person DrTarr    schedule 08.11.2016


Ответы (1)


Вот:

//Get first data to set system time
struct gps_data_t* firstdata;

//Loop until first GPS lock to set system time
while (((firstdata = gps_rec.read()) == NULL) ||
        (firstdata->fix.mode < 1)) {
    //Do nothing
}

//Convert gps_data_t* member 'time' to timeval
timeval tv;
double wholeseconds, decimalseconds, offsettime;
offsettime = firstdata->fix.time - (5.0 * 3600.0);  //5hr offset from GMT
decimalseconds = modf(offsettime, &wholeseconds);
tv.tv_sec = static_cast<int32_t>(wholeseconds);
tv.tv_usec = static_cast<int32_t>(decimalseconds * 1000000.0);

//Set system time
if ( settimeofday(&tv, NULL) >= 0) {
    std::cout << "Time set succesful!" << '\n';
} else {
    std::cout << "Time set failure!" << '\n';
}
person DrTarr    schedule 09.11.2016