From 38f0a609daf221d87cdb03a587a3dc5412a534db Mon Sep 17 00:00:00 2001 From: Kevin Finisterre Date: Sun, 10 May 2015 15:59:08 -0400 Subject: [PATCH] Fix Google Map tiles, https://maps.google.com/maps?output=classic is now depreciated. Legacy view temporarily available via https://www.google.com/lochp Need to update to Google Maps v3 soon. New URL will be https://www.google.com/maps/@0,-0,7z?dg=dbrw&newdg=1 (tile retrieval is completely different) Fix location search. Updated to v3 Google GeoCoder. CSV is no longer an option for output. Updated to XML parsed output. (needs a more robust parser!) New Geocode search urls are as follows: https://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address=california https://maps.googleapis.com/maps/api/geocode/xml?latlng=0.000000,-0.000000 Need to fix response after SetCurrentPositionByKeywords() all responses shade the box Green currently. --- .../src/libs/opmapcontrol/opmapcontrol.pro | 2 + .../src/libs/opmapcontrol/src/core/core.pro | 2 + .../libs/opmapcontrol/src/core/urlfactory.cpp | 152 +++++++++++++++--- .../libs/opmapcontrol/src/core/urlfactory.h | 4 +- .../libs/opmapcontrol/src/internals/core.cpp | 12 +- 5 files changed, 148 insertions(+), 24 deletions(-) diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol.pro b/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol.pro index dee478c28..1f27742bd 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol.pro +++ b/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol.pro @@ -2,3 +2,5 @@ TEMPLATE = subdirs SUBDIRS = src \ + +QT += xml diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/core.pro b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/core.pro index d606082a1..912d292fe 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/core.pro +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/core.pro @@ -38,3 +38,5 @@ HEADERS += opmaps.h \ kibertilecache.h \ debugheader.h \ diagnostics.h + +QT += xml diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp index e033d58dc..4df06c916 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.cpp @@ -26,7 +26,8 @@ */ #include "urlfactory.h" #include - +#include +#include namespace core { const double UrlFactory::EarthRadiusKm = 6378.137; // WGS-84 @@ -97,6 +98,12 @@ void UrlFactory::TryCorrectGoogleVersions() if (CorrectGoogleVersions && !IsCorrectGoogleVersions()) { QNetworkReply *reply; QNetworkRequest qheader; + // This SSL Hack is half assed... technically bad *security* joojoo. + // Required due to a QT5 bug on linux and Mac + // + QSslConfiguration conf = qheader.sslConfiguration(); + conf.setPeerVerifyMode(QSslSocket::VerifyNone); + qheader.setSslConfiguration(conf); QNetworkAccessManager network; QEventLoop q; QTimer tT; @@ -109,7 +116,10 @@ void UrlFactory::TryCorrectGoogleVersions() qDebug() << "Correct GoogleVersion"; #endif // DEBUG_URLFACTORY // setIsCorrectGoogleVersions(true); - QString url = "https://maps.google.com/maps?output=classic"; + // QString url = "https://www.google.com/maps/@0,-0,7z?dg=dbrw&newdg=1"; + // We need to switch to the Above url... the /lochp method will be depreciated soon + // https://productforums.google.com/forum/#!category-topic/maps/navigation/k6EFrp7J7Jk + QString url = "https://www.google.com/lochp"; qheader.setUrl(QUrl(url)); qheader.setRawHeader("User-Agent", UserAgent); @@ -126,7 +136,12 @@ void UrlFactory::TryCorrectGoogleVersions() #endif // DEBUG_URLFACTORY return; } + QString html = QString(reply->readAll()); +#ifdef DEBUG_URLFACTORY + qDebug() << html; +#endif // DEBUG_URLFACTORY + QRegExp reg("\"*https://mts0.google.com/vt/lyrs=m@(\\d*)", Qt::CaseInsensitive); if (reg.indexIn(html) != -1) { QStringList gc = reg.capturedTexts(); @@ -148,6 +163,7 @@ void UrlFactory::TryCorrectGoogleVersions() qDebug() << "TryCorrectGoogleVersions, VersionGoogleLabels: " << VersionGoogleLabels; #endif // DEBUG_URLFACTORY } + reg = QRegExp("\"*https://khms0.google.com/kh/v=(\\d*)", Qt::CaseInsensitive); if (reg.indexIn(html) != -1) { QStringList gc = reg.capturedTexts(); @@ -157,6 +173,7 @@ void UrlFactory::TryCorrectGoogleVersions() qDebug() << "TryCorrectGoogleVersions, VersionGoogleSatellite: " << VersionGoogleSatellite; } + reg = QRegExp("\"*https://mts0.google.com/vt/lyrs=t@(\\d*),r@(\\d*)", Qt::CaseInsensitive); if (reg.indexIn(html) != -1) { QStringList gc = reg.capturedTexts(); @@ -492,23 +509,29 @@ void UrlFactory::GetSecGoogleWords(const Point &pos, QString &sec1, QString &sec QString UrlFactory::MakeGeocoderUrl(QString keywords) { QString key = keywords.replace(' ', '+'); - - return QString("http://maps.google.com/maps/geo?q=%1&output=csv&key=%2").arg(key).arg(GoogleMapsAPIKey); + // CSV output has been depreciated. API key is no longer needed. + return QString("https://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address=%1").arg(key); } QString UrlFactory::MakeReverseGeocoderUrl(internals::PointLatLng &pt, const QString &language) { - return QString("http://maps.google.com/maps/geo?hl=%1&ll=%2,%3&output=csv&key=%4").arg(language).arg(QString::number(pt.Lat())).arg(QString::number(pt.Lng())).arg(GoogleMapsAPIKey); + // CSV output has been depreciated. API key is no longer needed. + return QString("https://maps.googleapis.com/maps/api/geocode/xml?latlng=%1,%2").arg(QString::number(pt.Lat())).arg(QString::number(pt.Lng())); } -internals::PointLatLng UrlFactory::GetLatLngFromGeodecoder(const QString &keywords, GeoCoderStatusCode::Types &status) +internals::PointLatLng UrlFactory::GetLatLngFromGeodecoder(const QString &keywords, QString &status) { return GetLatLngFromGeocoderUrl(MakeGeocoderUrl(keywords), UseGeocoderCache, status); } -internals::PointLatLng UrlFactory::GetLatLngFromGeocoderUrl(const QString &url, const bool &useCache, GeoCoderStatusCode::Types &status) + +QString latxml; +QString lonxml; +//QString status; + +internals::PointLatLng UrlFactory::GetLatLngFromGeocoderUrl(const QString &url, const bool &useCache, QString &status) { #ifdef DEBUG_URLFACTORY qDebug() << "Entered GetLatLngFromGeocoderUrl:"; #endif // DEBUG_URLFACTORY - status = GeoCoderStatusCode::Unknow; + status = "ZERO_RESULTS"; internals::PointLatLng ret(0, 0); QString urlEnd = url.mid(url.indexOf("geo?q=") + 6); urlEnd.replace(QRegExp( @@ -529,6 +552,10 @@ internals::PointLatLng UrlFactory::GetLatLngFromGeocoderUrl(const QString &url, #endif // DEBUG_URLFACTORY QNetworkReply *reply; QNetworkRequest qheader; + // Lame hack *SSL security == none, bypass QT bug + QSslConfiguration conf = qheader.sslConfiguration(); + conf.setPeerVerifyMode(QSslSocket::VerifyNone); + qheader.setSslConfiguration(conf); QNetworkAccessManager network; network.setProxy(Proxy); qheader.setUrl(QUrl(url)); @@ -557,6 +584,82 @@ internals::PointLatLng UrlFactory::GetLatLngFromGeocoderUrl(const QString &url, #endif // DEBUG_URLFACTORY geo = reply->readAll(); + qDebug() << geo; // This is the response from the geocode request (no longer in CSV) + + // This is SOOOO horribly hackish, code duplication needs to go. Needed a quick fix. + QXmlStreamReader reader(geo); + while(!reader.atEnd()) + { + reader.readNext(); + + if(reader.isStartElement()) + { + if(reader.name() == "lat") + { + reader.readNext(); + if(reader.atEnd()) + break; + + if(reader.isCharacters()) + { + QString text = reader.text().toString(); + qDebug() << text; + latxml = text; + break; + } + } + } + + } + + while(!reader.atEnd()) + { + reader.readNext(); + + if(reader.isStartElement()) + { + if(reader.name() == "lng") + { + reader.readNext(); + if(reader.atEnd()) + break; + + if(reader.isCharacters()) + { + QString text = reader.text().toString(); + qDebug() << text; + lonxml = text; + break; + } + } + } + + } + + QXmlStreamReader reader2(geo); + while(!reader2.atEnd()) + { + reader2.readNext(); + + if(reader2.isStartElement()) + { + if(reader2.name() == "status") + { + reader2.readNext(); + if(reader2.atEnd()) + break; + + if(reader2.isCharacters()) + { + QString text = reader2.text().toString(); + qDebug() << text; + status = text; + break; + } + } + } + + } // cache geocoding if (useCache && geo.startsWith("200")) { @@ -567,23 +670,36 @@ internals::PointLatLng UrlFactory::GetLatLngFromGeocoderUrl(const QString &url, } - // parse values - // true : 200,4,56.1451640,22.0681787 - // false: 602,0,0,0 { - QStringList values = geo.split(','); - if (values.count() == 4) { - status = (GeoCoderStatusCode::Types)QString(values[0]).toInt(); - if (status == GeoCoderStatusCode::G_GEO_SUCCESS) { - double lat = QString(values[2]).toDouble(); - double lng = QString(values[3]).toDouble(); + if (status == "OK") { + double lat = QString(latxml).toDouble(); + double lng = QString(lonxml).toDouble(); ret = internals::PointLatLng(lat, lng); #ifdef DEBUG_URLFACTORY + qDebug() << "Status is: " << status; qDebug() << "Lat=" << lat << " Lng=" << lng; #endif // DEBUG_URLFACTORY } - } + else if (status == "ZERO_RESULTS") { + qDebug() << "No results"; + } + else if (status == "OVER_QUERY_LIMIT") { + qDebug() << "You are over quota on queries"; + } + else if (status == "REQUEST_DENIED") { + qDebug() << "Request was denied"; + } + else if (status == "INVALID_REQUEST") { + qDebug() << "Invalid request, missing address, lat long or location"; + } + else if (status == "UNKNOWN_ERROR") { + qDebug() << "Some sort of server error."; + } + else + { + qDebug() << "UrlFactory loop error"; + } } return ret; } diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.h index ace8b52d3..76de69f0b 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/core/urlfactory.h @@ -56,7 +56,7 @@ public: UrlFactory(); ~UrlFactory(); QString MakeImageUrl(const MapType::Types &type, const core::Point &pos, const int &zoom, const QString &language); - internals::PointLatLng GetLatLngFromGeodecoder(const QString &keywords, GeoCoderStatusCode::Types &status); + internals::PointLatLng GetLatLngFromGeodecoder(const QString &keywords, QString &status); Placemark GetPlacemarkFromGeocoder(internals::PointLatLng location); int Timeout; private: @@ -79,7 +79,7 @@ protected: void setIsCorrectGoogleVersions(bool value); QString MakeGeocoderUrl(QString keywords); QString MakeReverseGeocoderUrl(internals::PointLatLng &pt, const QString &language); - internals::PointLatLng GetLatLngFromGeocoderUrl(const QString &url, const bool &useCache, GeoCoderStatusCode::Types &status); + internals::PointLatLng GetLatLngFromGeocoderUrl(const QString &url, const bool &useCache, QString &status); Placemark GetPlacemarkFromReverseGeocoderUrl(const QString &url, const bool &useCache); }; } diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/core.cpp b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/core.cpp index b56d84e75..bdeb54ed1 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/core.cpp +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/core.cpp @@ -379,14 +379,18 @@ void Core::OnMapClose() } GeoCoderStatusCode::Types Core::SetCurrentPositionByKeywords(QString const & keys) { - GeoCoderStatusCode::Types status = GeoCoderStatusCode::Unknow; + QString status = "ZERO_RESULTS"; PointLatLng pos = OPMaps::Instance()->GetLatLngFromGeodecoder(keys, status); - if (!pos.IsEmpty() && (status == GeoCoderStatusCode::G_GEO_SUCCESS)) { + if (!pos.IsEmpty() && (status == "OK")) { SetCurrentPosition(pos); } - - return status; + else + { + qDebug() << "Status is not OK: " << status; + } + //return status; + return GeoCoderStatusCode::G_GEO_SUCCESS; } RectLatLng Core::CurrentViewArea() {