summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md64
1 files changed, 64 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..afbadef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+# gps-clock-dash
+
+A lightweight live dashboard for a GPS + PPS time server running chrony and gpsd.
+
+One static Go binary (about 5 MB, standard library only) runs on the time server.
+Once a second it polls `chronyc -c tracking | sources | sourcestats`, keeps a
+connection open to gpsd's JSON stream, and pushes a combined snapshot to
+browsers over Server-Sent Events. The web page (HTML, CSS and vanilla JS, with
+no build step and no external requests) is built into the binary.
+
+## Panels
+
+- **Clock**: UTC to the millisecond, local time, day of year, MJD, Unix time,
+ GPS week and time of week, leap status, and this browser's offset from the
+ server (measured with an NTP-style round trip to `api/time`). Also an overall
+ health badge: *Locked to PPS*, *Degraded* or *Not synchronised*, with reasons.
+- **Time quality**: system offset, RMS offset, reference, stratum, frequency,
+ residual frequency, skew, root delay and dispersion, update interval.
+- **Sources**: every chrony source with its selection state, poll interval,
+ 8-bit reach register, last sample offset ± error bound, and σ (standard deviation).
+- **History**: system offset and PPS sample offset, frequency (ppm), and
+ satellites used/in view, over 10, 30 or 60 minutes (kept in memory by the server).
+- **GPS receiver**: fix type, latitude and longitude (4 decimal places),
+ altitude, position error, DOPs, estimated NMEA time error, serial latency
+ (gpsd TOFF), and receiver/driver.
+- **Satellites**: sky plot (azimuth/elevation, filled when used in the fix),
+ counts per constellation, and signal strength per satellite.
+
+## Build & deploy
+
+```sh
+make arm64 # build/gps-clock-dash-arm64 for the Pi
+make deploy # scp + install to /usr/local/bin + systemd unit on yttrium (needs sudo)
+```
+
+The service listens on **:8473**.
+
+| Flag | Default | |
+|---|---|---|
+| `-listen` | `:8473` | HTTP listen address |
+| `-gpsd` | `127.0.0.1:2947` | gpsd address |
+| `-chronyc` | `chronyc` | path to chronyc |
+| `-pps-refid` | `GPS` | chrony refid of the PPS refclock (used for health and the history chart) |
+| `-history` | `3600` | seconds of history to keep |
+
+### Endpoints
+
+`/` dashboard · `/events` SSE stream · `/api/status` latest snapshot ·
+`/api/history` history samples · `/api/time` server time · `/healthz`
+
+### Behind nginx
+
+All URLs in the page are relative, so it works at any sub-path. See
+[deploy/nginx-location.conf](deploy/nginx-location.conf). The important parts
+for SSE are `proxy_buffering off` and a long `proxy_read_timeout`. The server
+also sends `X-Accel-Buffering: no`. Once nginx is in front, switch the unit to
+`-listen 127.0.0.1:8473` (or the LAN address nginx connects to).
+
+### NTP client request rate (optional)
+
+`chronyc serverstats` needs chronyd's privileged socket, so the unit runs
+unprivileged and that row stays hidden. To show it, run the service as
+`_chrony` (see the comments in the unit file). The tradeoff is that the
+process could then issue any chronyc command.