« ◇顔がかゆい | トップページ | ◇GPS,PPSとインターネット上のNTPサーバの比較 »

◇自動GPS-システム時計強制同期

シリーズ「GPS-NTP」

ー - -

◆Raspi3でGPS-NTPサーバおよび ◇GPS+PPSでNTPサーバを立てるで未解決であった、 システム起動時の強制時刻合わせができるようになりました。

 起動時にシステム時刻をGPSで修正する

GPSを用いたNTPサーバを構築しようとする場合、システム時刻とGPS時刻の差が大きすぎると、NTPがGPSを信頼せず時刻修正ができません。

raspiのようにバッテリーバックアップされた時計を持たない場合、長時間システムを停止していると、時刻が合わなくなります。
(ネットワーク上に信頼できるNTPサーバがあればそれに強制的に合わせますが、自分自身が持つGPSに合わせる方法はまだ分かっていません)

そこで、システム起動時にシステム時刻とGPS時刻に一定以上の差がある場合自動的にGPS時刻に同期させる仕組みを仮作りしてみました。

GPS時刻はgpsdから得ます。

次のpythonプログラムを/usr/local/sbin/setGpsTime.pyに置いて、

# -*- coding: utf-8 -*-
# setGpsTime.py
# gpsdから時刻を取得し、一定以上の違いがある場合システム時刻を修正する
# システム起動時にroot権限で一度だけ実行されることを想定している
# INT割り込みで中断可能
import os
import gps
import time
import threading
import commands
import math
INITIAL_WAIT_SEC = 60  # gpsdへのアクセスを開始するまでの秒数
MAX_DIFF_SEC     = 300 # (秒)これより大きな差を持つ場合強制修正
RETRY_INTERVAL   = 1   # gpsdへのアクセス間隔
class GpsThread(threading.Thread):
   def __init__(self):
      threading.Thread.__init__(self)
      self.gpsd    = gps.gps(mode=gps.WATCH_ENABLE)
      self.running = True
   def run(self):
      while self.running:
         self.gpsd.next()           # 情報取得
         if self.gpsd.fix.mode > 2: # 情報の信頼性チェック
            try:# timeはなぜか秒のfloat表示の場合と時刻表示の場合がある
               time_str = self.gpsd.fix.time
               g_time   = float(time_str) # 例外発生の可能性あり
               if not math.isnan(g_time):
                  s_time = float(commands.getoutput('date -u +%s'))
                  diff = abs(g_time - s_time)
                  if diff > MAX_DIFF_SEC: # 指定値以上の差がある
                     os.system('date -s '+self.gpsd.utc) # 強制同期
                     self.running=False
                  else:          # 指定値以内の場合はそのまま終了
                     self.running=False
            except ValueError:# timeがfloat表示でない場合例外発生
               pass           # 何もしない
         time.sleep(RETRY_INTERVAL)
if __name__ == '__main__':
   time.sleep(INITIAL_WAIT_SEC)
   gpsThread = GpsThread()
   gpsThread.start()
   try: # 割り込みを待つだけのループ
      while gpsThread.running:
         time.sleep(1)
   except (KeyboardInterrupt, SystemExit, Exception):
      gpsThread.running = False;
   gpsThread.join()
/etc/rc.localから起動します
$ sudo nano /etc/rc.local
--- exit 0前に追加
...
python /usr/local/sbin/setGpsTime.py &
exit 0
---

sudo reboot

時刻を1日ずらした状態にしてリブートしてみました。
リブート直後は時刻のずれがありntpがGPS/PPSを使っていませんが、しばらく置くと一致し、ntpもGPS/PPSをベースに動くようになりました。

$ date
2017年 11月  8日 水曜日 22:02:26 JST
$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 SHM(0)          .GPS.           14 l    -   16    0    0.000    0.000   0.000
 PPS(0)          .PPS.            0 l    -   16    0    0.000    0.000   0.000
# しばらく待つと。。。
$ date
2017年 11月  9日 木曜日 22:10:49 JST
$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*SHM(0)          .GPS.           14 l    5   16    1    0.000    0.907   0.002
oPPS(0)          .PPS.            0 l    4   16    1    0.000    2.303   0.002

起動時に一度動くだけであり、システム時刻とGPS時刻の差が指定値(この例では5分)より小さい場合は何もせず終了します。
この差の適切な値はまだ分かっていません(120秒という記述も見ました。しかし不確かです)

 pythonについて

ここではPython2を使っています。 Python2はprintが他と異なり関数ではない、オブジェクトの長さの取得法がバラバラ、 数値系の関数もmathが必要であったりなかったりなど、 混乱した複雑極まりない記述法を持つためPython3にしたかったのですがgpsモジュールが見つからないので 断念しました。

|

« ◇顔がかゆい | トップページ | ◇GPS,PPSとインターネット上のNTPサーバの比較 »

トラックバック


この記事へのトラックバック一覧です: ◇自動GPS-システム時計強制同期:

« ◇顔がかゆい | トップページ | ◇GPS,PPSとインターネット上のNTPサーバの比較 »