Changeset 11136 in ntrip


Ignore:
Timestamp:
Oct 28, 2026, 4:23:04 PM (4 hours ago)
Author:
stuerze
Message:

Added:
EPH RINEX files can be written now per station like observation files and in PPP mode the Broadcast stream can be specified

Location:
trunk/BNC
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/CHANGELOG.md

    r11134 r11136  
    2121- ADDED: ANTEX file name, number of entries and latest satellite entry are logged; satellites without a valid ANTEX entry are reported (and not combined)
    2222- ADDED: Combination and PPP: a changed ANTEX file is read again while BNC is running and used from the GPS week given in it (SINEX code of the entries, e.g. IGS20_2437) on; the attitude model states are taken over
     23- ADDED: Option 'File per stream' (key ephFilePerStation) in the RINEX Ephemeris panel: one RINEX navigation file per stream, named after the stream like the observation files, each with all ephemerides of its stream; by default still one file with each ephemeris once
     24- ADDED: PPP option 'Ephemeris stream' (key PPP/ephMount): real-time PPP uses the Broadcast Ephemeris of the given stream(s) only, e.g. BCEP00BKG0, not those of the observation streams; empty: all streams as before
    2325- ADDED: Regression test suite ('tests'): example configurations and short raw captures replayed through BNC and compared with reference outputs
    2426- ADDED: macOS packaging script
  • trunk/BNC/src/bnccore.cpp

    r11075 r11136  
    7676  // Eph file(s)
    7777  // -----------
    78   _rinexVers        = 0;
    79   _ephFileGPS       = 0;
    80   _ephStreamGPS     = 0;
    81   _ephFileGlonass   = 0;
    82   _ephStreamGlonass = 0;
    83   _ephFileGalileo   = 0;
    84   _ephStreamGalileo = 0;
    85   _ephFileSBAS      = 0;
    86   _ephStreamSBAS    = 0;
     78  _rinexVers         = 0;
     79  _ephFilePerStation = false;
    8780
    8881  _portEph    = 0;
    … …  
    129122  delete _logStream; _logStream = 0;
    130123  delete _logFile;   _logFile   = 0;
    131   delete _ephStreamGPS;
    132   delete _ephFileGPS;
     124  qDeleteAll(_ephFiles);
    133125  delete _serverEph;
    134126  delete _socketsEph;
    135127  delete _serverCorr;
    136128  delete _socketsCorr;
    137   if (_rinexVers == 2) {
    138     delete _ephStreamGlonass;
    139     delete _ephFileGlonass;
    140   }
    141 
    142129  delete _dateAndTimeGPS;
    143130  if (_rawFile) {
    … …  
    230217  }
    231218#endif
    232   printEphHeader(eph->receptStaID());
    233   printEph(*eph, bool(ircPut == success));
     219  t_ephFile* ephFile = printEphHeader(eph->receptStaID());
     220  bool printFile = (ircPut == success);
     221  if (ephFile && ephFile->_ephUser) {
     222    // file per stream: new ephemerides of this stream, independent of other streams;
     223    // the check state of the emitted ephemeris stays that of the common check
     224    t_eph::e_checkState checkState = eph->checkState();
     225    printFile = (ephFile->_ephUser->putNewEph(eph, true) == success);
     226    eph->setCheckState(checkState);
     227  }
     228  printEph(ephFile, *eph, printFile);
    234229  return success;
    235230}
    … …  
    275270}
    276271
    277 // Print Header of the output File(s)
    278 ////////////////////////////////////////////////////////////////////////////
    279 void t_bncCore::printEphHeader(QString receptStaID) {
     272// Close RINEX Navigation File(s)
     273////////////////////////////////////////////////////////////////////////////
     274void t_bncCore::t_ephFile::close() {
     275  delete _streamN; _streamN = 0;
     276  delete _fileN;   _fileN   = 0;
     277  delete _streamG; _streamG = 0;
     278  delete _fileG;   _fileG   = 0;
     279}
     280
     281// Destructor
     282////////////////////////////////////////////////////////////////////////////
     283t_bncCore::t_ephFile::~t_ephFile() {
     284  close();
     285  delete _ephUser;
     286}
     287
     288// Station part of a RINEX navigation file name: "BRDC" (+ "00WRD" in RINEX 3/4)
     289// for the single file, otherwise derived from the stream like the observation files
     290////////////////////////////////////////////////////////////////////////////
     291QString t_bncCore::ephFileNameBase(const QString& staID, const QString& country) const {
     292  QString ID = staID.isEmpty() ? QString("BRDC") : staID.left(4).toUpper();
     293  if (_rinexVers <= 2) {
     294    return ID;
     295  }
     296  if (staID.size() >= 9 &&
     297      isdigit((unsigned char) staID[4].toLatin1()) &&
     298      isdigit((unsigned char) staID[5].toLatin1())) {
     299    return staID.left(9).toUpper();   // e.g. BCEP00BKG0 -> BCEP00BKG
     300  }
     301  return ID + "00" + ((!staID.isEmpty() && country.size() >= 3) ? country.left(3).toUpper()
     302                                                                : QString("WRD")); // WORLD
     303}
     304
     305// Print Header of the output File(s), returns the file of the stream
     306////////////////////////////////////////////////////////////////////////////
     307t_bncCore::t_ephFile* t_bncCore::printEphHeader(QString receptStaID) {
    280308
    281309  bncSettings settings;
     310
     311  // Initialization
     312  // --------------
     313  if (_rinexVers == 0) {
     314
     315    _rinexVers = settings.value("ephVersion").toInt();
     316
     317    _ephFilePerStation = Qt::CheckState(settings.value("ephFilePerStation").toInt()) == Qt::Checked;
     318
     319    _ephPath = settings.value("ephPath").toString();
     320
     321    if ( !_ephPath.isEmpty() ) {
     322      if ( _ephPath[_ephPath.length()-1] != QDir::separator() ) {
     323        _ephPath += QDir::separator();
     324      }
     325      expandEnvVar(_ephPath);
     326    }
     327  }
     328
     329  if (_ephPath.isEmpty()) {
     330    return 0;
     331  }
     332
     333  QString key = _ephFilePerStation ? receptStaID : QString();
     334
     335  // Source comments and station part of the file name
     336  // --------------------------------------------------
    282337  QStringList comments;
    283   bool separateFiles = false;// Qt::CheckState(settings.value("ephFilePerStation").toInt());
    284 
     338  QMap<QString, QString> nameBase;  // staID -> station part of its file name
    285339  QListIterator<QString> it(settings.value("mountPoints").toStringList());
    286340  while (it.hasNext()) {
    … …  
    290344    QUrl url(hlp[0]);
    291345    QString decoder = hlp[1];
    292     if (!separateFiles) {
     346    QString staID   = url.path().mid(1);
     347    if (key.isEmpty() || staID == key) {
    293348      comments.append("Source: " + decoder +
    294349                      " " + QUrl::toAce(url.host()) +
    295350                      "/" + url.path().mid(1).toLatin1());
    296351    }
    297   }
    298 
    299   // Initialization
    300   // --------------
    301   if (_rinexVers == 0) {
    302 
    303     _rinexVers = settings.value("ephVersion").toInt();
    304 
    305     _ephPath = settings.value("ephPath").toString();
    306 
    307     if ( !_ephPath.isEmpty() ) {
    308       if ( _ephPath[_ephPath.length()-1] != QDir::separator() ) {
    309         _ephPath += QDir::separator();
    310       }
    311       expandEnvVar(_ephPath);
     352    nameBase[staID] = ephFileNameBase(staID, hlp[2]);
     353  }
     354
     355  QString base = (!key.isEmpty() && nameBase.contains(key)) ? nameBase[key]
     356                                                           : ephFileNameBase(key, QString());
     357  QString distStr;
     358  if (!key.isEmpty()) {
     359    QMapIterator<QString, QString> im(nameBase);
     360    while (im.hasNext()) {
     361      im.next();
     362      if (im.key() != key && im.value() == base) { // name conflict with another stream
     363        distStr = "_" + key;
     364        break;
     365      }
     366    }
     367  }
     368
     369  t_ephFile*& ephFile = _ephFiles[key];
     370  if (!ephFile) {
     371    ephFile = new t_ephFile;
     372    if (_ephFilePerStation) {
     373      ephFile->_ephUser = new bncEphUser(false);
    312374    }
    313375  }
    … …  
    315377  // (Re-)Open output File(s)
    316378  // ------------------------
    317   if (!_ephPath.isEmpty()) {
    318 
    319     QDateTime datTim = currentDateAndTimeGPS();
    320 
    321     QString ephFileNameGPS = _ephPath; // + "BRDC";
    322 
    323     (separateFiles) ?  ephFileNameGPS += receptStaID.left(4) :
    324                        ephFileNameGPS += "BRDC";
    325 
    326     QString hlpStr = bncRinex::nextEpochStr(datTim,
    327                          settings.value("ephIntr").toString(), _rinexVers);
    328 
    329     if (_rinexVers > 2) {
    330       QString country = "WRD"; // WORLD
    331       QString monNum = "0";
    332       QString recNum = "0";
    333       if (separateFiles && receptStaID.size() >= 9) {
    334         monNum = receptStaID.mid(4,1);
    335         recNum = receptStaID.mid(5,1);
    336         country = receptStaID.mid(6,3);
    337       }
    338       ephFileNameGPS += QString("%1").arg(monNum, 1, 10) +
    339                         QString("%1").arg(recNum, 1, 10) +
    340                         country +
    341                         "_S_" +     // stream
    342                         QString("%1").arg(datTim.date().year()) +
    343                         QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
    344                         hlpStr +   // HM_period
    345                         "_MN.rnx"; // mixed BRDC
    346     }
    347     else { // RNX v2.11
    348       ephFileNameGPS += QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
    349                         hlpStr + datTim.toString(".yyN");
    350     }
    351 
    352     if (_ephFileNameGPS == ephFileNameGPS) {
    353       return;
    354     }
    355     else {
    356       _ephFileNameGPS = ephFileNameGPS;
    357     }
    358 
    359     delete _ephStreamGPS;
    360     delete _ephFileGPS;
    361 
    362     QFlags<QIODevice::OpenModeFlag> appendFlagGPS;
    363     QFlags<QIODevice::OpenModeFlag> appendFlagGlonass;
     379  QDateTime datTim = currentDateAndTimeGPS();
     380
     381  QString hlpStr = bncRinex::nextEpochStr(datTim,
     382                       settings.value("ephIntr").toString(), _rinexVers);
     383
     384  QString ephFileNameGPS = _ephPath + base;
     385
     386  if (_rinexVers > 2) {
     387    ephFileNameGPS += "_S_" +     // stream
     388                      QString("%1").arg(datTim.date().year()) +
     389                      QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
     390                      hlpStr +   // HM_period
     391                      "_MN" +    // mixed BRDC
     392                      distStr + ".rnx";
     393  }
     394  else { // RNX v2.11
     395    ephFileNameGPS += QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
     396                      hlpStr + distStr + datTim.toString(".yyN");
     397  }
     398
     399  if (ephFile->_name == ephFileNameGPS) {
     400    return ephFile;
     401  }
     402  ephFile->_name = ephFileNameGPS;
     403  ephFile->close();
     404
     405  QFlags<QIODevice::OpenModeFlag> appendFlagGPS;
     406  QFlags<QIODevice::OpenModeFlag> appendFlagGlonass;
     407
     408  if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
     409       QFile::exists(ephFileNameGPS) ) {
     410    appendFlagGPS = QIODevice::Append;
     411  }
     412
     413  ephFile->_fileN = new QFile(ephFileNameGPS);
     414  ephFile->_fileN->open(QIODevice::WriteOnly | appendFlagGPS);
     415  ephFile->_streamN = new QTextStream();
     416  ephFile->_streamN->setDevice(ephFile->_fileN);
     417  QTextStream* streamGPS = ephFile->_streamN;
     418
     419  if (_rinexVers == 2) {
     420    QString ephFileNameGlonass = _ephPath + base +
     421        QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
     422        hlpStr + distStr + datTim.toString(".yyG");
    364423
    365424    if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
    366          QFile::exists(ephFileNameGPS) ) {
    367       appendFlagGPS = QIODevice::Append;
    368     }
    369 
    370     _ephFileGPS = new QFile(ephFileNameGPS);
    371     _ephFileGPS->open(QIODevice::WriteOnly | appendFlagGPS);
    372     _ephStreamGPS = new QTextStream();
    373     _ephStreamGPS->setDevice(_ephFileGPS);
    374 
    375     if      (_rinexVers > 2) {
    376       _ephFileGlonass   = _ephFileGPS;
    377       _ephStreamGlonass = _ephStreamGPS;
    378       _ephFileGalileo   = _ephFileGPS;
    379       _ephStreamGalileo = _ephStreamGPS;
    380       _ephFileSBAS      = _ephFileGPS;
    381       _ephStreamSBAS    = _ephStreamGPS;
    382     }
    383     else {
    384       QString ephFileNameGlonass = _ephPath + "BRDC" +
    385           QString("%1").arg(datTim.date().dayOfYear(), 3, 10, QChar('0')) +
    386           hlpStr + datTim.toString(".yyG");
    387 
    388       delete _ephStreamGlonass;
    389       delete _ephFileGlonass;
    390 
    391       if ( Qt::CheckState(settings.value("rnxAppend").toInt()) == Qt::Checked &&
    392            QFile::exists(ephFileNameGlonass) ) {
    393         appendFlagGlonass = QIODevice::Append;
    394       }
    395 
    396       _ephFileGlonass = new QFile(ephFileNameGlonass);
    397       _ephFileGlonass->open(QIODevice::WriteOnly | appendFlagGlonass);
    398       _ephStreamGlonass = new QTextStream();
    399       _ephStreamGlonass->setDevice(_ephFileGlonass);
    400     }
    401 
    402     // Header - RINEX Version 3
    403     // ------------------------
    404     if (_rinexVers > 2) {
    405       if ( ! (appendFlagGPS & QIODevice::Append)) {
    406         double rinexVersion = defaultRnxNavVersion4;
    407         if (_rinexVers < 4.0) {
    408           rinexVersion = defaultRnxNavVersion3;
    409         }
    410         QString line = QString().asprintf("%9.2f%11sN: GNSS NAV DATA    M: Mixed%12sRINEX VERSION / TYPE\n",
    411             rinexVersion, "", "");
    412         *_ephStreamGPS << line;
    413         line.clear();
    414 
    415         QString hlp = currentDateAndTimeGPS().toString("yyyyMMdd hhmmss UTC").leftJustified(20, ' ', true);
    416         *_ephStreamGPS << _pgmName.toLatin1().data()
    417                        << _userName.toLatin1().data()
    418                        << hlp.toLatin1().data()
    419                        << "PGM / RUN BY / DATE\n";
    420 
    421         QStringListIterator it(comments);
    422         while (it.hasNext()) {
    423           *_ephStreamGPS << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
    424         }
    425 
    426         if (_rinexVers == 4) {
    427           int leapSecs = gnumleap(datTim.date().year(), datTim.date().month(), datTim.date().day());
    428           *_ephStreamGPS << QString("%1").arg(leapSecs, 6, 10, QLatin1Char(' ')).left(60).leftJustified(60)
    429                   << "LEAP SECONDS\n";
    430         }
    431 
    432         line = QString().asprintf("%60sEND OF HEADER\n", "");
    433         *_ephStreamGPS << line;
    434 
    435         _ephStreamGPS->flush();
    436       }
    437     }
    438 
    439     // Headers - RINEX Version 2
    440     // -------------------------
    441     else {
    442       if (! (appendFlagGPS & QIODevice::Append)) {
    443         QString line = QString().asprintf("%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n",
    444                      defaultRnxNavVersion2, "", "");
    445         *_ephStreamGPS << line;
    446         line.clear();
    447 
    448         QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
    449         *_ephStreamGPS << _pgmName.toLatin1().data()
    450                        << _userName.toLatin1().data()
    451                        << hlp.toLatin1().data()
    452                        << "PGM / RUN BY / DATE\n";
    453 
    454         QStringListIterator it(comments);
    455         while (it.hasNext()) {
    456           *_ephStreamGPS << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
    457         }
    458 
    459         line = QString().asprintf("%60sEND OF HEADER\n", "");
    460         *_ephStreamGPS << line;
    461 
    462         _ephStreamGPS->flush();
    463       }
    464       if (! (appendFlagGlonass & QIODevice::Append)) {
    465         QString line = QString().asprintf("%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n",
    466                      defaultRnxNavVersion2, "", "");
    467         *_ephStreamGlonass << line;
    468         line.clear();
    469 
    470         QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
    471         *_ephStreamGlonass << _pgmName.toLatin1().data()
    472                            << _userName.toLatin1().data()
    473                            << hlp.toLatin1().data()
    474                            << "PGM / RUN BY / DATE\n";
    475 
    476         QStringListIterator it(comments);
    477         while (it.hasNext()) {
    478           *_ephStreamGlonass << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
    479         }
    480 
    481         line = QString().asprintf("%60sEND OF HEADER\n", "");
    482         *_ephStreamGlonass << line;
    483 
    484         _ephStreamGlonass->flush();
    485       }
    486     }
    487   }
     425         QFile::exists(ephFileNameGlonass) ) {
     426      appendFlagGlonass = QIODevice::Append;
     427    }
     428
     429    ephFile->_fileG = new QFile(ephFileNameGlonass);
     430    ephFile->_fileG->open(QIODevice::WriteOnly | appendFlagGlonass);
     431    ephFile->_streamG = new QTextStream();
     432    ephFile->_streamG->setDevice(ephFile->_fileG);
     433  }
     434  QTextStream* streamGlonass = ephFile->_streamG;
     435
     436  // Header - RINEX Version 3
     437  // ------------------------
     438  if (_rinexVers > 2) {
     439    if ( ! (appendFlagGPS & QIODevice::Append)) {
     440      double rinexVersion = defaultRnxNavVersion4;
     441      if (_rinexVers < 4.0) {
     442        rinexVersion = defaultRnxNavVersion3;
     443      }
     444      QString line = QString().asprintf("%9.2f%11sN: GNSS NAV DATA    M: Mixed%12sRINEX VERSION / TYPE\n",
     445          rinexVersion, "", "");
     446      *streamGPS << line;
     447      line.clear();
     448
     449      QString hlp = currentDateAndTimeGPS().toString("yyyyMMdd hhmmss UTC").leftJustified(20, ' ', true);
     450      *streamGPS << _pgmName.toLatin1().data()
     451                 << _userName.toLatin1().data()
     452                 << hlp.toLatin1().data()
     453                 << "PGM / RUN BY / DATE\n";
     454
     455      QStringListIterator it(comments);
     456      while (it.hasNext()) {
     457        *streamGPS << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
     458      }
     459
     460      if (_rinexVers == 4) {
     461        int leapSecs = gnumleap(datTim.date().year(), datTim.date().month(), datTim.date().day());
     462        *streamGPS << QString("%1").arg(leapSecs, 6, 10, QLatin1Char(' ')).left(60).leftJustified(60)
     463                   << "LEAP SECONDS\n";
     464      }
     465
     466      line = QString().asprintf("%60sEND OF HEADER\n", "");
     467      *streamGPS << line;
     468
     469      streamGPS->flush();
     470    }
     471  }
     472
     473  // Headers - RINEX Version 2
     474  // -------------------------
     475  else {
     476    if (! (appendFlagGPS & QIODevice::Append)) {
     477      QString line = QString().asprintf("%9.2f%11sN: GPS NAV DATA%25sRINEX VERSION / TYPE\n",
     478                   defaultRnxNavVersion2, "", "");
     479      *streamGPS << line;
     480      line.clear();
     481
     482      QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
     483      *streamGPS << _pgmName.toLatin1().data()
     484                 << _userName.toLatin1().data()
     485                 << hlp.toLatin1().data()
     486                 << "PGM / RUN BY / DATE\n";
     487
     488      QStringListIterator it(comments);
     489      while (it.hasNext()) {
     490        *streamGPS << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
     491      }
     492
     493      line = QString().asprintf("%60sEND OF HEADER\n", "");
     494      *streamGPS << line;
     495
     496      streamGPS->flush();
     497    }
     498    if (! (appendFlagGlonass & QIODevice::Append)) {
     499      QString line = QString().asprintf("%9.2f%11sG: GLONASS NAV DATA%21sRINEX VERSION / TYPE\n",
     500                   defaultRnxNavVersion2, "", "");
     501      *streamGlonass << line;
     502      line.clear();
     503
     504      QString hlp = currentDateAndTimeGPS().date().toString("dd-MMM-yyyy").leftJustified(20, ' ', true);
     505      *streamGlonass << _pgmName.toLatin1().data()
     506                     << _userName.toLatin1().data()
     507                     << hlp.toLatin1().data()
     508                     << "PGM / RUN BY / DATE\n";
     509
     510      QStringListIterator it(comments);
     511      while (it.hasNext()) {
     512        *streamGlonass << it.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
     513      }
     514
     515      line = QString().asprintf("%60sEND OF HEADER\n", "");
     516      *streamGlonass << line;
     517
     518      streamGlonass->flush();
     519    }
     520  }
     521
     522  return ephFile;
    488523}
    489524
    490525// Print One Ephemeris
    491526////////////////////////////////////////////////////////////////////////////
    492 void t_bncCore::printEph(const t_eph& eph, bool printFile) {
     527void t_bncCore::printEph(t_ephFile* ephFile, const t_eph& eph, bool printFile) {
    493528
    494529  QString strV2 = eph.toString(defaultRnxNavVersion2);
    … …  
    496531  QString strV4 = eph.toString(defaultRnxNavVersion4);
    497532
     533  QTextStream* streamN = ephFile ? ephFile->_streamN : 0;
     534  QTextStream* streamG = ephFile ? ephFile->_streamG : 0;
     535
    498536  if      (_rinexVers == 2 && eph.system() == t_eph::GLONASS) {
    499     printOutputEph(printFile, _ephStreamGlonass, strV2, strV3, strV4);
     537    printOutputEph(printFile, streamG, strV2, strV3, strV4);
    500538  }
    501539  else if (_rinexVers == 2 && eph.system() == t_eph::GPS) {
    502     printOutputEph(printFile, _ephStreamGPS, strV2, strV3, strV4);
     540    printOutputEph(printFile, streamN, strV2, strV3, strV4);
    503541  }
    504542  else if (_rinexVers >= 3) {
    505     printOutputEph(printFile, _ephStreamGPS, strV2, strV3, strV4);
     543    printOutputEph(printFile, streamN, strV2, strV3, strV4);
    506544  }
    507545}
  • trunk/BNC/src/bnccore.h

    r11066 r11136  
    132132
    133133 private:
     134  // RINEX navigation file(s): one file, or one per stream (ephFilePerStation)
     135  class t_ephFile {
     136   public:
     137    t_ephFile() : _fileN(0), _streamN(0), _fileG(0), _streamG(0), _ephUser(0) {}
     138    ~t_ephFile();
     139    void close();
     140    QString      _name;     // current file name (RINEX 2: GPS file)
     141    QFile*       _fileN;    // mixed (RINEX 3/4) or GPS (RINEX 2)
     142    QTextStream* _streamN;
     143    QFile*       _fileG;    // GLONASS (RINEX 2 only)
     144    QTextStream* _streamG;
     145    bncEphUser*  _ephUser;  // file per stream: ephemerides of this stream only
     146  };
     147
    134148  t_irc checkPrintEph(t_eph* eph);
    135   void  printEphHeader(QString receptStaID);
    136   void  printEph(const t_eph& eph, bool printFile);
     149  t_ephFile* printEphHeader(QString receptStaID);
     150  QString ephFileNameBase(const QString& staID, const QString& country) const;
     151  void  printEph(t_ephFile* ephFile, const t_eph& eph, bool printFile);
    137152  void  printOutputEph(bool printFile, QTextStream* stream,
    138153                       const QString& strV2, const QString& strV3,
    … …  
    147162  QMutex                 _mutexMessage;
    148163  QString                _ephPath;
    149   QString                _ephFileNameGPS;
    150164  int                    _rinexVers;
    151   QFile*                 _ephFileGPS;
    152   QTextStream*           _ephStreamGPS;
    153   QFile*                 _ephFileGlonass;
    154   QTextStream*           _ephStreamGlonass;
    155   QFile*                 _ephFileGalileo;
    156   QTextStream*           _ephStreamGalileo;
    157   QFile*                 _ephFileSBAS;
    158   QTextStream*           _ephStreamSBAS;
     165  bool                   _ephFilePerStation;
     166  QMap<QString, t_ephFile*> _ephFiles;  // key: staID, "" for the single file
    159167  QString                _userName;
    160168  QString                _pgmName;
  • trunk/BNC/src/bnchelp.html

    r11134 r11136  
    129129    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.5.3 <a href="#ephport">Port</a><br>
    130130    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.5.4 <a href="#ephvers">Version</a><br>
     131    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.5.5 <a href="#ephperstream">File per Stream</a><br>
    131132    &nbsp; &nbsp; &nbsp; 2.6 <a href="#reqc"><b>RINEX Editing & QC</b></a><br>
    132133    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.6.1 <a href="#reqcact">Action</a><br>
    … …  
    189190      Stream</a><br>
    190191    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.7 <a href=#pppionofile>Ionosphere File</a><br>
    191     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.8 <a href=#ppprnxobs>RINEX Observation
     192    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.8 <a href=#pppephstream>Ephemeris Stream</a><br>
     193    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.9 <a href=#ppprnxobs>RINEX Observation
    192194      File</a><br>
    193     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.9 <a href=#ppprnxnav>RINEX Navigation
     195    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.10 <a href=#ppprnxnav>RINEX Navigation
    194196      File</a><br>
    195     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.10 <a href=#pppantexfile>ANTEX File</a><br>
    196     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.11 <a href=#pppmarkcoor>Coordinates
     197    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.11 <a href=#pppantexfile>ANTEX File</a><br>
     198    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.12 <a href=#pppmarkcoor>Coordinates
    197199      File</a><br>
    198     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.12 <a href=#pppblqfile>BLQ File</a><br>
    199     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.13 <a href=#ppplogfile>Logfile Directory and
     200    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.13 <a href=#pppblqfile>BLQ File</a><br>
     201    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.14 <a href=#ppplogfile>Logfile Directory and
    200202      Log mode</a><br>
    201     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.14 <a href=#pppnmeafile>NMEA Directory</a><br>
    202     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15 <a href=#pppsnxtrofile>SNX TRO
     203    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15 <a href=#pppnmeafile>NMEA Directory</a><br>
     204    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.16 <a href=#pppsnxtrofile>SNX TRO
    203205      Directory</a><br>
    204     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15.1 <a
     206    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.16.1 <a
    205207      href=#pppsnxtrointr>Interval</a><br>
    206     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15.2 <a
     208    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.16.2 <a
    207209      href=#pppsnxtrosampl>Sampling</a><br>
    208     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15.3 <a href=#pppsnxAc>Analysis
     210    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.16.3 <a href=#pppsnxAc>Analysis
    209211      Center</a><br>
    210     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.15.4 <a href=#pppsnxSol>Solution
     212    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.1.16.4 <a href=#pppsnxSol>Solution
    211213      ID</a><br>
    212214    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.13.2 <a href=#pppOptions><b>PPP (2): Processing Options</b></a><br>
    … …  
    34953497    Note that the here choosen Version concerns the Broadcast Ephemeris output through IP port as well.
    34963498  </p>
     3499  <p>
     3500  <h4 id="ephperstream">2.5.5 File per Stream - optional</h4>
     3501  </p>
     3502  <p>
     3503    By default, the Broadcast Ephemeris of all streams are saved in one RINEX Navigation file (BRDC). Each ephemeris is
     3504    saved only once, from the stream which first provided it, so the file does not show which stream an ephemeris
     3505    came from.
     3506  </p>
     3507  <p>
     3508    Tick 'File per stream' to save one RINEX Navigation file per stream instead. The files are named after the
     3509    stream like the RINEX Observation files, e.g. 'BCEP00BKG_S_20262730000_01D_MN.rnx' for stream 'BCEP00BKG0' (RINEX
     3510    Version 3 or 4) or 'BCEP2730.26N' (RINEX Version 2). If two streams would get the same file name, the complete
     3511    stream name is appended. Each file contains all ephemerides received from its stream, independent of the
     3512    other streams, and its header contains the source of this stream only. This allows to check the Broadcast
     3513    Ephemeris of a stream, e.g. of an ephemeris stream like 'BCEP00BKG0' compared to those contained in
     3514    observation streams.
     3515  </p>
     3516  <p>
     3517    The output through IP port is not affected by this option.
     3518  </p>
    34973519
    34983520  <p>
    … …  
    63936415  </p>
    63946416  <p>
    6395   <h4 id="ppprnxobs">2.13.1.8 RINEX Observation File - mandatory if 'Data source' is set to 'RINEX Files'</h4>
     6417  <h4 id="pppephstream">2.13.1.8 Ephemeris Stream - optional if 'Data source' is set to 'Real-Time Streams'</h4>
     6418  </p>
     6419  <p>
     6420    By default, real-time PPP uses the Broadcast Ephemeris of all streams you are pulling, including those contained
     6421    in the observation streams. Specify one or more 'mountpoints' (separated by comma) from the list of selected
     6422    'Streams' to use the Broadcast Ephemeris of these streams only, e.g. 'BCEP00BKG0'. Ephemerides of all other
     6423    streams, the observation streams included, are then not used in PPP.
     6424  </p>
     6425  <p>
     6426    Note that the ephemerides of the selected stream must match the IODs of the corrections stream. If you do not
     6427    specify an 'Ephemeris stream' via this option, BNC will use the Broadcast Ephemeris of all streams.
     6428  </p>
     6429  <p>
     6430  <h4 id="ppprnxobs">2.13.1.9 RINEX Observation File - mandatory if 'Data source' is set to 'RINEX Files'</h4>
    63966431  </p>
    63976432  <p>
    … …  
    63996434  </p>
    64006435  <p>
    6401   <h4 id="ppprnxnav">2.13.1.9 RINEX Navigation File - mandatory if 'Data source' is set to 'RINEX Files'</h4>
     6436  <h4 id="ppprnxnav">2.13.1.10 RINEX Navigation File - mandatory if 'Data source' is set to 'RINEX Files'</h4>
    64026437  </p>
    64036438  <p>
    … …  
    64056440  </p>
    64066441  <p>
    6407   <h4 id="pppantexfile">2.13.1.10 ANTEX File - optional</h4>
     6442  <h4 id="pppantexfile">2.13.1.11 ANTEX File - optional</h4>
    64086443  </p>
    64096444  <p>
    … …  
    64656500  </p>
    64666501  <p>
    6467   <h4 id="pppmarkcoor">2.13.1.11 Coordinates File - optional </h4>
     6502  <h4 id="pppmarkcoor">2.13.1.12 Coordinates File - optional </h4>
    64686503  </p>
    64696504  <p>
    … …  
    66116646
    66126647  <p>
    6613   <h4 id="pppblqfile">2.13.1.12 BLQ File - optional </h4>
     6648  <h4 id="pppblqfile">2.13.1.13 BLQ File - optional </h4>
    66146649  </p>
    66156650  <p>
    … …  
    66236658
    66246659  <p>
    6625   <h4 id="ppplogfile">2.13.1.13 Logfile Directory and Log mode - optional</h4>
     6660  <h4 id="ppplogfile">2.13.1.14 Logfile Directory and Log mode - optional</h4>
    66266661  </p>
    66276662  <p>
    … …  
    70597094
    70607095  <p>
    7061   <h4 id="pppnmeafile">2.13.1.14 NMEA Directory - optional</h4>
     7096  <h4 id="pppnmeafile">2.13.1.15 NMEA Directory - optional</h4>
    70627097  </p>
    70637098  <p>
    … …  
    71067141
    71077142  <p>
    7108   <h4 id="pppsnxtrofile">2.13.1.15 SNX TRO Directory - optional</h4>
     7143  <h4 id="pppsnxtrofile">2.13.1.16 SNX TRO Directory - optional</h4>
    71097144  </p>
    71107145  <p>
    … …  
    72637298
    72647299  <p>
    7265   <h4 id="pppsnxtrointr">2.13.1.15.1 Interval - mandatory if 'SINEX TRO Directory' is set</h4>
     7300  <h4 id="pppsnxtrointr">2.13.1.16.1 Interval - mandatory if 'SINEX TRO Directory' is set</h4>
    72667301  </p>
    72677302  <p>
    … …  
    72727307  </p>
    72737308  <p>
    7274   <h4 id="pppsnxtrosampl">2.13.1.15.2 Sampling - mandatory if 'SINEX TRO Directory' is set</h4>
     7309  <h4 id="pppsnxtrosampl">2.13.1.16.2 Sampling - mandatory if 'SINEX TRO Directory' is set</h4>
    72757310  </p>
    72767311  <p>
    … …  
    72827317
    72837318  <p>
    7284   <h4 id="pppsnxAc">2.13.1.15.3 Analysis Center - Mandatory if 'SINEX TRO Directory' is set</h4>
     7319  <h4 id="pppsnxAc">2.13.1.16.3 Analysis Center - Mandatory if 'SINEX TRO Directory' is set</h4>
    72857320  </p>
    72867321  <p>
    … …  
    72907325
    72917326  <p>
    7292   <h4 id="pppsnxSol">2.13.1.15.4 Solution ID - Mandatory if 'SINEX TRO Directory' is set</h4>
     7327  <h4 id="pppsnxSol">2.13.1.16.4 Solution ID - Mandatory if 'SINEX TRO Directory' is set</h4>
    72937328  </p>
    72947329  <p>
    … …  
    1096210997   ephOutPort     {Output port [integer number]}
    1096310998   ephVersion     {Specifies the RINEX version of the file contents [integer number: 2|3|4]}
     10999   ephFilePerStation {One RINEX navigation file per stream [integer number: 0=no,2=yes]}
    1096411000
    1096511001RINEX Editing and QC Panel keys:
    … …  
    1105811094   PPP/ionoMount     {VTEC mountpoint, [char string]}
    1105911095   PPP/ionoFile      {VTEC file, full path [char string]}
     11096   PPP/ephMount      {Broadcast Ephemeris mountpoint(s), comma separated [char string]}
    1106011097   PPP/nmeaPath      {Directory for NMEA output files [character string]}
    1106111098   PPP/snxtroPath    {Directory for SINEX troposphere output files [character string]}
  • trunk/BNC/src/bncmain.cpp

    r11130 r11136  
    161161        "   ephOutPort     {Output port [integer number]}\n"
    162162        "   ephVersion     {Specifies the RINEX version of the file contents [integer number: 2|3|4]}\n"
     163        "   ephFilePerStation {One RINEX navigation file per stream [integer number: 0=no,2=yes]}\n"
    163164        "\n"
    164165        "RINEX Editing and QC Panel keys:\n"
    … …  
    263264        "   PPP/ionoMount     {VTEC mountpoint, [char string]}\n"
    264265        "   PPP/ionoFile      {VTEC file, full path [char string]}\n"
     266        "   PPP/ephMount      {Broadcast Ephemeris mountpoint(s), comma separated [char string]}\n"
    265267        "   PPP/nmeaPath      {Directory for NMEA output files [character string]}\n"
    266268        "   PPP/snxtroPath    {Directory for SINEX troposphere output files [character string]}\n"
  • trunk/BNC/src/bncsettings.cpp

    r11129 r11136  
    9696        setValue_p("ephOutPort", "");
    9797        setValue_p("ephVersion", "3");
     98        setValue_p("ephFilePerStation", "0");
    9899        // Reqc
    99100        setValue_p("reqcAction", "");
  • trunk/BNC/src/bncwindow.cpp

    r11129 r11136  
    278278    _ephVersComboBox->setCurrentIndex(jk);
    279279  }
    280   //_ephFilePerStation = new QCheckBox();
    281   //_ephFilePerStation->setCheckState(Qt::CheckState(settings.value("ephFilePerStation").toInt()));
     280  _ephFilePerStation = new QCheckBox();
     281  _ephFilePerStation->setCheckState(Qt::CheckState(settings.value("ephFilePerStation").toInt()));
    282282
    283283  connect(_ephOutPortLineEdit, SIGNAL(textChanged(const QString&)),
    … …  
    902902  eLayout->addWidget(new QLabel("Version"), 4, 0);
    903903  eLayout->addWidget(_ephVersComboBox, 4, 1);
    904   eLayout->setRowStretch(5, 999);
    905   //eLayout->addWidget(new QLabel("File per Station"),              5, 0);
    906   //eLayout->addWidget(_ephFilePerStation,                          5, 1);
    907   //eLayout->setRowStretch(6, 999);
     904  eLayout->addWidget(new QLabel("File per stream"), 5, 0);
     905  eLayout->addWidget(_ephFilePerStation, 5, 1);
     906  eLayout->setRowStretch(6, 999);
    908907
    909908  egroup->setLayout(eLayout);
    … …  
    10661065  _pppWidgets._snxtroCampId->setMaximumWidth(7 * ww);
    10671066  _pppWidgets._ionoMount->setMaximumWidth(15 * ww);
     1067  _pppWidgets._ephMount->setMaximumWidth(15 * ww);
    10681068
    10691069
    … …  
    11001100  pppLayout1->addWidget(new QLabel("   SNX TRO sampling"), ir, 6);
    11011101  pppLayout1->addWidget(_pppWidgets._snxtroSampl, ir, 7, Qt::AlignRight);
     1102  ++ir;
     1103  pppLayout1->addWidget(new QLabel("Ephemeris stream"), ir, 0);
     1104  pppLayout1->addWidget(_pppWidgets._ephMount, ir, 1);
    11021105  ++ir;
    11031106  pppLayout1->addWidget(new QLabel("RINEX Obs file"), ir, 0);
    … …  
    15801583  _ephOutPortLineEdit->setWhatsThis(tr("<p>BNC can produce ephemeris data in RINEX Navigation ASCII format on your local host through an IP port.</p><p>Specify a port number here to activate this function. <i>[key: ephOutPort]</i></p>"));
    15811584  _ephVersComboBox->setWhatsThis(tr("<p>Select the format for RINEX Navigation files. <i>[key: ephVersion]</i></p>"));
    1582   //_ephFilePerStation->setWhatsThis(tr("<p>By default, all received Broadcast Ephemeris data will be stored within one File. Thick 'File per Stations' to get separate files per station/mountpoint. <i>[key: ephFilePerStation]</i></p>"));
     1585  _ephFilePerStation->setWhatsThis(tr("<p>By default, the Broadcast Ephemeris of all streams are saved in one RINEX Navigation file, each ephemeris once, from the stream which first provided it.</p><p>Tick 'File per stream' to save one file per stream instead, named after the stream like the RINEX Observation files (e.g. BCEP00BKG_S_... for stream BCEP00BKG0). Each file then contains all ephemerides received from its stream. The output through the IP port is not affected. <i>[key: ephFilePerStation]</i></p>"));
    15831586
    15841587  // WhatsThis, RINEX Editing & QC
    … …  
    16621665  _pppWidgets._biasMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides satellite biases in SSR format.</p><p>If you don't specify a corrections stream via this option, BNC will use satellite biases from the Corrections stream 'mountpoint', if available. <i>[key: PPP/biasMount]</i></p>"));
    16631666  _pppWidgets._ionoMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides VTEC informations in SSR format.</p><p>If you don't specify a corrections stream via this option, BNC will use VTEC informations from the Corrections stream 'mountpoint', if available. <i>[key: PPP/ionoMount]</i></p>"));
     1667  _pppWidgets._ephMount->setWhatsThis(tr("<p>Specify a 'mountpoint' from the 'Streams' canvas below which provides the Broadcast Ephemeris for PPP, e.g. 'BCEP00BKG0'. Several mountpoints can be given, separated by comma.</p><p>Ephemerides of all other streams, also those contained in the observation streams, are then not used in PPP. If you don't specify an ephemeris stream via this option, BNC will use the Broadcast Ephemeris of all streams. <i>[key: PPP/ephMount]</i></p>"));
    16641668  _pppWidgets._corrFile->setWhatsThis(tr("<p>Specify the Broadcast Ephemeris Corrections file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will fall back to Single Point Positioning (SPP, positioning from RINEX Obs and RINEX Nav files only) instead of doing PPP. <i>[key: PPP/corrFile]</i></p>"));
    16651669  _pppWidgets._biasFile->setWhatsThis(tr("<p>Specify the satellite bias file as saved beforehand using BNC.</p><p>If you don't specify corrections by this option, BNC will use satellite biases from the Corrections file, if available. <i>[key: PPP/biasFile]</i></p>"));
    … …  
    18811885  delete _rnxV2Priority;
    18821886  delete _ephPathLineEdit;
    1883   //delete _ephFilePerStation;
     1887  delete _ephFilePerStation;
    18841888  delete _ephIntrComboBox;
    18851889  delete _ephOutPortLineEdit;
    … …  
    24162420  settings.setValue("ephOutPort", _ephOutPortLineEdit->text());
    24172421  settings.setValue("ephVersion", _ephVersComboBox->currentText());
    2418   //settings.setValue("ephFilePerStation", _ephFilePerStation->checkState());
     2422  settings.setValue("ephFilePerStation", _ephFilePerStation->checkState());
    24192423  // Broadcast Corrections
    24202424  settings.setValue("corrPath", _corrPathLineEdit->text());
    … …  
    29512955    enableWidget(enable, _ephIntrComboBox);
    29522956    enableWidget(enable, _ephVersComboBox);
    2953     //enableWidget(enable, _ephVersComboBox);
    2954     //enableWidget(enable, _ephFilePerStation);
     2957    enableWidget(!_ephPathLineEdit->text().isEmpty(), _ephFilePerStation);
    29552958  }
    29562959
  • trunk/BNC/src/bncwindow.h

    r11129 r11136  
    179179    QLineEdit* _rnxV2Priority;
    180180    QComboBox* _ephVersComboBox;
    181     //QCheckBox* _ephFilePerStation;
     181    QCheckBox* _ephFilePerStation;
    182182    QCheckBox* _rnxFileCheckBox;
    183183    QLineEdit* _rnxScrpLineEdit;
  • trunk/BNC/src/pppMain.cpp

    r11079 r11136  
    217217      opt->_biasMount.assign(settings.value("PPP/biasMount").toString().toStdString());
    218218      opt->_ionoMount.assign(settings.value("PPP/ionoMount").toString().toStdString());
     219      opt->_ephMount.assign(settings.value("PPP/ephMount").toString().toStdString());
    219220    }
    220221    else {
  • trunk/BNC/src/pppOptions.h

    r11019 r11136  
    6666  std::string                   _biasMount;
    6767  std::string                   _ionoMount;
     68  std::string                   _ephMount;
    6869  bool                          _isAPC;
    6970  std::string                   _rinexObs;
  • trunk/BNC/src/pppRun.cpp

    r11047 r11136  
    8282
    8383  if (_opt->_realTime) {
     84    _ephMounts = QString::fromStdString(_opt->_ephMount).split(QRegularExpression("[,\\s]+"),
     85                                                                Qt::SkipEmptyParts);
     86    if (!_ephMounts.isEmpty()) {
     87      emit newMessage(QByteArray(_opt->_roverName.c_str()) + ": PPP uses the ephemerides of "
     88                      + _ephMounts.join(", ").toLatin1() + " only", true);
     89    }
     90
    8491    Qt::ConnectionType conType = Qt::AutoConnection;
    8592    if (BNC_CORE->mode() == t_bncCore::batchPostProcessing) {
    … …  
    248255}
    249256
     257// Ephemeris from a stream selected for PPP (PPP/ephMount)?
     258////////////////////////////////////////////////////////////////////////////
     259bool t_pppRun::useEph(const t_eph& eph) const {
     260  return _ephMounts.isEmpty() || _ephMounts.contains(eph.receptStaID());
     261}
     262
    250263//
    251264////////////////////////////////////////////////////////////////////////////
    252265void t_pppRun::slotNewGPSEph(t_ephGPS eph) {
     266  if (!useEph(eph)) {
     267    return;
     268  }
    253269  QMutexLocker locker(&_mutex);
    254270  _pppClient->putEphemeris(&eph);
    … …  
    258274////////////////////////////////////////////////////////////////////////////
    259275void t_pppRun::slotNewGlonassEph(t_ephGlo eph) {
     276  if (!useEph(eph)) {
     277    return;
     278  }
    260279  QMutexLocker locker(&_mutex);
    261280  _pppClient->putEphemeris(&eph);
    … …  
    265284////////////////////////////////////////////////////////////////////////////
    266285void t_pppRun::slotNewGalileoEph(t_ephGal eph) {
     286  if (!useEph(eph)) {
     287    return;
     288  }
    267289  QMutexLocker locker(&_mutex);
    268290  _pppClient->putEphemeris(&eph);
    … …  
    272294////////////////////////////////////////////////////////////////////////////
    273295void t_pppRun::slotNewBDSEph(t_ephBDS eph) {
     296  if (!useEph(eph)) {
     297    return;
     298  }
    274299  QMutexLocker locker(&_mutex);
    275300  _pppClient->putEphemeris(&eph);
  • trunk/BNC/src/pppRun.h

    r11041 r11136  
    6565  };
    6666
     67  bool useEph(const t_eph& eph) const;
     68
    6769  QMutex                 _mutex;
    6870  const t_pppOptions*    _opt;
     71  QStringList            _ephMounts;  // empty: ephemerides of all streams
    6972  t_pppClient*           _pppClient;
    7073  std::deque<t_epoData*> _epoData;
  • trunk/BNC/src/pppWidgets.cpp

    r11022 r11136  
    6767  _biasMount    = new QLineEdit();     _biasMount   ->setObjectName("PPP/biasMount");    _widgets << _biasMount;
    6868  _ionoMount    = new QLineEdit();     _ionoMount   ->setObjectName("PPP/ionoMount");    _widgets << _ionoMount;
     69  _ephMount     = new QLineEdit();     _ephMount    ->setObjectName("PPP/ephMount");     _widgets << _ephMount;
    6970  _corrFile     = new qtFileChooser(); _corrFile    ->setObjectName("PPP/corrFile");     _widgets << _corrFile;
    7071  _biasFile     = new qtFileChooser(); _biasFile    ->setObjectName("PPP/biasFile");     _widgets << _biasFile;
    … …  
    395396    _biasMount    ->setEnabled(false);
    396397    _ionoMount    ->setEnabled(false);
     398    _ephMount     ->setEnabled(false);
    397399    _audioResponse->setEnabled(false);
    398400  }
  • trunk/BNC/src/pppWidgets.h

    r11022 r11136  
    5151  QLineEdit*     _biasMount;
    5252  QLineEdit*     _ionoMount;
     53  QLineEdit*     _ephMount;
    5354  qtFileChooser* _corrFile;
    5455  qtFileChooser* _biasFile;
  • trunk/BNC/tests/README.md

    r11130 r11136  
    5252  `replay_rinex_eph` (02), `replay_feed_engine` (07, IP port disabled) and
    5353  `replay_save_sp3` (14, with SSRA00CNE1 instead of SSRA00BKG1).
     54* `replay_rinex_eph_perstream`: 02 with 'File per stream' on `data/eph_perstream_260930_4min.raw`
     55  (ephemeris messages of BCEP00BKG0, SSRA00EUH0, FFMJ00DEU0, WTZR00DEU0 cut from the
     56  merged capture): one RINEX 4 navigation file per stream.
    5457* `replay_save_sp3_has`: 14 with Galileo HAS (SSRA00EUH0) only; its epochs are
    5558  off the SP3/CLK sampling grid and are written at the preceding grid epoch.
Note: See TracChangeset for help on using the changeset viewer.