LIBGPS(3) | GPSD Documentation | LIBGPS(3) |
NAME¶
libgps - C service library for communicating with the GPS daemon
SYNOPSIS¶
C:
#include <gps.h> int gps_open(char * server, char * port, struct gps_data_t * gpsdata) int gps_send(struct gps_data_t * gpsdata, char * fmt, ...) int gps_read(struct gps_data_t * gpsdata, char * message,
int message_size) bool gps_waiting(const struct gps_data_t * gpsdata, int timeout) char * gps_data(const struct gps_data_t * gpsdata) int gps_unpack(char * buf, struct gps_data_t * gpsdata) int gps_close(struct gps_data_t * gpsdata) int gps_stream(struct gps_data_t * gpsdata, unsigned int flags,
void * data) int gps_mainloop(struct gps_data_t * gpsdata, int timeout,
void (* hook)(struct gps_data_t *gpsdata)) const char * gps_errstr(int err)
Python:
import gps session = gps.gps(host="localhost", port="2947") session.stream(flags=gps.WATCH_JSON) while 0 == session.read():
process(session) del session
DESCRIPTION¶
C¶
libgps is a service library which supports communicating with an instance of the gpsd(8), link it with the linker option -lgps. Some systems may also require -lm.
Warning
Take care to conditionalize your code on the major and minor API
version
symbols in gps.h; ideally, force a compilation failure if
GPSD_API_MAJOR_VERSION is not a version you recognize. See the GPSD project
website for more information on the protocol and API changes.
All the functions described here use the gps_data_t structure. Consult gps.h to learn more about gps_data_t, its data members, associated structures. associated timestamps. Note that information will accumulate in the session structure over time, and the 'valid' field is not automatically zeroed by each gps_read(). It is up to the client to zero that field when appropriate and to keep an eye on the fix and sentence timestamps.
Warning
gps_data_t sets floating point variables to NaN when the
actual
variable value is unknown. Check all floats and doubles with isfinite()
before using them. isnan() is not sufficient!
gps_open()
gps_open() returns 0 on success, -1 on errors and is re-entrant. errno is set depending on the error returned from the socket or shared-memory interface; see gps.h for values and explanations; also see gps_errstr(). The host address may be a DNS name, an IPv4 dotted quad, an IPV6 address, or the special value GPSD_SHARED_MEMORY referring to the shared-memory export; the library will do the right thing for any of these.
gps_close()
gps_send()
gps_read()
The second argument to gps_read() is usually NULL, and the third argument is zero. If your application wants to see the raw data from the gpsd daemon then set the second argument to the address of your message buffer, and the third argument is the size of your buffer. Use with care; this may not to be a NUL-terminated string if WATCH_RAW is enabled.
gps_waiting()
Warning: under the shared-memory interface there is a tiny race window between gps_waiting() and a following gps_read(); in that context, because the latter does not block, it is probably better to write a simple read loop.
gps_mainloop()
gps_unpack()
gps_data()
gps_stream()
WATCH_DEVICE
WATCH_DISABLE
WATCH_ENABLE
WATCH_JSON
WATCH_NEWSTYLE
WATCH_NMEA
WATCH_OLDSTYLE
WATCH_RARE
WATCH_RAW
WATCH_SCALED
gps_errstr()
Python¶
The Python implementation supports the same facilities as the the C library. gps_open() is replaced by the initialization of a gps session object: session = gps.gps(...). The other calls are methods of that object, and have the same names as the corresponding C functions.
In addtion to using gps.read() to read messages from gpsd, you can use the session object as an iterator, as in the code fragment given below. Python iterators implicitly call the function gps.\_\_next() which is just a shim over gps.read(). There is other advantage to using the implicit iterator and it does not allow the options that gps.read() does.
import gps session = gps.gps(host="localhost", port="2947") session.stream(flags=gps.WATCH_JSON) for report in session:
process(report) del session
Resources within the session object will be properly released when it is garbage-collected.
For further information on the Python gps module, read the comments in the modules files. There is a complete Python example in the file www/gpsd-client-example-code.adoc.
ENVIRONMENT VARIABLES¶
By setting the environment variable GPSD_SHM_KEY, you can control the key value used to create shared-memory segment used for communication with gpsd. This will be useful mainly when isolating test instances of gpsd from production ones.
EXAMPLES¶
The following is a fully functional minimal C client. Check the C source for the other gpsd clients for more ideas.
// example gpsd client // compile this way: // gcc example1.c -o example1 -lgps -lm #include <gps.h> .. for gps_*() #include <math.h> // for isfinite() #define MODE_STR_NUM 4 static char *mode_str[MODE_STR_NUM] = {
"n/a",
"None",
"2D",
"3D" }; int main(int argc, char *argv[]) {
struct gps_data_t gps_data;
if (0 != gps_open("localhost", "2947", &gps_data)) {
printf("Open error. Bye, bye\n");
return 1;
}
(void)gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);
while (gps_waiting(&gps_data, 5000000)) {
if (-1 == gps_read(&gps_data, NULL, 0)) {
printf("Read error. Bye, bye\n");
break;
}
if (MODE_SET != (MODE_SET & gps_data.set)) {
// did not even get mode, nothing to see here
continue;
}
if (0 > gps_data.fix.mode ||
MODE_STR_NUM <= gps_data.fix.mode) {
gps_data.fix.mode = 0;
}
printf("Fix mode: %s (%d) Time: ",
mode_str[gps_data.fix.mode],
gps_data.fix.mode);
if (TIME_SET == (TIME_SET & gps_data.set)) {
// not 32 bit safe
printf("%ld.%09ld ", gps_data.fix.time.tv_sec,
gps_data.fix.time.tv_nsec);
} else {
puts("n/a ");
}
if (isfinite(gps_data.fix.latitude) &&
isfinite(gps_data.fix.longitude)) {
// Display data from the GPS receiver if valid.
printf("Lat %.6f Lon %.6f\n",
gps_data.fix.latitude, gps_data.fix.longitude);
} else {
printf("Lat n/a Lon n/a\n");
}
}
// When you are done...
(void)gps_stream(&gps_data, WATCH_DISABLE, NULL);
(void)gps_close(&gps_data);
return 0; }
LIMITATIONS¶
On some systems (those which do not support implicit linking in libraries) you may need to add -lm to your link line when you link libgps. It is always safe to do this.
In the C API, incautious use of gps_send() may lead to subtle bugs. In order to not bloat struct gps_data_t with space used by responses that are not expected to be shipped in close sequence with each other, the storage for fields associated with certain responses are combined in a union.
The risky set of responses includes VERSION, DEVICELIST, RTCM2, RTCM3, SUBFRAME, AIS, GST, and ERROR; it may not be limited to that set. The logic of the gpsd daemon’s watcher mode is careful to avoid dangerous sequences, but you should read and understand the layout of struct gps_data_t before using gps_send() to request any of these responses.
COMPATIBILITY¶
The gps_query() supported in major versions 1 and 2 of this library has been removed. With the new streaming-oriented wire protocol behind this library, it is extremely unwise to assume that the first transmission from the gpsd daemon after a command is shipped to it will be the response to command.
If you must send commands to the gpsd daemon explicitly, use gps_send() but beware that this ties your code to the GPSD wire protocol. It is not recommended.
In some versions of the API gps_read() is a blocking call and there was a POLL_NONBLOCK option to make it nonblocking. gps_waiting() was added to reduce the number of wrong ways to code a polling loop.
See the comment above the symbol GPSD_API_MAJOR_VERSION in gps.h for recent changes.
ACKNOWLEDGEMENTS¶
C sample code by Gary E. Miller <gem@rellim.com> and Charles Curley <charlescurley@charlescurley.com>
SEE ALSO¶
RESOURCES¶
COPYING¶
This file is Copyright 2013 by the GPSD project
SPDX-License-Identifier: BSD-2-clause
AUTHOR¶
Eric S. Raymond
2023-01-10 | GPSD, Version 3.25 |