From 814eceb82c54ceb28a1915585af93731aa283337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 19 Aug 2021 19:35:26 +0200 Subject: [PATCH] Added support for ONmove 7xx series GHP files --- gpxsee.pro | 4 +- src/data/data.cpp | 6 +- src/data/{omdparser.cpp => onmoveparsers.cpp} | 105 +++++++++++++++++- src/data/{omdparser.h => onmoveparsers.h} | 31 +++++- 4 files changed, 138 insertions(+), 8 deletions(-) rename src/data/{omdparser.cpp => onmoveparsers.cpp} (62%) rename src/data/{omdparser.h => onmoveparsers.h} (55%) diff --git a/gpxsee.pro b/gpxsee.pro index 057ac0a6..d479d49a 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -95,7 +95,7 @@ HEADERS += src/common/config.h \ src/GUI/areaitem.h \ src/data/itnparser.h \ src/data/link.h \ - src/data/omdparser.h \ + src/data/onmoveparsers.h \ src/data/ov2parser.h \ src/map/IMG/bitmapline.h \ src/map/IMG/bitstream.h \ @@ -290,7 +290,7 @@ SOURCES += src/main.cpp \ src/GUI/areaitem.cpp \ src/data/address.cpp \ src/data/itnparser.cpp \ - src/data/omdparser.cpp \ + src/data/onmoveparsers.cpp \ src/data/ov2parser.cpp \ src/data/waypoint.cpp \ src/map/IMG/bitmapline.cpp \ diff --git a/src/data/data.cpp b/src/data/data.cpp index 49b2da02..babf1d5e 100644 --- a/src/data/data.cpp +++ b/src/data/data.cpp @@ -19,7 +19,7 @@ #include "smlparser.h" #include "ov2parser.h" #include "itnparser.h" -#include "omdparser.h" +#include "onmoveparsers.h" #include "data.h" @@ -43,6 +43,7 @@ static SMLParser sml; static OV2Parser ov2; static ITNParser itn; static OMDParser omd; +static GHPParser ghp; static QMap parsers() { @@ -70,6 +71,7 @@ static QMap parsers() map.insert("ov2", &ov2); map.insert("itn", &itn); map.insert("omd", &omd); + map.insert("ghp", &ghp); return map; } @@ -147,7 +149,7 @@ QString Data::formats() + qApp->translate("Data", "KML files") + " (*.kml);;" + qApp->translate("Data", "LOC files") + " (*.loc);;" + qApp->translate("Data", "NMEA files") + " (*.nmea);;" - + qApp->translate("Data", "OMD files") + " (*.omd);;" + + qApp->translate("Data", "ONmove files") + " (*.omd *.ghp);;" + qApp->translate("Data", "OV2 files") + " (*.ov2);;" + qApp->translate("Data", "OziExplorer files") + " (*.plt *.rte *.wpt);;" + qApp->translate("Data", "SLF files") + " (*.slf);;" diff --git a/src/data/omdparser.cpp b/src/data/onmoveparsers.cpp similarity index 62% rename from src/data/omdparser.cpp rename to src/data/onmoveparsers.cpp index bc4129bf..0f7d93eb 100644 --- a/src/data/omdparser.cpp +++ b/src/data/onmoveparsers.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "omdparser.h" +#include "onmoveparsers.h" static inline quint16 u16(const char *buffer) @@ -173,3 +173,106 @@ bool OMDParser::parse(QFile *file, QList &tracks, return true; } + + +bool GHPParser::readHeaderFile(const QString &ghpPath, Header &hdr) +{ + QFileInfo fi(ghpPath); + QString path = fi.absoluteDir().filePath(fi.baseName() + ".GHT"); + QFile file(path); + char buffer[96]; + + if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s: %s", qPrintable(path), qPrintable(file.errorString())); + return false; + } + if (file.read(buffer, sizeof(buffer)) != sizeof(buffer)) { + qWarning("%s: invalid GHT file", qPrintable(path)); + return false; + } + + quint8 Y = buffer[0]; + quint8 M = buffer[1]; + quint8 D = buffer[2]; + quint8 h = buffer[3]; + quint8 m = buffer[4]; + quint8 s = buffer[5]; + quint8 avgHr = buffer[61]; + quint8 maxHr = buffer[60]; + + QDateTime date(QDate(Y + 2000, M, D), QTime(h, m, s), Qt::UTC); + if (!date.isValid()) { + qWarning("%s: invalid date", qPrintable(path)); + return false; + } + + hdr.date = date; + hdr.hr = avgHr || maxHr; + + return true; +} + +bool GHPParser::readF0(const char *chunk, const Header &hdr, int &time, + SegmentData &segment) +{ + qint32 lat = s32(chunk); + qint32 lon = s32(chunk + 4); + qint16 alt = s16(chunk + 8); + quint16 speed = u16(chunk + 10); + quint8 hr = chunk[12]; + quint8 fia = chunk[13]; + quint8 ms = chunk[16]; + + if (fia == 3) { + Trackpoint t(Coordinates(lon / 1000000.0, lat / 1000000.0)); + if (!t.coordinates().isValid()) { + _errorString = "invalid coordinates"; + return false; + } + t.setTimestamp(QDateTime(hdr.date.date(), + hdr.date.time().addMSecs(time * 100), Qt::UTC)); + t.setSpeed(speed / 360.0); + t.setElevation(alt); + if (hdr.hr) + t.setHeartRate(hr); + + segment.append(t); + } + + time += ms; + + return true; +} + +bool GHPParser::parse(QFile *file, QList &tracks, + QList &routes, QList &polygons, QVector &waypoints) +{ + Q_UNUSED(routes); + Q_UNUSED(waypoints); + Q_UNUSED(polygons); + SegmentData segment; + Header hdr; + int time = 0; + char chunk[20]; + qint64 size; + + // see OMD + readHeaderFile(file->fileName(), hdr); + + while ((size = file->read(chunk, sizeof(chunk))) == sizeof(chunk)) + if (!readF0(chunk, hdr, time, segment)) + return false; + + if (size < 0) { + _errorString = "I/O error"; + return false; + } else if (size) { + _errorString = "unexpected end of file"; + return false; + } + + tracks.append(TrackData()); + tracks.last().append(segment); + + return true; +} diff --git a/src/data/omdparser.h b/src/data/onmoveparsers.h similarity index 55% rename from src/data/omdparser.h rename to src/data/onmoveparsers.h index d7c93a4e..62dca989 100644 --- a/src/data/omdparser.h +++ b/src/data/onmoveparsers.h @@ -1,5 +1,5 @@ -#ifndef OMDPARSER_H -#define OMDPARSER_H +#ifndef ONMOVEPARSERS_H +#define ONMOVEPARSERS_H #include "parser.h" @@ -39,4 +39,29 @@ private: QString _errorString; }; -#endif // OMDPARSER_H +class GHPParser : public Parser +{ +public: + bool parse(QFile *file, QList &tracks, QList &routes, + QList &polygons, QVector &waypoints); + QString errorString() const {return _errorString;} + int errorLine() const {return 0;} + +private: + struct Header + { + Header() : date(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC)), + hr(true) {} + + QDateTime date; + bool hr; + }; + + bool readHeaderFile(const QString &ghpPath, Header &hdr); + bool readF0(const char *chunk, const Header &hdr, int &time, + SegmentData &segment); + + QString _errorString; +}; + +#endif // ONMOVEPARSERS_H