Index: /trunk/BNC/CHANGELOG.md
===================================================================
--- /trunk/BNC/CHANGELOG.md	(revision 11122)
+++ /trunk/BNC/CHANGELOG.md	(revision 11123)
@@ -19,4 +19,5 @@
 - ADDED: Detection and conversion of outdated or erroneous IGS-SSR epoch time encodings (GLONASS as UTC seconds of day or of week, BDS as BDT) with an hourly warning, and a plausibility check of the orbit/clock epochs of all systems of a stream
 - ADDED: ANTEX file name, number of entries and latest satellite entry are logged; satellites without a valid ANTEX entry are reported (and not combined)
+- 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
 - ADDED: Regression test suite ('tests'): example configurations and short raw captures replayed through BNC and compared with reference outputs
 - ADDED: macOS packaging script
Index: /trunk/BNC/src/PPP/pppClient.cpp
===================================================================
--- /trunk/BNC/src/PPP/pppClient.cpp	(revision 11122)
+++ /trunk/BNC/src/PPP/pppClient.cpp	(revision 11123)
@@ -561,4 +561,12 @@
     }
 
+    // a changed ANTEX file is read and used from its GPS week on
+    if (_antex) {
+      QString msg = _antexReloader.update(_antex, _epoTimeRover);
+      if (!msg.isEmpty()) {
+        LOG << string(_epoTimeRover) << " " << msg.toStdString() << endl;
+      }
+    }
+
     for (int iter = 1; iter <= 2; iter++) {
       ColumnVector xyzc(4); xyzc = 0.0;
Index: /trunk/BNC/src/PPP/pppClient.h
===================================================================
--- /trunk/BNC/src/PPP/pppClient.h	(revision 11122)
+++ /trunk/BNC/src/PPP/pppClient.h	(revision 11123)
@@ -10,5 +10,5 @@
 #include "pppModel.h"
 
-class bncAntex;
+#include "bncantex.h"
 
 namespace BNC_PPP {
@@ -73,4 +73,5 @@
   t_pppStation*             _staRover;
   bncAntex*                 _antex;
+  bncAntexReloader          _antexReloader; // re-reads a changed ANTEX file
   e_ssrFormat               _ssrFormat;  // of the latest orbit corrections
   t_pppFilter*              _filter;
Index: /trunk/BNC/src/bncantex.cpp
===================================================================
--- /trunk/BNC/src/bncantex.cpp	(revision 11122)
+++ /trunk/BNC/src/bncantex.cpp	(revision 11123)
@@ -1110,4 +1110,107 @@
 }
 
+// GPS week of the file from the SINEX code of the satellite entries
+// (e.g. IGS20_2437): the week occurring most often
+////////////////////////////////////////////////////////////////////////////
+int bncAntex::gpsWeek() const {
+  static const QRegularExpression re("_(\\d{4})$");
+  QMap<int, int> count;
+  QMapIterator<QString, QVector<t_antMap*> > it(_satMaps);
+  while (it.hasNext()) {
+    it.next();
+    for (const t_antMap* map : it.value()) {
+      QRegularExpressionMatch mm = re.match(map->snxCode.trimmed());
+      if (mm.hasMatch()) {
+        count[mm.captured(1).toInt()] += 1;
+      }
+    }
+  }
+  int week = 0, num = 0;
+  QMapIterator<int, int> itC(count);
+  while (itC.hasNext()) {
+    itC.next();
+    if (itC.value() > num) {
+      week = itC.key();
+      num  = itC.value();
+    }
+  }
+  return week;
+}
+
+// Take over the attitude model states and warnings of another instance
+////////////////////////////////////////////////////////////////////////////
+void bncAntex::takeStates(const bncAntex& other) {
+  _glonassYaw       = other._glonassYaw;
+  _gpsYaw           = other._gpsYaw;
+  _onYaw            = other._onYaw;
+  _noSatEntryWarned = other._noSatEntryWarned;
+}
+
+// Re-read the ANTEX file while running
+////////////////////////////////////////////////////////////////////////////
+bncAntexReloader::bncAntexReloader() {
+  _fileSize    = 0;
+  _init        = false;
+  _pending     = 0;
+  _pendingWeek = 0;
+}
+
+bncAntexReloader::~bncAntexReloader() {
+  delete _pending;
+}
+
+QString bncAntexReloader::update(bncAntex*& antex, const bncTime& epoch) {
+  if (!antex || antex->fileName().isEmpty()) {
+    return QString();
+  }
+  QString msg;
+  QDateTime now = QDateTime::currentDateTimeUtc();
+  if (!_init) {
+    QFileInfo fi(antex->fileName());
+    _fileTime = fi.lastModified();
+    _fileSize = fi.size();
+    _lastCheck = now;
+    _init = true;
+  }
+
+  // file changed?
+  if (_lastCheck.secsTo(now) >= 60) {
+    _lastCheck = now;
+    QFileInfo fi(antex->fileName());
+    // read only once the file has not changed for 30 s (copy finished)
+    if (fi.exists() && (fi.lastModified() != _fileTime || fi.size() != _fileSize) &&
+        fi.lastModified().secsTo(now) >= 30) {
+      _fileTime = fi.lastModified();
+      _fileSize = fi.size();
+      bncAntex* newAntex = new bncAntex();
+      if (newAntex->readFile(antex->fileName()) != success || newAntex->numSatPrns() == 0) {
+        delete newAntex;
+        msg = "ANTEX file " + antex->fileName() + " changed but could not be read - previous file kept";
+      }
+      else {
+        int week = newAntex->gpsWeek();
+        delete _pending;
+        _pending     = newAntex;
+        _pendingWeek = week;
+        if (epoch.valid() && week > int(epoch.gpsw())) {
+          msg = QString("ANTEX file %1 changed (GPS week %2) - used from GPS week %2 on")
+                .arg(antex->fileName()).arg(week);
+        }
+      }
+    }
+  }
+
+  // pending file due?
+  if (_pending && (!epoch.valid() || _pendingWeek <= int(epoch.gpsw()))) {
+    _pending->takeStates(*antex);
+    delete antex;
+    antex    = _pending;
+    _pending = 0;
+    if (!msg.isEmpty()) msg += "; ";
+    msg += QString("ANTEX file re-read, used from now on (GPS week %1): ").arg(_pendingWeek) + antex->info();
+  }
+  return msg;
+}
+
 // True if a missing satellite antenna entry has to be reported (at most once
 // per hour and PRN)
Index: /trunk/BNC/src/bncantex.h
===================================================================
--- /trunk/BNC/src/bncantex.h	(revision 11122)
+++ /trunk/BNC/src/bncantex.h	(revision 11123)
@@ -52,4 +52,12 @@
   QString satBlockType(const QString& prn, const bncTime& epoch) const;
   QString info() const;
+  // GPS week from which the file is to be used: the week of the SINEX code of
+  // the antenna entries (e.g. IGS20_2437), 0 if not available
+  int     gpsWeek() const;
+  const QString& fileName() const {return _fileName;}
+  int     numSatPrns() const {return _satMaps.size();}
+  // take over the attitude model states and warnings of another (older)
+  // instance, so that a re-read file does not interrupt running turns
+  void    takeStates(const bncAntex& other);
   bool    hasSatEntry(const QString& prn, const bncTime& epoch) const {return satMap(prn, epoch) != 0;}
   bool    warnNoSatEntry(const QString& prn, const bncTime& epoch) const;
@@ -228,3 +236,24 @@
 };
 
