source: ntrip/trunk/BNC/src/bnccore.cpp@ 6461

Last change on this file since 6461 was 6461, checked in by mervart, 9 years ago
File size: 18.6 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: t_bncCore
30 *
31 * Purpose: This class implements the main application
32 *
33 * Author: L. Mervart
34 *
35 * Created: 29-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <sstream>
43#include <QMessageBox>
44#include <cmath>
45
46#include "bnccore.h"
47#include "bncutils.h"
48#include "bncrinex.h"
49#include "bncsettings.h"
50#include "bncversion.h"
51#include "ephemeris.h"
52#include "rinex/rnxobsfile.h"
53#include "rinex/rnxnavfile.h"
54#include "pppMain.h"
55
56#ifdef USE_COMBINATION
57# include "combination/bnccomb.h"
58#endif
59
60using namespace std;
61
62// Singleton
63////////////////////////////////////////////////////////////////////////////
64t_bncCore* t_bncCore::instance() {
65 static t_bncCore _bncCore;
66 return &_bncCore;
67}
68
69// Constructor
70////////////////////////////////////////////////////////////////////////////
71t_bncCore::t_bncCore() : _ephUser(false) {
72 _GUIenabled = true;
73 _logFileFlag = 0;
74 _logFile = 0;
75 _logStream = 0;
76 _rawFile = 0;
77 _caster = 0;
78#ifdef USE_COMBINATION
79 _bncComb = 0;
80#endif
81
82 // Eph file(s)
83 // -----------
84 _rinexVers = 0;
85 _ephFileGPS = 0;
86 _ephStreamGPS = 0;
87 _ephFileGlonass = 0;
88 _ephStreamGlonass = 0;
89 _ephFileGalileo = 0;
90 _ephStreamGalileo = 0;
91 _ephFileSBAS = 0;
92 _ephStreamSBAS = 0;
93
94 _portEph = 0;
95 _serverEph = 0;
96 _socketsEph = 0;
97
98 _portCorr = 0;
99 _serverCorr = 0;
100 _socketsCorr = 0;
101
102 _pgmName = QString(BNCPGMNAME).leftJustified(20, ' ', true);
103#ifdef WIN32
104 _userName = QString("${USERNAME}");
105#else
106 _userName = QString("${USER}");
107#endif
108 expandEnvVar(_userName);
109
110 _userName = _userName.leftJustified(20, ' ', true);
111 _dateAndTimeGPS = 0;
112 _mainWindow = 0;
113
114 _pppMain = new BNC_PPP::t_pppMain();
115 qRegisterMetaType< QVector<double> >("QVector<double>");
116 qRegisterMetaType<bncTime>("bncTime");
117 qRegisterMetaType<t_ephGPS>("t_ephGPS");
118 qRegisterMetaType<t_ephGlo>("t_ephGlo");
119 qRegisterMetaType<t_ephGal>("t_ephGal");
120 qRegisterMetaType<t_ephSBAS>("t_ephSBAS");
121 qRegisterMetaType<t_ephCompass>("t_ephCompass");
122}
123
124// Destructor
125////////////////////////////////////////////////////////////////////////////
126t_bncCore::~t_bncCore() {
127 delete _logStream;
128 delete _logFile;
129 delete _ephStreamGPS;
130 delete _ephFileGPS;
131 delete _serverEph;
132 delete _socketsEph;
133 delete _serverCorr;
134 delete _socketsCorr;
135 if (_rinexVers == 2) {
136 delete _ephStreamGlonass;
137 delete _ephFileGlonass;
138 }
139
140 delete _dateAndTimeGPS;
141 delete _rawFile;
142
143#ifdef USE_COMBINATION
144 delete _bncComb;
145#endif
146}
147
148// Write a Program Message
149////////////////////////////////////////////////////////////////////////////
150void t_bncCore::slotMessage(QByteArray msg, bool showOnScreen) {
151
152 QMutexLocker locker(&_mutexMessage);
153
154 messagePrivate(msg);
155 emit newMessage(msg, showOnScreen);
156}
157
158// Write a Program Message (private, no lock)
159////////////////////////////////////////////////////////////////////////////
160void t_bncCore::messagePrivate(const QByteArray& msg) {
161
162 // First time resolve the log file name
163 // ------------------------------------
164 QDate currDate = currentDateAndTimeGPS().date();
165 if (_logFileFlag == 0 || _fileDate != currDate) {
166 delete _logStream; _logStream = 0;
167 delete _logFile; _logFile = 0;
168 _logFileFlag = 1;
169 bncSettings settings;
170 QString logFileName = settings.value("logFile").toString();
171 if ( !logFileName.isEmpty() ) {
172 expandEnvVar(logFileName);
173 _logFile = new QFile(logFileName + "_" +
174 currDate.toString("yyMMdd").toAscii().data());
175 _fileDate = currDate;
176 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
177 _logFile->open(QIODevice::WriteOnly | QIODevice::Append);
178 }
179 else {
180 _logFile->open(QIODevice::WriteOnly);
181 }
182 _logStream = new QTextStream();
183 _logStream->setDevice(_logFile);
184 }
185 }
186
187 if (_logStream) {
188 QByteArray msgLocal = msg;
189 if (msg.indexOf('\n') == 0) {
190 *_logStream << endl;
191 msgLocal = msg.mid(1);
192 }
193 *_logStream << currentDateAndTimeGPS().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
194 *_logStream << msgLocal.data() << endl;
195 _logStream->flush();
196 _logFile->flush();
197 }
198}
199
200// New GPS Ephemeris
201////////////////////////////////////////////////////////////////////////////
202void t_bncCore::slotNewGPSEph(t_ephGPS eph) {
203
204 QMutexLocker locker(&_mutex);
205
206 emit newGPSEph(eph);
207
208 printEphHeader();
209
210 if (_ephUser.putNewEph(&eph, true) == success) {
211 printEph(eph, true);
212 }
213 else {
214 printEph(eph, false);
215 }
216}
217
218// New Glonass Ephemeris
219////////////////////////////////////////////////////////////////////////////
220void t_bncCore::slotNewGlonassEph(t_ephGlo eph) {
221
222 QMutexLocker locker(&_mutex);
223
224 emit newGlonassEph(eph);
225
226 printEphHeader();
227
228 if (_ephUser.putNewEph(&eph, true) == success) {
229 printEph(eph, true);
230 }
231 else {
232 printEph(eph, false);
233 }
234}
235
236// New Galileo Ephemeris
237////////////////////////////////////////////////////////////////////////////
238void t_bncCore::slotNewGalileoEph(t_ephGal eph) {
239
240 QMutexLocker locker(&_mutex);
241
242 emit newGalileoEph(eph);
243
244 printEphHeader();
245
246 if (_ephUser.putNewEph(&eph, true) == success) {
247 printEph(eph, true);
248 }
249 else {
250 printEph(eph, false);
251 }
252}
253
254// New SBAS Ephemeris
255////////////////////////////////////////////////////////////////////////////
256void t_bncCore::slotNewSBASEph(t_ephSBAS eph) {
257
258 QMutexLocker locker(&_mutex);
259
260 emit newSBASEph(eph);
261
262 printEphHeader();
263
264 if (_ephUser.putNewEph(&eph, true) == success) {
265 printEph(eph, true);
266 }
267 else {
268 printEph(eph, false);
269 }
270}
271
272
273// Print Header of the output File(s)
274////////////////////////////////////////////////////////////////////////////
275void t_bncCore::printEphHeader() {
276
277 bncSettings settings;
278
279 // Initialization
280 // --------------
281 if (_rinexVers == 0) {
282
283 if ( Qt::CheckState(settings.value("ephV3").toInt()) == Qt::Checked) {
284 _rinexVers = 3;
285 }
286 else {
287 _rinexVers = 2;
288 }
289
290 _ephPath = settings.value("ephPath").toString();
291
292 if ( !_ephPath.isEmpty() ) {
293 if ( _ephPath[_ephPath.length()-1] != QDir::separator() ) {
294 _ephPath += QDir::separator();
295 }
296 expandEnvVar(_ephPath);
297 }
298 }
299
300 // (Re-)Open output File(s)
301 // ------------------------
302 if (!_ephPath.isEmpty()) {
303
304 QDateTime datTim = currentDateAndTimeGPS();
305
306 QString ephFileNameGPS = _ephPath + "BRDC" +
307 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0'));
308
309 QString hlpStr = bncRinex::nextEpochStr(datTim,
310 settings.value("ephIntr").toString());
311
312 if (_rinexVers == 3) {
313 ephFileNameGPS += hlpStr + datTim.toString(".yyP");
314 }
315 else {
316 ephFileNameGPS += hlpStr + datTim.toString(".yyN");
317 }
318
319 if (_ephFileNameGPS == ephFileNameGPS) {
320 return;
321 }
322 else {
323 _ephFileNameGPS = ephFileNameGPS;
324 }
325
326 delete _ephStreamGPS;
327 delete _ephFileGPS;
328
329 QFlags<QIODevice::OpenModeFlag> appendFlagGPS;
330 QFlags<QIODevice::OpenModeFlag> appendFlagGlonass;
331
332 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
333 QFile::exists(ephFileNameGPS) ) {
334 appendFlagGPS = QIODevice::Append;
335 }
336
337 _ephFileGPS = new QFile(ephFileNameGPS);
338 _ephFileGPS->open(QIODevice::WriteOnly | appendFlagGPS);
339 _ephStreamGPS = new QTextStream();
340 _ephStreamGPS->setDevice(_ephFileGPS);
341
342 if (_rinexVers == 3) {
343 _ephFileGlonass = _ephFileGPS;
344 _ephStreamGlonass = _ephStreamGPS;
345 _ephFileGalileo = _ephFileGPS;
346 _ephStreamGalileo = _ephStreamGPS;
347 _ephFileSBAS = _ephFileGPS;
348 _ephStreamSBAS = _ephStreamGPS;
349 }
350 else if (_rinexVers == 2) {
351 QString ephFileNameGlonass = _ephPath + "BRDC" +
352 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
353 hlpStr + datTim.toString(".yyG");
354
355 delete _ephStreamGlonass;
356 delete _ephFileGlonass;
357
358 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
359 QFile::exists(ephFileNameGlonass) ) {
360 appendFlagGlonass = QIODevice::Append;
361 }
362
363 _ephFileGlonass = new QFile(ephFileNameGlonass);
364 _ephFileGlonass->open(QIODevice::WriteOnly | appendFlagGlonass);
365 _ephStreamGlonass = new QTextStream();
366 _ephStreamGlonass->setDevice(_ephFileGlonass);
367 }
368
369 // Header - RINEX Version 3
370 // ------------------------
371 if (_rinexVers == 3) {
372 if ( ! (appendFlagGPS & QIODevice::Append)) {
373 QString line;
374 line.sprintf(
375 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n",
376 3.0, "", "");
377 *_ephStreamGPS << line;
378
379 QString hlp = currentDateAndTimeGPS().toString("yyyyMMdd hhmmss UTC").leftJustified(20, ' ', true);
380 *_ephStreamGPS << _pgmName.toAscii().data()
381 << _userName.toAscii().data()
382 << hlp.toAscii().data()
383 << "PGM / RUN BY / DATE" << endl;
384
385 line.sprintf("%60sEND OF HEADER\n", "");
386 *_ephStreamGPS << line;
387
388 _ephStreamGPS->flush();
389 }
390 }
391
392 // Headers - RINEX Version 2
393 // -------------------------
394 else if (_rinexVers == 2) {
395 if (! (appendFlagGPS & QIODevice::Append)) {
396 QString line;
397 line.sprintf("%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n",
398 t_rnxNavFile::defaultRnxNavVersion2, "", "");
399 *_ephStreamGPS << line;
400
401 QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
402 *_ephStreamGPS << _pgmName.toAscii().data()
403 << _userName.toAscii().data()
404 << hlp.toAscii().data()
405 << "PGM / RUN BY / DATE" << endl;
406
407 line.sprintf("%60sEND OF HEADER\n", "");
408 *_ephStreamGPS << line;
409
410 _ephStreamGPS->flush();
411 }
412 if (! (appendFlagGlonass & QIODevice::Append)) {
413 QString line;
414 line.sprintf("%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n",
415 t_rnxNavFile::defaultRnxNavVersion2, "", "");
416 *_ephStreamGlonass << line;
417
418 QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
419 *_ephStreamGlonass << _pgmName.toAscii().data()
420 << _userName.toAscii().data()
421 << hlp.toAscii().data()
422 << "PGM / RUN BY / DATE" << endl;
423
424 line.sprintf("%60sEND OF HEADER\n", "");
425 *_ephStreamGlonass << line;
426
427 _ephStreamGlonass->flush();
428 }
429 }
430 }
431}
432
433// Print One Ephemeris
434////////////////////////////////////////////////////////////////////////////
435void t_bncCore::printEph(const t_eph& eph, bool printFile) {
436
437 QString strV2 = eph.toString(t_rnxNavFile::defaultRnxNavVersion2);
438 QString strV3 = eph.toString(t_rnxObsHeader::defaultRnxObsVersion3);
439
440 printOutputEph(printFile, _ephStreamGlonass, strV2, strV3);
441}
442
443// Output
444////////////////////////////////////////////////////////////////////////////
445void t_bncCore::printOutputEph(bool printFile, QTextStream* stream,
446 const QString& strV2, const QString& strV3) {
447
448 // Output into file
449 // ----------------
450 if (printFile && stream) {
451 if (_rinexVers == 2) {
452 *stream << strV2.toAscii();
453 }
454 else {
455 *stream << strV3.toAscii();
456 }
457 stream->flush();
458 }
459
460 // Output into the socket
461 // ----------------------
462 if (_socketsEph) {
463 QMutableListIterator<QTcpSocket*> is(*_socketsEph);
464 while (is.hasNext()) {
465 QTcpSocket* sock = is.next();
466 if (sock->state() == QAbstractSocket::ConnectedState) {
467 if (sock->write(strV3.toAscii()) == -1) {
468 delete sock;
469 is.remove();
470 }
471 }
472 else if (sock->state() != QAbstractSocket::ConnectingState) {
473 delete sock;
474 is.remove();
475 }
476 }
477 }
478}
479
480// Set Port Number
481////////////////////////////////////////////////////////////////////////////
482void t_bncCore::setPortEph(int port) {
483 _portEph = port;
484 if (_portEph != 0) {
485 delete _serverEph;
486 _serverEph = new QTcpServer;
487 if ( !_serverEph->listen(QHostAddress::Any, _portEph) ) {
488 slotMessage("t_bncCore: Cannot listen on ephemeris port", true);
489 }
490 connect(_serverEph, SIGNAL(newConnection()), this, SLOT(slotNewConnectionEph()));
491 delete _socketsEph;
492 _socketsEph = new QList<QTcpSocket*>;
493 }
494}
495
496// Set Port Number
497////////////////////////////////////////////////////////////////////////////
498void t_bncCore::setPortCorr(int port) {
499 _portCorr = port;
500 if (_portCorr != 0) {
501 delete _serverCorr;
502 _serverCorr = new QTcpServer;
503 if ( !_serverCorr->listen(QHostAddress::Any, _portCorr) ) {
504 slotMessage("t_bncCore: Cannot listen on correction port", true);
505 }
506 connect(_serverCorr, SIGNAL(newConnection()), this, SLOT(slotNewConnectionCorr()));
507 delete _socketsCorr;
508 _socketsCorr = new QList<QTcpSocket*>;
509 }
510}
511
512// New Connection
513////////////////////////////////////////////////////////////////////////////
514void t_bncCore::slotNewConnectionEph() {
515 _socketsEph->push_back( _serverEph->nextPendingConnection() );
516}
517
518// New Connection
519////////////////////////////////////////////////////////////////////////////
520void t_bncCore::slotNewConnectionCorr() {
521 _socketsCorr->push_back( _serverCorr->nextPendingConnection() );
522}
523
524//
525////////////////////////////////////////////////////////////////////////////
526void t_bncCore::slotQuit() {
527 delete _caster; _caster = 0;
528 qApp->quit();
529}
530
531//
532////////////////////////////////////////////////////////////////////////////
533void t_bncCore::slotNewOrbCorrections(QList<t_orbCorr> orbCorrections) {
534 QMutexLocker locker(&_mutex);
535 emit newOrbCorrections(orbCorrections);
536 if (_socketsCorr) {
537 ostringstream out;
538 t_orbCorr::writeEpoch(&out, orbCorrections);
539 QMutableListIterator<QTcpSocket*> is(*_socketsCorr);
540 while (is.hasNext()) {
541 QTcpSocket* sock = is.next();
542 if (sock->state() == QAbstractSocket::ConnectedState) {
543 if (sock->write(out.str().c_str()) == -1) {
544 delete sock;
545 is.remove();
546 }
547 }
548 else if (sock->state() != QAbstractSocket::ConnectingState) {
549 delete sock;
550 is.remove();
551 }
552 }
553 }
554}
555
556//
557////////////////////////////////////////////////////////////////////////////
558void t_bncCore::slotNewClkCorrections(QList<t_clkCorr> clkCorrections) {
559 QMutexLocker locker(&_mutex);
560 emit newClkCorrections(clkCorrections);
561 if (_socketsCorr) {
562 ostringstream out;
563 t_clkCorr::writeEpoch(&out, clkCorrections);
564 QMutableListIterator<QTcpSocket*> is(*_socketsCorr);
565 while (is.hasNext()) {
566 QTcpSocket* sock = is.next();
567 if (sock->state() == QAbstractSocket::ConnectedState) {
568 if (sock->write(out.str().c_str()) == -1) {
569 delete sock;
570 is.remove();
571 }
572 }
573 else if (sock->state() != QAbstractSocket::ConnectingState) {
574 delete sock;
575 is.remove();
576 }
577 }
578 }
579}
580
581//
582////////////////////////////////////////////////////////////////////////////
583void t_bncCore::setConfFileName(const QString& confFileName) {
584 if (confFileName.isEmpty()) {
585 _confFileName = QDir::homePath() + QDir::separator()
586 + ".config" + QDir::separator()
587 + qApp->organizationName() + QDir::separator()
588 + qApp->applicationName() + ".bnc";
589 }
590 else {
591 _confFileName = confFileName;
592 }
593}
594
595// Raw Output
596////////////////////////////////////////////////////////////////////////////
597void t_bncCore::writeRawData(const QByteArray& data, const QByteArray& staID,
598 const QByteArray& format) {
599
600 QMutexLocker locker(&_mutex);
601
602 if (!_rawFile) {
603 bncSettings settings;
604 QByteArray fileName = settings.value("rawOutFile").toByteArray();
605 if (!fileName.isEmpty()) {
606 _rawFile = new bncRawFile(fileName, staID, bncRawFile::output);
607 }
608 }
609
610 if (_rawFile) {
611 _rawFile->writeRawData(data, staID, format);
612 }
613}
614
615//
616////////////////////////////////////////////////////////////////////////////
617void t_bncCore::initCombination() {
618#ifdef USE_COMBINATION
619 _bncComb = new bncComb();
620 if (_bncComb->nStreams() < 1) {
621 delete _bncComb;
622 _bncComb = 0;
623 }
624#endif
625}
626
627//
628////////////////////////////////////////////////////////////////////////////
629void t_bncCore::stopCombination() {
630#ifdef USE_COMBINATION
631 delete _bncComb;
632 _bncComb = 0;
633#endif
634}
635
636//
637////////////////////////////////////////////////////////////////////////////
638bool t_bncCore::dateAndTimeGPSSet() const {
639 QMutexLocker locker(&_mutexDateAndTimeGPS);
640 if (_dateAndTimeGPS) {
641 return true;
642 }
643 else {
644 return false;
645 }
646}
647
648//
649////////////////////////////////////////////////////////////////////////////
650QDateTime t_bncCore::dateAndTimeGPS() const {
651 QMutexLocker locker(&_mutexDateAndTimeGPS);
652 if (_dateAndTimeGPS) {
653 return *_dateAndTimeGPS;
654 }
655 else {
656 return QDateTime();
657 }
658}
659
660//
661////////////////////////////////////////////////////////////////////////////
662void t_bncCore::setDateAndTimeGPS(QDateTime dateTime) {
663 QMutexLocker locker(&_mutexDateAndTimeGPS);
664 delete _dateAndTimeGPS;
665 _dateAndTimeGPS = new QDateTime(dateTime);
666}
667
668//
669////////////////////////////////////////////////////////////////////////////
670void t_bncCore::startPPP() {
671 _pppMain->start();
672}
673
674//
675////////////////////////////////////////////////////////////////////////////
676void t_bncCore::stopPPP() {
677 _pppMain->stop();
678 emit stopRinexPPP();
679}
680
Note: See TracBrowser for help on using the repository browser.