summaryrefslogtreecommitdiff
path: root/include/nmeaparse
diff options
context:
space:
mode:
Diffstat (limited to 'include/nmeaparse')
-rw-r--r--include/nmeaparse/Event.h215
-rw-r--r--include/nmeaparse/GPSFix.h180
-rw-r--r--include/nmeaparse/GPSService.h45
-rw-r--r--include/nmeaparse/NMEACommand.h115
-rw-r--r--include/nmeaparse/NMEAParser.h120
-rw-r--r--include/nmeaparse/NumberConversion.h47
-rw-r--r--include/nmeaparse/nmea.h28
7 files changed, 750 insertions, 0 deletions
diff --git a/include/nmeaparse/Event.h b/include/nmeaparse/Event.h
new file mode 100644
index 0000000..4343496
--- /dev/null
+++ b/include/nmeaparse/Event.h
@@ -0,0 +1,215 @@
+/*
+ * Event.h
+ *
+ * Created on: Sep 5, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef EVENT_H_
+#define EVENT_H_
+
+#include <list>
+#include <functional>
+#include <cstdint>
+
+
+
+namespace nmea {
+
+
+ template<class> class EventHandler;
+ template<class> class Event;
+
+
+ template<typename... Args>
+ class EventHandler<void(Args...)>
+ {
+ friend Event<void(Args...)>;
+ private:
+ // Typenames
+ typename Event<void(Args...)>::ListIterator _iterator;
+
+ // Static members
+ static uint64_t LastID;
+
+ // Properties
+ uint64_t ID;
+ std::function<void(Args...)> handler;
+
+ // Functions
+ void _copy(const EventHandler& ref){
+ if (&ref != this){
+ _iterator = ref._iterator;
+ handler = ref.handler;
+ ID = ref.ID;
+ }
+ }
+
+ public:
+ // Typenames
+ typedef void(*CFunctionPointer)(Args...);
+
+ // Static members
+ // (none)
+
+ // Properties
+ // (none)
+
+ // Functions
+ EventHandler(std::function<void(Args...)> h) : _iterator(), handler(h), ID(++LastID)
+ {}
+
+ EventHandler(const EventHandler& ref){
+ _copy(ref);
+ }
+
+ virtual ~EventHandler(){};
+
+ EventHandler& operator=(const EventHandler& ref){
+ _copy(ref);
+ return *this;
+ }
+
+ void operator() (Args... args){
+ handler(args...);
+ }
+
+ bool operator==(const EventHandler& ref){
+ return ID == ref.ID;
+ }
+
+ bool operator!=(const EventHandler& ref){
+ return ID != ref.ID;
+ }
+
+ uint64_t getID(){
+ return ID;
+ }
+
+ // Returns function pointer to the underlying function
+ // or null if it's not a function but implements operator()
+ CFunctionPointer* getFunctionPointer(){
+ CFunctionPointer* ptr = handler.template target<CFunctionPointer>();
+ return ptr;
+ }
+ };
+
+ template<typename... Args>
+ uint64_t EventHandler<void(Args...)>::LastID = 0;
+
+
+ template <typename ... Args>
+ class Event<void(Args...)>
+ {
+ friend EventHandler<void(Args...)>;
+ private:
+ // Typenames
+ typedef typename std::list<EventHandler<void(Args...)>>::iterator ListIterator;
+
+ // Static members
+ // (none)
+
+ // Properties
+ std::list<EventHandler<void(Args...)>> handlers;
+
+ //Functions
+ void _copy(const Event& ref){
+ if (&ref != this){
+ handlers = ref.handlers;
+ }
+ };
+
+ bool removeHandler(ListIterator handlerIter) {
+ if (handlerIter == handlers.end()){
+ return false;
+ }
+
+ handlers.erase(handlerIter);
+ return true;
+ };
+
+ public:
+ // Typenames
+ // (none)
+
+ // Static members
+ // (none)
+
+ // Properties
+ bool enabled;
+
+ // Functions
+ Event() : enabled(true)
+ {}
+
+ virtual ~Event()
+ {}
+
+ Event(const Event& ref) {
+ _copy(ref);
+ }
+
+ void call(Args... args) {
+ if (!enabled) { return; }
+ for (auto h = handlers.begin(); h != handlers.end(); h++)
+ {
+ (*h)(args...);
+ }
+ }
+
+ EventHandler<void(Args...)> registerHandler(EventHandler<void(Args...)> handler) {
+ bool found = false;
+ for (auto h = handlers.begin(); h != handlers.end(); h++)
+ {
+ if ((*h) == handler) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ ListIterator itr = handlers.insert(handlers.end(), handler);
+ handler._iterator = itr;
+ }
+ return handler;
+ }
+
+ EventHandler<void(Args...)> registerHandler(std::function<void(Args...)> handler) {
+ EventHandler<void(Args...)> wrapper(handler);
+ ListIterator itr = handlers.insert(handlers.end(), wrapper);
+ wrapper._iterator = itr;
+ return wrapper;
+ }
+
+ bool removeHandler(EventHandler<void(Args...)>& handler) {
+ bool sts = removeHandler(handler._iterator);
+ handler._iterator = handlers.end();
+ return sts;
+ };
+
+ void clear(){
+ for (auto h = handlers.begin(); h != handlers.end(); h++)
+ {
+ (*h)._iterator = handlers.end();
+ }
+ handlers.clear();
+ };
+
+ void operator ()(Args... args) { return call(args...); };
+ EventHandler<void(Args...)> operator +=(EventHandler<void(Args...)> handler) { return registerHandler(handler); };
+ EventHandler<void(Args...)> operator +=(std::function<void(Args...)> handler) { return registerHandler(handler); };
+ bool operator -=(EventHandler<void(Args...)>& handler) { return removeHandler(handler); };
+ bool operator -=(uint64_t handlerID) { return removeHandler(handlerID); };
+
+ EventHandler<void(Args...)>& operator =(const EventHandler<void(Args...)>& ref){
+ _copy(ref);
+ return *this;
+ };
+
+ };
+
+
+
+}
+
+#endif /* EVENT_H_ */
diff --git a/include/nmeaparse/GPSFix.h b/include/nmeaparse/GPSFix.h
new file mode 100644
index 0000000..85adc0c
--- /dev/null
+++ b/include/nmeaparse/GPSFix.h
@@ -0,0 +1,180 @@
+/*
+ * GPSFix.h
+ *
+ * Created on: Jul 23, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef GPSFIX_H_
+#define GPSFIX_H_
+
+#include <cstdint>
+#include <ctime>
+#include <string>
+#include <chrono>
+#include <vector>
+#include <cmath>
+#include <sstream>
+
+namespace nmea {
+
+ class GPSSatellite;
+ class GPSAlmanac;
+ class GPSFix;
+ class GPSService;
+
+
+ // =========================== GPS SATELLITE =====================================
+
+ class GPSSatellite {
+ public:
+ GPSSatellite() :
+ snr(0),
+ prn(0),
+ elevation(0),
+ azimuth(0)
+ {};
+
+ //satellite data
+ double snr; // 0-99 dB
+ uint32_t prn; // id - 0-32
+ double elevation; // 0-90 deg
+ double azimuth; // 0-359 deg
+ std::string toString();
+ operator std::string();
+ };
+
+
+
+
+
+
+ // =========================== GPS ALMANAC =====================================
+
+
+ class GPSAlmanac {
+ friend GPSService;
+ private:
+ uint32_t visibleSize;
+ uint32_t lastPage;
+ uint32_t totalPages;
+ uint32_t processedPages;
+ void clear(); //will remove all information from the satellites
+ void updateSatellite(GPSSatellite sat);
+ public:
+ GPSAlmanac() :
+ lastPage(0),
+ totalPages(0),
+ processedPages(0)
+ {};
+
+ //mapped by prn
+ std::vector<GPSSatellite> satellites;
+ double averageSNR();
+ double minSNR();
+ double maxSNR();
+ double percentComplete();
+
+ };
+
+
+
+
+ // =========================== GPS TIMESTAMP =====================================
+
+ // UTC time
+ class GPSTimestamp {
+ private:
+ std::string monthName(uint32_t index);
+ public:
+ GPSTimestamp();
+
+ int32_t hour;
+ int32_t min;
+ double sec;
+
+ int32_t month;
+ int32_t day;
+ int32_t year;
+
+ // Values collected directly from the GPS
+ double rawTime;
+ int32_t rawDate;
+
+ time_t getTime();
+
+ // Set directly from the NMEA time stamp
+ // hhmmss.sss
+ void setTime(double raw_ts);
+
+ // Set directly from the NMEA date stamp
+ // ddmmyy
+ void setDate(int32_t raw_date);
+
+ std::string toString();
+ };
+
+
+
+
+
+
+ // =========================== GPS FIX =====================================
+
+ class GPSFix {
+ friend GPSService;
+
+ private:
+
+ bool haslock;
+ bool setlock(bool b); //returns true if lock status **changed***, false otherwise.
+
+
+ public:
+
+ GPSFix();
+ virtual ~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:
+ // 0 = invalid
+ // 1 = GPS fix (SPS)
+ // 2 = DGPS fix
+ // 3 = PPS fix
+ // 4 = Real Time Kinematic (RTK)
+ // 5 = Float RTK
+ // 6 = estimated (dead reckoning) (2.3 feature)
+
+ double dilution; // Combination of Vertical & Horizontal
+ double horizontalDilution; // Horizontal dilution of precision, initialized to 100, 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-360)
+ int32_t trackingSatellites;
+ int32_t visibleSatellites;
+
+ bool locked();
+ double horizontalAccuracy();
+ double verticalAccuracy();
+ bool hasEstimate();
+
+ std::chrono::seconds timeSinceLastUpdate(); // Returns seconds difference from last timestamp and right now.
+
+ std::string toString();
+ operator std::string();
+
+ static std::string travelAngleToCompassDirection(double deg, bool abbrev = false);
+ };
+
+}
+
+#endif /* GPSFIX_H_ */
diff --git a/include/nmeaparse/GPSService.h b/include/nmeaparse/GPSService.h
new file mode 100644
index 0000000..4d10dbd
--- /dev/null
+++ b/include/nmeaparse/GPSService.h
@@ -0,0 +1,45 @@
+/*
+ * GPSService.h
+ *
+ * Created on: Aug 14, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef GPSSERVICE_H_
+#define GPSSERVICE_H_
+
+#include <string>
+#include <chrono>
+#include <functional>
+#include <nmeaparse/GPSFix.h>
+#include <nmeaparse/NMEAParser.h>
+#include <nmeaparse/Event.h>
+
+namespace nmea {
+
+class GPSService {
+private:
+
+ void read_PSRF150(const NMEASentence& nmea);
+ void read_GPGGA (const NMEASentence& nmea);
+ void read_GPGSA (const NMEASentence& nmea);
+ void read_GPGSV (const NMEASentence& nmea);
+ void read_GPRMC (const NMEASentence& nmea);
+ void read_GPVTG (const NMEASentence& nmea);
+
+public:
+ GPSFix fix;
+
+ GPSService(NMEAParser& parser);
+ virtual ~GPSService();
+
+ Event<void(bool)> onLockStateChanged; // user assignable handler, called whenever lock changes
+ Event<void()> onUpdate; // user assignable handler, called whenever fix changes
+
+ void attachToParser(NMEAParser& parser); // will attach to this parser's nmea sentence events
+};
+
+
+}
+
+#endif /* GPSSERVICE_H_ */
diff --git a/include/nmeaparse/NMEACommand.h b/include/nmeaparse/NMEACommand.h
new file mode 100644
index 0000000..d71b9b7
--- /dev/null
+++ b/include/nmeaparse/NMEACommand.h
@@ -0,0 +1,115 @@
+/*
+ * NMEACommand.h
+ *
+ * Created on: Sep 8, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef NMEACOMMAND_H_
+#define NMEACOMMAND_H_
+
+#include <string>
+#include <nmeaparse/NMEAParser.h>
+
+namespace nmea {
+
+ class NMEACommand {
+ public:
+ std::string message;
+ std::string name;
+ char checksum;
+ NMEACommand();
+ virtual ~NMEACommand();
+ virtual std::string toString();
+ std::string addChecksum(std::string s);
+ };
+
+
+
+ class NMEACommandSerialConfiguration : public NMEACommand {
+ public:
+ /*
+ // $PSRF100,0,9600,8,1,0*0C
+
+ Table 2-4 Set Serial Port Data Format
+ Name Example Unit Description
+ Message ID $PSRF100 PSRF100 protocol header
+ Protocol 0 0=SiRF binary, 1=NMEA
+ Baud 9600 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200
+ DataBits 8 8,71
+
+ StopBits 1 0,1 1. SiRF protocol is only valid for 8 data bits, 1stop bit, and no parity.
+ Parity 0 0=None, 1=Odd, 2=Even
+ Checksum *0C
+ <CR> <LF> End of message termination
+ */
+ int32_t baud; //4800, 9600, 19200, 38400
+ int32_t databits; //7, 8 Databits
+ int32_t stopbits; //0, 1 Stopbits
+ int32_t parity; //0=none, 1=odd, 2=even Parity
+
+ NMEACommandSerialConfiguration(){
+ name = "PSRF100";
+ baud = 4800;
+ databits = 8;
+ stopbits = 1;
+ parity = 0;
+ };
+ virtual std::string toString();
+ };
+
+ class NMEACommandQueryRate : public NMEACommand {
+ public:
+ // data fields that will be stringed.
+
+
+ // $PSRF103,00,01,00,01*25
+ /*
+ * Table 2-9 Query/Rate Control Data Format
+ Name Example Unit Description
+ Message ID $PSRF103 PSRF103 protocol header
+ Msg 00 See Table 2-10
+ Mode 01 0=SetRate, 1=Query
+ Rate 00 sec Output—off=0, max=255
+ CksumEnable 01 0=Disable Checksum, 1=Enable Checksum
+ Checksum *25
+ <CR> <LF> End of message termination
+ */
+ /*
+ * Table 2-10 Messages
+ Value Description
+ 0 GGA
+ 1 GLL
+ 2 GSA
+ 3 GSV
+ 4 RMC
+ 5 VTG
+ 6 MSS (If internal beacon is supported)
+ 7 Not defined
+ 8 ZDA (if 1PPS output is supported)
+ 9 Not defined
+ */
+
+ enum QueryRateMode {
+ SETRATE = 0,
+ QUERY = 1
+ };
+
+ NMEASentence::MessageID messageID;
+ QueryRateMode mode;
+ int rate;
+ int checksumEnable;
+ NMEACommandQueryRate(){
+ name = "PSRF103";
+ messageID = NMEASentence::Unknown;
+ mode = QueryRateMode::SETRATE;
+ rate = 0;
+ checksumEnable = 1;
+ };
+ virtual std::string toString();
+ };
+
+
+}
+
+#endif /* NMEACOMMAND_H_ */
diff --git a/include/nmeaparse/NMEAParser.h b/include/nmeaparse/NMEAParser.h
new file mode 100644
index 0000000..6f63b85
--- /dev/null
+++ b/include/nmeaparse/NMEAParser.h
@@ -0,0 +1,120 @@
+/*
+ * NMEAParser.h
+ *
+ * Created on: Aug 12, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef NMEAPARSER_H_
+#define NMEAPARSER_H_
+
+
+#include <nmeaparse/Event.h>
+#include <string>
+#include <functional>
+#include <unordered_map>
+#include <vector>
+#include <cstdint>
+#include <exception>
+
+
+
+//read class definition for info
+#define NMEA_PARSER_MAX_BUFFER_SIZE 2000
+
+
+
+
+
+namespace nmea {
+
+class NMEAParser;
+
+
+class NMEASentence {
+ friend NMEAParser;
+private:
+ bool isvalid;
+public:
+ std::string text; //whole plaintext of the received command
+ std::string name; //name of the command
+ std::vector<std::string> parameters; //list of parameters from the command
+ std::string checksum;
+ uint8_t parsedChecksum;
+ uint8_t calculatedChecksum;
+
+ enum MessageID { // These ID's are according to NMEA standard.
+ Unknown = -1,
+ GGA = 0,
+ GLL = 1,
+ GSA = 2,
+ GSV = 3,
+ RMC = 4,
+ VTG = 5, // notice missing 6,7
+ ZDA = 8
+ };
+public:
+ NMEASentence();
+ //NMEASentence(const NMEASentence& ref);
+ virtual ~NMEASentence();
+
+ bool checksumOK() const;
+ bool valid() const;
+
+};
+
+
+
+
+class NMEAParseError : public std::exception {
+public:
+ std::string message;
+ NMEASentence nmea;
+
+ NMEAParseError(std::string msg);
+ NMEAParseError(std::string msg, NMEASentence n);
+ virtual ~NMEAParseError();
+
+ std::string what();
+};
+
+
+
+
+class NMEAParser {
+private:
+ std::unordered_map<std::string, std::function<void(NMEASentence)>> eventTable;
+ std::string buffer;
+ bool fillingbuffer;
+ uint32_t maxbuffersize; //limit the max size if no newline ever comes... Prevents huge buffer string internally
+
+ void parseText (NMEASentence& nmea, std::string s); //fills the given NMEA sentence with the results of parsing the string.
+
+ void onInfo (NMEASentence& n, std::string s);
+ void onWarning (NMEASentence& n, std::string s);
+ void onError (NMEASentence& n, std::string s);
+public:
+
+ NMEAParser();
+ virtual ~NMEAParser();
+
+ bool log;
+
+ Event<void(const NMEASentence&)> onSentence; // called every time parser receives any NMEA sentence
+ void setSentenceHandler(std::string cmdKey, std::function<void(const NMEASentence&)> handler); //one handler called for any named sentence where name is the "cmdKey"
+
+ // Byte streaming functions
+ void readByte (uint8_t b);
+ void readBuffer (uint8_t* b, uint32_t size);
+ void readLine (std::string line);
+
+ // This function expects the data to be a single line with an actual sentence in it, else it throws an error.
+ void readSentence (std::string cmd); // called when parser receives a sentence from the byte stream. Can also be called by user to inject sentences.
+
+ static uint8_t calculateChecksum(std::string); // returns checksum of string -- XOR
+
+};
+
+}
+
+#endif /* NMEAPARSER_H_ */
diff --git a/include/nmeaparse/NumberConversion.h b/include/nmeaparse/NumberConversion.h
new file mode 100644
index 0000000..b872124
--- /dev/null
+++ b/include/nmeaparse/NumberConversion.h
@@ -0,0 +1,47 @@
+/*
+ * NumberConversion.h
+ *
+ * Created on: Aug 14, 2014
+ * Author: Cameron Karlsson
+ */
+
+#ifndef NUMBERCONVERSION_H_
+#define NUMBERCONVERSION_H_
+
+
+#include <cstdint>
+#include <string>
+#include <sstream>
+#include <exception>
+
+
+namespace nmea {
+
+class NumberConversionError : public std::exception {
+public:
+ std::string message;
+ NumberConversionError(std::string msg)
+ : message(msg)
+ {};
+
+ virtual ~NumberConversionError()
+ {};
+
+ std::string what(){
+ return message;
+ }
+};
+
+
+
+
+double parseDouble(std::string s);
+int64_t parseInt(std::string s, int radix = 10);
+
+//void NumberConversion_test();
+
+}
+
+
+
+#endif /* NUMBERCONVERSION_H_ */
diff --git a/include/nmeaparse/nmea.h b/include/nmeaparse/nmea.h
new file mode 100644
index 0000000..271dc55
--- /dev/null
+++ b/include/nmeaparse/nmea.h
@@ -0,0 +1,28 @@
+/*
+* nmea.h
+*
+* Created on: March 23, 2014
+* Author: Cameron Karlsson
+*/
+
+
+// The implementation of a NMEA 0183 parser.
+// The implementation of a NMEA 0183 sentence generator.
+// The implementation of a GPS data service.
+
+
+#ifndef NMEA_H_
+#define NMEA_H_
+
+
+
+#include <nmeaparse/NMEAParser.h>
+#include <nmeaparse/NMEACommand.h>
+#include <nmeaparse/GPSService.h>
+
+#include <nmeaparse/NumberConversion.h>
+
+
+
+
+#endif NMEA_H_ \ No newline at end of file