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

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

* empty log message *

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