gpsd-knowledge-patch

Installation
SKILL.md

gpsd Knowledge Patch

Covers gpsd JSON protocol fields, libgps C client API, and timing interfaces. Claude knows gpsd daemon basics, gpspipe, cgps, and JSON protocol fundamentals, but is unaware of the specific field semantics, deprecations, and API patterns below.

Index

Topic Reference Key content
TPV message fields references/tpv-message.md altHAE/altMSL, status codes, ECEF/NED, float validity
Timing & PPS references/timing-pps.md TOFF/PPS reports, sawtooth correction, NTP integration
Client API (libgps) references/client-api.md gps_mainloop(), shared-memory interface, usage patterns

Essential Quick Reference

ECEF and NED Velocity/Position Fields

TPV can include ECEF (Earth-Centered, Earth-Fixed) coordinates and NED (North-East-Down) components:

{
  "class": "TPV",
  "ecefx": 3981234.56,
  "ecefy": 123456.78,
  "ecefz": 4966789.01,
  "ecefpAcc": 2.5,
  "ecefvx": 0.12,
  "ecefvy": -0.05,
  "ecefvz": 0.03,
  "ecefvAcc": 0.1,
  "velN": 0.12,
  "velE": -0.05,
  "velD": -0.03,
  "relN": 1.234,
  "relE": -0.567,
  "relD": 0.089
}

relN/relE/relD are RTK baseline vectors relative to a base station (meters). Only populated when the receiver reports RTK baseline data.

TPV Key Fields

Field Type Unit Description
altHAE float meters Height Above Ellipsoid (WGS84) — raw GPS altitude
altMSL float meters Mean Sea Level altitude — what maps show
geoidSep float meters Geoid separation: altHAE - altMSL
status int Fix quality: 2=DGPS, 3=RTK Fixed, 4=RTK Float, 5=DR
ecefx/y/z float meters ECEF position from Earth center
ecefpAcc float meters ECEF 3D position accuracy
velN/E/D float m/s North/East/Down velocity components
relN/E/D float meters RTK baseline relative to base station

Altitude — "alt" Is Deprecated

The alt field in TPV is deprecated and undefined. Always use altHAE or altMSL:

{
  "class": "TPV",
  "altHAE": 120.345,
  "altMSL": 85.678,
  "geoidSep": 34.667
}

altMSL is what most users want (matches map elevations). altHAE is the raw GPS measurement.

Float Validity — Use isfinite(), Not isnan()

Unknown/invalid floats in gpsd are NaN. Always check with isfinite():

// WRONG: misses infinity
if (!isnan(gpsdata->fix.speed)) { ... }

// CORRECT: catches NaN AND infinity
if (isfinite(gpsdata->fix.speed)) { ... }

TPV Status Field Values

The status field modifies mode (not a replacement). Values 0 (Unknown) and 1 (Normal) are omitted from JSON output — if absent, assume Normal:

Value Meaning Accuracy
2 DGPS Sub-meter
3 RTK Fixed Centimeter
4 RTK Floating Decimeter
5 DR Dead Reckoning
6 GNSSDR GNSS + DR combined
7 Time (surveyed) Time-only mode
8 Simulated Test data
9 P(Y) Military code

Timing — Enable TOFF/PPS

?WATCH={"enable":true,"json":true,"pps":true}

Both TOFF and PPS carry real_sec/real_nsec (GPS time) and clock_sec/clock_nsec (system time).

Report Source Precision Extra fields
TOFF Serial data stream ~1–10 ms
PPS Hardware 1PPS pulse ~0.1–1 µs precision, shm, qErr

PPS qErr is the sawtooth correction in picoseconds — subtract from measured offset for higher accuracy.


Client API Patterns

gps_mainloop() — Simple Event Loop

int gps_mainloop(struct gps_data_t *gpsdata, int timeout,
                 void (*hook)(struct gps_data_t *gpsdata));

timeout is in microseconds. Returns -1 on timeout or error. Calls hook on each data arrival.

#include <gps.h>
#include <math.h>

void on_gps(struct gps_data_t *gpsdata) {
    if (gpsdata->fix.mode >= MODE_2D && isfinite(gpsdata->fix.latitude))
        printf("%.6f, %.6f\n", gpsdata->fix.latitude, gpsdata->fix.longitude);
}

int main(void) {
    struct gps_data_t gpsdata;
    gps_open("localhost", "2947", &gpsdata);
    gps_stream(&gpsdata, WATCH_ENABLE | WATCH_JSON, NULL);
    gps_mainloop(&gpsdata, 5000000, on_gps);  /* 5s timeout */
    gps_stream(&gpsdata, WATCH_DISABLE, NULL);
    gps_close(&gpsdata);
}

Shared-Memory Interface

Pass GPSD_SHARED_MEMORY as host for fast local-only access. Cannot use gps_stream(), gps_send(), gps_waiting(), or gps_data(). gps_read() always returns current snapshot; gps_fd is always -1.

struct gps_data_t gpsdata;
gps_open(GPSD_SHARED_MEMORY, NULL, &gpsdata);
if (gps_read(&gpsdata, NULL, 0) > 0) {
    if (isfinite(gpsdata.fix.latitude))
        printf("%.6f, %.6f\n", gpsdata.fix.latitude, gpsdata.fix.longitude);
}
gps_close(&gpsdata);

Use for: embedded systems, simple pollers, monitoring scripts (local only). Avoid when: you need streaming (gps_stream), device filtering, gps_waiting(), or remote access.

Shared Memory vs TCP Socket

Feature TCP Socket Shared Memory
gps_stream() Yes No
gps_send() Yes No
gps_waiting() Yes No
Device filtering Yes No
gps_read() behavior Blocks for new data Returns current snapshot
gps_fd Socket fd Always -1
Remote access Yes No (local only)
Related skills
Installs
2
GitHub Stars
19
First Seen
Apr 7, 2026
Security Audits