unbounded_gpsd/
types.rs

1//! Types employed in the GPSD API.
2//!
3//! For further information (or where documentation may be sparse), refer to the
4//! GPSD API documentation [here](http://www.catb.org/gpsd/gpsd_json.html).
5use chrono::*;
6
7fn serde_true() -> bool { true }
8fn serde_false() -> bool { false }
9
10#[derive(Serialize, Deserialize, Debug)]
11#[serde(untagged)]
12/// A time-position-velocity (TPV) report.
13///
14/// The API here splits the TPV object that GPSD sends into various variants, in
15/// a bid to classify common responses so that you don't have to do this
16/// yourself. See the variant documentation for details.
17///
18/// Basically, the aim here is to reduce the amount of Option unwrapping
19/// you have to do, as gpsd specifies that all these fields are optional.
20///
21/// The field documentation is exactly the same across variants; it may be omitted
22/// for brevity.
23pub enum TpvResponse {
24    /// 3D GPS fix, with speed and climb data.
25    Fix3D {
26        /// Name of originating device.
27        device: Option<String>,
28        /// Timestamp.
29        time: DateTime<Utc>,
30        /// Fix type: 0 = unknown, 1 = no fix, 2 = 2D fix, 3 = 3D fix.
31        mode: u8,
32        /// Estimated timestamp error (seconds, 95% confidence).
33        #[serde(rename = "ept")]
34        time_err: f64,
35        /// Latitude in degrees: +/- signifies North/South. Present when mode is 2 or 3.
36        lat: f64,
37        /// Latitude error estimate in meters, 95% confidence. Present if mode
38        /// is 2 or 3 and DOPs can be calculated from the satellite view.
39        #[serde(rename = "epy")]
40        lat_err: Option<f64>,
41        /// Longitude in degrees: +/- signifies East/West. Present when mode is 2 or 3.
42        lon: f64,
43        /// Longitude error estimate in meters, 95% confidence. Present if mode
44        /// is 2 or 3 and DOPs can be calculated from the satellite view.
45        #[serde(rename = "epx")]
46        lon_err: Option<f64>,
47        /// Altitude in meters. Present if mode is 3.
48        alt: f64,
49        /// Estimated vertical error in meters, 95% confidence. Present if mode
50        /// is 3 and DOPs can be calculated from the satellite view.
51        #[serde(rename = "epv")]
52        alt_err: Option<f64>,
53        /// Course over ground, degrees from true north.
54        track: Option<f64>,
55        /// Direction error estimate in degrees, 95% confidence.
56        #[serde(rename = "epd")]
57        track_err: Option<f64>,
58        /// Speed over ground, meters per second.
59        speed: f64,
60        /// Speed error estinmate in meters/sec, 95% confidence.
61        #[serde(rename = "eps")]
62        speed_err: Option<f64>,
63        /// Climb (positive) or sink (negative) rate, meters per second.
64        climb: f64,
65        /// Climb/sink error estimate in meters/sec, 95% confidence.
66        #[serde(rename = "epc")]
67        climb_err: Option<f64>
68    },
69    /// 2D GPS fix, with speed data.
70    Fix2D {
71        /// Name of originating device.
72        device: Option<String>,
73        /// Timestamp.
74        time: DateTime<Utc>,
75        /// Fix type: 0 = unknown, 1 = no fix, 2 = 2D fix, 3 = 3D fix.
76        mode: u8,
77        /// Estimated timestamp error (seconds, 95% confidence).
78        #[serde(rename = "ept")]
79        time_err: f64,
80        /// Latitude in degrees: +/- signifies North/South. Present when mode is 2 or 3.
81        lat: f64,
82        #[serde(rename = "epy")]
83        lat_err: Option<f64>,
84        /// Longitude in degrees: +/- signifies East/West. Present when mode is 2 or 3.
85        lon: f64,
86        #[serde(rename = "epx")]
87        lon_err: Option<f64>,
88        /// Course over ground, degrees from true north.
89        track: Option<f64>,
90        #[serde(rename = "epd")]
91        track_err: Option<f64>,
92        /// Speed over ground, meters per second.
93        speed: f64,
94        #[serde(rename = "eps")]
95        speed_err: Option<f64>,
96    },
97    /// Fix with lat/lon, and an unknown smattering of fields.
98    /// You'll get this variant if a fix is obtained (lat/lon available), but GPSD
99    /// otherwise sent data that doesn't exactly fit into any of the categories above.
100    ///
101    /// If you are getting this variant, we'd greatly appreciate it if you filed an issue,
102    /// so we can see what sort of strange data your GPSD is sending!
103    LatLonOnly {
104        /// Name of originating device.
105        device: Option<String>,
106        /// Timestamp.
107        time: DateTime<Utc>,
108        /// Fix type: 0 = unknown, 1 = no fix, 2 = 2D fix, 3 = 3D fix.
109        mode: u8,
110        /// Estimated timestamp error (seconds, 95% confidence).
111        #[serde(rename = "ept")]
112        time_err: f64,
113        /// Latitude in degrees: +/- signifies North/South. Present when mode is 2 or 3.
114        lat: f64,
115        #[serde(rename = "epy")]
116        lat_err: Option<f64>,
117        /// Longitude in degrees: +/- signifies East/West. Present when mode is 2 or 3.
118        lon: f64,
119        #[serde(rename = "epx")]
120        lon_err: Option<f64>,
121        /// Altitude in meters. Present if mode is 3.
122        alt: Option<f64>,
123        #[serde(rename = "epv")]
124        alt_err: Option<f64>,
125        /// Course over ground, degrees from true north.
126        track: Option<f64>,
127        #[serde(rename = "epd")]
128        track_err: Option<f64>,
129        /// Speed over ground, meters per second.
130        speed: Option<f64>,
131        #[serde(rename = "eps")]
132        speed_err: Option<f64>,
133        /// Climb (positive) or sink (negative) rate, meters per second.
134        climb: Option<f64>,
135        #[serde(rename = "epc")]
136        climb_err: Option<f64>,
137    },
138    /// No fix.
139    NoFix {
140        /// Name of originating device.
141        device: Option<String>,
142        /// Timestamp.
143        time: DateTime<Utc>,
144        /// Fix type: 0 = unknown, 1 = no fix, 2 = 2D fix, 3 = 3D fix.
145        mode: u8
146    },
147    /// Possibly no useful data whatsoever.
148    Nothing {
149        /// Name of originating device.
150        device: Option<String>,
151        /// Timestamp.
152        time: Option<DateTime<Utc>>,
153        /// Fix type: 0 = unknown, 1 = no fix, 2 = 2D fix, 3 = 3D fix.
154        mode: Option<u8>
155    },
156    /// Something else! You'll get this variant if GPSD sent data that doesn't
157    /// exactly fit into any of the categories above.
158    ///
159    /// If you are getting this variant, we'd greatly appreciate it if you filed an issue,
160    /// so we can see what sort of strange data your GPSD is sending!
161    Dustbin {
162        device: Option<String>,
163        time: Option<DateTime<Utc>>,
164        mode: Option<u8>,
165        #[serde(rename = "ept")]
166        time_err: Option<f64>,
167        lat: Option<f64>,
168        #[serde(rename = "epy")]
169        lat_err: Option<f64>,
170        lon: Option<f64>,
171        #[serde(rename = "epx")]
172        lon_err: Option<f64>,
173        alt: Option<f64>,
174        #[serde(rename = "epv")]
175        alt_err: Option<f64>,
176        track: Option<f64>,
177        #[serde(rename = "epd")]
178        track_err: Option<f64>,
179        speed: Option<f64>,
180        #[serde(rename = "eps")]
181        speed_err: Option<f64>,
182        climb: Option<f64>,
183        #[serde(rename = "epc")]
184        climb_err: Option<f64>,
185    },
186}
187impl Default for TpvResponse {
188    fn default() -> TpvResponse {
189        TpvResponse::Nothing { device: None, time: None, mode: None }
190    }
191}
192/// A single satellite.
193#[derive(Serialize, Deserialize, Debug)]
194pub struct SatelliteObject {
195    #[serde(rename = "PRN")]
196    /// PRN ID of the satellite. 1-63 are GNSS satellites, 64-96 are GLONASS
197    /// satellites, 100-164 are SBAS satellites
198    pub prn: u16,
199    #[serde(rename = "az")]
200    /// Azimuth, degrees from true north.
201    pub azimuth: f32,
202    #[serde(rename = "el")]
203    /// Elevation in degrees.
204    pub elevation: f32,
205    #[serde(rename = "ss")]
206    /// Signal strength in dB.
207    pub signal_strength: f32,
208    /// Used in current solution? (SBAS/WAAS/EGNOS satellites may be flagged
209    /// used if the solution has corrections from them, but not all drivers make
210    /// this information available.)
211    pub used: bool
212}
213#[derive(Serialize, Deserialize, Debug)]
214/// A sky view report (SKY) of GPS satellite positions.
215///
216/// If there is no GPS device available, or no skyview has been reported yet,
217/// all fields will be blank.
218///
219/// # Dilutions of precision
220///
221/// Fields ending `dop` denote dilutions of precision. These are dimensionless
222/// factors that should be multiplied by a base UERE to get an error estimate.
223///
224/// Many devices compute dilution of precision factors but do not include them
225/// in their reports. Many that do report DOPs report only HDOP, two-dimensional
226/// circular error. gpsd always passes through whatever the device actually
227/// reports, then attempts to fill in other DOPs by calculating the appropriate
228/// determinants in a covariance matrix based on the satellite view. DOPs may be
229/// missing if some of these determinants are singular. It can even happen that
230/// the device reports an error estimate in meters when the corresponding DOP is
231/// unavailable; some devices use more sophisticated error modeling than the
232/// covariance calculation.
233pub struct SkyResponse {
234    /// Name of originating device.
235    pub device: Option<String>,
236    /// Timestamp.
237    pub time: Option<DateTime<Utc>>,
238    /// Longitudinal d.o.p.
239    pub xdop: Option<f32>,
240    /// Latitutinal d.o.p.
241    pub ydop: Option<f32>,
242    /// Altitude d.o.p.
243    pub vdop: Option<f32>,
244    /// Time d.o.p.
245    pub tdop: Option<f32>,
246    /// Horizontal d.o.p.
247    pub hdop: Option<f32>,
248    /// Spherical d.o.p.
249    pub pdop: Option<f32>,
250    /// Hyperspherical d.o.p.
251    pub gdop: Option<f32>,
252    /// Satellites in skyview.
253    pub satellites: Vec<SatelliteObject>
254}
255#[derive(Serialize, Deserialize, Debug)]
256#[serde(untagged)]
257/// Information about a device known to gpsd.
258///
259/// The API splits the DEVICE object into three variants:
260/// - `ActiveSeenPackets`: the device is active, and we've seen packets from it.
261/// - `Active`: the device is active, but we haven't seen any packets.
262/// - `Inactive`: the device is inactive.
263///
264/// Basically, the aim here is to reduce the amount of Option unwrapping
265/// you have to do, as gpsd specifies that all these fields are optional.
266pub enum DeviceObject {
267    ActiveSeenPackets {
268        /// Name the device for which the control bits are being reported, or
269        /// for which they are to be applied. This attribute may be omitted only
270        /// when there is exactly one subscribed channel
271        path: Option<String>,
272        /// Time the device was activated as an ISO8601 timestamp. If the device
273        /// is inactive this attribute is absent.
274        activated: DateTime<Utc>,
275        /// Bit vector of property flags. Currently defined flags are: describe
276        /// packet types seen so far (GPS, RTCM2, RTCM3, AIS). Won't be reported
277        /// if empty, e.g. before gpsd has seen identifiable packets from the
278        /// device.
279        ///
280        /// # Flags
281        ///
282        /// - 0x01: GPS data seen
283        /// - 0x02: RTCM2 data seen
284        /// - 0x04: RTCM3 data seen
285        /// - 0x08: AIS data seen
286        ///
287        /// Yes, I know manual bitflags suck. I'll fix it one day if you bug me.
288        flags: u8,
289        /// GPSD's name for the device driver type. Won't be reported before
290        /// gpsd has seen identifiable packets from the device.
291        driver: String,
292        /// Whatever version information the device returned.
293        subtype: Option<String>,
294        /// Device speed in bits per second.
295        bps: Option<u32>,
296        /// N, O or E for no parity, odd, or even.
297        parity: Option<String>,
298        /// Stop bits (1 or 2).
299        stopbits: Option<String>,
300        /// 0 means NMEA mode and 1 means alternate mode (binary if it has one,
301        /// for SiRF and Evermore chipsets in particular). Attempting to set
302        /// this mode on a non-GPS device will yield an error.
303        native: Option<u8>,
304        /// Device cycle time in seconds.
305        cycle: Option<f32>,
306        /// Device minimum cycle time in seconds. Reported from ?DEVICE when
307        /// (and only when) the rate is switchable. It is read-only and not
308        /// settable.
309        minicycle: Option<f32>
310    },
311    Active {
312        path: Option<String>,
313        activated: DateTime<Utc>,
314        subtype: Option<String>,
315        bps: Option<u32>,
316        parity: Option<String>,
317        stopbits: Option<String>,
318        native: Option<u8>,
319        cycle: Option<f32>,
320        minicycle: Option<f32>
321    },
322    Inactive {
323        path: Option<String>
324    }
325}
326#[derive(Serialize, Deserialize, Debug)]
327/// Information about watcher mode parameters.
328pub struct WatchObject {
329    #[serde(default = "serde_true")]
330    /// Enable (true) or disable (false) watcher mode. Default is true.
331    pub enable: bool,
332    #[serde(default = "serde_false")]
333    /// Enable (true) or disable (false) dumping of JSON reports. Default is
334    /// false.
335    pub json: bool,
336    #[serde(default = "serde_false")]
337    /// Enable (true) or disable (false) dumping of binary packets as
338    /// pseudo-NMEA. Default is false.
339    pub nmea: bool,
340    /// Controls 'raw' mode. When this attribute is set to 1 for a channel, gpsd
341    /// reports the unprocessed NMEA or AIVDM data stream from whatever device
342    /// is attached. Binary GPS packets are hex-dumped. RTCM2 and RTCM3 packets
343    /// are not dumped in raw mode. When this attribute is set to 2 for a
344    /// channel that processes binary data, gpsd reports the received data
345    /// verbatim without hex-dumping.
346    pub raw: Option<u32>,
347    #[serde(default = "serde_false")]
348    /// If true, apply scaling divisors to output before dumping; default is
349    /// false.
350    pub scaled: bool,
351    #[serde(default = "serde_false")]
352    /// If true, aggregate AIS type24 sentence parts. If false, report each part
353    /// as a separate JSON object, leaving the client to match MMSIs and
354    /// aggregate. Default is false. Applies only to AIS reports.
355    pub split24: bool,
356    #[serde(default = "serde_false")]
357    /// If true, emit the TOFF JSON message on each cycle and a PPS JSON message
358    /// when the device issues 1PPS. Default is false.
359    pub pps: bool,
360    /// If present, enable watching only of the specified device rather than all
361    /// devices. Useful with raw and NMEA modes in which device responses aren't
362    /// tagged. Has no effect when used with enable:false.
363    pub device: Option<String>,
364    /// URL of the remote daemon reporting the watch set. If empty, this is a
365    /// WATCH response from the local daemon.
366    pub remote: Option<String>
367}
368impl Default for WatchObject {
369    fn default() -> Self {
370        Self {
371            enable: true,
372            json: false,
373            nmea: false,
374            raw: None,
375            scaled: false,
376            split24: false,
377            pps: false,
378            device: None,
379            remote: None
380        }
381    }
382}
383#[derive(Serialize, Deserialize, Debug)]
384#[serde(tag = "class")]
385/// A response from GPSD.
386///
387/// For single-struct variants, the documentation on the struct usually has
388/// more information.
389pub enum Response {
390    #[serde(rename = "TPV")]
391    Tpv(TpvResponse),
392    #[serde(rename = "SKY")]
393    Sky(SkyResponse),
394    #[serde(rename = "POLL")]
395    /// Data from the last-seen fixes on all active GPS devices.
396    Poll {
397        time: DateTime<Utc>,
398        /// Count of active devices.
399        active: u32,
400        tpv: Vec<TpvResponse>,
401        sky: Vec<SkyResponse>
402    },
403    #[serde(rename = "DEVICE")]
404    Device(DeviceObject),
405    #[serde(rename = "DEVICES")]
406    Devices {
407        devices: Vec<DeviceObject>,
408        remote: Option<String>
409    },
410    #[serde(rename = "WATCH")]
411    Watch(WatchObject),
412    #[serde(rename = "VERSION")]
413    Version {
414        release: String,
415        rev: String,
416        proto_major: u32,
417        proto_minor: u32,
418        remote: Option<String>
419    },
420    #[serde(rename = "ERROR")]
421    Error {
422        message: String
423    },
424    Raw(String)
425}