summaryrefslogtreecommitdiff
path: root/README.md
blob: 4a8b70044746e3275c241bb37d59134ec65b90b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# NemaTode

*C++ NMEA Parser & GPS Framework*

NemaTode is yet another lightweight generic NMEA parser.

It also comes with a GPS data interface to handle the most popular GPS NMEA sentences.

## It's too easy!
This is all you need to use the GPS NMEA sentence data.


    NMEAParser parser;
    GPSService gps(parser);
    // (optional) Called when a sentence is valid syntax
    parser.onSentence += [](const NMEASentence& nmea){
        cout << "Received $" << nmea.name << endl;
    };
    // (optional) Called when data is read/changed
    gps.onUpdate += [](GPSService& gps){
        // There are *tons* of GPSFix properties
        if( gps.fix.locked() ){
            cout << " # Position: " << gps.fix.latitude << ", " << gps.fix.longitude << endl;
        } else {
            cout << " # Searching..." << endl;
        }
    };
    // Send in a log file or a byte stream
    try {
        parser.readLine("FILL WITH A NMEA MESSAGE");
    } catch (NMEAParseError&) {
        // Syntax error, skip
    }
    

    
    

      

----
##Features

* **NMEA Parsing** of standard and custom sentences.

  - Standard:
```` 
    GPGGA, GPGSA, GPGSV, GPRMC, GPVTG
````

* **NMEA Generation** of "standard" and custom sentences.
  - SiRF Control sentences: ```` PSRF100, PSRF103 ````

* **GPS Fix** class to manage and organize all the GPS related data.


* **Flexible**
   - Stream data directly from a hardware byte stream
   - Read log files, even if they are cluttered with other unrelated data.
   - Easily hook into the parser to handle custom sentences and get their data.
   - Simplified GPS data
    
* **C++ 11 features**
   - Those fancy event handlers...
   - If you are on an embedded system... sorry. This might not work for you.

## Details
NMEA is very popular with GPS. Unfortunately the GPS data is fragmented
between many different NMEA sentences. Sometimes there is even conflicting 
information in them!

The underlying **NMEAParser** can read a byte stream from a hardware device or 
it can read log files with flexibility in the formatting. The accepted strings are...

````
"$[name:alphanum],[param[i]:alphanum],...(*alphanum[2]\r)\n"
````

The params allow '-' and any combination of whitespace.

The handler for "MYNMEA" is called. This is where you can catch the sentence and process it.

    parser.setSentenceHandler("MYNMEA",[](const NMEASentence& nmea){
        if( ! nmea.checksumOK() ){
            // bad checksum, but valid syntax
        }
        if( nmea.parameters.size() < 3 ){
            // missing data, throw something.
            // catch it at the read*() call.
        }
        int mydata = parseInt(nmea.parameters[2]);
    };



There are 2 ways to operate...

* **LAX**  It will eat anything.
    - Useful for reading log files.
    - Call ````readByte(), readBuffer(), readLine()````
* **STRICT**   It will throw errors on anything that's not explicitly NMEA.
    - Call ```` readSentence() ````


## Demos
**"demo_simple.cpp"**

 * Just reads the GPS position data.


**"demo_advanced.cpp"**

 * Reads **all** the data
 * Sentence Generation
 * Custom Sentence handling

.

**Generation**
    
    NMEACommand mycmd;
    mycmd.name = "MYCMD";
    mycmd.message = "your,data,csv";
    string nmea = mycmd.toString();  // Creates: 


There are 2 included NMEACommands that can configure a GPS.

 * ```` PSRF103```` Configures message output ID and rate, and 

 * ```` PSRF100```` Configures the UART serial connection (if the chip has one).




## GPS Fix data available
Available data when all 5 GPS sentences are received. If some are missing then some parameters will never change from their default values.
All data is checked for consistency. For example, visible satellites can never be less than the tracking satellites, etc.


**GPSFix**

    GPSAlmanac     almanac;
    GPSTimestamp 	timestamp;

    char 		status;		// Status: A=active, V=void (not locked)
    uint8_t 	type;		// Type: 1=none, 2=2d, 3=3d
    uint8_t 	quality;	// Quality (1-6) 

    double 		dilution;		// Combination of Vertical & Horizontal
    double 		horizontalDilution;	// Horizontal dilution of precision, initialized to 10, best =1, worst = >20
    double 		verticalDilution;	// Vertical is less accurate

    double 		altitude;		// meters
    double 		latitude;		// degrees N
    double 		longitude;		// degrees E
    double 		speed;			// km/h
    double 		travelAngle;		// degrees true north (0-359)
    int32_t 	trackingSatellites;
    int32_t 	visibleSatellites;

    bool 		locked();		// Whether or not the position is locked on, or accurate.
    double 		horizontalAccuracy();	// Gets accuracy of position in meters
    double 		verticalAccuracy();
    bool 		hasEstimate();		// If no fix is available, this says the position data is close to a real fix.
		
    std::chrono::seconds timeSinceLastUpdate();	// Returns time from last timestamp to right now, in seconds.
    

**GPSSatellite**

    double 		snr;		// Signal-to-noise ratio. 0-99 dB
    uint32_t 	prn;		// pseudo-random number.  (basically a satellite id)
    double 		elevation;	// 0-90 deg
    double 		azimuth;	// 0-359 deg


**GPSAlmanac**

    std::vector<GPSSatellite> satellites;	// mapped by prn (id number)
    double 		averageSNR(); 
    double 		minSNR();
    double 		maxSNR();
    double 		percentComplete();	// if all the satellite information is loaded (0-100)

		
**GPSTimestamp**    *(UTC Time)*

    int32_t 	hour;		// Parsed values from GPS
    int32_t 	min;		
    double 		sec;		
    int32_t 	month;		
    int32_t 	day;		
    int32_t 	year;		
    double 		rawTime;	// Values collected directly from the GPS
    int32_t 	rawDate;	
    time_t 		getTime();	// Converts timestamp into Epoch time, seconds since 1/1/1970.


# NemaTode?

NMEA -> ME -> EM -> NEMA

+Tode