From 09a3c9c3485a023b5ae98652c46129941ca7fd41 Mon Sep 17 00:00:00 2001 From: ckgt Date: Sat, 28 Mar 2015 19:08:43 -0400 Subject: Initial commit. --- include/nmeaparse/Event.h | 215 +++++++++++++++++++++++++++++++++++ include/nmeaparse/GPSFix.h | 180 +++++++++++++++++++++++++++++ include/nmeaparse/GPSService.h | 45 ++++++++ include/nmeaparse/NMEACommand.h | 115 +++++++++++++++++++ include/nmeaparse/NMEAParser.h | 120 +++++++++++++++++++ include/nmeaparse/NumberConversion.h | 47 ++++++++ include/nmeaparse/nmea.h | 28 +++++ 7 files changed, 750 insertions(+) create mode 100644 include/nmeaparse/Event.h create mode 100644 include/nmeaparse/GPSFix.h create mode 100644 include/nmeaparse/GPSService.h create mode 100644 include/nmeaparse/NMEACommand.h create mode 100644 include/nmeaparse/NMEAParser.h create mode 100644 include/nmeaparse/NumberConversion.h create mode 100644 include/nmeaparse/nmea.h (limited to 'include') 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 +#include +#include + + + +namespace nmea { + + + template class EventHandler; + template class Event; + + + template + class EventHandler + { + friend Event; + private: + // Typenames + typename Event::ListIterator _iterator; + + // Static members + static uint64_t LastID; + + // Properties + uint64_t ID; + std::function 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 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(); + return ptr; + } + }; + + template + uint64_t EventHandler::LastID = 0; + + + template + class Event + { + friend EventHandler; + private: + // Typenames + typedef typename std::list>::iterator ListIterator; + + // Static members + // (none) + + // Properties + std::list> 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 registerHandler(EventHandler 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 registerHandler(std::function handler) { + EventHandler wrapper(handler); + ListIterator itr = handlers.insert(handlers.end(), wrapper); + wrapper._iterator = itr; + return wrapper; + } + + bool removeHandler(EventHandler& 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 operator +=(EventHandler handler) { return registerHandler(handler); }; + EventHandler operator +=(std::function handler) { return registerHandler(handler); }; + bool operator -=(EventHandler& handler) { return removeHandler(handler); }; + bool operator -=(uint64_t handlerID) { return removeHandler(handlerID); }; + + EventHandler& operator =(const EventHandler& 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 +#include +#include +#include +#include +#include +#include + +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 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 +#include +#include +#include +#include +#include + +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 onLockStateChanged; // user assignable handler, called whenever lock changes + Event 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 +#include + +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 + 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 + 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 +#include +#include +#include +#include +#include +#include + + + +//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 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> 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 onSentence; // called every time parser receives any NMEA sentence + void setSentenceHandler(std::string cmdKey, std::function 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 +#include +#include +#include + + +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 +#include +#include + +#include + + + + +#endif NMEA_H_ \ No newline at end of file -- cgit v1.2.3