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