◇自動GPS-システム時計強制同期
シリーズ「GPS-NTP」
- ◆Raspi3でGPS-NTPサーバ
- ◇電波時計用NTPリピータ
- ◇GPS+PPSでNTPサーバを立てる
- ◇自動GPS-システム時計強制同期〇
- ◇GPS,PPSとインターネット上のNTPサーバの比較
- ◇GPS,GPS+PPSを使う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モジュールが見つからないので 断念しました。
| 固定リンク