Linux で gps timestamp_t 構造体を使用してシステム時刻を設定する
皆さんこんにちは、
私は成功した GPS ロック (Adafruit Ultimate GPS w/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 に変換する方法に関する情報を見つけましたが、この double を *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 を区別することです。ここに違いがあることを理解しているので、そうでない場合は修正してください:
いずれも 1970 年 1 月 1 日以降の秒単位の時間ですが...
timeval は (2) long 値の構造体で、tv_sec は 1970 年 1 月 1 日からの秒数、tv_usec はその後のマイクロ秒数です。
time_t は長いですか? これも 1970 年 1 月 1 日から数秒後です
timestamp_t は double で、1970 年 1 月 1 日からの秒数であるため、小数部分はマイクロ秒を計算して、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);