+// Re-reads an ANTEX file while BNC is running: a changed file (modification
+// time or size, checked at most once a minute) is read, and used from the
+// GPS week given in the file (SINEX code of its entries) on; a new file of a
+// week not yet reached is kept pending until the processed epochs reach it.
+////////////////////////////////////////////////////////////////////////////
+class bncAntexReloader {
+ public:
+  bncAntexReloader();
+  ~bncAntexReloader();
+  // to be called per processed epoch; replaces antex if a new file is due
+  // and returns a message for the logfile (empty if nothing happened)
+  QString update(bncAntex*& antex, const bncTime& epoch);
+ private:
+  QDateTime _lastCheck;     // wall clock of the last file check
+  QDateTime _fileTime;      // modification time of the file read last
+  qint64    _fileSize;
+  bool      _init;
+  bncAntex* _pending;       // new file of a later GPS week
+  int       _pendingWeek;
+};
+
 #endif
Index: /trunk/BNC/src/bnchelp.html
===================================================================
--- /trunk/BNC/src/bnchelp.html	(revision 11122)
+++ /trunk/BNC/src/bnchelp.html	(revision 11123)
@@ -6399,4 +6399,17 @@
   </p>
   <p>
+    <b>Updated ANTEX file:</b> In real-time PPP, BNC checks once a minute whether the ANTEX file has changed (modification time or size)
+    and reads it again while running, once it has not changed for 30 seconds (copy finished). The new file is used from
+    the GPS week given in it on, i.e. the week of the SINEX code of its entries (e.g. 'IGS20_2437' for the file
+    igs20_2437.atx): if this week has already been reached by the processed epochs, the new file is used from the next
+    epoch on, otherwise it is kept and used from the first epoch of that week. The running attitude model states (e.g.
+    a noon turn) are taken over. A file that cannot be read is reported and the previous one kept. To provide a new
+    ANTEX file, overwrite the file given here (e.g. with a copy of the latest igs20_WWWW.atx), e.g.
+  </p>
+  <pre>
+ANTEX file /home/user/igs20.atx changed (GPS week 2440) - used from GPS week 2440 on
+ANTEX file re-read, used from now on (GPS week 2440): ANTEX file /home/user/igs20.atx: ...
+</pre>
+  <p>
     Whether the orbit corrections refer to the satellite's Antenna Phase Center (APC) or to its Center of Mass (CoM) is
     derived from the name of the correction stream or file: names beginning with 'SSRA' refer to the APC, the combined
