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

Last change on this file since 6444 was 6444, checked in by mervart, 9 years ago
File size: 18.7 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 _port = 0;
94 _server = 0;
95 _sockets = 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 _server;
131 delete _sockets;
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 printOutput(printFile, _ephStreamGlonass, strV2, strV3);
440}
441
442// Output
443////////////////////////////////////////////////////////////////////////////
444void t_bncCore::printOutput(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 (_sockets) {
462 QMutableListIterator<QTcpSocket*> is(*_sockets);
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::setPort(int port) {
482 _port = port;
483 if (_port != 0) {
484 delete _server;
485 _server = new QTcpServer;
486 if ( !_server->listen(QHostAddress::Any, _port) ) {
487 slotMessage("t_bncCore: Cannot listen on ephemeris port", true);
488 }
489 connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
490 delete _sockets;
491 _sockets = 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::slotNewConnection() {
514 _sockets->push_back( _server->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 QListIterator<t_orbCorr> it(orbCorrections);
537 while (it.hasNext()) {
538 const t_orbCorr& corr = it.next();
539 QMutableListIterator<QTcpSocket*> is(*_socketsCorr);
540 while (is.hasNext()) {
541 QTcpSocket* sock = is.next();
542 if (sock->state() == QAbstractSocket::ConnectedState) {
543 if (sock->write(corr.toLine().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//
558////////////////////////////////////////////////////////////////////////////
559void t_bncCore::slotNewClkCorrections(QList<t_clkCorr> clkCorrections) {
560 QMutexLocker locker(&_mutex);
561 emit newClkCorrections(clkCorrections);
562 if (_socketsCorr) {
563 QListIterator<t_clkCorr> it(clkCorrections);
564 while (it.hasNext()) {
565 const t_clkCorr& corr = it.next();
566 QMutableListIterator<QTcpSocket*> is(*_socketsCorr);
567 while (is.hasNext()) {
568 QTcpSocket* sock = is.next();
569 if (sock->state() == QAbstractSocket::ConnectedState) {
570 if (sock->write(corr.toLine().c_str()) == -1) {
571 delete sock;
572 is.remove();
573 }
574 }
575 else if (sock->state() != QAbstractSocket::ConnectingState) {
576 delete sock;
577 is.remove();
578 }
579 }
580 }
581 }
582}
583
584//
585////////////////////////////////////////////////////////////////////////////
586void t_bncCore::setConfFileName(const QString& confFileName) {
587 if (confFileName.isEmpty()) {
588 _confFileName = QDir::homePath() + QDir::separator()
589 + ".config" + QDir::separator()
590 + qApp->organizationName() + QDir::separator()
591 + qApp->applicationName() + ".bnc";
592 }
593 else {
594 _confFileName = confFileName;
595 }
596}
597
598// Raw Output
599////////////////////////////////////////////////////////////////////////////
600void t_bncCore::writeRawData(const QByteArray& data, const QByteArray& staID,
601 const QByteArray& format) {
602
603 QMutexLocker locker(&_mutex);
604
605 if (!_rawFile) {
606 bncSettings settings;
607 QByteArray fileName = settings.value("rawOutFile").toByteArray();
608 if (!fileName.isEmpty()) {
609 _rawFile = new bncRawFile(fileName, staID, bncRawFile::output);
610 }
611 }
612
613 if (_rawFile) {
614 _rawFile->writeRawData(data, staID, format);
615 }
616}
617
618//
619////////////////////////////////////////////////////////////////////////////
620void t_bncCore::initCombination() {
621#ifdef USE_COMBINATION
622 _bncComb = new bncComb();
623 if (_bncComb->nStreams() < 1) {
624 delete _bncComb;
625 _bncComb = 0;
626 }
627#endif
628}
629
630//
631////////////////////////////////////////////////////////////////////////////
632void t_bncCore::stopCombination() {
633#ifdef USE_COMBINATION
634 delete _bncComb;
635 _bncComb = 0;
636#endif
637}
638
639//
640////////////////////////////////////////////////////////////////////////////
641bool t_bncCore::dateAndTimeGPSSet() const {
642 QMutexLocker locker(&_mutexDateAndTimeGPS);
643 if (_dateAndTimeGPS) {
644 return true;
645 }
646 else {
647 return false;
648 }
649}
650
651//
652////////////////////////////////////////////////////////////////////////////
653QDateTime t_bncCore::dateAndTimeGPS() const {
654 QMutexLocker locker(&_mutexDateAndTimeGPS);
655 if (_dateAndTimeGPS) {
656 return *_dateAndTimeGPS;
657 }
658 else {
659 return QDateTime();
660 }
661}
662
663//
664////////////////////////////////////////////////////////////////////////////
665void t_bncCore::setDateAndTimeGPS(QDateTime dateTime) {
666 QMutexLocker locker(&_mutexDateAndTimeGPS);
667 delete _dateAndTimeGPS;
668 _dateAndTimeGPS = new QDateTime(dateTime);
669}
670
671//
672////////////////////////////////////////////////////////////////////////////
673void t_bncCore::startPPP() {
674 _pppMain->start();
675}
676
677//
678////////////////////////////////////////////////////////////////////////////
679void t_bncCore::stopPPP() {
680 _pppMain->stop();
681 emit stopRinexPPP();
682}
683
Note: See TracBrowser for help on using the repository browser.