source: ntrip/trunk/BNC/bncapp.cpp@ 885

Last change on this file since 885 was 885, checked in by mervart, 16 years ago

* empty log message *

File size: 16.8 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: bncApp
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 <QSettings>
43#include <QMessageBox>
44#include <cmath>
45#include <unistd.h>
46
47#include "bncapp.h"
48#include "bncutils.h"
49#include "bncrinex.h"
50
51using namespace std;
52
53struct converttimeinfo {
54 int second; /* seconds of GPS time [0..59] */
55 int minute; /* minutes of GPS time [0..59] */
56 int hour; /* hour of GPS time [0..24] */
57 int day; /* day of GPS time [1..28..30(31)*/
58 int month; /* month of GPS time [1..12]*/
59 int year; /* year of GPS time [1980..] */
60};
61
62extern "C" {
63 void converttime(struct converttimeinfo *c, int week, int tow);
64 void updatetime(int *week, int *tow, int tk, int fixnumleap);
65}
66
67// Constructor
68////////////////////////////////////////////////////////////////////////////
69bncApp::bncApp(int argc, char* argv[], bool GUIenabled) :
70 QApplication(argc, argv, GUIenabled) {
71
72 _bncVersion = "BNC 1.6";
73
74 _logFileFlag = 0;
75 _logFile = 0;
76 _logStream = 0;
77 _caster = 0;
78
79 // Lists of Ephemeris
80 // ------------------
81 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
82 _gpsEph[ii-PRN_GPS_START] = 0;
83 }
84 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
85 _glonassEph[ii-PRN_GLONASS_START] = 0;
86 }
87
88 // Eph file(s)
89 // -----------
90 _rinexVers = 0;
91 _ephFileGPS = 0;
92 _ephStreamGPS = 0;
93 _ephFileGlonass = 0;
94 _ephStreamGlonass = 0;
95
96 _port = 0;
97 _server = 0;
98 _sockets = 0;
99
100 _pgmName = _bncVersion.leftJustified(20, ' ', true);
101#ifdef WIN32
102 _userName = QString("${USERNAME}");
103#else
104 _userName = QString("${USER}");
105#endif
106 expandEnvVar(_userName);
107 _userName = _userName.leftJustified(20, ' ', true);
108}
109
110// Destructor
111////////////////////////////////////////////////////////////////////////////
112bncApp::~bncApp() {
113 delete _logStream;
114 delete _logFile;
115 delete _ephStreamGPS;
116 delete _ephFileGPS;
117 delete _server;
118 delete _sockets;
119 if (_rinexVers == 2) {
120 delete _ephStreamGlonass;
121 delete _ephFileGlonass;
122 }
123 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
124 delete _gpsEph[ii-PRN_GPS_START];
125 }
126 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
127 delete _glonassEph[ii-PRN_GLONASS_START];
128 }
129}
130
131// Write a Program Message
132////////////////////////////////////////////////////////////////////////////
133void bncApp::slotMessage(const QByteArray msg) {
134
135 QMutexLocker locker(&_mutex);
136
137 // First time resolve the log file name
138 // ------------------------------------
139 if (_logFileFlag == 0) {
140 _logFileFlag = 1;
141 QSettings settings;
142 QString logFileName = settings.value("logFile").toString();
143 if ( !logFileName.isEmpty() ) {
144 expandEnvVar(logFileName);
145 _logFile = new QFile(logFileName);
146 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
147 _logFile->open(QIODevice::WriteOnly | QIODevice::Append);
148 }
149 else {
150 _logFile->open(QIODevice::WriteOnly);
151 }
152 _logStream = new QTextStream();
153 _logStream->setDevice(_logFile);
154 }
155 }
156
157 if (_logStream) {
158 *_logStream << QDateTime::currentDateTime().toUTC().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
159 *_logStream << msg.data() << endl;
160 _logStream->flush();
161 }
162}
163
164// New GPS Ephemeris
165////////////////////////////////////////////////////////////////////////////
166void bncApp::slotNewGPSEph(gpsephemeris* gpseph) {
167
168 QMutexLocker locker(&_mutex);
169
170 printEphHeader();
171
172 gpsephemeris** ee = &_gpsEph[gpseph->satellite-1];
173 if ( *ee == 0 ||
174 gpseph->GPSweek > (*ee)->GPSweek ||
175 (gpseph->GPSweek == (*ee)->GPSweek && gpseph->TOC > (*ee)->TOC) ) {
176 delete *ee;
177 *ee = gpseph;
178 printGPSEph(gpseph, true);
179 }
180 else {
181 printGPSEph(gpseph, false);
182 delete gpseph;
183 }
184}
185
186// New Glonass Ephemeris
187////////////////////////////////////////////////////////////////////////////
188void bncApp::slotNewGlonassEph(glonassephemeris* glonasseph) {
189
190 QMutexLocker locker(&_mutex);
191
192 printEphHeader();
193
194 glonassephemeris** ee = &_glonassEph[glonasseph->almanac_number-1];
195
196 int wwOld, towOld, wwNew, towNew;
197 if (*ee != 0) {
198 wwOld = (*ee)->GPSWeek;
199 towOld = (*ee)->GPSTOW;
200 updatetime(&wwOld, &towOld, (*ee)->tb*1000, 1);
201
202 wwNew = glonasseph->GPSWeek;
203 towNew = glonasseph->GPSTOW;
204 updatetime(&wwNew, &towNew, glonasseph->tb*1000, 1);
205 }
206
207 if ( *ee == 0 ||
208 wwNew > wwOld ||
209 (wwNew == wwOld && towNew > towOld) ) {
210 delete *ee;
211 *ee = glonasseph;
212 printGlonassEph(glonasseph, true);
213 }
214 else {
215 printGlonassEph(glonasseph, false);
216 delete glonasseph;
217 }
218}
219
220// Print Header of the output File(s)
221////////////////////////////////////////////////////////////////////////////
222void bncApp::printEphHeader() {
223
224 QSettings settings;
225
226 // Initialization
227 // --------------
228 if (_rinexVers == 0) {
229
230 if ( Qt::CheckState(settings.value("ephV3").toInt()) == Qt::Checked) {
231 _rinexVers = 3;
232 }
233 else {
234 _rinexVers = 2;
235 }
236
237 _ephPath = settings.value("ephPath").toString();
238
239 if ( !_ephPath.isEmpty() ) {
240 if ( _ephPath[_ephPath.length()-1] != QDir::separator() ) {
241 _ephPath += QDir::separator();
242 }
243 expandEnvVar(_ephPath);
244 }
245 }
246
247 // (Re-)Open output File(s)
248 // ------------------------
249 if (!_ephPath.isEmpty()) {
250
251 QDateTime datTim = QDateTime::currentDateTime().toUTC();
252
253 QString ephFileNameGPS = _ephPath + "BRDC" +
254 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0'));
255
256 QString hlpStr = bncRinex::nextEpochStr(datTim,
257 settings.value("ephIntr").toString());
258
259 if (_rinexVers == 3) {
260 ephFileNameGPS += hlpStr + datTim.toString(".yyP");
261 }
262 else {
263 ephFileNameGPS += hlpStr + datTim.toString(".yyN");
264 }
265
266 if (_ephFileNameGPS == ephFileNameGPS) {
267 return;
268 }
269 else {
270 _ephFileNameGPS = ephFileNameGPS;
271 }
272
273 for (int ii = PRN_GPS_START; ii <= PRN_GPS_END; ii++) {
274 delete _gpsEph[ii-PRN_GPS_START];
275 _gpsEph[ii-PRN_GPS_START] = 0;
276 }
277 for (int ii = PRN_GLONASS_START; ii <= PRN_GLONASS_END; ii++) {
278 delete _glonassEph[ii-PRN_GLONASS_START];
279 _glonassEph[ii-PRN_GLONASS_START] = 0;
280 }
281
282 delete _ephStreamGPS;
283 delete _ephFileGPS;
284
285 QFlags<QIODevice::OpenModeFlag> appendFlagGPS;
286 QFlags<QIODevice::OpenModeFlag> appendFlagGlonass;
287
288 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
289 QFile::exists(ephFileNameGPS) ) {
290 appendFlagGPS = QIODevice::Append;
291 }
292
293 _ephFileGPS = new QFile(ephFileNameGPS);
294 _ephFileGPS->open(QIODevice::WriteOnly | appendFlagGPS);
295 _ephStreamGPS = new QTextStream();
296 _ephStreamGPS->setDevice(_ephFileGPS);
297
298 if (_rinexVers == 3) {
299 _ephFileGlonass = _ephFileGPS;
300 _ephStreamGlonass = _ephStreamGPS;
301 }
302 else if (_rinexVers == 2) {
303 QString ephFileNameGlonass = _ephPath + "BRDC" +
304 QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
305 hlpStr + datTim.toString(".yyG");
306
307 delete _ephStreamGlonass;
308 delete _ephFileGlonass;
309
310 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
311 QFile::exists(ephFileNameGlonass) ) {
312 appendFlagGlonass = QIODevice::Append;
313 }
314
315 _ephFileGlonass = new QFile(ephFileNameGlonass);
316 _ephFileGlonass->open(QIODevice::WriteOnly | appendFlagGlonass);
317 _ephStreamGlonass = new QTextStream();
318 _ephStreamGlonass->setDevice(_ephFileGlonass);
319 }
320
321 // Header - RINEX Version 3
322 // ------------------------
323 if (_rinexVers == 3) {
324 if ( ! (appendFlagGPS & QIODevice::Append)) {
325 QString line;
326 line.sprintf(
327 "%9.2f%11sN: GNSS NAV DATA M: Mixed%12sRINEX VERSION / TYPE\n",
328 3.0, "", "");
329 *_ephStreamGPS << line;
330
331 QString hlp = QDateTime::currentDateTime().toUTC().toString("yyyyMMdd hhmmss UTC").leftJustified(20, ' ', true);
332 *_ephStreamGPS << _pgmName.toAscii().data()
333 << _userName.toAscii().data()
334 << hlp.toAscii().data()
335 << "PGM / RUN BY / DATE" << endl;
336
337 line.sprintf("%60sEND OF HEADER\n", "");
338 *_ephStreamGPS << line;
339
340 _ephStreamGPS->flush();
341 }
342 }
343
344 // Headers - RINEX Version 2
345 // -------------------------
346 else if (_rinexVers == 2) {
347 if (! (appendFlagGPS & QIODevice::Append)) {
348 QString line;
349 line.sprintf(
350 "%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n", 2.11, "", "");
351 *_ephStreamGPS << line;
352
353 QString hlp = QDateTime::currentDateTime().toUTC().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
354 *_ephStreamGPS << _pgmName.toAscii().data()
355 << _userName.toAscii().data()
356 << hlp.toAscii().data()
357 << "PGM / RUN BY / DATE" << endl;
358
359 line.sprintf("%60sEND OF HEADER\n", "");
360 *_ephStreamGPS << line;
361
362 _ephStreamGPS->flush();
363 }
364 if (! (appendFlagGlonass & QIODevice::Append)) {
365 QString line;
366 line.sprintf(
367 "%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n",2.11,"","");
368 *_ephStreamGlonass << line;
369
370 QString hlp = QDateTime::currentDateTime().toUTC().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
371 *_ephStreamGlonass << _pgmName.toAscii().data()
372 << _userName.toAscii().data()
373 << hlp.toAscii().data()
374 << "PGM / RUN BY / DATE" << endl;
375
376 line.sprintf("%60sEND OF HEADER\n", "");
377 *_ephStreamGlonass << line;
378
379 _ephStreamGlonass->flush();
380 }
381 }
382 }
383}
384
385// Print One GPS Ephemeris
386////////////////////////////////////////////////////////////////////////////
387void bncApp::printGPSEph(gpsephemeris* ep, bool printFile) {
388
389 QString line;
390 QByteArray allLines;
391
392 struct converttimeinfo cti;
393 converttime(&cti, ep->GPSweek, ep->TOC);
394 if (_rinexVers == 3) {
395 line.sprintf("G%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
396 ep->satellite, cti.year, cti.month, cti.day, cti.hour,
397 cti.minute, cti.second, ep->clock_bias, ep->clock_drift,
398 ep->clock_driftrate);
399 }
400 else if (_rinexVers == 2) {
401 line.sprintf("%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
402 ep->satellite, cti.year%100, cti.month, cti.day, cti.hour,
403 cti.minute, (double) cti.second, ep->clock_bias,
404 ep->clock_drift, ep->clock_driftrate);
405 }
406 allLines += line;
407
408 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", (double)ep->IODE,
409 ep->Crs, ep->Delta_n, ep->M0);
410 allLines += line;
411
412 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->Cuc,
413 ep->e, ep->Cus, ep->sqrt_A);
414 allLines += line;
415
416 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n",
417 (double) ep->TOE, ep->Cic, ep->OMEGA0, ep->Cis);
418 allLines += line;
419
420 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->i0,
421 ep->Crc, ep->omega, ep->OMEGADOT);
422 allLines += line;
423
424 double dd = 0;
425 unsigned long ii = ep->flags;
426 if(ii & GPSEPHF_L2CACODE)
427 dd += 2.0;
428 if(ii & GPSEPHF_L2PCODE)
429 dd += 1.0;
430 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->IDOT, dd,
431 (double) ep->GPSweek, ii & GPSEPHF_L2PCODEDATA ? 1.0 : 0.0);
432 allLines += line;
433
434 if(ep->URAindex <= 6) /* URA index */
435 dd = ceil(10.0*pow(2.0, 1.0+((double)ep->URAindex)/2.0))/10.0;
436 else
437 dd = ceil(10.0*pow(2.0, ((double)ep->URAindex)/2.0))/10.0;
438 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", dd,
439 ((double) ep->SVhealth), ep->TGD, ((double) ep->IODC));
440 allLines += line;
441
442 line.sprintf(" %19.12e%19.12e\n", ((double)ep->TOW), 0.0);
443 allLines += line;
444
445 // Output into file
446 // ----------------
447 if (printFile && _ephStreamGPS) {
448 *_ephStreamGPS << allLines;
449 _ephStreamGPS->flush();
450 }
451
452 // Output into the socket
453 // ----------------------
454 if (_sockets) {
455 QMutableListIterator<QTcpSocket*> is(*_sockets);
456 while (is.hasNext()) {
457 QTcpSocket* sock = is.next();
458 if (sock->state() == QAbstractSocket::ConnectedState) {
459 int fd = sock->socketDescriptor();
460 if (::write(fd, allLines.data(), allLines.size()) != allLines.size()) {
461 delete sock;
462 is.remove();
463 }
464 }
465 else if (sock->state() != QAbstractSocket::ConnectingState) {
466 delete sock;
467 is.remove();
468 }
469 }
470 }
471}
472
473// Print One Glonass Ephemeris
474////////////////////////////////////////////////////////////////////////////
475void bncApp::printGlonassEph(glonassephemeris* ep, bool printFile) {
476
477 QString line;
478 QByteArray allLines;
479
480 int ww = ep->GPSWeek;
481 int tow = ep->GPSTOW;
482 struct converttimeinfo cti;
483
484 updatetime(&ww, &tow, ep->tb*1000, 1);
485 converttime(&cti, ww, tow);
486
487 int tk = ep->tk-3*60*60;
488 if (tk < 0) {
489 tk += 86400;
490 }
491
492 if (_rinexVers == 3) {
493 line.sprintf("R%02d %04d %02d %02d %02d %02d %02d%19.12e%19.12e%19.12e\n",
494 ep->almanac_number, cti.year, cti.month, cti.day, cti.hour,
495 cti.minute, cti.second, -ep->tau, ep->gamma, (double) tk);
496 }
497 else if (_rinexVers == 2) {
498 line.sprintf("%02d %02d %02d %02d %02d %02d%5.1f%19.12e%19.12e%19.12e\n",
499 ep->almanac_number, cti.year%100, cti.month, cti.day,
500 cti.hour, cti.minute, (double) cti.second, -ep->tau,
501 ep->gamma, (double) tk);
502 }
503 allLines += line;
504
505 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->x_pos,
506 ep->x_velocity, ep->x_acceleration,
507 (ep->flags & GLOEPHF_UNHEALTHY) ? 1.0 : 0.0);
508 allLines += line;
509
510 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->y_pos,
511 ep->y_velocity, ep->y_acceleration,
512 (double) ep->frequency_number);
513 allLines += line;
514
515 line.sprintf(" %19.12e%19.12e%19.12e%19.12e\n", ep->z_pos,
516 ep->z_velocity, ep->z_acceleration, (double) ep->E);
517 allLines += line;
518
519 // Output into file
520 // ----------------
521 if (printFile && _ephStreamGlonass) {
522 *_ephStreamGlonass << allLines;
523 _ephStreamGlonass->flush();
524 }
525
526 // Output into the socket
527 // ----------------------
528 if (_sockets) {
529 QMutableListIterator<QTcpSocket*> is(*_sockets);
530 while (is.hasNext()) {
531 QTcpSocket* sock = is.next();
532 if (sock->state() == QAbstractSocket::ConnectedState) {
533 int fd = sock->socketDescriptor();
534 if (::write(fd, allLines.data(), allLines.size()) != allLines.size()) {
535 delete sock;
536 is.remove();
537 }
538 }
539 else if (sock->state() != QAbstractSocket::ConnectingState) {
540 delete sock;
541 is.remove();
542 }
543 }
544 }
545}
546
547// Set Port Number
548////////////////////////////////////////////////////////////////////////////
549void bncApp::setPort(int port) {
550 _port = port;
551 if (_port != 0) {
552 _server = new QTcpServer;
553 _server->listen(QHostAddress::Any, _port);
554 connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
555 _sockets = new QList<QTcpSocket*>;
556 }
557}
558
559// New Connection
560////////////////////////////////////////////////////////////////////////////
561void bncApp::slotNewConnection() {
562 _sockets->push_back( _server->nextPendingConnection() );
563}
564
565//
566////////////////////////////////////////////////////////////////////////////
567void bncApp::slotQuit() {
568 cout << "bncApp::slotQuit" << endl;
569 delete _caster;
570 quit();
571}
572
573
Note: See TracBrowser for help on using the repository browser.