source: ntrip/trunk/BNS/bns.cpp@ 948

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

* empty log message *

File size: 11.5 KB
RevLine 
[756]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Server
3 * -------------------------------------------------------------------------
4 *
5 * Class: bns
6 *
7 * Purpose: This class implements the main application behaviour
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Mar-2008
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
[858]17#include <math.h>
[756]18#include <iostream>
[800]19#include <newmatio.h>
[756]20
21#include "bns.h"
[799]22#include "bnsutils.h"
[847]23#include "bnsrinex.h"
[848]24#include "bnssp3.h"
[756]25
26using namespace std;
27
28// Constructor
29////////////////////////////////////////////////////////////////////////////
[757]30t_bns::t_bns(QObject* parent) : QThread(parent) {
[760]31
[764]32 this->setTerminationEnabled(true);
[828]33
[836]34 connect(this, SIGNAL(moveSocket(QThread*)),
35 this, SLOT(slotMoveSocket(QThread*)));
36
[828]37 // Thread that handles broadcast ephemeris
38 // ---------------------------------------
39 _bnseph = new t_bnseph(parent);
[827]40
[884]41 connect(_bnseph, SIGNAL(newEph(t_eph*)), this, SLOT(slotNewEph(t_eph*)));
[828]42 connect(_bnseph, SIGNAL(newMessage(QByteArray)),
43 this, SLOT(slotMessage(const QByteArray)));
44 connect(_bnseph, SIGNAL(error(QByteArray)),
45 this, SLOT(slotError(const QByteArray)));
[760]46
[827]47 // Server listening for rtnet results
48 // ----------------------------------
[786]49 QSettings settings;
[828]50 _clkSocket = 0;
[827]51 _clkServer = new QTcpServer;
52 _clkServer->listen(QHostAddress::Any, settings.value("clkPort").toInt());
[828]53 connect(_clkServer, SIGNAL(newConnection()),this, SLOT(slotNewConnection()));
[827]54
[828]55 // Socket and file for outputting the results
56 // -------------------------------------------
[858]57 _outSocket = 0;
58 _outSocketOpenTrial = 0;
[827]59
[816]60 QString outFileName = settings.value("outFile").toString();
61 if (outFileName.isEmpty()) {
[833]62 _outFile = 0;
63 _outStream = 0;
[811]64 }
[816]65 else {
66 _outFile = new QFile(outFileName);
[817]67 if (_outFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
[816]68 _outStream = new QTextStream(_outFile);
69 }
70 }
[812]71
72 // Log File
73 // --------
[816]74 QString logFileName = settings.value("logFile").toString();
75 if (logFileName.isEmpty()) {
[947]76 _logFile = 0;
77 _logStream = 0;
[812]78 }
[816]79 else {
80 _logFile = new QFile(logFileName);
[817]81 if (_logFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
[816]82 _logStream = new QTextStream(_logFile);
83 }
[948]84 else {
85 _logStream = 0;
86 }
[816]87 }
[847]88
89 // RINEX writer
90 // ------------
91 if ( settings.value("rnxPath").toString().isEmpty() ) {
92 _rnx = 0;
93 }
94 else {
[850]95 QString prep = "BNS";
[857]96 QString ext = ".clk";
[850]97 QString path = settings.value("rnxPath").toString();
98 QString intr = settings.value("rnxIntr").toString();
99 int sampl = settings.value("rnxSampl").toInt();
100 _rnx = new bnsRinex(prep, ext, path, intr, sampl);
[847]101 }
[848]102
103 // SP3 writer
104 // ----------
105 if ( settings.value("sp3Path").toString().isEmpty() ) {
106 _sp3 = 0;
107 }
108 else {
[850]109 QString prep = "BNS";
[857]110 QString ext = ".sp3";
[850]111 QString path = settings.value("sp3Path").toString();
112 QString intr = settings.value("sp3Intr").toString();
113 int sampl = settings.value("sp3Sampl").toInt();
114 _sp3 = new bnsSP3(prep, ext, path, intr, sampl);
[848]115 }
[756]116}
117
118// Destructor
119////////////////////////////////////////////////////////////////////////////
[757]120t_bns::~t_bns() {
[763]121 deleteBnsEph();
[769]122 delete _clkServer;
[837]123 delete _clkSocket;
[770]124 delete _outSocket;
[816]125 delete _outStream;
126 delete _logStream;
[812]127 delete _outFile;
128 delete _logFile;
[779]129 QMapIterator<QString, t_ephPair*> it(_ephList);
130 while (it.hasNext()) {
131 it.next();
132 delete it.value();
133 }
[849]134 delete _rnx;
135 delete _sp3;
[756]136}
137
[763]138// Delete bns thread
139////////////////////////////////////////////////////////////////////////////
140void t_bns::deleteBnsEph() {
141 if (_bnseph) {
142 _bnseph->terminate();
[764]143 _bnseph->wait(100);
[763]144 delete _bnseph;
145 _bnseph = 0;
146 }
147}
148
[756]149// Write a Program Message
150////////////////////////////////////////////////////////////////////////////
[758]151void t_bns::slotMessage(const QByteArray msg) {
[816]152 if (_logStream) {
153 *_logStream << msg << endl;
[818]154 _logStream->flush();
[812]155 }
[757]156 emit(newMessage(msg));
[756]157}
158
[760]159// Write a Program Message
160////////////////////////////////////////////////////////////////////////////
161void t_bns::slotError(const QByteArray msg) {
[816]162 if (_logStream) {
163 *_logStream << msg << endl;
[818]164 _logStream->flush();
[812]165 }
[763]166 deleteBnsEph();
[760]167 emit(error(msg));
168}
169
[769]170// New Connection
171////////////////////////////////////////////////////////////////////////////
172void t_bns::slotNewConnection() {
[786]173 slotMessage("t_bns::slotNewConnection");
[787]174 delete _clkSocket;
[769]175 _clkSocket = _clkServer->nextPendingConnection();
176}
177
[770]178// Start the Communication with NTRIP Caster
179////////////////////////////////////////////////////////////////////////////
180void t_bns::openCaster() {
[858]181
182 delete _outSocket; _outSocket = 0;
183
184 double minDt = exp2(_outSocketOpenTrial);
185 if (++_outSocketOpenTrial > 8) {
186 _outSocketOpenTrial = 8;
187 }
188 if (_outSocketOpenTime.isValid() &&
189 _outSocketOpenTime.secsTo(QDateTime::currentDateTime()) < minDt) {
190 return;
191 }
192 else {
193 _outSocketOpenTime = QDateTime::currentDateTime();
194 }
195
[770]196 QSettings settings;
197 _outSocket = new QTcpSocket();
[811]198 _outSocket->connectToHost(settings.value("outHost").toString(),
199 settings.value("outPort").toInt());
[770]200
[819]201 const int timeOut = 100; // 0.1 seconds
202 if (!_outSocket->waitForConnected(timeOut)) {
203 delete _outSocket;
204 _outSocket = 0;
205 emit(error("bns::openCaster Connect Timeout"));
[840]206 return;
[819]207 }
208
[770]209 QString mountpoint = settings.value("mountpoint").toString();
210 QString password = settings.value("password").toString();
211
212 QByteArray msg = "SOURCE " + password.toAscii() + " /" +
213 mountpoint.toAscii() + "\r\n" +
214 "Source-Agent: NTRIP BNS/1.0\r\n\r\n";
215
216 _outSocket->write(msg);
[820]217 _outSocket->waitForBytesWritten();
[770]218
[820]219 _outSocket->waitForReadyRead();
[770]220 QByteArray ans = _outSocket->readLine();
221
222 if (ans.indexOf("OK") == -1) {
223 delete _outSocket;
224 _outSocket = 0;
[831]225 slotMessage("bns::openCaster socket deleted");
[770]226 }
[831]227 else {
228 slotMessage("bns::openCaster socket OK");
[858]229 _outSocketOpenTrial = 0;
[831]230 }
[770]231}
232
[784]233//
234////////////////////////////////////////////////////////////////////////////
[884]235void t_bns::slotNewEph(t_eph* ep) {
[784]236
237 QMutexLocker locker(&_mutex);
238
239 t_ephPair* pair;
[884]240 if ( !_ephList.contains(ep->prn()) ) {
[784]241 pair = new t_ephPair();
[884]242 _ephList.insert(ep->prn(), pair);
[784]243 }
244 else {
[884]245 pair = _ephList[ep->prn()];
[784]246 }
247
248 if (pair->eph == 0) {
249 pair->eph = ep;
250 }
251 else {
[884]252 if (ep->isNewerThan(pair->eph)) {
[784]253 delete pair->oldEph;
254 pair->oldEph = pair->eph;
255 pair->eph = ep;
256 }
257 else {
258 delete ep;
259 }
260 }
261}
262
[756]263// Start
264////////////////////////////////////////////////////////////////////////////
[757]265void t_bns::run() {
[769]266
[758]267 slotMessage("============ Start BNS ============");
[770]268
[828]269 // Start Thread that retrieves broadcast Ephemeris
270 // -----------------------------------------------
[758]271 _bnseph->start();
[769]272
[770]273 // Endless loop
274 // ------------
[769]275 while (true) {
[836]276
277 if (_clkSocket && _clkSocket->thread() != currentThread()) {
278 emit(moveSocket(currentThread()));
279 }
280
[796]281 if (_clkSocket && _clkSocket->state() == QAbstractSocket::ConnectedState) {
282 if ( _clkSocket->canReadLine()) {
[832]283 if (_outSocket == 0 ||
284 _outSocket->state() != QAbstractSocket::ConnectedState) {
[830]285 openCaster();
286 }
[796]287 readEpoch();
288 }
[809]289 else {
290 _clkSocket->waitForReadyRead(10);
291 }
[769]292 }
293 else {
[794]294 msleep(10);
[769]295 }
296 }
[756]297}
298
[778]299//
300////////////////////////////////////////////////////////////////////////////
[784]301void t_bns::readEpoch() {
[778]302
[784]303 QByteArray line = _clkSocket->readLine();
[786]304
[784]305 if (line.indexOf('*') == -1) {
306 return;
[778]307 }
308
[784]309 QTextStream in(line);
310
311 QString hlp;
[798]312 int GPSweek, numSat;
313 double GPSweeks;
[784]314
[798]315 in >> hlp >> GPSweek >> GPSweeks >> numSat;
[784]316
[874]317 if (numSat > 0) {
318
[922]319 QStringList prns;
320
[924]321 /// for (int oldEph = 0; oldEph <= 1; oldEph++) {
322 for (int oldEph = 0; oldEph <= 0; oldEph++) {
[905]323
324 struct ClockOrbit co;
325 memset(&co, 0, sizeof(co));
[907]326 co.GPSEpochTime = (int)GPSweeks;
[909]327 co.GLONASSEpochTime = (int)fmod(GPSweeks, 86400.0);
[905]328 co.ClockDataSupplied = 1;
329 co.OrbitDataSupplied = 1;
330 co.SatRefPoint = POINT_CENTER;
331 co.SatRefDatum = DATUM_ITRF;
332
333 for (int ii = 1; ii <= numSat; ii++) {
334
335 QString prn;
[927]336 ColumnVector xx(5);
[905]337 t_eph* ep = 0;
338
339 if (oldEph == 0) {
340 line = _clkSocket->readLine();
341 QTextStream in(line);
342 in >> prn;
[922]343 prns << prn;
[905]344 if ( _ephList.contains(prn) ) {
[927]345 in >> xx(1) >> xx(2) >> xx(3) >> xx(4) >> xx(5); xx(4) *= 1e-6;
346
347 //// beg test (zero clock correction for Gerhard Wuebbena)
[946]348 //// xx(4) -= xx(5) / 299792458.0;
[927]349 //// end test
350
[905]351 t_ephPair* pair = _ephList[prn];
352 pair->xx = xx;
353 ep = pair->eph;
[872]354 }
[905]355 }
356 else {
[922]357 prn = prns[ii-1];
[905]358 if ( _ephList.contains(prn) ) {
359 t_ephPair* pair = _ephList[prn];
360 prn = pair->eph->prn();
361 xx = pair->xx;
362 ep = pair->oldEph;
[873]363 }
364 }
[905]365
366 if (ep != 0) {
367 struct ClockOrbit::SatData* sd = 0;
368 if (prn[0] == 'G') {
369 sd = co.Sat + co.NumberOfGPSSat;
370 ++co.NumberOfGPSSat;
[872]371 }
[905]372 else if (prn[0] == 'R') {
373 sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfGLONASSSat;
374 ++co.NumberOfGLONASSSat;
375 }
376 if (sd) {
[923]377 processSatellite(oldEph, ep, GPSweek, GPSweeks, prn, xx, sd);
[905]378 }
[872]379 }
[863]380 }
[905]381
382 if ( _outSocket &&
383 (co.NumberOfGPSSat > 0 || co.NumberOfGLONASSSat > 0) ) {
384 char obuffer[CLOCKORBIT_BUFFERSIZE];
385 int len = MakeClockOrbit(&co, COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
386 if (len > 0) {
387 _outSocket->write(obuffer, len);
388 _outSocket->flush();
389 }
390 }
[863]391 }
[780]392 }
[778]393}
[784]394
395//
396////////////////////////////////////////////////////////////////////////////
[923]397void t_bns::processSatellite(int oldEph, t_eph* ep, int GPSweek, double GPSweeks,
[872]398 const QString& prn, const ColumnVector& xx,
[863]399 struct ClockOrbit::SatData* sd) {
[784]400
[799]401 ColumnVector xB(4);
[802]402 ColumnVector vv(3);
[799]403
[884]404 ep->position(GPSweek, GPSweeks, xB, vv);
[799]405
[804]406 ColumnVector dx = xx.Rows(1,3) - xB.Rows(1,3);
[927]407
[804]408 double dClk = (xx(4) - xB(4)) * 299792458.0;
409 ColumnVector rsw(3);
[800]410
[806]411 XYZ_to_RSW(xB.Rows(1,3), vv, dx, rsw);
[804]412
[863]413 if (sd) {
414 sd->ID = prn.mid(1).toInt();
[884]415 sd->IOD = ep->IOD();
[862]416 sd->Clock.DeltaA0 = dClk;
417 sd->Orbit.DeltaRadial = rsw(1);
418 sd->Orbit.DeltaAlongTrack = rsw(2);
419 sd->Orbit.DeltaCrossTrack = rsw(3);
[863]420 }
[862]421
[863]422 if (_outStream) {
423 QString line;
[923]424 char oldCh = (oldEph ? '!' : ' ');
425 line.sprintf("%c %d %.1f %s %3d %10.3f %8.3f %8.3f %8.3f\n",
426 oldCh, GPSweek, GPSweeks, ep->prn().toAscii().data(),
[884]427 ep->IOD(), dClk, rsw(1), rsw(2), rsw(3));
428 *_outStream << line;
[863]429 _outStream->flush();
[811]430 }
[923]431 if (!oldEph) {
432 if (_rnx) {
433 _rnx->write(GPSweek, GPSweeks, prn, xx);
434 }
435 if (_sp3) {
436 _sp3->write(GPSweek, GPSweeks, prn, xx);
437 }
[847]438 }
[784]439}
[836]440
441//
442////////////////////////////////////////////////////////////////////////////
443void t_bns::slotMoveSocket(QThread* tt) {
444 _clkSocket->setParent(0);
445 _clkSocket->moveToThread(tt);
446 slotMessage("bns::slotMoveSocket");
447}
Note: See TracBrowser for help on using the repository browser.