123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- = libgps(3)
- :author: Eric S. Raymond
- :date: 7 March 2021
- :email: <esr@thyrsus.com.>
- :keywords: gps, gpsd, libgps
- :manmanual: GPSD Documentation
- :mansource: GPSD, Version {gpsdver}
- :robots: index,follow
- :sectlinks:
- :toc: macro
- :type: manpage
- :webfonts!:
- include::../www/inc-menu.adoc[]
- == 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)
- for report in session:
- process(report) del session
- ----
- == DESCRIPTION
- *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()*::
- Calling *gps_open()* initializes a *gps_data_t* structure to hold the data
- collected by the GPS, and sets up access to *gpsd*(8) via either the socket
- or shared-memory export. The shared-memory export is faster, but does
- not carry information about device activation and deactivation events
- and will not allow you to monitor device packet traffic.
- +
- *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_close()* ends the session and should only be called after a
- successful *gps_open()*. It returns 0 on success, -1 on errors. The
- shared-memory interface close always returns 0, whereas a socket close
- can result in an error. For a socket close error it will have set an
- errno from the call to the system's *close()*.
- *gps_send()*::
- *gps_send()* writes a command to the *gpsd* daemon. It does nothing when
- using the shared-memory export. The second argument must be a format
- string containing elements from the command set documented at *gpsd*(8).
- It may have % elements as for sprintf(3), which will be filled in
- from any following arguments. This function returns a -1 if there was
- a Unix-level write error, otherwise 0. Please read the LIMITATIONS
- section for additional information and cautions. See *gps_stream()* as a
- possible alternative.
- *gps_read()*::
- *gps_read()* accepts a response, or sequence of responses, from the
- *gpsd* daemon and decodes the response into a *gps_data_t*. By default,
- this function does either a blocking read for data from the *gpsd*
- daemon or a fetch from shared memory; it returns a count of bytes read
- for success, -1 with errno set on a Unix-level read error, -1 with
- errno not set if the socket to the *gpsd* daemon has closed or if the
- shared-memory segment was unavailable, and 0 if no data is available.
- +
- 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()*::
- *gps_waiting()* can be used to check whether there is new data from the
- *gpsd* daemon. The second argument is the maximum amount of time to block
- (in microseconds) waiting on input before returning. It returns true if there is
- input waiting, false on timeout (no data waiting) or error condition.
- When using the socket export, this function is a convenience wrapper
- around a *select*(2) call, and zeros *errno* on entry; you can test *errno*
- after exit to get more information about error conditions.
- +
- 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_mainloop()* enables the provided hook function to be continually
- called whenever there is *gpsd* data. The second argument is the maximum
- amount of time to wait (in microseconds) on input before exiting the
- loop (and return a value of -1). It will also return a negative value on
- various errors.
- *gps_unpack()*::
- *gps_unpack()* parses JSON from the argument buffer into the target of
- the session structure pointer argument. Included in case your
- application wishes to manage socket I/O itself.
- *gps_data()*::
- *gps_data()* returns the contents of the client data buffer (it
- returns NULL when using the shared-memory export). Use with care; this
- may not to be a NUL-terminated string if WATCH_RAW is enabled.
- *gps_stream()*::
- *gps_stream()* asks *gpsd* to stream the reports it has at you, to be
- made available when you poll (not available when using the shared-memory
- export). The second argument is a flag mask that sets various policy
- bits; see the list below. Calling *gps_stream()* more than once with
- different flag masks is allowed.
- *WATCH_DEVICE*;;
- Restrict watching to a specified device. The device path string is
- given as the third argument (data).
- *WATCH_DISABLE*;;
- Disable the reporting modes specified by the other WATCH_ flags.
- *WATCH_ENABLE*;;
- Enable the reporting modes specified by the other WATCH_ flags. This
- is the default.
- *WATCH_JSON*;;
- Enable JSON reporting of data. If WATCH_ENABLE is set, and no other
- WATCH flags are set, this is the default.
- *WATCH_NEWSTYLE*;;
- Force issuing a JSON initialization and getting new-style responses.
- This is the default.
- *WATCH_NMEA*;;
- Enable generated pseudo-NMEA reporting on binary devices.
- *WATCH_OLDSTYLE*;;
- Force issuing a W or R command and getting old-style responses.
- Warning: this flag (and the capability) will be removed in a future
- release.
- *WATCH_RARE*;;
- Enable reporting of binary packets in encoded hex.
- *WATCH_RAW*;;
- Enable literal passthrough of binary packets.
- *WATCH_SCALED*;;
- When reporting AIS or Subframe data, scale integer quantities to
- floats if they have a divisor or rendering formula associated with
- them.
- *gps_errstr()*::
- *gps_errstr()* returns an ASCII string (in English) describing the
- error indicated by a nonzero return value from *gps_open()*.
- The Python implementation supports the same facilities as the
- socket-export calls in the C library; there is no shared-memory
- interface. *gps_open()* is replaced by the initialization of a gps
- session object; the other calls are methods of that object, and have the
- same names as the corresponding C functions. However, it is simpler just
- to use the session object as an iterator, as in the example given below.
- Resources within the session object will be properly released when it is
- garbage-collected.
- ----
- import gps
- session = gps.gps(host="localhost", port="2947")
- session.stream(flags=gps.WATCH_JSON)
- for report in session:
- process(report) del session
- ----
- == 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 example.c -o example -lgps -lm
- #include <gps.h>
- #include <math.h> // for isfinite()
- #include <unistd.h> // for sleep()
- #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);
- // Wait for data available.
- while (gps_waiting(&gps_data, 5000000)) {
- // will not block because we know data is available.
- 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);
- }
- }
- // 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
- *gpsd*(8), *gps*(1), *gpsd_json*(5), *libgpsmm*(3)
- == RESOURCES
- * {gpsdweb}gpsd-client-example-code.html[GPSD Client Example Code] An
- annotated example client.
- * {gpsdweb}client-howto.html[GPSD Client HOWTO] A GPS client HOWTO.
- * *Project web site:* {gpsdweb}
- == COPYING
- This file is Copyright 2013 by the GPSD project +
- SPDX-License-Identifier: BSD-2-clause
|