xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/rtc/datetimewidget.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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