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

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