source: ntrip/trunk/BNC/src/pppRun.cpp@ 7557

Last change on this file since 7557 was 7520, checked in by stuerze, 10 years ago

minor changes to allow directory entries in ppp panel with and wihout final slash

File size: 19.6 KB
Line 
1
2// Part of BNC, a utility for retrieving decoding and
3// converting GNSS data streams from NTRIP broadcasters.
4//
5// Copyright (C) 2007
6// German Federal Agency for Cartography and Geodesy (BKG)
7// http://www.bkg.bund.de
8// Czech Technical University Prague, Department of Geodesy
9// http://www.fsv.cvut.cz
10//
11// Email: euref-ip@bkg.bund.de
12//
13// This program is free software; you can redistribute it and/or
14// modify it under the terms of the GNU General Public License
15// as published by the Free Software Foundation, version 2.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26/* -------------------------------------------------------------------------
27 * BKG NTRIP Client
28 * -------------------------------------------------------------------------
29 *
30 * Class: t_pppRun
31 *
32 * Purpose: Single Real-Time PPP Client
33 *
34 * Author: L. Mervart
35 *
36 * Created: 29-Jul-2014
37 *
38 * Changes:
39 *
40 * -----------------------------------------------------------------------*/
41
42
43#include <iostream>
44#include <iomanip>
45#include <sstream>
46#include <string.h>
47#include <map>
48
49#include "pppRun.h"
50#include "pppThread.h"
51#include "bnccore.h"
52#include "bncephuser.h"
53#include "bncsettings.h"
54#include "bncoutf.h"
55#include "bncsinextro.h"
56#include "rinex/rnxobsfile.h"
57#include "rinex/rnxnavfile.h"
58#include "rinex/corrfile.h"
59#include "combination/bnccomb.h"
60
61using namespace BNC_PPP;
62using namespace std;
63
64// Constructor
65////////////////////////////////////////////////////////////////////////////
66t_pppRun::t_pppRun(const t_pppOptions* opt) {
67
68 _opt = opt;
69
70 connect(this, SIGNAL(newMessage(QByteArray,bool)),
71 BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
72
73 connect(this, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)),
74 BNC_CORE, SIGNAL(newPosition(QByteArray, bncTime, QVector<double>)));
75
76 connect(this, SIGNAL(newNMEAstr(QByteArray, QByteArray)),
77 BNC_CORE, SIGNAL(newNMEAstr(QByteArray, QByteArray)));
78
79 _pppClient = new t_pppClient(_opt);
80
81 bncSettings settings;
82
83 if (_opt->_realTime) {
84 Qt::ConnectionType conType = Qt::AutoConnection;
85 if (BNC_CORE->mode() == t_bncCore::batchPostProcessing) {
86 conType = Qt::BlockingQueuedConnection;
87 }
88
89 connect(BNC_CORE->caster(), SIGNAL(newObs(QByteArray, QList<t_satObs>)),
90 this, SLOT(slotNewObs(QByteArray, QList<t_satObs>)),conType);
91
92 connect(BNC_CORE, SIGNAL(newGPSEph(t_ephGPS)),
93 this, SLOT(slotNewGPSEph(t_ephGPS)),conType);
94
95 connect(BNC_CORE, SIGNAL(newGlonassEph(t_ephGlo)),
96 this, SLOT(slotNewGlonassEph(t_ephGlo)),conType);
97
98 connect(BNC_CORE, SIGNAL(newGalileoEph(t_ephGal)),
99 this, SLOT(slotNewGalileoEph(t_ephGal)),conType);
100
101 connect(BNC_CORE, SIGNAL(newBDSEph(t_ephBDS)),
102 this, SLOT(slotNewBDSEph(t_ephBDS)),conType);
103
104 connect(BNC_CORE, SIGNAL(newTec(t_vTec)),
105 this, SLOT(slotNewTec(t_vTec)),conType);
106
107 connect(BNC_CORE, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
108 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)),conType);
109
110 connect(BNC_CORE, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
111 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)),conType);
112
113 connect(BNC_CORE, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
114 this, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)),conType);
115
116 connect(BNC_CORE, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
117 this, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)),conType);
118
119 connect(BNC_CMB, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
120 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)),conType);
121
122 connect(BNC_CMB, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
123 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)),conType);
124 }
125 else {
126 _rnxObsFile = 0;
127 _rnxNavFile = 0;
128 _corrFile = 0;
129 _speed = settings.value("PPP/mapSpeedSlider").toInt();
130 connect(this, SIGNAL(progressRnxPPP(int)), BNC_CORE, SIGNAL(progressRnxPPP(int)));
131 connect(this, SIGNAL(finishedRnxPPP()), BNC_CORE, SIGNAL(finishedRnxPPP()));
132 connect(BNC_CORE, SIGNAL(mapSpeedSliderChanged(int)),
133 this, SLOT(slotSetSpeed(int)));
134 connect(BNC_CORE, SIGNAL(stopRinexPPP()), this, SLOT(slotSetStopFlag()));
135 }
136
137 _stopFlag = false;
138
139 QString roverName(_opt->_roverName.c_str()), fullRoverName("");
140 QString country;
141 QString monNum = "0";
142 QString recNum = "0";
143 QString intr = "1 day";
144 int sampl = 0;
145 QListIterator<QString> it(settings.value("mountPoints").toStringList());
146 while (it.hasNext()) {
147 QStringList hlp = it.next().split(" ");
148 if (hlp.size() < 7)
149 continue;
150 if (hlp.join(" ").indexOf(roverName, 0) != -1) {
151 country = hlp[2];
152 }
153 }
154 fullRoverName = roverName.left(4) +
155 QString("%1").arg(monNum, 1, 10) +
156 QString("%1").arg(recNum, 1, 10) +
157 country;
158
159 bool v3filenames = settings.value("PPP/v3filenames").toBool();
160 QString logFileSkl = settings.value("PPP/logPath").toString();
161 int l = logFileSkl.length();
162 if (logFileSkl.isEmpty()) {
163 _logFile = 0;
164 }
165 else {
166 if (l && logFileSkl[l-1] != QDir::separator() ) {
167 logFileSkl += QDir::separator();
168 }
169 if (v3filenames) {
170 logFileSkl = logFileSkl + fullRoverName + "${V3}" + ".ppp";
171 }
172 else {
173 logFileSkl = logFileSkl + roverName.left(4) + "${GPSWD}" + ".ppp";
174 }
175 _logFile = new bncoutf(logFileSkl, intr, sampl);
176 }
177
178 QString nmeaFileSkl = settings.value("PPP/nmeaPath").toString();
179 l = nmeaFileSkl.length();
180 if (nmeaFileSkl.isEmpty()) {
181 _nmeaFile = 0;
182 }
183 else {
184 if (l > 0 && nmeaFileSkl[l-1] != QDir::separator() ) {
185 nmeaFileSkl += QDir::separator();
186 }
187 if (v3filenames) {
188 nmeaFileSkl = nmeaFileSkl + fullRoverName + "${V3}" + ".nmea";
189 }
190 else {
191 nmeaFileSkl = nmeaFileSkl + roverName.left(4) + "${GPSWD}" + ".nmea";
192 }
193 _nmeaFile = new bncoutf(nmeaFileSkl, intr, sampl);
194 }
195
196 QString snxtroFileSkl = settings.value("PPP/snxtroPath").toString();
197 l = snxtroFileSkl.length();
198 if (snxtroFileSkl.isEmpty()) {
199 _snxtroFile = 0;
200 }
201 else {
202 if (l > 0 && snxtroFileSkl[l-1] != QDir::separator() ) {
203 snxtroFileSkl += QDir::separator();
204 }
205 if (v3filenames) {
206 snxtroFileSkl = snxtroFileSkl + fullRoverName + "${V3}" + ".tra";
207 }
208 else {
209 snxtroFileSkl = snxtroFileSkl + roverName.left(4) + "${GPSWD}" + ".tro";
210 }
211 sampl = settings.value("PPP/snxtroSampl").toInt();
212 intr = settings.value("PPP/snxtroIntr").toString();
213 _snxtroFile = new bncSinexTro(_opt, snxtroFileSkl, intr, sampl);
214 }
215}
216
217
218
219// Destructor
220////////////////////////////////////////////////////////////////////////////
221t_pppRun::~t_pppRun() {
222 delete _logFile;
223 delete _nmeaFile;
224 delete _snxtroFile;
225}
226
227//
228////////////////////////////////////////////////////////////////////////////
229void t_pppRun::slotNewGPSEph(t_ephGPS eph) {
230 QMutexLocker locker(&_mutex);
231 _pppClient->putEphemeris(&eph);
232}
233
234//
235////////////////////////////////////////////////////////////////////////////
236void t_pppRun::slotNewGlonassEph(t_ephGlo eph) {
237 QMutexLocker locker(&_mutex);
238 _pppClient->putEphemeris(&eph);
239}
240
241//
242////////////////////////////////////////////////////////////////////////////
243void t_pppRun::slotNewGalileoEph(t_ephGal eph) {
244 QMutexLocker locker(&_mutex);
245 _pppClient->putEphemeris(&eph);
246}
247
248//
249////////////////////////////////////////////////////////////////////////////
250void t_pppRun::slotNewBDSEph(t_ephBDS eph) {
251 QMutexLocker locker(&_mutex);
252 _pppClient->putEphemeris(&eph);
253}
254
255//
256////////////////////////////////////////////////////////////////////////////
257void t_pppRun::slotNewObs(QByteArray staID, QList<t_satObs> obsList) {
258 QMutexLocker locker(&_mutex);
259
260 if (string(staID.data()) != _opt->_roverName) {
261 return;
262 }
263
264 // Loop over all observations (possible different epochs)
265 // -----------------------------------------------------
266 QListIterator<t_satObs> it(obsList);
267 while (it.hasNext()) {
268 const t_satObs& oldObs = it.next();
269 t_satObs* newObs = new t_satObs(oldObs);
270
271 // Find the corresponding data epoch or create a new one
272 // -----------------------------------------------------
273 t_epoData* epoch = 0;
274 deque<t_epoData*>::const_iterator it;
275 for (it = _epoData.begin(); it != _epoData.end(); it++) {
276 if (newObs->_time == (*it)->_time) {
277 epoch = *it;
278 break;
279 }
280 }
281 if (epoch == 0) {
282 if (_epoData.empty() || newObs->_time > _epoData.back()->_time) {
283 epoch = new t_epoData;
284 epoch->_time = newObs->_time;
285 _epoData.push_back(epoch);
286 }
287 }
288
289 // Put data into the epoch
290 // -----------------------
291 if (epoch != 0) {
292 epoch->_satObs.push_back(newObs);
293 }
294 else {
295 delete newObs;
296 }
297 }
298
299 // Process the oldest epochs
300 // ------------------------
301 while (_epoData.size() && !waitForCorr(_epoData.front()->_time)) {
302
303 const vector<t_satObs*>& satObs = _epoData.front()->_satObs;
304
305 t_output output;
306 _pppClient->processEpoch(satObs, &output);
307
308 if (!output._error) {
309 QVector<double> xx(6);
310 xx.data()[0] = output._xyzRover[0];
311 xx.data()[1] = output._xyzRover[1];
312 xx.data()[2] = output._xyzRover[2];
313 xx.data()[3] = output._neu[0];
314 xx.data()[4] = output._neu[1];
315 xx.data()[5] = output._neu[2];
316 emit newPosition(staID, output._epoTime, xx);
317 }
318
319 delete _epoData.front(); _epoData.pop_front();
320
321 ostringstream log;
322 if (output._error) {
323 log << output._log;
324 }
325 else {
326 log.setf(ios::fixed);
327 log << string(output._epoTime) << ' ' << staID.data()
328 << " X = " << setprecision(4) << output._xyzRover[0]
329 << " Y = " << setprecision(4) << output._xyzRover[1]
330 << " Z = " << setprecision(4) << output._xyzRover[2]
331 << " NEU: " << showpos << setw(8) << setprecision(4) << output._neu[0]
332 << " " << showpos << setw(8) << setprecision(4) << output._neu[1]
333 << " " << showpos << setw(8) << setprecision(4) << output._neu[2]
334 << " TRP: " << showpos << setw(8) << setprecision(4) << output._trp0
335 << " " << showpos << setw(8) << setprecision(4) << output._trp;
336 }
337
338 if (_logFile && output._epoTime.valid()) {
339 _logFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(),
340 QString(output._log.c_str()));
341 }
342
343 if (!output._error) {
344 QString rmcStr = nmeaString('R', output);
345 QString ggaStr = nmeaString('G', output);
346 if (_nmeaFile) {
347 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), rmcStr);
348 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), ggaStr);
349 }
350 emit newNMEAstr(staID, rmcStr.toAscii());
351 emit newNMEAstr(staID, ggaStr.toAscii());
352 }
353
354 if (_snxtroFile && output._epoTime.valid()) {
355 _snxtroFile->write(staID, int(output._epoTime.gpsw()), output._epoTime.gpssec(),
356 output._trp0 + output._trp, output._trpStdev);
357 }
358
359 emit newMessage(QByteArray(log.str().c_str()), true);
360 }
361}
362
363//
364////////////////////////////////////////////////////////////////////////////
365void t_pppRun::slotNewTec(t_vTec vTec) {
366 if (vTec._layers.size() == 0) {
367 return;
368 }
369
370 if (_opt->_realTime) {
371 if (_opt->_corrMount.empty() || _opt->_corrMount != vTec._staID) {
372 return;
373 }
374 }
375
376 _pppClient->putTec(&vTec);
377}
378
379//
380////////////////////////////////////////////////////////////////////////////
381void t_pppRun::slotNewOrbCorrections(QList<t_orbCorr> orbCorr) {
382 if (orbCorr.size() == 0) {
383 return;
384 }
385
386 if (_opt->_realTime) {
387 if (_opt->_corrMount.empty() || _opt->_corrMount != orbCorr[0]._staID) {
388 return;
389 }
390 }
391 vector<t_orbCorr*> corrections;
392 for (int ii = 0; ii < orbCorr.size(); ii++) {
393 corrections.push_back(new t_orbCorr(orbCorr[ii]));
394 }
395
396 _pppClient->putOrbCorrections(corrections);
397
398 for (unsigned ii = 0; ii < corrections.size(); ii++) {
399 delete corrections[ii];
400 }
401}
402
403//
404////////////////////////////////////////////////////////////////////////////
405void t_pppRun::slotNewClkCorrections(QList<t_clkCorr> clkCorr) {
406 if (clkCorr.size() == 0) {
407 return;
408 }
409
410 if (_opt->_realTime) {
411 if (_opt->_corrMount.empty() || _opt->_corrMount != clkCorr[0]._staID) {
412 return;
413 }
414 }
415 vector<t_clkCorr*> corrections;
416 for (int ii = 0; ii < clkCorr.size(); ii++) {
417 corrections.push_back(new t_clkCorr(clkCorr[ii]));
418 _lastClkCorrTime = clkCorr[ii]._time;
419 }
420 _pppClient->putClkCorrections(corrections);
421
422 for (unsigned ii = 0; ii < corrections.size(); ii++) {
423 delete corrections[ii];
424 }
425}
426
427//
428////////////////////////////////////////////////////////////////////////////
429void t_pppRun::slotNewCodeBiases(QList<t_satCodeBias> codeBiases) {
430 if (codeBiases.size() == 0) {
431 return;
432 }
433
434 if (_opt->_realTime) {
435 if (_opt->_corrMount.empty() || _opt->_corrMount != codeBiases[0]._staID) {
436 return;
437 }
438 }
439 vector<t_satCodeBias*> biases;
440 for (int ii = 0; ii < codeBiases.size(); ii++) {
441 biases.push_back(new t_satCodeBias(codeBiases[ii]));
442 }
443
444 _pppClient->putCodeBiases(biases);
445
446 for (unsigned ii = 0; ii < biases.size(); ii++) {
447 delete biases[ii];
448 }
449}
450
451//
452////////////////////////////////////////////////////////////////////////////
453void t_pppRun::slotNewPhaseBiases(QList<t_satPhaseBias> phaseBiases) {
454 if (phaseBiases.size() == 0) {
455 return;
456 }
457
458 if (_opt->_realTime) {
459 if (_opt->_corrMount.empty() || _opt->_corrMount != phaseBiases[0]._staID) {
460 return;
461 }
462 }
463 vector<t_satPhaseBias*> biases;
464 for (int ii = 0; ii < phaseBiases.size(); ii++) {
465 biases.push_back(new t_satPhaseBias(phaseBiases[ii]));
466 }
467
468 _pppClient->putPhaseBiases(biases);
469
470 for (unsigned ii = 0; ii < biases.size(); ii++) {
471 delete biases[ii];
472 }
473}
474
475//
476////////////////////////////////////////////////////////////////////////////
477void t_pppRun::processFiles() {
478
479 try {
480 _rnxObsFile = new t_rnxObsFile(QString(_opt->_rinexObs.c_str()), t_rnxObsFile::input);
481 }
482 catch (...) {
483 delete _rnxObsFile; _rnxObsFile = 0;
484 emit finishedRnxPPP();
485 return;
486 }
487
488 _rnxNavFile = new t_rnxNavFile(QString(_opt->_rinexNav.c_str()), t_rnxNavFile::input);
489
490 if (!_opt->_corrFile.empty()) {
491 _corrFile = new t_corrFile(QString(_opt->_corrFile.c_str()));
492 connect(_corrFile, SIGNAL(newTec(t_vTec)),
493 this, SLOT(slotNewTec(t_vTec)));
494 connect(_corrFile, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
495 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)));
496 connect(_corrFile, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
497 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)));
498 connect(_corrFile, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
499 this, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)));
500 connect(_corrFile, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
501 this, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)));
502 }
503
504 // Read/Process Observations
505 // -------------------------
506 int nEpo = 0;
507 const t_rnxObsFile::t_rnxEpo* epo = 0;
508 while ( !_stopFlag && (epo = _rnxObsFile->nextEpoch()) != 0 ) {
509 ++nEpo;
510
511 if (_speed < 100) {
512 double sleepTime = 2.0 / _speed;
513 t_pppThread::msleep(int(sleepTime*1.e3));
514 }
515
516 // Get Corrections
517 // ---------------
518 if (_corrFile) {
519 try {
520 _corrFile->syncRead(epo->tt);
521 }
522 catch (const char* msg) {
523 emit newMessage(QByteArray(msg), true);
524 break;
525 }
526 catch (const string& msg) {
527 emit newMessage(QByteArray(msg.c_str()), true);
528 break;
529 }
530 catch (...) {
531 emit newMessage("unknown exceptions in corrFile", true);
532 break;
533 }
534 }
535
536 // Get Ephemerides
537 // ----------------
538 t_eph* eph = 0;
539 const QMap<QString, unsigned int>* corrIODs = _corrFile ? &_corrFile->corrIODs() : 0;
540 while ( (eph = _rnxNavFile->getNextEph(epo->tt, corrIODs)) != 0 ) {
541 _pppClient->putEphemeris(eph);
542 delete eph; eph = 0;
543 }
544
545 // Create list of observations and start epoch processing
546 // ------------------------------------------------------
547 QList<t_satObs> obsList;
548 for (unsigned iObs = 0; iObs < epo->rnxSat.size(); iObs++) {
549 const t_rnxObsFile::t_rnxSat& rnxSat = epo->rnxSat[iObs];
550
551 t_satObs obs;
552 t_rnxObsFile::setObsFromRnx(_rnxObsFile, epo, rnxSat, obs);
553 obsList << obs;
554 }
555 slotNewObs(QByteArray(_opt->_roverName.c_str()), obsList);
556
557
558 if (nEpo % 10 == 0) {
559 emit progressRnxPPP(nEpo);
560 }
561
562 QCoreApplication::processEvents();
563 }
564
565 emit finishedRnxPPP();
566
567 if (BNC_CORE->mode() != t_bncCore::interactive) {
568 qApp->exit(0);
569 }
570 else {
571 BNC_CORE->stopPPP();
572 }
573}
574
575//
576////////////////////////////////////////////////////////////////////////////
577void t_pppRun::slotSetSpeed(int speed) {
578 QMutexLocker locker(&_mutex);
579 _speed = speed;
580}
581
582//
583////////////////////////////////////////////////////////////////////////////
584void t_pppRun::slotSetStopFlag() {
585 QMutexLocker locker(&_mutex);
586 _stopFlag = true;
587}
588
589//
590////////////////////////////////////////////////////////////////////////////
591QString t_pppRun::nmeaString(char strType, const t_output& output) {
592
593 double ell[3];
594 xyz2ell(output._xyzRover, ell);
595 double phiDeg = ell[0] * 180 / M_PI;
596 double lamDeg = ell[1] * 180 / M_PI;
597
598 char phiCh = 'N';
599 if (phiDeg < 0) {
600 phiDeg = -phiDeg;
601 phiCh = 'S';
602 }
603 char lamCh = 'E';
604 if (lamDeg < 0) {
605 lamDeg = -lamDeg;
606 lamCh = 'W';
607 }
608
609 ostringstream out;
610 out.setf(ios::fixed);
611
612 if (strType == 'R') {
613 string datestr = output._epoTime.datestr(0); // yyyymmdd
614 out << "GPRMC,"
615 << output._epoTime.timestr(0,0) << ",A,"
616 << setw(2) << setfill('0') << int(phiDeg)
617 << setw(6) << setprecision(3) << setfill('0')
618 << fmod(60*phiDeg,60) << ',' << phiCh << ','
619 << setw(3) << setfill('0') << int(lamDeg)
620 << setw(6) << setprecision(3) << setfill('0')
621 << fmod(60*lamDeg,60) << ',' << lamCh << ",,,"
622 << datestr[6] << datestr[7] << datestr[4] << datestr[5]
623 << datestr[2] << datestr[3] << ",,";
624 }
625 else if (strType == 'G') {
626 out << "GPGGA,"
627 << output._epoTime.timestr(0,0) << ','
628 << setw(2) << setfill('0') << int(phiDeg)
629 << setw(10) << setprecision(7) << setfill('0')
630 << fmod(60*phiDeg,60) << ',' << phiCh << ','
631 << setw(3) << setfill('0') << int(lamDeg)
632 << setw(10) << setprecision(7) << setfill('0')
633 << fmod(60*lamDeg,60) << ',' << lamCh
634 << ",1," << setw(2) << setfill('0') << output._numSat << ','
635 << setw(3) << setprecision(1) << output._pDop << ','
636 << setprecision(3) << ell[2] << ",M,0.0,M,,";
637 }
638 else {
639 return "";
640 }
641
642 QString nmStr(out.str().c_str());
643 unsigned char XOR = 0;
644 for (int ii = 0; ii < nmStr.length(); ii++) {
645 XOR ^= (unsigned char) nmStr[ii].toAscii();
646 }
647
648 return '$' + nmStr + QString("*%1\n").arg(int(XOR), 0, 16).toUpper();
649}
650
651//
652////////////////////////////////////////////////////////////////////////////
653bool t_pppRun::waitForCorr(const bncTime& epoTime) const {
654
655 if (!_opt->_realTime || _opt->_corrMount.empty()) {
656 return false;
657 }
658 else if (!_lastClkCorrTime.valid()) {
659 return true;
660 }
661 else {
662 double dt = epoTime - _lastClkCorrTime;
663 if (dt > 1.0 && dt < _opt->_corrWaitTime) {
664 return true;
665 }
666 else {
667 return false;
668 }
669 }
670 return false;
671}
Note: See TracBrowser for help on using the repository browser.