00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "cxutils/time.h"
00041 #include <cassert>
00042 #include <cstdlib>
00043 #include <cstring>
00044 #include "cxutils/networking/udpclient.h"
00045 #include "cxutils/networking/udpserver.h"
00046 #include "cxutils/thread.h"
00047
00048 #ifdef WIN32
00049 #include "cxutils/timer.h"
00050 #include <windows.h>
00051 #include <conio.h>
00052 #include <ctime>
00053 #else
00054 #include <unistd.h>
00055 #include <sys/time.h>
00056 #include <termios.h>
00057 #include <assert.h>
00058 #include <cstdio>
00059 #include <ctime>
00060 #endif
00061 #include <iostream>
00062
00073 void CxUtils::SleepMs(const unsigned int ms)
00074 {
00075 #ifdef WIN32
00076 Sleep(ms);
00077 #else
00078 usleep(ms*1000);
00079 #endif
00080 }
00081
00087 unsigned long long int CxUtils::GetTimeMs()
00088 {
00089 unsigned int day, hour, min, sec, ms;
00090 CxUtils::GetSystemTime(day, hour, min, sec, ms);
00091 return (unsigned long long int)(day*86400000) +
00092 (unsigned long long int)(ms) +
00093 (unsigned long long int)(sec*1000) +
00094 (unsigned long long int)(min*60000) +
00095 (unsigned long long int)(hour*3600000);
00096 }
00097
00103 double CxUtils::GetTimeSeconds()
00104 {
00105 unsigned int day, hour, min, sec, ms;
00106 CxUtils::GetSystemTime(day, hour, min, sec, ms);
00107 return (double)(day*86400.0) +
00108 (double)(ms/1000.0) +
00109 (double)(sec) +
00110 (double)(min*60) +
00111 (double)(hour*3600);
00112 }
00113
00114
00126 void CxUtils::GetSystemTime(unsigned int& day,
00127 unsigned int& hour,
00128 unsigned int& minute,
00129 unsigned int& second,
00130 unsigned int& msecond)
00131 {
00132 CxUtils::Time cxtime;
00133
00134 if(cxtime.HaveExternalTime())
00135 {
00136 cxtime = cxtime.GetExternalTime();
00137 day = cxtime.mDay;
00138 hour = cxtime.mHour;
00139 minute = cxtime.mMinute;
00140 second = cxtime.mSecond;
00141 msecond = cxtime.mMilliseconds;
00142 return;
00143 }
00144 #ifdef WIN32
00145 SYSTEMTIME t;
00146 ::GetSystemTime(&t);
00147 day = t.wDay;
00148 hour = t.wHour;
00149 minute = t.wMinute;
00150 second = t.wSecond;
00151 msecond = t.wMilliseconds;
00152 #else
00153 struct timeval tv;
00154 struct tm *timeinfo;
00155 gettimeofday(&tv, NULL);
00156 msecond = (unsigned short)(tv.tv_usec/1000.0);
00157 timeinfo = gmtime(&tv.tv_sec);
00158
00159 day = timeinfo->tm_mday;
00160 hour = timeinfo->tm_hour;
00161 minute = timeinfo->tm_min;
00162 second = timeinfo->tm_sec;
00163 #endif
00164 }
00165
00177 void CxUtils::GetSystemTime(unsigned short& day,
00178 unsigned short& hour,
00179 unsigned short& minute,
00180 unsigned short& second,
00181 unsigned short& msecond)
00182 {
00183 #ifdef WIN32
00184 SYSTEMTIME t;
00185 ::GetSystemTime(&t);
00186 day = t.wDay;
00187 hour = t.wHour;
00188 minute = t.wMinute;
00189 second = t.wSecond;
00190 msecond = t.wMilliseconds;
00191 #else
00192 struct timeval tv;
00193 struct tm *timeinfo;
00194 gettimeofday(&tv, NULL);
00195 msecond = (unsigned short)(tv.tv_usec/1000.0);
00196 timeinfo = gmtime(&tv.tv_sec);
00197
00198 day = timeinfo->tm_mday;
00199 hour = timeinfo->tm_hour;
00200 minute = timeinfo->tm_min;
00201 second = timeinfo->tm_sec;
00202 #endif
00203 }
00204
00205
00219 bool CxUtils::SetSystemTime(unsigned int year,
00220 unsigned int month,
00221 unsigned int day,
00222 unsigned int hour,
00223 unsigned int minute,
00224 unsigned int second,
00225 unsigned int msecond)
00226 {
00227 #ifdef WIN32
00228 SYSTEMTIME t;
00229 ::GetSystemTime(&t);
00230 t.wYear = year;
00231 t.wDay = day;
00232 t.wHour = hour;
00233 t.wMinute = minute;
00234 t.wSecond = second;
00235 t.wMilliseconds = msecond;
00236
00237 struct tm *timeinfo;
00238 time_t rawtime;
00239 time(&rawtime);
00240 timeinfo = gmtime ( &rawtime );
00241 timeinfo->tm_year = year - 1900;
00242 timeinfo->tm_mon = month;
00243 timeinfo->tm_mday = day;
00244 timeinfo->tm_hour = hour;
00245 timeinfo->tm_min = minute;
00246 timeinfo->tm_sec = second;
00247 mktime(timeinfo);
00248 t.wDayOfWeek = timeinfo->tm_wday;
00249
00250 return ::SetSystemTime(&t) ? true : false;
00251 #else
00252 struct timeval tv;
00253 struct tm *timeinfo;
00254 struct timezone tz;
00255 time_t rawtime;
00256
00257 gettimeofday(&tv, &tz);
00258
00259 time(&rawtime);
00260 timeinfo = gmtime ( &rawtime );
00261
00262 timeinfo->tm_year = year - 1900;
00263 timeinfo->tm_mon = month;
00264 timeinfo->tm_mday = day;
00265 timeinfo->tm_hour = hour;
00266 timeinfo->tm_min = minute;
00267 timeinfo->tm_sec = second;
00268 tv.tv_sec = mktime(timeinfo);
00269 tv.tv_usec = (__suseconds_t)(msecond*1000);
00270 int result = 0;
00271 result = settimeofday(&tv, &tz);
00272 return result == 0 ? true : false;
00273 #endif
00274 }
00275
00276
00277 using namespace CxUtils;
00278
00279 volatile bool Time::mExternalTimeFlag = false;
00280 Time Time::mExternalTime = Time();
00281 Mutex Time::mExternalTimeMutex;
00282
00290 Time::Time(const bool setCurrentTime)
00291 {
00292 mDay = 0;
00293 mHour = 0;
00294 mMinute = 0;
00295 mSecond = 0;
00296 mMilliseconds = 0;
00297
00298 if(setCurrentTime)
00299 {
00300 SetCurrentTime();
00301 }
00302 }
00303
00304
00310 Time::Time(const Time& time)
00311 {
00312 mDay = time.mDay;
00313 mHour = time.mHour;
00314 mMinute = time.mMinute;
00315 mSecond = time.mSecond;
00316 mMilliseconds = time.mMilliseconds;
00317 }
00318
00319
00325 Time::~Time()
00326 {
00327 }
00328
00329
00335 void Time::SetCurrentTime()
00336 {
00337 CxUtils::GetSystemTime((unsigned int &)mDay,
00338 (unsigned int &)mHour,
00339 (unsigned int &)mMinute,
00340 (unsigned int &)mSecond,
00341 (unsigned int &)mMilliseconds);
00342 }
00343
00344
00350 void Time::SetLocalTime()
00351 {
00352 #ifdef WIN32
00353 SYSTEMTIME t;
00354 ::GetLocalTime(&t);
00355 mDay = (unsigned int)t.wDay;
00356 mHour = (unsigned int)t.wHour;
00357 mMinute = (unsigned int)t.wMinute;
00358 mSecond = (unsigned int)t.wSecond;
00359 mMilliseconds = (unsigned int)t.wMilliseconds;
00360 #else
00361 struct timeval tv;
00362 struct tm *timeinfo;
00363 gettimeofday(&tv, NULL);
00364 mMilliseconds = (unsigned short)(tv.tv_usec/1000.0);
00365 timeinfo = localtime ( &tv.tv_sec );
00366
00367 mDay = timeinfo->tm_mday;
00368 mHour = timeinfo->tm_hour;
00369 mMinute = timeinfo->tm_min;
00370 mSecond = timeinfo->tm_sec;
00371 #endif
00372 }
00373
00374
00380 Time::Stamp Time::ToMs() const
00381 {
00382 return (unsigned long long int)(mDay*86400000) +
00383 (unsigned long long int)(mMilliseconds) +
00384 (unsigned long long int)(mSecond*1000) +
00385 (unsigned long long int)(mMinute*60000) +
00386 (unsigned long long int)(mHour*3600000);
00387 }
00388
00389
00395 double Time::ToSeconds() const
00396 {
00397 return (double)(mDay*86400.0) +
00398 (double)(mMilliseconds/1000.0) +
00399 (double)(mSecond) +
00400 (double)(mMinute*60) +
00401 (double)(mHour*3600);
00402 }
00403
00404
00410 Time::Stamp Time::GetUtcTimeMs()
00411 {
00412 return CxUtils::GetTimeMs();
00413 }
00414
00415
00421 Time::Stamp Time::GetLocalTimeMs()
00422 {
00423 Time t;
00424 t.SetLocalTime();
00425 return t.ToMs();
00426 }
00427
00428
00434 std::string Time::ToString() const
00435 {
00436 char buffer[512];
00437 sprintf(buffer,
00438 "%02d.%02d.%02d.%02d.%03d",
00439 mDay, mHour, mMinute, mSecond, mMilliseconds);
00440 return std::string(buffer);
00441 }
00442
00443
00449 Time& Time::FromString(const std::string& str)
00450 {
00451 Clear();
00452
00453 if(sscanf(str.c_str(),
00454 "%d.%d.%d.%d.%d",
00455 &mDay,
00456 &mHour,
00457 &mMinute,
00458 &mSecond,
00459 &mMilliseconds) == 5)
00460 {
00461 return *this;
00462 }
00463 Clear();
00464 if(strchr(str.c_str(), ':'))
00465 {
00466
00467 if(sscanf(str.c_str(),
00468 "%d:%d:%d:%d",
00469 &mHour,
00470 &mMinute,
00471 &mSecond,
00472 &mMilliseconds) == 4)
00473 {
00474 return *this;
00475 }
00476 Clear();
00477
00478 if(sscanf(str.c_str(),
00479 "%d:%d:%d:%d:%d",
00480 &mDay,
00481 &mHour,
00482 &mMinute,
00483 &mSecond,
00484 &mMilliseconds) == 5)
00485 {
00486 return *this;
00487 }
00488 }
00489 Clear();
00490
00491 if(sscanf(str.c_str(),
00492 "%d.%d.%d.%d",
00493 &mHour,
00494 &mMinute,
00495 &mSecond,
00496 &mMilliseconds) == 5)
00497 {
00498 return *this;
00499 }
00500 Clear();
00501
00502 if(sscanf(str.c_str(),
00503 "%d.%d.%d",
00504 &mMinute,
00505 &mSecond,
00506 &mMilliseconds) == 3)
00507 {
00508 return *this;
00509 }
00510 Clear();
00511
00512 if(sscanf(str.c_str(),
00513 "%d.%d",
00514 &mMinute,
00515 &mSecond) == 2)
00516 {
00517
00518
00519 mDay = mHour = mMilliseconds = 0;
00520
00521
00522 mHour = mMinute/60;
00523 mMinute -= mHour*60;
00524 return *this;
00525 }
00526
00527 return *this;
00528 }
00529
00530
00531
00537 Time& Time::operator =(const Time& time)
00538 {
00539 mDay = time.mDay;
00540 mHour = time.mHour;
00541 mMinute = time.mMinute;
00542 mSecond = time.mSecond;
00543 mMilliseconds = time.mMilliseconds;
00544
00545 return *this;
00546 }
00547
00548
00554 Time Time::Add(const Time& t1, const Time& t2)
00555 {
00556 Time result(t1);
00557
00558 result.mMilliseconds += t2.mMilliseconds;
00559 result.mSecond += t2.mSecond;
00560 result.mMinute += t2.mMinute;
00561 result.mHour += t2.mHour;
00562 result.mDay += t2.mDay;
00563
00564 unsigned int extra;
00565
00566 extra = result.mMilliseconds/1000;
00567 result.mMilliseconds -= extra*1000;
00568 result.mSecond += extra;
00569
00570 extra = result.mSecond/60;
00571 result.mSecond -= extra*60;
00572 result.mMinute += extra;
00573
00574 extra = result.mMinute/60;
00575 result.mMinute -= extra*60;
00576 result.mHour += extra;
00577
00578 extra = result.mHour/24;
00579 result.mHour -= extra*24;
00580 result.mDay += extra;
00581
00582 return result;
00583 }
00584
00585
00591 Time Time::Subtract(const Time& t1, const Time& t2)
00592 {
00593 assert(t1 >= t2);
00594 return Time(t1.ToSeconds() - t2.ToSeconds());
00595 }
00596
00597
00603 Time Time::GetExternalTime()
00604 {
00605 Time ext;
00606
00607 ext = mExternalTime;
00608
00609 return ext;
00610 }
00611
00612
00618 Time::Synchronizer::Synchronizer()
00619 {
00620 mpThreadObject = new Thread();
00621 mpSocket = NULL;
00622 mDelayUs = 1;
00623 }
00624
00625
00631 Time::Synchronizer::~Synchronizer()
00632 {
00633 Stop();
00634 if(mpThreadObject)
00635 if(((Thread *)mpThreadObject) != NULL)
00636 {
00637 delete ((Thread *)mpThreadObject);
00638 mpThreadObject = NULL;
00639 }
00640 if(mpSocket)
00641 {
00642 delete mpSocket;
00643 mpSocket = NULL;
00644 }
00645 }
00646
00647
00667 bool Time::Synchronizer::Start(const bool server,
00668 const unsigned short port,
00669 const IP4Address& multicastGroup,
00670 const unsigned int udelay)
00671 {
00672 Stop();
00673 Thread* thread = (Thread *)mpThreadObject;
00674 if(server)
00675 {
00676 UdpClient* client = new UdpClient();
00677 mpSocket = client;
00678 mDelayUs = udelay;
00679 if(client->InitializeMulticastSocket(multicastGroup, port) &&
00680 thread->CreateThread(Time::Synchronizer::ServerThread, this))
00681 {
00682 thread->SetThreadPriority(50);
00683 thread->SetThreadName("TimeSynchronization");
00684 return true;
00685 }
00686 }
00687 else
00688 {
00689 UdpServer* server = new UdpServer();
00690 mpSocket = server;
00691 if(server->InitializeMulticastSocket(port, multicastGroup, true) &&
00692 thread->CreateThread(Time::Synchronizer::ServerThread, this))
00693 {
00694 thread->SetThreadPriority(50);
00695 thread->SetThreadName("TimeSynchronization");
00696 return true;
00697 }
00698 }
00699
00700 Stop();
00701 return false;
00702 }
00703
00704
00710 void Time::Synchronizer::Stop()
00711 {
00712 ((Thread *)mpThreadObject)->StopThread();
00713 if(mpSocket)
00714 {
00715 delete mpSocket;
00716 mpSocket = NULL;
00717 }
00718 mpSocket = NULL;
00719 }
00720
00721
00727 void Time::Synchronizer::ServerThread(void *args)
00728 {
00729 Synchronizer* sync = (Synchronizer*)args;
00730 UdpClient* client = dynamic_cast<UdpClient*>(sync->mpSocket);
00731 UdpServer* server = dynamic_cast<UdpServer*>(sync->mpSocket);
00732 Packet packet;
00733 packet.Reserve(32);
00734 #ifdef WIN32
00735 unsigned int loopCounter = 0;
00736 #endif
00737
00738
00739
00740 #ifdef TEST_TIME_SYNC
00741 Time::Stamp buff[3000];
00742 unsigned int size = 0;
00743 unsigned int limit = 3000;
00744 #endif
00745
00746 if(client)
00747 {
00748 unsigned int tstamp = 0;
00749
00750 Time cur, prev, startUtc;
00751 packet.WriteByte('T');
00752 packet.Write(tstamp);
00753
00754 #ifdef WIN32
00755 double startMs = 0.0, curMs = 0.0;
00756 Time staticTime;
00757 #endif
00758
00759 while(sync && ((Thread *)sync->mpThreadObject)->QuitThreadFlag() == false)
00760 {
00761
00762 #ifdef WIN32
00763 if(startMs <= 0.00001)
00764 {
00765 startMs = Timer::GetTimeMs();
00766 startUtc.SetCurrentTime();
00767 }
00768 else
00769 {
00770 curMs = Timer::GetTimeMs();
00771 unsigned int diffMs = (unsigned int)(curMs - startMs);
00772
00773 cur = startUtc;
00774 cur.mMilliseconds += diffMs;
00775
00776 unsigned int extra;
00777
00778 extra = cur.mMilliseconds/1000;
00779 cur.mMilliseconds -= extra*1000;
00780 cur.mSecond += extra;
00781
00782 extra = cur.mSecond/60;
00783 cur.mSecond -= extra*60;
00784 cur.mMinute += extra;
00785
00786 extra = cur.mMinute/60;
00787 cur.mMinute -= extra*60;
00788 cur.mHour += extra;
00789
00790 extra = cur.mHour/24;
00791 cur.mHour -= extra*24;
00792 cur.mDay += extra;
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 #else
00804 struct timeval tv;
00805 struct tm *timeinfo;
00806 gettimeofday(&tv, NULL);
00807 cur.mMilliseconds = (unsigned int)(tv.tv_usec/1000.0);
00808 timeinfo = gmtime(&tv.tv_sec);
00809 cur.mDay = timeinfo->tm_mday;
00810 cur.mHour = timeinfo->tm_hour;
00811 cur.mMinute = timeinfo->tm_min;
00812 cur.mSecond = timeinfo->tm_sec;
00813 #endif
00814
00815 tstamp = 0;
00816 tstamp |= (cur.mDay << 27);
00817 tstamp |= (cur.mHour << 22);
00818 tstamp |= (cur.mMinute << 16);
00819 tstamp |= (cur.mSecond << 10);
00820 tstamp |= cur.mMilliseconds;
00821
00822
00823 if(cur > prev)
00824 {
00825 packet.Write(tstamp, 1);
00826 client->Send(packet);
00827 prev = cur;
00828 #ifdef WIN32
00829 staticTime.mExternalTimeFlag = true;
00830 staticTime.mExternalTime = cur;
00831 #endif
00832 }
00833 #ifdef WIN32
00834 if(sync->mDelayUs > 0)
00835 {
00836
00837 if( loopCounter++ == 10)
00838 {
00839 loopCounter = 0;
00840 Sleep(1);
00841 }
00842 }
00843 #else
00844 if(sync->mDelayUs > 0)
00845 {
00846 usleep(sync->mDelayUs);
00847 }
00848 #endif
00849 }
00850 #ifdef WIN32
00851 staticTime.mExternalTimeFlag = false;
00852 #endif
00853 }
00854 else if(server)
00855 {
00856 unsigned int tstamp = 0;
00857 unsigned int day = 0, hour = 0, minute = 0, second = 0, msecond = 0;
00858 Time cur, prev;
00859 Time staticTime;
00860 while(sync && ((Thread *)sync->mpThreadObject)->QuitThreadFlag() == false)
00861 {
00862 if(server->Recv(packet, 5, 500) > 0)
00863 {
00864 char h = 0;
00865 if(packet.Read(h) && h == 'T' &&
00866 packet.Read(tstamp))
00867 {
00868 msecond = tstamp & 0x3FF;
00869 second = ((tstamp >> 10) & 0x3F);
00870 minute = ((tstamp >> 16) & 0x3F);
00871 hour = ((tstamp >> 22) & 0x1F);
00872 day = ((tstamp >> 27) & 0x1F);
00873
00874 cur.mDay = day;
00875 cur.mHour = hour;
00876 cur.mMinute = minute;
00877 cur.mSecond = second;
00878 cur.mMilliseconds = msecond;
00879
00880 if(cur > prev)
00881 {
00882
00883
00884 staticTime.mExternalTimeFlag = true;
00885 staticTime.mExternalTime = cur;
00886
00887
00888 #ifdef TEST_TIME_SYNC
00889 buff[size++] = cur.ToMs();
00890 if(size == limit)
00891 {
00892 for(unsigned int i = 0; i < limit - 1; i++)
00893 {
00894 Time::Stamp diff = buff[i + 1] - buff[i];
00895 if(diff > 1)
00896 {
00897 int x;
00898 x = 3;
00899 }
00900 }
00901 size = 0;
00902 }
00903 #endif
00904
00905 prev = cur;
00906 }
00907 }
00908 }
00909 else
00910 {
00911 cur.Clear();
00912 prev.Clear();
00913
00914
00915 staticTime.mExternalTimeFlag = false;
00916
00917 }
00918 }
00919
00920
00921
00922 staticTime.mExternalTimeFlag = false;
00923
00924 }
00925 }
00926
00927