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

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

* empty log message *

File size: 10.3 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"
[862]25extern "C" {
26#include "RTCM/clock_orbit_rtcm.h"
27}
[756]28
29using namespace std;
30
31// Constructor
32////////////////////////////////////////////////////////////////////////////
[757]33t_bns::t_bns(QObject* parent) : QThread(parent) {
[760]34
[764]35 this->setTerminationEnabled(true);
[828]36
[836]37 connect(this, SIGNAL(moveSocket(QThread*)),
38 this, SLOT(slotMoveSocket(QThread*)));
39
[828]40 // Thread that handles broadcast ephemeris
41 // ---------------------------------------
42 _bnseph = new t_bnseph(parent);
[827]43
[828]44 connect(_bnseph, SIGNAL(newEph(gpsEph*)), this, SLOT(slotNewEph(gpsEph*)));
45 connect(_bnseph, SIGNAL(newMessage(QByteArray)),
46 this, SLOT(slotMessage(const QByteArray)));
47 connect(_bnseph, SIGNAL(error(QByteArray)),
48 this, SLOT(slotError(const QByteArray)));
[760]49
[827]50 // Server listening for rtnet results
51 // ----------------------------------
[786]52 QSettings settings;
[828]53 _clkSocket = 0;
[827]54 _clkServer = new QTcpServer;
55 _clkServer->listen(QHostAddress::Any, settings.value("clkPort").toInt());
[828]56 connect(_clkServer, SIGNAL(newConnection()),this, SLOT(slotNewConnection()));
[827]57
[828]58 // Socket and file for outputting the results
59 // -------------------------------------------
[858]60 _outSocket = 0;
61 _outSocketOpenTrial = 0;
[827]62
[816]63 QString outFileName = settings.value("outFile").toString();
64 if (outFileName.isEmpty()) {
[833]65 _outFile = 0;
66 _outStream = 0;
[811]67 }
[816]68 else {
69 _outFile = new QFile(outFileName);
[817]70 if (_outFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
[816]71 _outStream = new QTextStream(_outFile);
72 }
73 }
[812]74
75 // Log File
76 // --------
[816]77 QString logFileName = settings.value("logFile").toString();
78 if (logFileName.isEmpty()) {
79 _logFile = 0;
[812]80 }
[816]81 else {
82 _logFile = new QFile(logFileName);
[817]83 if (_logFile->open(QIODevice::WriteOnly | QIODevice::Unbuffered)) {
[816]84 _logStream = new QTextStream(_logFile);
85 }
86 }
[847]87
88 // RINEX writer
89 // ------------
90 if ( settings.value("rnxPath").toString().isEmpty() ) {
91 _rnx = 0;
92 }
93 else {
[850]94 QString prep = "BNS";
[857]95 QString ext = ".clk";
[850]96 QString path = settings.value("rnxPath").toString();
97 QString intr = settings.value("rnxIntr").toString();
98 int sampl = settings.value("rnxSampl").toInt();
99 _rnx = new bnsRinex(prep, ext, path, intr, sampl);
[847]100 }
[848]101
102 // SP3 writer
103 // ----------
104 if ( settings.value("sp3Path").toString().isEmpty() ) {
105 _sp3 = 0;
106 }
107 else {
[850]108 QString prep = "BNS";
[857]109 QString ext = ".sp3";
[850]110 QString path = settings.value("sp3Path").toString();
111 QString intr = settings.value("sp3Intr").toString();
112 int sampl = settings.value("sp3Sampl").toInt();
113 _sp3 = new bnsSP3(prep, ext, path, intr, sampl);
[848]114 }
[756]115}
116
117// Destructor
118////////////////////////////////////////////////////////////////////////////
[757]119t_bns::~t_bns() {
[763]120 deleteBnsEph();
[769]121 delete _clkServer;
[837]122 delete _clkSocket;
[770]123 delete _outSocket;
[816]124 delete _outStream;
125 delete _logStream;
[812]126 delete _outFile;
127 delete _logFile;
[779]128 QMapIterator<QString, t_ephPair*> it(_ephList);
129 while (it.hasNext()) {
130 it.next();
131 delete it.value();
132 }
[849]133 delete _rnx;
134 delete _sp3;
[756]135}
136
[763]137// Delete bns thread
138////////////////////////////////////////////////////////////////////////////
139void t_bns::deleteBnsEph() {
140 if (_bnseph) {
141 _bnseph->terminate();
[764]142 _bnseph->wait(100);
[763]143 delete _bnseph;
144 _bnseph = 0;
145 }
146}
147
[756]148// Write a Program Message
149////////////////////////////////////////////////////////////////////////////
[758]150void t_bns::slotMessage(const QByteArray msg) {
[816]151 if (_logStream) {
152 *_logStream << msg << endl;
[818]153 _logStream->flush();
[812]154 }
[757]155 emit(newMessage(msg));
[756]156}
157
[760]158// Write a Program Message
159////////////////////////////////////////////////////////////////////////////
160void t_bns::slotError(const QByteArray msg) {
[816]161 if (_logStream) {
162 *_logStream << msg << endl;
[818]163 _logStream->flush();
[812]164 }
[763]165 deleteBnsEph();
[760]166 emit(error(msg));
167}
168
[769]169// New Connection
170////////////////////////////////////////////////////////////////////////////
171void t_bns::slotNewConnection() {
[786]172 slotMessage("t_bns::slotNewConnection");
[787]173 delete _clkSocket;
[769]174 _clkSocket = _clkServer->nextPendingConnection();
175}
176
[770]177// Start the Communication with NTRIP Caster
178////////////////////////////////////////////////////////////////////////////
179void t_bns::openCaster() {
[858]180
181 delete _outSocket; _outSocket = 0;
182
183 double minDt = exp2(_outSocketOpenTrial);
184 if (++_outSocketOpenTrial > 8) {
185 _outSocketOpenTrial = 8;
186 }
187 if (_outSocketOpenTime.isValid() &&
188 _outSocketOpenTime.secsTo(QDateTime::currentDateTime()) < minDt) {
189 return;
190 }
191 else {
192 _outSocketOpenTime = QDateTime::currentDateTime();
193 }
194
[770]195 QSettings settings;
196 _outSocket = new QTcpSocket();
[811]197 _outSocket->connectToHost(settings.value("outHost").toString(),
198 settings.value("outPort").toInt());
[770]199
[819]200 const int timeOut = 100; // 0.1 seconds
201 if (!_outSocket->waitForConnected(timeOut)) {
202 delete _outSocket;
203 _outSocket = 0;
204 emit(error("bns::openCaster Connect Timeout"));
[840]205 return;
[819]206 }
207
[770]208 QString mountpoint = settings.value("mountpoint").toString();
209 QString password = settings.value("password").toString();
210
211 QByteArray msg = "SOURCE " + password.toAscii() + " /" +
212 mountpoint.toAscii() + "\r\n" +
213 "Source-Agent: NTRIP BNS/1.0\r\n\r\n";
214
215 _outSocket->write(msg);
[820]216 _outSocket->waitForBytesWritten();
[770]217
[820]218 _outSocket->waitForReadyRead();
[770]219 QByteArray ans = _outSocket->readLine();
220
221 if (ans.indexOf("OK") == -1) {
222 delete _outSocket;
223 _outSocket = 0;
[831]224 slotMessage("bns::openCaster socket deleted");
[770]225 }
[831]226 else {
227 slotMessage("bns::openCaster socket OK");
[858]228 _outSocketOpenTrial = 0;
[831]229 }
[770]230}
231
[784]232//
233////////////////////////////////////////////////////////////////////////////
234void t_bns::slotNewEph(gpsEph* ep) {
235
236 QMutexLocker locker(&_mutex);
237
238 t_ephPair* pair;
239 if ( !_ephList.contains(ep->prn) ) {
240 pair = new t_ephPair();
241 _ephList.insert(ep->prn, pair);
242 }
243 else {
244 pair = _ephList[ep->prn];
245 }
246
247 if (pair->eph == 0) {
248 pair->eph = ep;
249 }
250 else {
251 if (ep->GPSweek > pair->eph->GPSweek ||
252 (ep->GPSweek == pair->eph->GPSweek && ep->TOC > pair->eph->TOC)) {
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
317 for (int ii = 1; ii <= numSat; ii++) {
[792]318 line = _clkSocket->readLine();
[791]319
[784]320 QTextStream in(line);
321
322 QString prn;
323 ColumnVector xx(4);
324
[795]325 in >> prn >> xx(1) >> xx(2) >> xx(3) >> xx(4);
[797]326 xx(4) *= 1e-6;
[784]327
[798]328 processSatellite(GPSweek, GPSweeks, prn, xx);
[780]329 }
[778]330}
[784]331
332//
333////////////////////////////////////////////////////////////////////////////
[798]334void t_bns::processSatellite(int GPSweek, double GPSweeks, const QString& prn,
[784]335 const ColumnVector& xx) {
336
[795]337 // No broadcast ephemeris available
338 // --------------------------------
339 if ( !_ephList.contains(prn) ) {
340 return;
341 }
342
343 t_ephPair* pair = _ephList[prn];
344 gpsEph* ep = pair->eph;
345
[799]346 ColumnVector xB(4);
[802]347 ColumnVector vv(3);
[799]348
[803]349 satellitePosition(GPSweek, GPSweeks, ep, xB(1), xB(2), xB(3), xB(4),
[802]350 vv(1), vv(2), vv(3));
[799]351
[804]352 ColumnVector dx = xx.Rows(1,3) - xB.Rows(1,3);
353 double dClk = (xx(4) - xB(4)) * 299792458.0;
354 ColumnVector rsw(3);
[800]355
[806]356 XYZ_to_RSW(xB.Rows(1,3), vv, dx, rsw);
[804]357
[811]358 QString line;
[817]359 line.sprintf("%d %.1f %s %3d %3d %8.3f %8.3f %8.3f %8.3f\n",
[811]360 GPSweek, GPSweeks, ep->prn.toAscii().data(),
361 int(ep->IODC), int(ep->IODE), dClk, rsw(1), rsw(2), rsw(3));
362
[816]363 if (_outStream) {
364 *_outStream << line;
[818]365 _outStream->flush();
[811]366 }
367 if (_outSocket) {
[862]368 struct ClockOrbit co;
369 memset(&co, 0, sizeof(co));
370 co.GPSEpochTime = (int)GPSweeks;
371 co.ClockDataSupplied = 1;
372 co.OrbitDataSupplied = 1;
373 co.SatRefPoint = POINT_CENTER;
374 co.SatRefDatum = DATUM_ITRF;
375 co.NumberOfGPSSat = 1;
376
377 struct ClockOrbit::SatData* sd = co.Sat;
378 /// sd->ID = prn;
379 sd->IOD = int(ep->IODE);
380 sd->Clock.DeltaA0 = dClk;
381 sd->Orbit.DeltaRadial = rsw(1);
382 sd->Orbit.DeltaAlongTrack = rsw(2);
383 sd->Orbit.DeltaCrossTrack = rsw(3);
384
385 char obuffer[CLOCKORBIT_BUFFERSIZE];
386 int len = MakeClockOrbit(&co, COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
387 if (len > 0) {
388 _outSocket->write(obuffer, len);
389 _outSocket->flush();
390 }
[811]391 }
[847]392 if (_rnx) {
393 _rnx->write(GPSweek, GPSweeks, prn, xx);
394 }
[848]395 if (_sp3) {
396 _sp3->write(GPSweek, GPSweeks, prn, xx);
397 }
[784]398}
[836]399
400//
401////////////////////////////////////////////////////////////////////////////
402void t_bns::slotMoveSocket(QThread* tt) {
403 _clkSocket->setParent(0);
404 _clkSocket->moveToThread(tt);
405 slotMessage("bns::slotMoveSocket");
406}
Note: See TracBrowser for help on using the repository browser.