xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/rtc/datetimewidget.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #include "datetimewidget.h"
2*4882a593Smuzhiyun #include "ui_datetimewidget.h"
3*4882a593Smuzhiyun #include <QTimer>
4*4882a593Smuzhiyun #include <QDebug>
5*4882a593Smuzhiyun #include "terminal.h"
6*4882a593Smuzhiyun #include <QTimeZone>
7*4882a593Smuzhiyun #include "terminal.h"
8*4882a593Smuzhiyun #include <QDateTime>
9*4882a593Smuzhiyun #include "messagebox.h"
10*4882a593Smuzhiyun #include "systemmanager.h"
11*4882a593Smuzhiyun #include <QLocale>
12*4882a593Smuzhiyun #include <QTimeZone>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun Q_LOGGING_CATEGORY(flapp,  "app.rtc")
DateTimeWidget(QWidget * parent)15*4882a593Smuzhiyun DateTimeWidget::DateTimeWidget( QWidget *parent) :
16*4882a593Smuzhiyun     IWidget(parent),
17*4882a593Smuzhiyun     ui(new Ui::DateTimeWidget),
18*4882a593Smuzhiyun     m_checker(Q_NULLPTR)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun     ui->setupUi(this);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun 
~DateTimeWidget()23*4882a593Smuzhiyun DateTimeWidget::~DateTimeWidget()
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun     delete ui;
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun 
id()28*4882a593Smuzhiyun QString DateTimeWidget::id()
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun     return "rtc";
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
initUi()33*4882a593Smuzhiyun void DateTimeWidget::initUi()
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun    ui->zoneLbl->setText(QTimeZone::systemTimeZoneId());
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun     auto addDateTime= [=]( QComboBox *pComBox, int start, int end, const QString &unit=""){
38*4882a593Smuzhiyun         for(int n=start; n<=end; n++){
39*4882a593Smuzhiyun             QString s = QString::number(n);
40*4882a593Smuzhiyun             if(n<10)
41*4882a593Smuzhiyun             {
42*4882a593Smuzhiyun                 s ="0" +s;
43*4882a593Smuzhiyun             }
44*4882a593Smuzhiyun             pComBox->addItem(tr((s +" " + unit).toLocal8Bit().data()) , n);
45*4882a593Smuzhiyun         }
46*4882a593Smuzhiyun     };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun     auto changDay= [=]( ){
49*4882a593Smuzhiyun         ui->dayComBox->clear();
50*4882a593Smuzhiyun         QDate d(currentvalue(ui->yearCombox),
51*4882a593Smuzhiyun                 currentvalue(ui->monthComBox),
52*4882a593Smuzhiyun                 1);
53*4882a593Smuzhiyun         int maxDays = d.daysInMonth();
54*4882a593Smuzhiyun         addDateTime(ui->dayComBox, 1, maxDays, "Day");
55*4882a593Smuzhiyun     };
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun     addDateTime(ui->yearCombox, 2020, 2050, "Year");
58*4882a593Smuzhiyun     addDateTime(ui->monthComBox, 1, 12, "Month");
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun     connect(ui->yearCombox, &QComboBox::currentTextChanged, this, [=](){
61*4882a593Smuzhiyun         changDay();
62*4882a593Smuzhiyun     });
63*4882a593Smuzhiyun     connect(ui->monthComBox, &QComboBox::currentTextChanged, this, [=](){
64*4882a593Smuzhiyun         changDay();
65*4882a593Smuzhiyun     });
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun     addDateTime(ui->hourComBox, 0, 24, "Houre");
68*4882a593Smuzhiyun     addDateTime(ui->minutuComBo, 0, 59,"Minute");
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun     ui->yearCombox->setCurrentIndex(2);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun     auto setEnable= [=](bool checked ){
73*4882a593Smuzhiyun         ui->yearCombox->setEnabled(checked);
74*4882a593Smuzhiyun         ui->monthComBox->setEnabled(checked);
75*4882a593Smuzhiyun         ui->dayComBox->setEnabled(checked);
76*4882a593Smuzhiyun         ui->hourComBox->setEnabled(checked);
77*4882a593Smuzhiyun         ui->minutuComBo->setEnabled(checked);
78*4882a593Smuzhiyun     };
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun     connect(ui->manualRaidoBtn, &QRadioButton::clicked, this, [=](bool checked){
81*4882a593Smuzhiyun         setEnable(checked);
82*4882a593Smuzhiyun     });
83*4882a593Smuzhiyun     connect(ui->ntpRadioBtn, &QRadioButton::clicked, this, [=](bool checked){
84*4882a593Smuzhiyun         setEnable(!checked);
85*4882a593Smuzhiyun     });
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     ui->manualRaidoBtn->click();
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun     QTimer *timer = new QTimer(this);
90*4882a593Smuzhiyun     connect(timer, &QTimer::timeout, this, [=](){
91*4882a593Smuzhiyun         ui->systimeDataeLbl->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
92*4882a593Smuzhiyun         QString result = Terminal::execCmd("hwclock -r");
93*4882a593Smuzhiyun         if(SystemManager::instance()->getMatch(result, "[0-9]+").isEmpty())
94*4882a593Smuzhiyun         {
95*4882a593Smuzhiyun             ui->rtctimeLbl->setText("ERROR");
96*4882a593Smuzhiyun         }else{
97*4882a593Smuzhiyun             ui->rtctimeLbl->setText(result);
98*4882a593Smuzhiyun         }
99*4882a593Smuzhiyun     });
100*4882a593Smuzhiyun     timer->start(1000);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun     m_checker = new NetworkChecker(this);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
currentvalue(QComboBox * d)106*4882a593Smuzhiyun int DateTimeWidget::currentvalue(QComboBox *d)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun     return d->itemData(d->currentIndex()).toInt();
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
on_applyBtn_clicked()111*4882a593Smuzhiyun void DateTimeWidget::on_applyBtn_clicked()
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     QDateTime datetime;
114*4882a593Smuzhiyun     if(ui->manualRaidoBtn->isChecked())
115*4882a593Smuzhiyun     {
116*4882a593Smuzhiyun         QDate d(currentvalue(ui->yearCombox),
117*4882a593Smuzhiyun                 currentvalue(ui->monthComBox),
118*4882a593Smuzhiyun                 currentvalue(ui->dayComBox));
119*4882a593Smuzhiyun         QTime t(currentvalue(ui->hourComBox),
120*4882a593Smuzhiyun                 currentvalue(ui->minutuComBo));
121*4882a593Smuzhiyun         datetime.setDate(d);
122*4882a593Smuzhiyun         datetime.setTime(t);
123*4882a593Smuzhiyun     }else{
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun         if(!m_checker->networkIsOk())
126*4882a593Smuzhiyun         {
127*4882a593Smuzhiyun             MessageBox::showMessage(this, "Unable to access the network by DNS name,");
128*4882a593Smuzhiyun             return;
129*4882a593Smuzhiyun         }
130*4882a593Smuzhiyun         long long mSeconds =NTPGetTimeBeijingMSeconds() ;
131*4882a593Smuzhiyun         datetime = QDateTime::fromMSecsSinceEpoch(mSeconds);
132*4882a593Smuzhiyun         ui->applyBtn->setEnabled(false);
133*4882a593Smuzhiyun         QTimer::singleShot(2000, this, [=](){
134*4882a593Smuzhiyun             ui->applyBtn->setEnabled(true);
135*4882a593Smuzhiyun         });
136*4882a593Smuzhiyun     }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun     QString cmd =  QString("date -s %1  %2").
139*4882a593Smuzhiyun             arg("\"" + datetime.toString("yyyy-MM-dd hh:mm:ss") + "\"").
140*4882a593Smuzhiyun             arg("\"+%Y-%m-%d %H:%M:%S\"");
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun     qCDebug(flapp)<< cmd;
143*4882a593Smuzhiyun     system(cmd.toLocal8Bit().constData());
144*4882a593Smuzhiyun     system("hwclock -w");
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun #include <sys/types.h>
149*4882a593Smuzhiyun #include <sys/socket.h>
150*4882a593Smuzhiyun #include <netdb.h>
151*4882a593Smuzhiyun #include <unistd.h>
152*4882a593Smuzhiyun #include <QDateTime>
153*4882a593Smuzhiyun #include <QDebug>
154*4882a593Smuzhiyun //NTP 标度与 Unix 标度只相差一个常数 2208988800,这是 1900/1/1 (NTP 标度起点)与 1970/1/1 (Unix 标度起点)之间的秒数差别
NTPGetTimeBeijingMSeconds()155*4882a593Smuzhiyun long long DateTimeWidget::NTPGetTimeBeijingMSeconds()
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun #define NTP_TIMESTAMP_DELTA 2208988800
159*4882a593Smuzhiyun     int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.
160*4882a593Smuzhiyun     int portno = 123; // NTP UDP port number.
161*4882a593Smuzhiyun     const char* host_name = "ntp.aliyun.com"; // NTP server host-name.
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun     typedef struct
164*4882a593Smuzhiyun     {
165*4882a593Smuzhiyun         uint8_t li_vn_mode;      // Eight bits. li, vn, and mode.
166*4882a593Smuzhiyun         // li.   Two bits.   Leap indicator.
167*4882a593Smuzhiyun         // vn.   Three bits. Version number of the protocol.
168*4882a593Smuzhiyun         // mode. Three bits. Client will pick mode 3 for client.
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun         uint8_t stratum;         // Eight bits. Stratum level of the local clock.
171*4882a593Smuzhiyun         uint8_t poll;            // Eight bits. Maximum interval between successive messages.
172*4882a593Smuzhiyun         uint8_t precision;       // Eight bits. Precision of the local clock.
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun         uint32_t rootDelay;      // 32 bits. Total round trip delay time.
175*4882a593Smuzhiyun         uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
176*4882a593Smuzhiyun         uint32_t refId;          // 32 bits. Reference clock identifier.
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun         uint32_t refTm_s;        // 32 bits. Reference time-stamp seconds.
179*4882a593Smuzhiyun         uint32_t refTm_f;        // 32 bits. Reference time-stamp fraction of a second.
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun         uint32_t origTm_s;       // 32 bits. Originate time-stamp seconds.
182*4882a593Smuzhiyun         uint32_t origTm_f;       // 32 bits. Originate time-stamp fraction of a second.
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun         uint32_t rxTm_s;         // 32 bits. Received time-stamp seconds.
185*4882a593Smuzhiyun         uint32_t rxTm_f;         // 32 bits. Received time-stamp fraction of a second.
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun         uint32_t txTm_s;         // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
188*4882a593Smuzhiyun         uint32_t txTm_f;         // 32 bits. Transmit time-stamp fraction of a second.
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     } ntp_packet;              // Total: 384 bits or 48 bytes.
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun     // Create and zero out the packet. All 48 bytes worth.
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun     ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun     memset( &packet, 0, sizeof( ntp_packet ) );
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun     // Set the first byte’s bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero.
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     *( ( char * ) &packet + 0 ) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2.
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     struct sockaddr_in serv_addr; // Server address data structure.
203*4882a593Smuzhiyun     struct hostent *server;      // Server data structure.
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); // Create a UDP socket.
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     if ( sockfd < 0 )
208*4882a593Smuzhiyun         printf("ERROR opening socket\n");
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     server = gethostbyname( host_name ); // Convert URL to IP.
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun     if ( server == NULL )
213*4882a593Smuzhiyun         printf("ERROR, no such host\n");
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun     // Zero out the server address structure.
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun     bzero( ( char* ) &serv_addr, sizeof( serv_addr ) );
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun     serv_addr.sin_family = AF_INET;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     // Copy the server’s IP address to the server address structure.
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun     bcopy( ( char* )server->h_addr, ( char* ) &serv_addr.sin_addr.s_addr, server->h_length );
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     serv_addr.sin_port = htons( portno );
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun     // Call up the server using its IP address and port number.
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun     if ( ::connect( sockfd, ( struct sockaddr * ) &serv_addr, sizeof( serv_addr) ) < 0 )
230*4882a593Smuzhiyun         printf("ERROR connecting\n");
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     n = write( sockfd, ( char* ) &packet, sizeof( ntp_packet ) );
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun     if ( n < 0 )
235*4882a593Smuzhiyun         printf("ERROR writing to socket\n");
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     // Wait and receive the packet back from the server. If n == -1, it failed.
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     n = read( sockfd, ( char* ) &packet, sizeof( ntp_packet ) );
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun     if ( n < 0 )
242*4882a593Smuzhiyun         printf( "ERROR reading from socket\n");
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     packet.txTm_s = ntohl( packet.txTm_s ); // Time-stamp seconds.
245*4882a593Smuzhiyun     packet.txTm_f = ntohl( packet.txTm_f ); // Time-stamp fraction of a second.
246*4882a593Smuzhiyun    long long mSecond =(packet.txTm_s- NTP_TIMESTAMP_DELTA)*1000+ packet.txTm_f*232/1000/1000/1000;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun    qDebug()<<QDateTime::fromMSecsSinceEpoch(mSecond);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun    return mSecond;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
NetworkChecker(QObject * parent)253*4882a593Smuzhiyun NetworkChecker::NetworkChecker(QObject *parent):QObject(parent)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun     this->start("ping www.forlinx.com");
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
processMessage(const QString & info)258*4882a593Smuzhiyun void NetworkChecker::processMessage(const QString &info)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun    m_info +=info;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
networkIsOk()263*4882a593Smuzhiyun bool NetworkChecker::networkIsOk()
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun     bool bOk =m_info.contains("ttl=");
266*4882a593Smuzhiyun     m_info.clear();
267*4882a593Smuzhiyun   return bOk;
268*4882a593Smuzhiyun }
269