@@ -9655,4 +9668,17 @@
     logfile, at most once per hour and satellite.
   </p>
+  <p>
+    <b>Updated ANTEX file:</b> In the combination, BNC checks once a minute whether the ANTEX file has changed (modification time or size)
+    and reads it again while running, once it has not changed for 30 seconds (copy finished). The new file is used from
+    the GPS week given in it on, i.e. the week of the SINEX code of its entries (e.g. 'IGS20_2437' for the file
+    igs20_2437.atx): if this week has already been reached by the processed epochs, the new file is used from the next
+    epoch on, otherwise it is kept and used from the first epoch of that week. The running attitude model states (e.g.
+    a noon turn) are taken over. A file that cannot be read is reported and the previous one kept. To provide a new
+    ANTEX file, overwrite the file given here (e.g. with a copy of the latest igs20_WWWW.atx), e.g.
+  </p>
+  <pre>
+bncComb: ANTEX file /home/user/igs20.atx changed (GPS week 2440) - used from GPS week 2440 on
+bncComb: ANTEX file re-read, used from now on (GPS week 2440): ANTEX file /home/user/igs20.atx: ...
+</pre>
   <p>
     The following screenshot shows the encoding and uploading of several Broadcast Ephemeris correction streams combined
Index: /trunk/BNC/src/combination/bnccomb.cpp
===================================================================
--- /trunk/BNC/src/combination/bnccomb.cpp	(revision 11122)
+++ /trunk/BNC/src/combination/bnccomb.cpp	(revision 11123)
@@ -792,4 +792,12 @@
   QDateTime now = currentDateAndTimeGPS();
   bncTime   currentTime(now.toString(Qt::ISODate).toStdString());
+
+  // a changed ANTEX file is read and used from its GPS week on
+  if (_antex) {
+    QString msg = _antexReloader.update(_antex, epoTime);
+    if (!msg.isEmpty()) {
+      emit newMessage(("bncComb: " + msg).toLatin1(), true);
+    }
+  }
   for (unsigned ii = 0; ii < clkCorrVec.size(); ii++) {
     const t_clkCorr& clkCorr = clkCorrVec[ii];
Index: /trunk/BNC/src/combination/bnccomb.h
===================================================================
--- /trunk/BNC/src/combination/bnccomb.h	(revision 11122)
+++ /trunk/BNC/src/combination/bnccomb.h	(revision 11123)
@@ -21,5 +21,5 @@
 
 class bncRtnetDecoder;
-class bncAntex;
+#include "bncantex.h"
 class bncBiasSnx;
 
@@ -283,4 +283,5 @@
   QByteArray                                 _log;
   bncAntex*                                  _antex;
+  bncAntexReloader                           _antexReloader; // re-reads a changed ANTEX file
   bncBiasSnx*                                _bsx;
   bncoutf*                                   _logFile;
