[280] | 1 | // Part of BNC, a utility for retrieving decoding and
|
---|
[464] | 2 | // converting GNSS data streams from NTRIP broadcasters.
|
---|
[280] | 3 | //
|
---|
[464] | 4 | // Copyright (C) 2007
|
---|
[280] | 5 | // German Federal Agency for Cartography and Geodesy (BKG)
|
---|
| 6 | // http://www.bkg.bund.de
|
---|
[464] | 7 | // Czech Technical University Prague, Department of Geodesy
|
---|
[280] | 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.
|
---|
[35] | 24 |
|
---|
| 25 | /* -------------------------------------------------------------------------
|
---|
[93] | 26 | * BKG NTRIP Client
|
---|
[35] | 27 | * -------------------------------------------------------------------------
|
---|
| 28 | *
|
---|
| 29 | * Class: bncTableDlg
|
---|
| 30 | *
|
---|
| 31 | * Purpose: Displays the source table, allows mountpoints selection
|
---|
| 32 | *
|
---|
| 33 | * Author: L. Mervart
|
---|
| 34 | *
|
---|
| 35 | * Created: 24-Dec-2005
|
---|
| 36 | *
|
---|
| 37 | * Changes:
|
---|
| 38 | *
|
---|
| 39 | * -----------------------------------------------------------------------*/
|
---|
| 40 |
|
---|
| 41 | #include "bnctabledlg.h"
|
---|
| 42 | #include "bncgetthread.h"
|
---|
| 43 |
|
---|
| 44 | // Constructor
|
---|
| 45 | ////////////////////////////////////////////////////////////////////////////
|
---|
[90] | 46 | bncTableDlg::bncTableDlg(QWidget* parent) : QDialog(parent) {
|
---|
[35] | 47 |
|
---|
| 48 | setMinimumSize(600,400);
|
---|
[237] | 49 | setWindowTitle(tr("Add Mountpoints"));
|
---|
[35] | 50 |
|
---|
| 51 | QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
---|
| 52 |
|
---|
| 53 | QSettings settings;
|
---|
[88] | 54 | _casterHostLineEdit = new QLineEdit(settings.value("casterHost").toString());
|
---|
| 55 | int ww = QFontMetrics(_casterHostLineEdit->font()).width('w');
|
---|
| 56 | _casterHostLineEdit->setMaximumWidth(18*ww);
|
---|
| 57 | _casterPortLineEdit = new QLineEdit(settings.value("casterPort").toString());
|
---|
| 58 | _casterPortLineEdit->setMaximumWidth(9*ww);
|
---|
| 59 | _casterUserLineEdit = new QLineEdit(settings.value("casterUser").toString());
|
---|
| 60 | _casterUserLineEdit->setMaximumWidth(9*ww);
|
---|
| 61 | _casterPasswordLineEdit = new QLineEdit(settings.value("casterPassword").toString());
|
---|
| 62 | _casterPasswordLineEdit->setMaximumWidth(9*ww);
|
---|
| 63 | _casterPasswordLineEdit->setEchoMode(QLineEdit::Password);
|
---|
[683] | 64 |
|
---|
| 65 | // WhatsThis
|
---|
| 66 | // ---------
|
---|
| 67 | _casterUserLineEdit->setWhatsThis(tr("Access to some streams on NTRIP broadcasters may be restricted. You'll need to enter a valid 'User ID' and 'Password' for access to these protected streams. Accounts are usually provided per NTRIP broadcaster through a registration process. Register through <u>http://igs.bkg.bund.de/index_ntrip_reg.htm</u> for access to protected streams on <u>www.euref-ip.net</u> and <u>www.igs-ip.net</u>."));
|
---|
| 68 | _casterPortLineEdit->setWhatsThis(tr("Enter the NTRIP broadcaster hostname or IP number and port number. <u>http://www.rtcm-ntrip.org/home</u> provides information about known NTRIP broadcaster installations. Note that EUREF and IGS operate NTRIP broadcasters at <u>http://www.euref-ip.net/home</u> and <u>http://www.igs-ip.net/home</u>."));
|
---|
| 69 | _casterHostLineEdit->setWhatsThis(tr("Enter the NTRIP broadcaster hostname or IP number and port number. <u>http://www.rtcm-ntrip.org/home</u> provides information about known NTRIP broadcaster installations. Note that EUREF and IGS operate NTRIP broadcasters at <u>http://www.euref-ip.net/home</u> and <u>http://www.igs-ip.net/home</u>."));
|
---|
[682] | 70 | _casterPasswordLineEdit->setWhatsThis(tr("Access to some streams on NTRIP broadcasters may be restricted. You'll need to enter a valid 'User ID' and 'Password' for access to these protected streams. Accounts are usually provided per NTRIP broadcaster through a registration procedure. Register through <u>http://igs.bkg.bund.de/index_ntrip_reg.htm</u> for access to protected streams on <u>www.euref-ip.net</u> and <u>www.igs-ip.net</u>."));
|
---|
[35] | 71 |
|
---|
[88] | 72 | QGridLayout* editLayout = new QGridLayout;
|
---|
[105] | 73 | editLayout->addWidget(new QLabel(tr("Caster host")), 0, 0);
|
---|
| 74 | editLayout->addWidget(_casterHostLineEdit, 0, 1);
|
---|
| 75 | editLayout->addWidget(new QLabel(tr("Caster port")), 0, 2);
|
---|
| 76 | editLayout->addWidget(_casterPortLineEdit, 0, 3);
|
---|
| 77 | editLayout->addWidget(new QLabel(tr("User")), 1, 0);
|
---|
| 78 | editLayout->addWidget(_casterUserLineEdit, 1, 1);
|
---|
| 79 | editLayout->addWidget(new QLabel(tr("Password")), 1, 2);
|
---|
| 80 | editLayout->addWidget(_casterPasswordLineEdit, 1, 3);
|
---|
[88] | 81 |
|
---|
[35] | 82 | mainLayout->addLayout(editLayout);
|
---|
| 83 |
|
---|
| 84 | _table = new QTableWidget(this);
|
---|
[682] | 85 | _table->setWhatsThis(tr("<p>Use the 'Get Table' button to download the sourcetable from the NTRIP broadcaster. Select the desired streams line by line, using +Shift and +Ctrl when necessary. Hit 'OK' to return to the main window.</p><p>Pay attention to data fields 'format' and 'format-details'. Keep in mind that BNC can only decode and convert streams that come in RTCM Version 2.x, RTCM Version 3.x, or RTIGS format. RTCM Version 2.x streams must contain message Type 18 and 19 while RTCM Version 3.x streams must contain GPS or SBAS message Type 1002 or 1004 and may contain GLONASS message types 1010 or 1012. See data field 'format-details' for available message types and their repetition rates in brackets.</p><p>Note that in order to produce RINEX Navigation files, RTCM Version 3.x streams containing message Type 1019 (GPS) and 1020 (GLONASS) or RTIGS streams are required.</p><p>The content of data field 'nmea' tells you whether a stream retrieval needs to be initiated by BNC by sending an NMEA-GGA message containing the user (or virtual reference station)'s coordinate.</p>"));
|
---|
[195] | 86 | connect(_table, SIGNAL(itemSelectionChanged()),
|
---|
| 87 | this, SLOT(slotSelectionChanged()));
|
---|
[35] | 88 | mainLayout->addWidget(_table);
|
---|
| 89 |
|
---|
[402] | 90 | _buttonWhatsThis = new QPushButton(tr("Help=Shift+F1"), this);
|
---|
[399] | 91 | connect(_buttonWhatsThis, SIGNAL(clicked()), this, SLOT(slotWhatsThis()));
|
---|
| 92 |
|
---|
[195] | 93 | _buttonGet = new QPushButton(tr("Get table"), this);
|
---|
[399] | 94 | _buttonGet->setDefault(true);
|
---|
[35] | 95 | connect(_buttonGet, SIGNAL(clicked()), this, SLOT(slotGetTable()));
|
---|
[366] | 96 |
|
---|
[35] | 97 | _buttonCancel = new QPushButton(tr("Cancel"), this);
|
---|
| 98 | connect(_buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
|
---|
| 99 |
|
---|
| 100 | _buttonOK = new QPushButton(tr("OK"), this);
|
---|
| 101 | connect(_buttonOK, SIGNAL(clicked()), this, SLOT(accept()));
|
---|
| 102 |
|
---|
| 103 | QHBoxLayout* buttonLayout = new QHBoxLayout;
|
---|
[399] | 104 | buttonLayout->addWidget(_buttonWhatsThis);
|
---|
[35] | 105 | buttonLayout->addStretch(1);
|
---|
| 106 | buttonLayout->addWidget(_buttonGet);
|
---|
| 107 | buttonLayout->addWidget(_buttonCancel);
|
---|
| 108 | buttonLayout->addWidget(_buttonOK);
|
---|
| 109 |
|
---|
| 110 | mainLayout->addLayout(buttonLayout);
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | // Destructor
|
---|
| 114 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 115 | bncTableDlg::~bncTableDlg() {
|
---|
| 116 | if (_table) {
|
---|
| 117 | for (int ir = 0; ir < _table->rowCount(); ir++) {
|
---|
| 118 | for (int ic = 0; ic < _table->columnCount(); ic++) {
|
---|
| 119 | delete _table->item(ir,ic);
|
---|
| 120 | }
|
---|
| 121 | }
|
---|
| 122 | }
|
---|
| 123 | }
|
---|
| 124 |
|
---|
[191] | 125 | // Read Table the caster (static)
|
---|
[35] | 126 | ////////////////////////////////////////////////////////////////////////////
|
---|
[191] | 127 | t_irc bncTableDlg::getFullTable(const QString& casterHost,
|
---|
[298] | 128 | int casterPort, QStringList& allLines,
|
---|
| 129 | bool alwaysRead) {
|
---|
[35] | 130 |
|
---|
[299] | 131 | static QMutex mutex;
|
---|
[298] | 132 | static QMap<QString, QStringList> allTables;
|
---|
| 133 |
|
---|
[299] | 134 | QMutexLocker locker(&mutex);
|
---|
| 135 |
|
---|
[298] | 136 | if (!alwaysRead && allTables.find(casterHost) != allTables.end()) {
|
---|
| 137 | allLines = allTables.find(casterHost).value();
|
---|
| 138 | return success;
|
---|
| 139 | }
|
---|
| 140 |
|
---|
[191] | 141 | allLines.clear();
|
---|
| 142 |
|
---|
[88] | 143 | QUrl url;
|
---|
[191] | 144 | url.setHost(casterHost);
|
---|
| 145 | url.setPort(casterPort);
|
---|
[35] | 146 |
|
---|
| 147 | // Send the Request
|
---|
| 148 | // ----------------
|
---|
[136] | 149 | const int timeOut = 10*1000;
|
---|
[82] | 150 | QString msg;
|
---|
[366] | 151 | QByteArray _latitude;
|
---|
| 152 | QByteArray _longitude;
|
---|
| 153 | QByteArray _nmea;
|
---|
| 154 | QTcpSocket* socket = bncGetThread::request(url, _latitude, _longitude, _nmea, timeOut, msg);
|
---|
[88] | 155 |
|
---|
[35] | 156 | if (!socket) {
|
---|
[191] | 157 | return failure;
|
---|
[35] | 158 | }
|
---|
| 159 |
|
---|
| 160 | // Read Caster Response
|
---|
| 161 | // --------------------
|
---|
[473] | 162 | bool proxyRespond = false;
|
---|
[35] | 163 | bool first = true;
|
---|
| 164 | while (true) {
|
---|
| 165 | if (socket->canReadLine()) {
|
---|
| 166 | QString line = socket->readLine();
|
---|
[473] | 167 |
|
---|
| 168 | // Skip messages from proxy server
|
---|
| 169 | // -------------------------------
|
---|
| 170 | if (line.indexOf("SOURCETABLE 200 OK") == -1 &&
|
---|
| 171 | line.indexOf("200 OK") != -1 ) {
|
---|
| 172 | proxyRespond = true;
|
---|
| 173 | }
|
---|
| 174 | if (proxyRespond) {
|
---|
| 175 | if (line.trimmed().isEmpty()) {
|
---|
| 176 | proxyRespond = false;
|
---|
| 177 | }
|
---|
| 178 | continue;
|
---|
| 179 | }
|
---|
| 180 |
|
---|
[191] | 181 | allLines.push_back(line);
|
---|
[35] | 182 | if (first) {
|
---|
| 183 | first = false;
|
---|
| 184 | if (line.indexOf("SOURCETABLE 200 OK") != 0) {
|
---|
| 185 | break;
|
---|
| 186 | }
|
---|
| 187 | }
|
---|
| 188 | else {
|
---|
| 189 | if (line.indexOf("ENDSOURCETABLE") == 0) {
|
---|
| 190 | break;
|
---|
| 191 | }
|
---|
| 192 | }
|
---|
| 193 | }
|
---|
| 194 | else {
|
---|
| 195 | socket->waitForReadyRead(timeOut);
|
---|
| 196 | if (socket->bytesAvailable() > 0) {
|
---|
| 197 | continue;
|
---|
| 198 | }
|
---|
| 199 | else {
|
---|
| 200 | break;
|
---|
| 201 | }
|
---|
| 202 | }
|
---|
| 203 | }
|
---|
| 204 | delete socket;
|
---|
| 205 |
|
---|
[298] | 206 | allTables.insert(casterHost, allLines);
|
---|
[191] | 207 | return success;
|
---|
| 208 | }
|
---|
| 209 |
|
---|
| 210 | // Read Table from Caster
|
---|
| 211 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 212 | void bncTableDlg::slotGetTable() {
|
---|
| 213 |
|
---|
[555] | 214 | _buttonGet->setEnabled(false);
|
---|
| 215 |
|
---|
[196] | 216 | _allLines.clear();
|
---|
[191] | 217 |
|
---|
| 218 | if ( getFullTable(_casterHostLineEdit->text(),
|
---|
| 219 | _casterPortLineEdit->text().toInt(),
|
---|
[196] | 220 | _allLines) != success ) {
|
---|
[191] | 221 | QMessageBox::warning(0, "BNC", "Cannot retrieve table of data");
|
---|
[645] | 222 | _buttonGet->setEnabled(true);
|
---|
[191] | 223 | return;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | QStringList lines;
|
---|
[196] | 227 | QStringListIterator it(_allLines);
|
---|
[191] | 228 | while (it.hasNext()) {
|
---|
| 229 | QString line = it.next();
|
---|
| 230 | if (line.indexOf("STR") == 0) {
|
---|
| 231 | lines.push_back(line);
|
---|
| 232 | }
|
---|
| 233 | }
|
---|
| 234 |
|
---|
[103] | 235 | static const QStringList labels = QString("mountpoint,identifier,format,"
|
---|
[371] | 236 | "format-details,carrier,system,network,country,latitude,longitude,"
|
---|
[410] | 237 | "nmea,solution,generator,compress.,authentic.,fee,bitrate,"
|
---|
[103] | 238 | "misc").split(",");
|
---|
| 239 |
|
---|
[191] | 240 | if (lines.size() > 0) {
|
---|
[35] | 241 | _table->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
---|
| 242 | _table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
---|
| 243 |
|
---|
[191] | 244 | QStringList hlp = lines[0].split(";");
|
---|
[35] | 245 | _table->setColumnCount(hlp.size()-1);
|
---|
[191] | 246 | _table->setRowCount(lines.size());
|
---|
[35] | 247 |
|
---|
[191] | 248 | QListIterator<QString> it(lines);
|
---|
[35] | 249 | int nRow = -1;
|
---|
| 250 | while (it.hasNext()) {
|
---|
| 251 | QStringList columns = it.next().split(";");
|
---|
| 252 | ++nRow;
|
---|
| 253 | for (int ic = 0; ic < columns.size()-1; ic++) {
|
---|
[366] | 254 |
|
---|
[410] | 255 | if (ic+1 == 11) { if (columns[ic+1] == "0") { columns[ic+1] = "no"; } else { columns[ic+1] = "yes"; }}
|
---|
[366] | 256 |
|
---|
[107] | 257 | QTableWidgetItem* it = new QTableWidgetItem(columns[ic+1]);
|
---|
[115] | 258 | it->setFlags(it->flags() & ~Qt::ItemIsEditable);
|
---|
[107] | 259 | _table->setItem(nRow, ic, it);
|
---|
[35] | 260 | }
|
---|
| 261 | }
|
---|
[83] | 262 | _table->sortItems(0);
|
---|
[103] | 263 | _table->setHorizontalHeaderLabels(labels);
|
---|
[104] | 264 | _table->setSortingEnabled(true);
|
---|
[371] | 265 |
|
---|
| 266 | int ww = QFontMetrics(this->font()).width('w');
|
---|
[375] | 267 | _table->horizontalHeader()->resizeSection(0,10*ww);
|
---|
[371] | 268 | _table->horizontalHeader()->resizeSection(2,8*ww);
|
---|
| 269 | _table->horizontalHeader()->resizeSection(3,15*ww);
|
---|
| 270 | _table->horizontalHeader()->resizeSection(4,8*ww);
|
---|
| 271 | _table->horizontalHeader()->resizeSection(5,8*ww);
|
---|
| 272 | _table->horizontalHeader()->resizeSection(6,8*ww);
|
---|
| 273 | _table->horizontalHeader()->resizeSection(7,8*ww);
|
---|
| 274 | _table->horizontalHeader()->resizeSection(8,8*ww);
|
---|
| 275 | _table->horizontalHeader()->resizeSection(9,8*ww);
|
---|
| 276 | _table->horizontalHeader()->resizeSection(10,8*ww);
|
---|
| 277 | _table->horizontalHeader()->resizeSection(11,8*ww);
|
---|
| 278 | _table->horizontalHeader()->resizeSection(12,15*ww);
|
---|
| 279 | _table->horizontalHeader()->resizeSection(13,8*ww);
|
---|
| 280 | _table->horizontalHeader()->resizeSection(14,8*ww);
|
---|
| 281 | _table->horizontalHeader()->resizeSection(15,8*ww);
|
---|
| 282 | _table->horizontalHeader()->resizeSection(16,8*ww);
|
---|
| 283 | _table->horizontalHeader()->resizeSection(17,15*ww);
|
---|
[35] | 284 | }
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 | // Accept slot
|
---|
| 288 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 289 | void bncTableDlg::accept() {
|
---|
| 290 |
|
---|
| 291 | QSettings settings;
|
---|
| 292 | settings.setValue("casterHost", _casterHostLineEdit->text());
|
---|
| 293 | settings.setValue("casterPort", _casterPortLineEdit->text());
|
---|
[88] | 294 | settings.setValue("casterUser", _casterUserLineEdit->text());
|
---|
| 295 | settings.setValue("casterPassword", _casterPasswordLineEdit->text());
|
---|
[35] | 296 |
|
---|
| 297 | QStringList* mountPoints = new QStringList;
|
---|
| 298 |
|
---|
| 299 | if (_table) {
|
---|
| 300 | for (int ir = 0; ir < _table->rowCount(); ir++) {
|
---|
[59] | 301 | QTableWidgetItem* item = _table->item(ir,0);
|
---|
| 302 | QString format = _table->item(ir,2)->text();
|
---|
[366] | 303 | QString latitude = _table->item(ir,8)->text();
|
---|
| 304 | QString longitude = _table->item(ir,9)->text();
|
---|
| 305 | QString nmea = _table->item(ir,10)->text();
|
---|
[59] | 306 | format.replace(" ", "_");
|
---|
[35] | 307 | if (_table->isItemSelected(item)) {
|
---|
| 308 | QUrl url;
|
---|
[444] | 309 | url.setUserName(QUrl::toPercentEncoding(_casterUserLineEdit->text()));
|
---|
| 310 | url.setPassword(QUrl::toPercentEncoding(_casterPasswordLineEdit->text()));
|
---|
[35] | 311 | url.setHost(_casterHostLineEdit->text());
|
---|
| 312 | url.setPort(_casterPortLineEdit->text().toInt());
|
---|
| 313 | url.setPath(item->text());
|
---|
[59] | 314 |
|
---|
[366] | 315 | mountPoints->push_back(url.toString() + " " + format + " " + latitude + " " + longitude + " " + nmea);
|
---|
[35] | 316 | }
|
---|
| 317 | }
|
---|
| 318 | }
|
---|
| 319 | emit newMountPoints(mountPoints);
|
---|
| 320 |
|
---|
| 321 | QDialog::accept();
|
---|
| 322 | }
|
---|
[195] | 323 |
|
---|
| 324 | // User changed the selection of mountPoints
|
---|
| 325 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 326 | void bncTableDlg::slotSelectionChanged() {
|
---|
| 327 | if (_table->selectedItems().isEmpty()) {
|
---|
| 328 | }
|
---|
| 329 | }
|
---|
| 330 |
|
---|
[196] | 331 | // Create RINEX skeleton header
|
---|
[195] | 332 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 333 | void bncTableDlg::slotSkl() {
|
---|
| 334 |
|
---|
[196] | 335 | int nRows = _table->rowCount();
|
---|
| 336 | for (int iRow = 0; iRow < nRows; iRow++) {
|
---|
| 337 | if (_table->isItemSelected(_table->item(iRow,1))) {
|
---|
| 338 | QString staID = _table->item(iRow,0)->text();
|
---|
| 339 | QString net = _table->item(iRow,6)->text();
|
---|
[195] | 340 |
|
---|
[196] | 341 | QString ftpDir;
|
---|
| 342 | QStringListIterator it(_allLines);
|
---|
| 343 | while (it.hasNext()) {
|
---|
| 344 | QString line = it.next();
|
---|
| 345 | if (line.indexOf("NET") == 0) {
|
---|
| 346 | QStringList tags = line.split(';');
|
---|
| 347 | if (tags.at(1) == net) {
|
---|
| 348 | ftpDir = tags.at(6);
|
---|
| 349 | break;
|
---|
| 350 | }
|
---|
| 351 | }
|
---|
| 352 | }
|
---|
| 353 |
|
---|
[197] | 354 | if (!ftpDir.isEmpty()) {
|
---|
| 355 | QUrl url(ftpDir);
|
---|
| 356 | QMessageBox::warning(0, "Warning", url.host() + "\n" + url.path() +
|
---|
| 357 | "\nnot yet implemented");
|
---|
| 358 | }
|
---|
[196] | 359 | }
|
---|
| 360 | }
|
---|
[197] | 361 | }
|
---|
[196] | 362 |
|
---|
[399] | 363 | // Whats This Help
|
---|
| 364 | void bncTableDlg::slotWhatsThis() {
|
---|
| 365 | QWhatsThis::enterWhatsThisMode();
|
---|
| 366 | }
|
---|
| 367 |
|
---|
| 368 |
|
---|