gpsd + ntpdでStratum 1(GPSD NG版)

# きっかけ
PPS対応GPSを用意し、`ldattach PPS /dev/ttyS0`で`/dev/pps0`を生成し、ntpdの[Type20](https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver20.html)や[Type22](https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver22.html)でStratum 1を運用されている方は多いだろう。
ただ、この運用の場合、`ttyS0`はntpdが占有し、GPSはNTP以外の目的に使えない。

# gpsd
`ttyS0`から取れたGPSのNMEAを広く活用できるようにするのが[gpsd](http://www.catb.org/gpsd/)で、ntpdとも連携できる優れものだ。
ただ、自分の環境では、まれにjitterのスパイクが発生したのと、気がついたらntpdと連携できなくなっていたので、`/dev/pps0`運用に戻してしまった。

# gpsd再び
ところが、やっぱりntpdを使いながら、gpsdを使いたい。[Ntrip](https://en.wikipedia.org/wiki/Networked_Transport_of_RTCM_via_Internet_Protocol)を使って位置の精度がどれくらい変わるか、見てみたい。そして、gpsdは、Ntripに対応している。

# ntpdでgpsdを使う
ググるとたくさん出てくるが、みな[Type28](https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver28.html)の共有メモリ(SHM)ドライバを用いている。ところが、これを使うと、`ntpq -p`で見た時に、delay, offset, jitter全て0.000になってしまい、GPSに同期しない。(課題1)

# gpsdでPPS
そもそも、`gpsmon`でgpsdの出力データを眺めると、`PPS:`の後が空白で、PPS情報が取れていない。(課題2)
まずは、gpsdでPPSを使えるように、課題2を解決する。

# 課題2
情報源が不足しているので、[こちら](http://www.catb.org/gpsd/gpsd-time-service-howto.html)の長い文章をひたすら一言一句読む。すると、

>If you’re going to use gpsd for time service, you must run in -n mode so the clock will be updated even when no clients are active.

なんて書いてある。これか?
ArchLinuxの場合、`/etc/gpsd`を編集し、`gpsd -n`で起動できるようにする。

```shell-session:/etc/gpsd
# Default settings for gpsd.
START_DAEMON="true"
GPSD_OPTIONS="-n"
DEVICES="/dev/gps0"
USBAUTO="true"
```

`gpsmon`で見ると、`PPS:`に数値が入る。わーい。

## `gpsd -n`でもPPSにならない場合
一旦gpsdを止めて、`ldattach PPS /dev/ttyS0`した後、`ppstest /dev/pps0`でPPSになることを確認してから、`killall ldattach`して、gpsd走らせると、何故かPPSになる気がする…。

# 課題1
次に、課題1に戻る。
GPSはArchLinux上で運用しているので、[ArchWiki](https://wiki.archlinux.org/index.php/Network_Time_Protocol_daemon#Using_ntpd_with_GPS)を確認すると、なんとType46なんていうものがある。[こちら](https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver46.html)を確認すると、GPSD NGと言うようで、

>It is important to understand that this driver works best using a GPS device with PPS support.

とのこと。SHMの代わりにJSONでPPSごと取ってくるようだ。これか?

先ほどの[ArchWiki](https://wiki.archlinux.org/index.php/Network_Time_Protocol_daemon#Using_ntpd_with_GPS)の通りに設定する。

```shell-session:/etc/ntp.conf
server 127.127.46.0 
fudge 127.127.46.0 time1 0.0 time2 0.0 refid GPS
```

ところが、`ntpq -p`で見ても、一向にPPSらしい値にならない…気がする…。

もういちど[こちら](https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver46.html)を見直すと、The Mode Wordの1に、

>This mode is a possible choice for receivers that provide a PPS signal most of the time

との記載がある。mode 1にすれば良いのか?

```shell-session:/etc/ntp.conf
server 127.127.46.0 
fudge 127.127.46.0 mode 1 time1 0.0 time2 0.0 refid GPS
```

# 確認
しばらく放置して…。

```shell-session
$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*GPSD_JSON(0)    .GPS.            0 l   15   16  377    0.000   -0.002   0.001
```
こうでなくっちゃね! でもPPS同期を示す`o`じゃなく`*`なのね…気になる。

# ntpdのソースの確認
```c:refclock_gpsdjson.c
	/* dispatch to the mode-dependent processing functions */
	switch (up->mode) {
        default:
        case MODE_OP_STI:
                eval_serial(peer, pp, up);
        	break;

	case MODE_OP_STRICT:
                eval_strict(peer, pp, up);
                break;
```
defaultはmode 0か?

# 謎
gpsdを経由すると、SHMでなくても、やっぱり9時間毎にスパイクが発生する…
![ntp_offset-day.png](https://qiita-image-store.s3.amazonaws.com/0/104225/da3200f3-d7c7-4fe9-348d-c48576614f51.png)

# ツッコミ
Ntripやってないじゃん!