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

Last change on this file since 8056 was 7972, checked in by stuerze, 10 years ago

consideration of provider ID changes in SSR correction streams during PPP processing

File size: 20.7 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 connect(BNC_CORE, SIGNAL(providerIDChanged(QString)),
126 this, SLOT(slotProviderIDChanged(QString)));
127 }
128 else {
129 _rnxObsFile = 0;
130 _rnxNavFile = 0;
131 _corrFile = 0;
132 _speed = settings.value("PPP/mapSpeedSlider").toInt();
133 connect(this, SIGNAL(progressRnxPPP(int)), BNC_CORE, SIGNAL(progressRnxPPP(int)));
134 connect(this, SIGNAL(finishedRnxPPP()), BNC_CORE, SIGNAL(finishedRnxPPP()));
135 connect(BNC_CORE, SIGNAL(mapSpeedSliderChanged(int)),
136 this, SLOT(slotSetSpeed(int)));
137 connect(BNC_CORE, SIGNAL(stopRinexPPP()), this, SLOT(slotSetStopFlag()));
138 }
139
140 _stopFlag = false;
141
142 QString roverName(_opt->_roverName.c_str()), fullRoverName("");
143 QString country;
144 QString monNum = "0";
145 QString recNum = "0";
146 QString intr = "1 day";
147 int sampl = 0;
148 QListIterator<QString> it(settings.value("mountPoints").toStringList());
149 while (it.hasNext()) {
150 QStringList hlp = it.next().split(" ");
151 if (hlp.size() < 7)
152 continue;
153 if (hlp.join(" ").indexOf(roverName, 0) != -1) {
154 country = hlp[2];
155 }
156 }
157 fullRoverName = roverName.left(4) +
158 QString("%1").arg(monNum, 1, 10) +
159 QString("%1").arg(recNum, 1, 10) +
160 country;
161
162 bool v3filenames = settings.value("PPP/v3filenames").toBool();
163 QString logFileSkl = settings.value("PPP/logPath").toString();
164 int l = logFileSkl.length();
165 if (logFileSkl.isEmpty()) {
166 _logFile = 0;
167 }
168 else {
169 if (l && logFileSkl[l-1] != QDir::separator() ) {
170 logFileSkl += QDir::separator();
171 }
172 if (v3filenames) {
173 logFileSkl = logFileSkl + fullRoverName + "${V3}" + ".ppp";
174 }
175 else {
176 logFileSkl = logFileSkl + roverName.left(4) + "${GPSWD}" + ".ppp";
177 }
178 _logFile = new bncoutf(logFileSkl, intr, sampl);
179 }
180
181 QString nmeaFileSkl = settings.value("PPP/nmeaPath").toString();
182 l = nmeaFileSkl.length();
183 if (nmeaFileSkl.isEmpty()) {
184 _nmeaFile = 0;
185 }
186 else {
187 if (l > 0 && nmeaFileSkl[l-1] != QDir::separator() ) {
188 nmeaFileSkl += QDir::separator();
189 }
190 if (v3filenames) {
191 nmeaFileSkl = nmeaFileSkl + fullRoverName + "${V3}" + ".nmea";
192 }
193 else {
194 nmeaFileSkl = nmeaFileSkl + roverName.left(4) + "${GPSWD}" + ".nmea";
195 }
196 _nmeaFile = new bncoutf(nmeaFileSkl, intr, sampl);
197 }
198
199 QString snxtroFileSkl = settings.value("PPP/snxtroPath").toString();
200 l = snxtroFileSkl.length();
201 if (snxtroFileSkl.isEmpty()) {
202 _snxtroFile = 0;
203 }
204 else {
205 if (l > 0 && snxtroFileSkl[l-1] != QDir::separator() ) {
206 snxtroFileSkl += QDir::separator();
207 }
208 if (v3filenames) {
209 snxtroFileSkl = snxtroFileSkl + fullRoverName + "${V3}" + ".tra";
210 }
211 else {
212 snxtroFileSkl = snxtroFileSkl + roverName.left(4) + "${GPSWD}" + ".tro";
213 }
214 sampl = settings.value("PPP/snxtroSampl").toInt();
215 intr = settings.value("PPP/snxtroIntr").toString();
216 _snxtroFile = new bncSinexTro(_opt, snxtroFileSkl, intr, sampl);
217 }
218}
219
220
221
222// Destructor
223////////////////////////////////////////////////////////////////////////////
224t_pppRun::~t_pppRun() {
225 delete _logFile;
226 delete _nmeaFile;
227 delete _snxtroFile;
228 while (!_epoData.empty()) {
229 delete _epoData.front();
230 _epoData.pop_front();
231 }
232}
233
234//
235////////////////////////////////////////////////////////////////////////////
236void t_pppRun::slotNewGPSEph(t_ephGPS eph) {
237 QMutexLocker locker(&_mutex);
238 _pppClient->putEphemeris(&eph);
239}
240
241//
242////////////////////////////////////////////////////////////////////////////
243void t_pppRun::slotNewGlonassEph(t_ephGlo eph) {
244 QMutexLocker locker(&_mutex);
245 _pppClient->putEphemeris(&eph);
246}
247
248//
249////////////////////////////////////////////////////////////////////////////
250void t_pppRun::slotNewGalileoEph(t_ephGal eph) {
251 QMutexLocker locker(&_mutex);
252 _pppClient->putEphemeris(&eph);
253}
254
255//
256////////////////////////////////////////////////////////////////////////////
257void t_pppRun::slotNewBDSEph(t_ephBDS eph) {
258 QMutexLocker locker(&_mutex);
259 _pppClient->putEphemeris(&eph);
260}
261
262//
263////////////////////////////////////////////////////////////////////////////
264void t_pppRun::slotNewObs(QByteArray staID, QList<t_satObs> obsList) {
265 QMutexLocker locker(&_mutex);
266
267 if (string(staID.data()) != _opt->_roverName) {
268 return;
269 }
270
271 // Loop over all observations (possible different epochs)
272 // -----------------------------------------------------
273 QListIterator<t_satObs> it(obsList);
274 while (it.hasNext()) {
275 const t_satObs& oldObs = it.next();
276 t_satObs* newObs = new t_satObs(oldObs);
277
278 // Find the corresponding data epoch or create a new one
279 // -----------------------------------------------------
280 t_epoData* epoch = 0;
281 deque<t_epoData*>::const_iterator it;
282 for (it = _epoData.begin(); it != _epoData.end(); it++) {
283 if (newObs->_time == (*it)->_time) {
284 epoch = *it;
285 break;
286 }
287 }
288 if (epoch == 0) {
289 if (_epoData.empty() || newObs->_time > _epoData.back()->_time) {
290 epoch = new t_epoData;
291 epoch->_time = newObs->_time;
292 _epoData.push_back(epoch);
293 }
294 }
295
296 // Put data into the epoch
297 // -----------------------
298 if (epoch != 0) {
299 epoch->_satObs.push_back(newObs);
300 }
301 else {
302 delete newObs;
303 }
304 }
305
306 // Make sure the buffer does not grow beyond any limit
307 // ---------------------------------------------------
308 const unsigned MAX_EPODATA_SIZE = 120;
309 if (_epoData.size() > MAX_EPODATA_SIZE) {
310 delete _epoData.front();
311 _epoData.pop_front();
312 }
313
314 // Process the oldest epochs
315 // ------------------------
316 while (_epoData.size()) {
317
318 const vector<t_satObs*>& satObs = _epoData.front()->_satObs;
319
320 // No corrections yet, skip the epoch
321 // ----------------------------------
322 if (_opt->_corrWaitTime && !_lastClkCorrTime.valid()) {
323 return;
324 }
325
326 // Process the front epoch
327 // -----------------------
328 if (_opt->_corrWaitTime == 0 ||
329 _epoData.front()->_time - _lastClkCorrTime < _opt->_corrWaitTime) {
330
331 t_output output;
332 _pppClient->processEpoch(satObs, &output);
333
334 if (!output._error) {
335 QVector<double> xx(6);
336 xx.data()[0] = output._xyzRover[0];
337 xx.data()[1] = output._xyzRover[1];
338 xx.data()[2] = output._xyzRover[2];
339 xx.data()[3] = output._neu[0];
340 xx.data()[4] = output._neu[1];
341 xx.data()[5] = output._neu[2];
342 emit newPosition(staID, output._epoTime, xx);
343 }
344
345 delete _epoData.front();
346 _epoData.pop_front();
347
348 ostringstream log;
349 if (output._error) {
350 log << output._log;
351 }
352 else {
353 log.setf(ios::fixed);
354 log << string(output._epoTime) << ' ' << staID.data()
355 << " X = " << setprecision(4) << output._xyzRover[0]
356 << " Y = " << setprecision(4) << output._xyzRover[1]
357 << " Z = " << setprecision(4) << output._xyzRover[2]
358 << " NEU: " << showpos << setw(8) << setprecision(4) << output._neu[0]
359 << " " << showpos << setw(8) << setprecision(4) << output._neu[1]
360 << " " << showpos << setw(8) << setprecision(4) << output._neu[2]
361 << " TRP: " << showpos << setw(8) << setprecision(4) << output._trp0
362 << " " << showpos << setw(8) << setprecision(4) << output._trp;
363 }
364
365 if (_logFile && output._epoTime.valid()) {
366 _logFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(),
367 QString(output._log.c_str()));
368 }
369
370 if (!output._error) {
371 QString rmcStr = nmeaString('R', output);
372 QString ggaStr = nmeaString('G', output);
373 if (_nmeaFile) {
374 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), rmcStr);
375 _nmeaFile->write(output._epoTime.gpsw(), output._epoTime.gpssec(), ggaStr);
376 }
377 emit newNMEAstr(staID, rmcStr.toAscii());
378 emit newNMEAstr(staID, ggaStr.toAscii());
379 if (_snxtroFile && output._epoTime.valid()) {
380 _snxtroFile->write(staID, int(output._epoTime.gpsw()), output._epoTime.gpssec(),
381 output._trp0 + output._trp, output._trpStdev);
382 }
383 }
384 emit newMessage(QByteArray(log.str().c_str()), true);
385 }
386 else {
387 return;
388 }
389 }
390}
391
392//
393////////////////////////////////////////////////////////////////////////////
394void t_pppRun::slotNewTec(t_vTec vTec) {
395 if (vTec._layers.size() == 0) {
396 return;
397 }
398
399 if (_opt->_realTime) {
400 if (_opt->_corrMount.empty() || _opt->_corrMount != vTec._staID) {
401 return;
402 }
403 }
404
405 _pppClient->putTec(&vTec);
406}
407
408//
409////////////////////////////////////////////////////////////////////////////
410void t_pppRun::slotNewOrbCorrections(QList<t_orbCorr> orbCorr) {
411 if (orbCorr.size() == 0) {
412 return;
413 }
414
415 if (_opt->_realTime) {
416 if (_opt->_corrMount.empty() || _opt->_corrMount != orbCorr[0]._staID) {
417 return;
418 }
419 }
420 vector<t_orbCorr*> corrections;
421 for (int ii = 0; ii < orbCorr.size(); ii++) {
422 corrections.push_back(new t_orbCorr(orbCorr[ii]));
423 }
424
425 _pppClient->putOrbCorrections(corrections);
426
427 for (unsigned ii = 0; ii < corrections.size(); ii++) {
428 delete corrections[ii];
429 }
430}
431
432//
433////////////////////////////////////////////////////////////////////////////
434void t_pppRun::slotNewClkCorrections(QList<t_clkCorr> clkCorr) {
435 if (clkCorr.size() == 0) {
436 return;
437 }
438
439 if (_opt->_realTime) {
440 if (_opt->_corrMount.empty() || _opt->_corrMount != clkCorr[0]._staID) {
441 return;
442 }
443 }
444 vector<t_clkCorr*> corrections;
445 for (int ii = 0; ii < clkCorr.size(); ii++) {
446 corrections.push_back(new t_clkCorr(clkCorr[ii]));
447 _lastClkCorrTime = clkCorr[ii]._time;
448 }
449 _pppClient->putClkCorrections(corrections);
450
451 for (unsigned ii = 0; ii < corrections.size(); ii++) {
452 delete corrections[ii];
453 }
454}
455
456//
457////////////////////////////////////////////////////////////////////////////
458void t_pppRun::slotNewCodeBiases(QList<t_satCodeBias> codeBiases) {
459 if (codeBiases.size() == 0) {
460 return;
461 }
462
463 if (_opt->_realTime) {
464 if (_opt->_corrMount.empty() || _opt->_corrMount != codeBiases[0]._staID) {
465 return;
466 }
467 }
468 vector<t_satCodeBias*> biases;
469 for (int ii = 0; ii < codeBiases.size(); ii++) {
470 biases.push_back(new t_satCodeBias(codeBiases[ii]));
471 }
472
473 _pppClient->putCodeBiases(biases);
474
475 for (unsigned ii = 0; ii < biases.size(); ii++) {
476 delete biases[ii];
477 }
478}
479
480//
481////////////////////////////////////////////////////////////////////////////
482void t_pppRun::slotNewPhaseBiases(QList<t_satPhaseBias> phaseBiases) {
483 if (phaseBiases.size() == 0) {
484 return;
485 }
486
487 if (_opt->_realTime) {
488 if (_opt->_corrMount.empty() || _opt->_corrMount != phaseBiases[0]._staID) {
489 return;
490 }
491 }
492 vector<t_satPhaseBias*> biases;
493 for (int ii = 0; ii < phaseBiases.size(); ii++) {
494 biases.push_back(new t_satPhaseBias(phaseBiases[ii]));
495 }
496
497 _pppClient->putPhaseBiases(biases);
498
499 for (unsigned ii = 0; ii < biases.size(); ii++) {
500 delete biases[ii];
501 }
502}
503
504//
505////////////////////////////////////////////////////////////////////////////
506void t_pppRun::processFiles() {
507
508 try {
509 _rnxObsFile = new t_rnxObsFile(QString(_opt->_rinexObs.c_str()), t_rnxObsFile::input);
510 }
511 catch (...) {
512 delete _rnxObsFile; _rnxObsFile = 0;
513 emit finishedRnxPPP();
514 return;
515 }
516
517 _rnxNavFile = new t_rnxNavFile(QString(_opt->_rinexNav.c_str()), t_rnxNavFile::input);
518
519 if (!_opt->_corrFile.empty()) {
520 _corrFile = new t_corrFile(QString(_opt->_corrFile.c_str()));
521 connect(_corrFile, SIGNAL(newTec(t_vTec)),
522 this, SLOT(slotNewTec(t_vTec)));
523 connect(_corrFile, SIGNAL(newOrbCorrections(QList<t_orbCorr>)),
524 this, SLOT(slotNewOrbCorrections(QList<t_orbCorr>)));
525 connect(_corrFile, SIGNAL(newClkCorrections(QList<t_clkCorr>)),
526 this, SLOT(slotNewClkCorrections(QList<t_clkCorr>)));
527 connect(_corrFile, SIGNAL(newCodeBiases(QList<t_satCodeBias>)),
528 this, SLOT(slotNewCodeBiases(QList<t_satCodeBias>)));
529 connect(_corrFile, SIGNAL(newPhaseBiases(QList<t_satPhaseBias>)),
530 this, SLOT(slotNewPhaseBiases(QList<t_satPhaseBias>)));
531 }
532
533 // Read/Process Observations
534 // -------------------------
535 int nEpo = 0;
536 const t_rnxObsFile::t_rnxEpo* epo = 0;
537 while ( !_stopFlag && (epo = _rnxObsFile->nextEpoch()) != 0 ) {
538 ++nEpo;
539
540 if (_speed < 100) {
541 double sleepTime = 2.0 / _speed;
542 t_pppThread::msleep(int(sleepTime*1.e3));
543 }
544
545 // Get Corrections
546 // ---------------
547 if (_corrFile) {
548 try {
549 _corrFile->syncRead(epo->tt);
550 }
551 catch (const char* msg) {
552 emit newMessage(QByteArray(msg), true);
553 break;
554 }
555 catch (const string& msg) {
556 emit newMessage(QByteArray(msg.c_str()), true);
557 break;
558 }
559 catch (...) {
560 emit newMessage("unknown exceptions in corrFile", true);
561 break;
562 }
563 }
564
565 // Get Ephemerides
566 // ----------------
567 t_eph* eph = 0;
568 const QMap<QString, unsigned int>* corrIODs = _corrFile ? &_corrFile->corrIODs() : 0;
569 while ( (eph = _rnxNavFile->getNextEph(epo->tt, corrIODs)) != 0 ) {
570 _pppClient->putEphemeris(eph);
571 delete eph; eph = 0;
572 }
573
574 // Create list of observations and start epoch processing
575 // ------------------------------------------------------
576 QList<t_satObs> obsList;
577 for (unsigned iObs = 0; iObs < epo->rnxSat.size(); iObs++) {
578 const t_rnxObsFile::t_rnxSat& rnxSat = epo->rnxSat[iObs];
579
580 t_satObs obs;
581 t_rnxObsFile::setObsFromRnx(_rnxObsFile, epo, rnxSat, obs);
582 obsList << obs;
583 }
584 slotNewObs(QByteArray(_opt->_roverName.c_str()), obsList);
585
586
587 if (nEpo % 10 == 0) {
588 emit progressRnxPPP(nEpo);
589 }
590
591 QCoreApplication::processEvents();
592 }
593
594 emit finishedRnxPPP();
595
596 if (BNC_CORE->mode() != t_bncCore::interactive) {
597 qApp->exit(0);
598 }
599 else {
600 BNC_CORE->stopPPP();
601 }
602}
603
604//
605////////////////////////////////////////////////////////////////////////////
606void t_pppRun::slotSetSpeed(int speed) {
607 QMutexLocker locker(&_mutex);
608 _speed = speed;
609}
610
611//
612////////////////////////////////////////////////////////////////////////////
613void t_pppRun::slotSetStopFlag() {
614 QMutexLocker locker(&_mutex);
615 _stopFlag = true;
616}
617
618//
619////////////////////////////////////////////////////////////////////////////
620QString t_pppRun::nmeaString(char strType, const t_output& output) {
621
622 double ell[3];
623 xyz2ell(output._xyzRover, ell);
624 double phiDeg = ell[0] * 180 / M_PI;
625 double lamDeg = ell[1] * 180 / M_PI;
626
627 unsigned year, month, day;
628 output._epoTime.civil_date(year, month, day);
629 double gps_utc = gnumleap(year, month, day);
630
631 char phiCh = 'N';
632 if (phiDeg < 0) {
633 phiDeg = -phiDeg;
634 phiCh = 'S';
635 }
636 char lamCh = 'E';
637 if (lamDeg < 0) {
638 lamDeg = -lamDeg;
639 lamCh = 'W';
640 }
641
642 ostringstream out;
643 out.setf(ios::fixed);
644
645 if (strType == 'R') {
646 string datestr = output._epoTime.datestr(0); // yyyymmdd
647 out << "GPRMC,"
648 << (output._epoTime - gps_utc).timestr(3,0) << ",A,"
649 << setw(2) << setfill('0') << int(phiDeg)
650 << setw(6) << setprecision(3) << setfill('0')
651 << fmod(60*phiDeg,60) << ',' << phiCh << ','
652 << setw(3) << setfill('0') << int(lamDeg)
653 << setw(6) << setprecision(3) << setfill('0')
654 << fmod(60*lamDeg,60) << ',' << lamCh << ",,,"
655 << datestr[6] << datestr[7] << datestr[4] << datestr[5]
656 << datestr[2] << datestr[3] << ",,";
657 }
658 else if (strType == 'G') {
659 out << "GPGGA,"
660 << (output._epoTime - gps_utc).timestr(2,0) << ','
661 << setw(2) << setfill('0') << int(phiDeg)
662 << setw(10) << setprecision(7) << setfill('0')
663 << fmod(60*phiDeg,60) << ',' << phiCh << ','
664 << setw(3) << setfill('0') << int(lamDeg)
665 << setw(10) << setprecision(7) << setfill('0')
666 << fmod(60*lamDeg,60) << ',' << lamCh
667 << ",1," << setw(2) << setfill('0') << output._numSat << ','
668 << setw(3) << setprecision(1) << output._hDop << ','
669 << setprecision(3) << ell[2] << ",M,0.0,M,,";
670 }
671 else {
672 return "";
673 }
674
675 QString nmStr(out.str().c_str());
676 unsigned char XOR = 0;
677 for (int ii = 0; ii < nmStr.length(); ii++) {
678 XOR ^= (unsigned char) nmStr[ii].toAscii();
679 }
680
681 return '$' + nmStr + QString("*%1\n").arg(int(XOR), 0, 16).toUpper();
682}
683
684//
685////////////////////////////////////////////////////////////////////////////
686void t_pppRun::slotProviderIDChanged(QString mountPoint) {
687 QMutexLocker locker(&_mutex);
688
689 if (mountPoint.toStdString() !=_opt->_corrMount) {
690 return;
691 }
692
693 QString msg = "pppRun " + QString(_opt->_roverName.c_str()) + ": Provider Changed: " + mountPoint;
694 emit newMessage(msg.toAscii(), true);
695
696 _pppClient->reset();
697
698 while (!_epoData.empty()) {
699 delete _epoData.front();
700 _epoData.pop_front();
701 }
702}
Note: See TracBrowser for help on using the repository browser.