source: ntrip/trunk/BNC/bnccaster.cpp@ 622

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

* empty log message *

File size: 8.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: bncCaster
30 *
31 * Purpose: buffers and disseminates the data
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Dec-2005
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <math.h>
42
43#include "bnccaster.h"
44#include "bncgetthread.h"
45#include "bncutils.h"
46#include "RTCM/GPSDecoder.h"
47
48// Constructor
49////////////////////////////////////////////////////////////////////////////
50bncCaster::bncCaster(const QString& outFileName, int port) {
51
52 QSettings settings;
53
54 if ( !outFileName.isEmpty() ) {
55 QString lName = outFileName;
56 expandEnvVar(lName);
57 _outFile = new QFile(lName);
58 if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked) {
59 _outFile->open(QIODevice::WriteOnly | QIODevice::Append);
60 }
61 else {
62 _outFile->open(QIODevice::WriteOnly);
63 }
64 _out = new QTextStream(_outFile);
65 _out->setRealNumberNotation(QTextStream::FixedNotation);
66 }
67 else {
68 _outFile = 0;
69 _out = 0;
70 }
71
72 _port = port;
73
74 if (_port != 0) {
75 _server = new QTcpServer;
76 _server->listen(QHostAddress::Any, _port);
77 connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
78 _sockets = new QList<QTcpSocket*>;
79 }
80 else {
81 _server = 0;
82 _sockets = 0;
83 }
84
85 _epochs = new QMultiMap<long, p_obs>;
86
87 _lastDumpSec = 0;
88
89 _samplingRate = settings.value("rnxSampl").toInt();
90 _waitTime = settings.value("waitTime").toInt();
91 if (_waitTime < 1) {
92 _waitTime = 1;
93 }
94}
95
96// Destructor
97////////////////////////////////////////////////////////////////////////////
98bncCaster::~bncCaster() {
99 QListIterator<bncGetThread*> it(_threads);
100 while(it.hasNext()){
101 bncGetThread* thread = it.next();
102 thread->terminate();
103 thread->wait();
104 delete thread;
105 }
106 delete _out;
107 delete _outFile;
108 delete _server;
109 delete _sockets;
110 if (_epochs) {
111 QListIterator<p_obs> it(_epochs->values());
112 while (it.hasNext()) {
113 delete it.next();
114 }
115 delete _epochs;
116 }
117}
118
119// New Observations
120////////////////////////////////////////////////////////////////////////////
121void bncCaster::newObs(const QByteArray staID, bool firstObs, p_obs obs) {
122
123 QMutexLocker locker(&_mutex);
124
125 long iSec = long(floor(obs->_o.GPSWeeks+0.5));
126 long newTime = obs->_o.GPSWeek * 7*24*3600 + iSec;
127
128 // Rename the Station
129 // ------------------
130 strncpy(obs->_o.StatID, staID.constData(),sizeof(obs->_o.StatID));
131 obs->_o.StatID[sizeof(obs->_o.StatID)-1] = '\0';
132
133 // First time, set the _lastDumpSec immediately
134 // --------------------------------------------
135 if (_lastDumpSec == 0) {
136 _lastDumpSec = newTime - 1;
137 }
138
139 // An old observation - throw it away
140 // ----------------------------------
141 if (newTime <= _lastDumpSec) {
142 if (firstObs) {
143 QSettings settings;
144 if ( !settings.value("outFile").toString().isEmpty() ||
145 !settings.value("outPort").toString().isEmpty() ) {
146 emit( newMessage(QString("Station %1: old epoch %2 thrown away")
147 .arg(staID.data()).arg(iSec).toAscii()) );
148 }
149 }
150 delete obs;
151 return;
152 }
153
154 // Save the observation
155 // --------------------
156 _epochs->insert(newTime, obs);
157
158 // Dump Epochs
159 // -----------
160 if (newTime - _waitTime > _lastDumpSec) {
161 dumpEpochs(_lastDumpSec + 1, newTime - _waitTime);
162 _lastDumpSec = newTime - _waitTime;
163 }
164}
165
166// New Connection
167////////////////////////////////////////////////////////////////////////////
168void bncCaster::slotNewConnection() {
169 _sockets->push_back( _server->nextPendingConnection() );
170}
171
172// Add New Thread
173////////////////////////////////////////////////////////////////////////////
174void bncCaster::addGetThread(bncGetThread* getThread) {
175 connect(getThread, SIGNAL(newObs(const QByteArray, bool, p_obs)),
176 this, SLOT(newObs(const QByteArray, bool, p_obs)));
177
178 connect(getThread, SIGNAL(error(const QByteArray)),
179 this, SLOT(slotGetThreadError(const QByteArray)));
180
181 _staIDs.push_back(getThread->staID());
182 _threads.push_back(getThread);
183}
184
185// Error in get thread
186////////////////////////////////////////////////////////////////////////////
187void bncCaster::slotGetThreadError(const QByteArray staID) {
188 QMutexLocker locker(&_mutex);
189 _staIDs.removeAll(staID);
190 emit( newMessage(
191 QString("Mountpoint size %1").arg(_staIDs.size()).toAscii()) );
192 if (_staIDs.size() == 0) {
193 emit(newMessage("bncCaster:: last get thread terminated"));
194 emit getThreadErrors();
195 }
196}
197
198// Dump Complete Epochs
199////////////////////////////////////////////////////////////////////////////
200void bncCaster::dumpEpochs(long minTime, long maxTime) {
201
202 const char begEpoch = 'A';
203 const char begObs = 'B';
204 const char endEpoch = 'C';
205
206 for (long sec = minTime; sec <= maxTime; sec++) {
207
208 bool first = true;
209 QList<p_obs> allObs = _epochs->values(sec);
210 QListIterator<p_obs> it(allObs);
211 while (it.hasNext()) {
212 p_obs obs = it.next();
213
214 if (_samplingRate == 0 || sec % _samplingRate == 0) {
215
216 // Output into the file
217 // --------------------
218 if (_out) {
219 if (first) {
220 _out->setFieldWidth(1); *_out << begEpoch << endl;;
221 }
222 _out->setFieldWidth(0); *_out << obs->_o.StatID;
223 _out->setFieldWidth(1); *_out << " " << obs->_o.satSys;
224 _out->setPadChar('0');
225 _out->setFieldWidth(2); *_out << obs->_o.satNum;
226 _out->setPadChar(' ');
227 _out->setFieldWidth(1); *_out << " ";
228 _out->setFieldWidth(4); *_out << obs->_o.GPSWeek;
229 _out->setFieldWidth(1); *_out << " ";
230 _out->setFieldWidth(14); _out->setRealNumberPrecision(7); *_out << obs->_o.GPSWeeks;
231 _out->setFieldWidth(1); *_out << " ";
232 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.C1;
233 _out->setFieldWidth(1); *_out << " ";
234 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.C2;
235 _out->setFieldWidth(1); *_out << " ";
236 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.P1;
237 _out->setFieldWidth(1); *_out << " ";
238 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.P2;
239 _out->setFieldWidth(1); *_out << " ";
240 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.L1;
241 _out->setFieldWidth(1); *_out << " ";
242 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.L2;
243 _out->setFieldWidth(1); *_out << " ";
244 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.S1;
245 _out->setFieldWidth(1); *_out << " ";
246 _out->setFieldWidth(14); _out->setRealNumberPrecision(3); *_out << obs->_o.S2;
247 _out->setFieldWidth(1);
248 *_out << " " << obs->_o.SNR1 << " " << obs->_o.SNR2 << endl;
249 if (!it.hasNext()) {
250 _out->setFieldWidth(1); *_out << endEpoch << endl;
251 }
252 _out->flush();
253 }
254
255 // Output into the socket
256 // ----------------------
257 if (_sockets) {
258 int numBytes = sizeof(obs->_o);
259 QListIterator<QTcpSocket*> is(*_sockets);
260 while (is.hasNext()) {
261 QTcpSocket* sock = is.next();
262 if (sock->state() == QAbstractSocket::ConnectedState) {
263 if (first) {
264 sock->write(&begEpoch, 1);
265 }
266 sock->write(&begObs, 1);
267 sock->write((char*) &obs->_o, numBytes);
268 if (!it.hasNext()) {
269 sock->write(&endEpoch, 1);
270 }
271 }
272 }
273 }
274 }
275
276 delete obs;
277 _epochs->remove(sec);
278 first = false;
279 }
280 }
281}
Note: See TracBrowser for help on using the repository browser.