source: ntrip/branches/BNC_2.12/src/pppRun.cpp @ 8793

Last change on this file since 8793 was 8793, checked in by stuerze, 12 months ago

minor changes for correct marker and receiver numbers in PPP logfile (rinex v3 style) names

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