source: ntrip/trunk/BNC/src/bncgetthread.cpp@ 7223

Last change on this file since 7223 was 7180, checked in by stuerze, 10 years ago

NMEA TCP port functionlity removed into bncgetthread class in order to have it available for each PPP station

File size: 27.3 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: bncGetThread
30 *
31 * Purpose: Thread that retrieves data from NTRIP caster
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Dec-2005
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <stdlib.h>
42#include <iomanip>
43#include <sstream>
44
45#include <QFile>
46#include <QTextStream>
47#include <QMutex>
48#include <QtNetwork>
49#include <QTime>
50
51#include "bncgetthread.h"
52#include "bnctabledlg.h"
53#include "bnccore.h"
54#include "bncutils.h"
55#include "bnczerodecoder.h"
56#include "bncnetqueryv0.h"
57#include "bncnetqueryv1.h"
58#include "bncnetqueryv2.h"
59#include "bncnetqueryrtp.h"
60#include "bncnetqueryudp.h"
61#include "bncnetqueryudp0.h"
62#include "bncnetquerys.h"
63#include "bncsettings.h"
64#include "latencychecker.h"
65#include "upload/bncrtnetdecoder.h"
66#include "RTCM/RTCM2Decoder.h"
67#include "RTCM3/RTCM3Decoder.h"
68#include "serial/qextserialport.h"
69
70using namespace std;
71
72// Constructor 1
73////////////////////////////////////////////////////////////////////////////
74bncGetThread::bncGetThread(bncRawFile* rawFile) {
75
76 _rawFile = rawFile;
77 _format = rawFile->format();
78 _staID = rawFile->staID();
79 _rawOutput = false;
80 _ntripVersion = "N";
81
82 initialize();
83}
84
85// Constructor 2
86////////////////////////////////////////////////////////////////////////////
87bncGetThread::bncGetThread(const QUrl& mountPoint,
88 const QByteArray& format,
89 const QByteArray& latitude,
90 const QByteArray& longitude,
91 const QByteArray& nmea,
92 const QByteArray& ntripVersion) {
93 _rawFile = 0;
94 _mountPoint = mountPoint;
95 _staID = mountPoint.path().mid(1).toAscii();
96 _format = format;
97 _latitude = latitude;
98 _longitude = longitude;
99 _nmea = nmea;
100 _ntripVersion = ntripVersion;
101
102 bncSettings settings;
103 if (!settings.value("rawOutFile").toString().isEmpty()) {
104 _rawOutput = true;
105 } else {
106 _rawOutput = false;
107 }
108
109 initialize();
110 initDecoder();
111}
112
113// Initialization (common part of the constructor)
114////////////////////////////////////////////////////////////////////////////
115void bncGetThread::initialize() {
116
117 bncSettings settings;
118
119 setTerminationEnabled(true);
120
121 connect(this, SIGNAL(newMessage(QByteArray,bool)),
122 BNC_CORE, SLOT(slotMessage(const QByteArray,bool)));
123
124 _isToBeDeleted = false;
125 _query = 0;
126 _nextSleep = 0;
127 _miscMount = settings.value("miscMount").toString();
128 _decoder = 0;
129
130 // NMEA Port
131 // -----------
132 QListIterator<QString> iSta(settings.value("PPP/staTable").toStringList());
133 int nmeaPort = 0;
134 while (iSta.hasNext()) {
135 QStringList hlp = iSta.next().split(",");
136 if (hlp.size() < 10) {continue;}
137 QByteArray mp = hlp[0].toAscii();
138 if (_staID == mp) {
139 nmeaPort = hlp[9].toInt();
140 }
141 }
142 if (nmeaPort != 0) {
143 _nmeaServer = new QTcpServer;
144 if ( !_nmeaServer->listen(QHostAddress::Any, nmeaPort) ) {
145 emit newMessage("bncCaster: Cannot listen on port", true);
146 }
147 else {
148 connect(_nmeaServer, SIGNAL(newConnection()), this, SLOT(slotNewNMEAConnection()));
149 connect(BNC_CORE, SIGNAL(newNMEAstr(QByteArray, QByteArray)),
150 this, SLOT(slotNewNMEAstr(QByteArray, QByteArray)));
151 _nmeaSockets = new QList<QTcpSocket*>;
152 _nmeaPortsMap[_staID] = nmeaPort;
153 }
154 } else {
155 _nmeaServer = 0;
156 _nmeaSockets = 0;
157 }
158
159 // Serial Port
160 // -----------
161 _serialNMEA = NO_NMEA;
162 _serialOutFile = 0;
163 _serialPort = 0;
164
165 if (!_staID.isEmpty() &&
166 settings.value("serialMountPoint").toString() == _staID) {
167 _serialPort = new QextSerialPort(settings.value("serialPortName").toString() );
168 _serialPort->setTimeout(0,100);
169
170 // Baud Rate
171 // ---------
172 QString hlp = settings.value("serialBaudRate").toString();
173 if (hlp == "110") {
174 _serialPort->setBaudRate(BAUD110);
175 }
176 else if (hlp == "300") {
177 _serialPort->setBaudRate(BAUD300);
178 }
179 else if (hlp == "600") {
180 _serialPort->setBaudRate(BAUD600);
181 }
182 else if (hlp == "1200") {
183 _serialPort->setBaudRate(BAUD1200);
184 }
185 else if (hlp == "2400") {
186 _serialPort->setBaudRate(BAUD2400);
187 }
188 else if (hlp == "4800") {
189 _serialPort->setBaudRate(BAUD4800);
190 }
191 else if (hlp == "9600") {
192 _serialPort->setBaudRate(BAUD9600);
193 }
194 else if (hlp == "19200") {
195 _serialPort->setBaudRate(BAUD19200);
196 }
197 else if (hlp == "38400") {
198 _serialPort->setBaudRate(BAUD38400);
199 }
200 else if (hlp == "57600") {
201 _serialPort->setBaudRate(BAUD57600);
202 }
203 else if (hlp == "115200") {
204 _serialPort->setBaudRate(BAUD115200);
205 }
206
207 // Parity
208 // ------
209 hlp = settings.value("serialParity").toString();
210 if (hlp == "NONE") {
211 _serialPort->setParity(PAR_NONE);
212 }
213 else if (hlp == "ODD") {
214 _serialPort->setParity(PAR_ODD);
215 }
216 else if (hlp == "EVEN") {
217 _serialPort->setParity(PAR_EVEN);
218 }
219 else if (hlp == "SPACE") {
220 _serialPort->setParity(PAR_SPACE);
221 }
222
223 // Data Bits
224 // ---------
225 hlp = settings.value("serialDataBits").toString();
226 if (hlp == "5") {
227 _serialPort->setDataBits(DATA_5);
228 }
229 else if (hlp == "6") {
230 _serialPort->setDataBits(DATA_6);
231 }
232 else if (hlp == "7") {
233 _serialPort->setDataBits(DATA_7);
234 }
235 else if (hlp == "8") {
236 _serialPort->setDataBits(DATA_8);
237 }
238 hlp = settings.value("serialStopBits").toString();
239 if (hlp == "1") {
240 _serialPort->setStopBits(STOP_1);
241 }
242 else if (hlp == "2") {
243 _serialPort->setStopBits(STOP_2);
244 }
245
246 // Flow Control
247 // ------------
248 hlp = settings.value("serialFlowControl").toString();
249 if (hlp == "XONXOFF") {
250 _serialPort->setFlowControl(FLOW_XONXOFF);
251 }
252 else if (hlp == "HARDWARE") {
253 _serialPort->setFlowControl(FLOW_HARDWARE);
254 }
255 else {
256 _serialPort->setFlowControl(FLOW_OFF);
257 }
258
259 // Open Serial Port
260 // ----------------
261 _serialPort->open(QIODevice::ReadWrite|QIODevice::Unbuffered);
262 if (!_serialPort->isOpen()) {
263 delete _serialPort;
264 _serialPort = 0;
265 emit(newMessage((_staID + ": Cannot open serial port\n"), true));
266 }
267 connect(_serialPort, SIGNAL(readyRead()),
268 this, SLOT(slotSerialReadyRead()));
269
270 // Automatic NMEA
271 // --------------
272 QString nmeaMode = settings.value("serialAutoNMEA").toString();
273 if (nmeaMode == "Auto") {
274 _serialNMEA = AUTO_NMEA;
275 QString fName = settings.value("serialFileNMEA").toString();
276 if (!fName.isEmpty()) {
277 _serialOutFile = new QFile(fName);
278 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
279 _serialOutFile->open(QIODevice::WriteOnly | QIODevice::Append);
280 }
281 else {
282 _serialOutFile->open(QIODevice::WriteOnly);
283 }
284 }
285 }
286 // Manual NMEA
287 // -----------
288 if ((nmeaMode == "Manual GPGGA") ||(nmeaMode == "Manual GNGGA")) {
289 _serialNMEA = MANUAL_NMEA;
290 bncSettings settings;
291 _manualNMEASampl = settings.value("serialManualNMEASampling").toInt();
292 QString hlp = settings.value("serialHeightNMEA").toString();
293 if (hlp.isEmpty()) {
294 hlp = "0.0";
295 }
296 QByteArray _serialHeightNMEA = hlp.toAscii();
297 _manualNMEAString = ggaString(_latitude, _longitude, _serialHeightNMEA, nmeaMode);
298 }
299 }
300
301 if (!_staID.isEmpty()) {
302 _latencyChecker = new latencyChecker(_staID);
303 }
304 else {
305 _latencyChecker = 0;
306 }
307}
308
309// Instantiate the decoder
310//////////////////////////////////////////////////////////////////////////////
311t_irc bncGetThread::initDecoder() {
312
313 _decoder = 0;
314
315 if (_format.indexOf("RTCM_2") != -1 || _format.indexOf("RTCM2") != -1 ||
316 _format.indexOf("RTCM 2") != -1 ) {
317 emit(newMessage(_staID + ": Get data in RTCM 2.x format", true));
318 _decoder = new RTCM2Decoder(_staID.data());
319 }
320 else if (_format.indexOf("RTCM_3") != -1 || _format.indexOf("RTCM3") != -1 ||
321 _format.indexOf("RTCM 3") != -1 ) {
322 emit(newMessage(_staID + ": Get data in RTCM 3.x format", true));
323 RTCM3Decoder* newDecoder = new RTCM3Decoder(_staID, _rawFile);
324 _decoder = newDecoder;
325 connect((RTCM3Decoder*) newDecoder, SIGNAL(newMessage(QByteArray,bool)),
326 this, SIGNAL(newMessage(QByteArray,bool)));
327 }
328 else if (_format.indexOf("ZERO") != -1) {
329 emit(newMessage(_staID + ": Get data in original format", true));
330 _decoder = new bncZeroDecoder(_staID);
331 }
332 else if (_format.indexOf("RTNET") != -1) {
333 emit(newMessage(_staID + ": Get data in RTNet format", true));
334 _decoder = new bncRtnetDecoder();
335 }
336 else {
337 emit(newMessage(_staID + ": Unknown data format " + _format, true));
338 _isToBeDeleted = true;
339 return failure;
340 }
341
342 msleep(100); //sleep 0.1 sec
343
344 _decoder->initRinex(_staID, _mountPoint, _latitude, _longitude,
345 _nmea, _ntripVersion);
346
347 if (_rawFile) {
348 _decodersRaw[_staID] = _decoder;
349 }
350
351 return success;
352}
353
354// Current decoder in use
355////////////////////////////////////////////////////////////////////////////
356GPSDecoder* bncGetThread::decoder() {
357 if (!_rawFile) {
358 return _decoder;
359 }
360 else {
361 if (_decodersRaw.contains(_staID) || initDecoder() == success) {
362 return _decodersRaw[_staID];
363 }
364 }
365 return 0;
366}
367
368// Destructor
369////////////////////////////////////////////////////////////////////////////
370bncGetThread::~bncGetThread() {
371 if (isRunning()) {
372 wait();
373 }
374 if (_query) {
375 _query->stop();
376 _query->deleteLater();
377 }
378 if (_rawFile) {
379 QMapIterator<QString, GPSDecoder*> it(_decodersRaw);
380 while (it.hasNext()) {
381 it.next();
382 delete it.value();
383 }
384 }
385 else {
386 delete _decoder;
387 }
388 delete _rawFile;
389 delete _serialOutFile;
390 delete _serialPort;
391 delete _latencyChecker;
392 emit getThreadFinished(_staID);
393}
394
395//
396////////////////////////////////////////////////////////////////////////////
397void bncGetThread::terminate() {
398 _isToBeDeleted = true;
399 if (!isRunning()) {
400 delete this;
401 }
402 _nmeaPortsMap.remove(_staID);
403 delete _nmeaServer;
404 delete _nmeaSockets;
405}
406
407// Run
408////////////////////////////////////////////////////////////////////////////
409void bncGetThread::run() {
410
411 while (true) {
412 try {
413 if (_isToBeDeleted) {
414 QThread::exit(0);
415 this->deleteLater();
416 return;
417 }
418
419 if (tryReconnect() != success) {
420 if (_latencyChecker) {
421 _latencyChecker->checkReconnect();
422 }
423 continue;
424 }
425
426 // Delete old observations
427 // -----------------------
428 if (_rawFile) {
429 QMapIterator<QString, GPSDecoder*> itDec(_decodersRaw);
430 while (itDec.hasNext()) {
431 itDec.next();
432 GPSDecoder* decoder = itDec.value();
433 decoder->_obsList.clear();
434 }
435 }
436 else {
437 _decoder->_obsList.clear();
438 }
439
440 // Read Data
441 // ---------
442 QByteArray data;
443 if (_query) {
444 _query->waitForReadyRead(data);
445 }
446 else if (_rawFile) {
447 data = _rawFile->readChunk();
448 _format = _rawFile->format();
449 _staID = _rawFile->staID();
450
451 QCoreApplication::processEvents();
452
453 if (data.isEmpty()) {
454 cout << "no more data" << endl;
455 BNC_CORE->stopCombination();
456 BNC_CORE->stopPPP();
457 ::exit(0);
458 }
459 }
460 qint64 nBytes = data.size();
461
462 // Timeout, reconnect
463 // ------------------
464 if (nBytes == 0) {
465 if (_latencyChecker) {
466 _latencyChecker->checkReconnect();
467 }
468 emit(newMessage(_staID + ": Data timeout, reconnecting", true));
469 msleep(10000); //sleep 10 sec, G. Weber
470 continue;
471 }
472 else {
473 emit newBytes(_staID, nBytes);
474 emit newRawData(_staID, data);
475 }
476
477 // Output Data
478 // -----------
479 if (_rawOutput) {
480 BNC_CORE->writeRawData(data, _staID, _format);
481 }
482
483 if (_serialPort) {
484 slotSerialReadyRead();
485 _serialPort->write(data);
486 }
487
488 // Decode Data
489 // -----------
490 vector<string> errmsg;
491 if (!decoder()) {
492 _isToBeDeleted = true;
493 continue;
494 }
495 decoder()->_obsList.clear();
496 t_irc irc = decoder()->Decode(data.data(), data.size(), errmsg);
497
498 // Perform various scans and checks
499 // --------------------------------
500 if (_latencyChecker) {
501 _latencyChecker->checkOutage(irc == success);
502 _latencyChecker->checkObsLatency(decoder()->_obsList);
503 _latencyChecker->checkCorrLatency(decoder()->corrGPSEpochTime());
504
505 emit newLatency(_staID, _latencyChecker->currentLatency());
506 }
507
508 scanRTCM();
509
510 // Loop over all observations (observations output)
511 // ------------------------------------------------
512 QListIterator<t_satObs> it(decoder()->_obsList);
513
514 QList<t_satObs> obsListHlp;
515
516 while (it.hasNext()) {
517 const t_satObs& obs = it.next();
518
519 QString prn(obs._prn.toString().c_str());
520 long iSec = long(floor(obs._time.gpssec()+0.5));
521 long obsTime = obs._time.gpsw()*7*24*3600 + iSec;
522
523 // Check observation epoch
524 // -----------------------
525 if (!_rawFile) {
526 int week;
527 double sec;
528 currentGPSWeeks(week, sec);
529 long currTime = week * 7*24*3600 + long(sec);
530 const double maxDt = 600.0;
531 if (fabs(currTime - obsTime) > maxDt) {
532 emit( newMessage(_staID + ": Wrong observation epoch(s)", false) );
533 continue;
534 }
535 }
536
537 // Check observations coming twice (e.g. KOUR0 Problem)
538 // ----------------------------------------------------
539 if (!_rawFile) {
540 QMap<QString, long>::const_iterator it = _prnLastEpo.find(prn);
541 if (it != _prnLastEpo.end()) {
542 long oldTime = it.value();
543 if (obsTime < oldTime) {
544 emit( newMessage(_staID +
545 ": old observation " + prn.toAscii(), false));
546 continue;
547 }
548 else if (obsTime == oldTime) {
549 emit( newMessage(_staID +
550 ": observation coming more than once " + prn.toAscii(), false));
551 continue;
552 }
553 }
554 _prnLastEpo[prn] = obsTime;
555 }
556
557 decoder()->dumpRinexEpoch(obs, _format);
558
559 // Save observations
560 // -----------------
561 obsListHlp.append(obs);
562 }
563
564 // Emit signal
565 // -----------
566 if (!_isToBeDeleted && obsListHlp.size() > 0) {
567 emit newObs(_staID, obsListHlp);
568 }
569
570 decoder()->_obsList.clear();
571 }
572 catch (Exception& exc) {
573 emit(newMessage(_staID + " " + exc.what(), true));
574 _isToBeDeleted = true;
575 }
576 catch (...) {
577 emit(newMessage(_staID + " bncGetThread exception", true));
578 _isToBeDeleted = true;
579 }
580 }
581}
582
583// Try Re-Connect
584////////////////////////////////////////////////////////////////////////////
585t_irc bncGetThread::tryReconnect() {
586
587 // Easy Return
588 // -----------
589 if (_query && _query->status() == bncNetQuery::running) {
590 _nextSleep = 0;
591 if (_rawFile) {
592 QMapIterator<QString, GPSDecoder*> itDec(_decodersRaw);
593 while (itDec.hasNext()) {
594 itDec.next();
595 GPSDecoder* decoder = itDec.value();
596 decoder->setRinexReconnectFlag(false);
597 }
598 }
599 else {
600 _decoder->setRinexReconnectFlag(false);
601 }
602 return success;
603 }
604
605 // Start a new query
606 // -----------------
607 if (!_rawFile) {
608
609 sleep(_nextSleep);
610 if (_nextSleep == 0) {
611 _nextSleep = 1;
612 }
613 else {
614 _nextSleep = 2 * _nextSleep;
615 if (_nextSleep > 256) {
616 _nextSleep = 256;
617 }
618#ifdef MLS_SOFTWARE
619 if (_nextSleep > 4) {
620 _nextSleep = 4;
621 }
622#endif
623 }
624
625 delete _query;
626 if (_ntripVersion == "U") {
627 _query = new bncNetQueryUdp();
628 }
629 else if (_ntripVersion == "R") {
630 _query = new bncNetQueryRtp();
631 }
632 else if (_ntripVersion == "S") {
633 _query = new bncNetQueryS();
634 }
635 else if (_ntripVersion == "N") {
636 _query = new bncNetQueryV0();
637 }
638 else if (_ntripVersion == "UN") {
639 _query = new bncNetQueryUdp0();
640 }
641 else if (_ntripVersion == "2") {
642 _query = new bncNetQueryV2(false);
643 }
644 else if (_ntripVersion == "2s") {
645 _query = new bncNetQueryV2(true);
646 }
647 else {
648 _query = new bncNetQueryV1();
649 }
650 if (_nmea == "yes") {
651 if (_serialNMEA == MANUAL_NMEA) {
652 _query->startRequest(_mountPoint, _manualNMEAString);
653 _lastManualNMEA = QDateTime::currentDateTime();
654 }
655 else if (_serialNMEA == AUTO_NMEA) {
656 if (_serialPort) {
657 int nb = _serialPort->bytesAvailable();
658 if (nb > 0) {
659 QByteArray data = _serialPort->read(nb);
660 int i1 = data.indexOf("$GPGGA");
661 if (i1 == -1) {
662 i1 = data.indexOf("$GNGGA");
663 }
664 if (i1 != -1) {
665 int i2 = data.indexOf("*", i1);
666 if (i2 != -1 && data.size() > i2 + 1) {
667 QByteArray gga = data.mid(i1, i2 - i1 + 3);
668 _query->startRequest(_mountPoint, gga);
669 }
670 }
671 }
672 }
673 }
674 }
675 else {
676 _query->startRequest(_mountPoint, "");
677 }
678
679 if (_query->status() != bncNetQuery::running) {
680 return failure;
681 }
682 }
683
684 if (_rawFile) {
685 QMapIterator<QString, GPSDecoder*> itDec(_decodersRaw);
686 while (itDec.hasNext()) {
687 itDec.next();
688 GPSDecoder* decoder = itDec.value();
689 decoder->setRinexReconnectFlag(false);
690 }
691 }
692 else {
693 _decoder->setRinexReconnectFlag(false);
694 }
695
696 return success;
697}
698
699// RTCM scan output
700//////////////////////////////////////////////////////////////////////////////
701void bncGetThread::scanRTCM() {
702
703 if ( !decoder() ) {
704 return;
705 }
706
707 bncSettings settings;
708 if ( Qt::CheckState(settings.value("scanRTCM").toInt()) == Qt::Checked ) {
709
710 if ( _miscMount == _staID || _miscMount == "ALL" ) {
711 // RTCM message types
712 // ------------------
713 for (int ii = 0; ii < decoder()->_typeList.size(); ii++) {
714 QString type = QString("%1 ").arg(decoder()->_typeList[ii]);
715 emit(newMessage(_staID + ": Received message type " + type.toAscii(), true));
716 }
717
718 // Check Observation Types
719 // -----------------------
720 for (int ii = 0; ii < decoder()->_obsList.size(); ii++) {
721 t_satObs& obs = decoder()->_obsList[ii];
722 QVector<QString>& rnxTypes = _rnxTypes[obs._prn.system()];
723 bool allFound = true;
724 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) {
725 if (obs._obs[iFrq]->_codeValid) {
726 QString rnxStr('C');
727 rnxStr.append(obs._obs[iFrq]->_rnxType2ch.c_str());
728 if (_format.indexOf("RTCM_2") != -1 ||
729 _format.indexOf("RTCM2") != -1 ||
730 _format.indexOf("RTCM 2") != -1 ) {
731 rnxStr = t_rnxObsFile::type3to2(obs._prn.system(), rnxStr);
732 }
733 if (rnxTypes.indexOf(rnxStr) == -1) {
734 rnxTypes.push_back(rnxStr);
735 allFound = false;
736 }
737 }
738 if (obs._obs[iFrq]->_phaseValid) {
739 QString rnxStr('L');
740 rnxStr.append(obs._obs[iFrq]->_rnxType2ch.c_str());
741 if (_format.indexOf("RTCM_2") != -1 ||
742 _format.indexOf("RTCM2") != -1 ||
743 _format.indexOf("RTCM 2") != -1 ) {
744 rnxStr = t_rnxObsFile::type3to2(obs._prn.system(), rnxStr);
745 }
746 if (rnxTypes.indexOf(rnxStr) == -1) {
747 rnxTypes.push_back(rnxStr);
748 allFound = false;
749 }
750 }
751 if (obs._obs[iFrq]->_dopplerValid){
752 QString rnxStr('D');
753 rnxStr.append(obs._obs[iFrq]->_rnxType2ch.c_str());
754 if (_format.indexOf("RTCM_2") != -1 ||
755 _format.indexOf("RTCM2") != -1 ||
756 _format.indexOf("RTCM 2") != -1 ) {
757 rnxStr = t_rnxObsFile::type3to2(obs._prn.system(), rnxStr);
758 }
759 if (rnxTypes.indexOf(rnxStr) == -1) {
760 rnxTypes.push_back(rnxStr);
761 allFound = false;
762 }
763 }
764 if (obs._obs[iFrq]->_snrValid){
765 QString rnxStr('S');
766 rnxStr.append(obs._obs[iFrq]->_rnxType2ch.c_str());
767 if (_format.indexOf("RTCM_2") != -1 ||
768 _format.indexOf("RTCM2") != -1 ||
769 _format.indexOf("RTCM 2") != -1 ) {
770 rnxStr = t_rnxObsFile::type3to2(obs._prn.system(), rnxStr);
771 }
772 if (rnxTypes.indexOf(rnxStr) == -1) {
773 rnxTypes.push_back(rnxStr);
774 allFound = false;
775 }
776 }
777 }
778 if (!allFound) {
779 QString msg;
780 QTextStream str(&msg);
781 QString s;
782 str << obs._prn.system() << " " << s.sprintf("%2d", rnxTypes.size()) << " ";
783 for (int iType = 0; iType < rnxTypes.size(); iType++) {
784 str << " " << rnxTypes[iType];
785 }
786 emit(newMessage(_staID + ": Observation Types: " + msg.toAscii(), true));
787 }
788 }
789
790 // RTCMv3 antenna descriptor
791 // -------------------------
792 for (int ii = 0; ii < decoder()->_antType.size(); ii++) {
793 QString ant1 = QString("%1 ").arg(decoder()->_antType[ii]);
794 emit(newMessage(_staID + ": Antenna descriptor " + ant1.toAscii(), true));
795 }
796
797 // RTCM Antenna Coordinates
798 // ------------------------
799 for (int ii=0; ii < decoder()->_antList.size(); ii++) {
800 QByteArray antT;
801 if (decoder()->_antList[ii].type == GPSDecoder::t_antInfo::ARP) {
802 antT = "ARP";
803 }
804 else if (decoder()->_antList[ii].type == GPSDecoder::t_antInfo::APC) {
805 antT = "APC";
806 }
807 QByteArray ant1, ant2, ant3;
808 ant1 = QString("%1 ").arg(decoder()->_antList[ii].xx,0,'f',4).toAscii();
809 ant2 = QString("%1 ").arg(decoder()->_antList[ii].yy,0,'f',4).toAscii();
810 ant3 = QString("%1 ").arg(decoder()->_antList[ii].zz,0,'f',4).toAscii();
811 emit(newMessage(_staID + ": " + antT + " (ITRF) X " + ant1 + "m", true));
812 emit(newMessage(_staID + ": " + antT + " (ITRF) Y " + ant2 + "m", true));
813 emit(newMessage(_staID + ": " + antT + " (ITRF) Z " + ant3 + "m", true));
814 double hh = 0.0;
815 if (decoder()->_antList[ii].height_f) {
816 hh = decoder()->_antList[ii].height;
817 QByteArray ant4 = QString("%1 ").arg(hh,0,'f',4).toAscii();
818 emit(newMessage(_staID + ": Antenna height above marker " + ant4 + "m", true));
819 }
820 emit(newAntCrd(_staID, decoder()->_antList[ii].xx,
821 decoder()->_antList[ii].yy, decoder()->_antList[ii].zz,
822 hh, antT));
823 }
824
825 // RTCM GLONASS slots
826 // ------------------
827 if (decoder()->_gloFrq.size()) {
828 bool allFound = true;
829 QString slot = decoder()->_gloFrq;
830 slot.replace(" "," ").replace(" ",":");
831 if (_gloSlots.indexOf(slot) == -1) {
832 _gloSlots.append(slot);
833 allFound = false;
834 }
835 if (!allFound) {
836 _gloSlots.sort();
837 emit(newMessage(_staID + ": GLONASS Slot:Freq " + _gloSlots.join(" ").toAscii(), true));
838 }
839 }
840 }
841 }
842
843#ifdef MLS_SOFTWARE
844 for (int ii=0; ii <decoder()->_antList.size(); ii++) {
845 QByteArray antT;
846 if (decoder()->_antList[ii].type == GPSDecoder::t_antInfo::ARP) {
847 antT = "ARP";
848 }
849 else if (decoder()->_antList[ii].type == GPSDecoder::t_antInfo::APC) {
850 antT = "APC";
851 }
852 double hh = 0.0;
853 if (decoder()->_antList[ii].height_f) {
854 hh = decoder()->_antList[ii].height;
855 }
856 emit(newAntCrd(_staID, decoder()->_antList[ii].xx,
857 decoder()->_antList[ii].yy, decoder()->_antList[ii].zz,
858 hh, antT));
859 }
860
861 for (int ii = 0; ii <decoder()->_typeList.size(); ii++) {
862 emit(newRTCMMessage(_staID, decoder()->_typeList[ii]));
863 }
864#endif
865
866 decoder()->_gloFrq.clear();
867 decoder()->_typeList.clear();
868 decoder()->_antType.clear();
869 decoder()->_antList.clear();
870}
871
872// Handle Data from Serial Port
873////////////////////////////////////////////////////////////////////////////
874void bncGetThread::slotSerialReadyRead() {
875
876 if (_serialPort) {
877
878 if (_nmea == "yes" && _serialNMEA == MANUAL_NMEA) {
879 if (_manualNMEASampl) {
880 int dt = _lastManualNMEA.secsTo(QDateTime::currentDateTime());
881 if (dt && (fmod(double(dt), double(_manualNMEASampl)) == 0.0)) {
882 _query->sendNMEA(_manualNMEAString);
883 _lastManualNMEA = QDateTime::currentDateTime();
884 }
885 }
886 }
887
888 int nb = _serialPort->bytesAvailable();
889 if (nb > 0) {
890 QByteArray data = _serialPort->read(nb);
891
892 if (_nmea == "yes" && _serialNMEA == AUTO_NMEA) {
893 int i1 = data.indexOf("$GPGGA");
894 if (i1 == -1) {
895 i1 = data.indexOf("$GNGGA");
896 }
897 if (i1 != -1) {
898 int i2 = data.indexOf("*", i1);
899 if (i2 != -1 && data.size() > i2 + 1) {
900 QByteArray gga = data.mid(i1, i2 - i1 + 3);
901 _query->sendNMEA(gga);
902 }
903 }
904 }
905
906 if (_serialOutFile) {
907 _serialOutFile->write(data);
908 _serialOutFile->flush();
909 }
910 }
911 }
912}
913
914void bncGetThread::slotNewNMEAConnection() {
915 _nmeaSockets->push_back(_nmeaServer->nextPendingConnection());
916 emit( newMessage(QString("New PPP client on port: # %1")
917 .arg(_nmeaSockets->size()).toAscii(), true) );
918}
919
920//
921////////////////////////////////////////////////////////////////////////////
922void bncGetThread::slotNewNMEAstr(QByteArray staID, QByteArray str) {
923 if (_nmeaPortsMap.contains(staID)) {
924 int nmeaPort = _nmeaPortsMap.value(staID);
925 QMutableListIterator<QTcpSocket*> is(*_nmeaSockets);
926 while (is.hasNext()) {
927 QTcpSocket* sock = is.next();
928 if (sock->localPort() == nmeaPort) {
929 if (sock->state() == QAbstractSocket::ConnectedState) {
930 sock->write(str);
931 }
932 else if (sock->state() != QAbstractSocket::ConnectingState) {
933 delete sock;
934 is.remove();
935 }
936 }
937 }
938 }
939}
Note: See TracBrowser for help on using the repository browser.