mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 08:38:45 +00:00
.. configuration is injected into the CloudService by the CloudServiceFactory. .. next steps are to include this into the AddCloudWizard and OAuthDialog and ConfigDialog's Pages code. .. cloud services should still be working fully after this commit -- so long as config is performed via Options and not via the AddCloudWizard (although its close to complete).
231 lines
7.1 KiB
C++
231 lines
7.1 KiB
C++
/*
|
|
* Copyright (c) 2017 Mark Liversedge (liversedge@gmail.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "RideWithGPS.h"
|
|
#include "Athlete.h"
|
|
#include "Settings.h"
|
|
#include "Units.h"
|
|
#include "mvjson.h"
|
|
#include <QByteArray>
|
|
#include <QHttpMultiPart>
|
|
#include <QJsonDocument>
|
|
#include <QJsonArray>
|
|
#include <QJsonObject>
|
|
#include <QJsonValue>
|
|
|
|
#ifndef RIDEWITHGPS_DEBUG
|
|
#define RIDEWITHGPS_DEBUG false
|
|
#endif
|
|
#ifdef Q_CC_MSVC
|
|
#define printd(fmt, ...) do { \
|
|
if (RIDEWITHGPS_DEBUG) { \
|
|
printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \
|
|
__FUNCTION__, __VA_ARGS__); \
|
|
fflush(stdout); \
|
|
} \
|
|
} while(0)
|
|
#else
|
|
#define printd(fmt, args...) \
|
|
do { \
|
|
if (RIDEWITHGPS_DEBUG) { \
|
|
printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \
|
|
__FUNCTION__, ##args); \
|
|
fflush(stdout); \
|
|
} \
|
|
} while(0)
|
|
#endif
|
|
|
|
RideWithGPS::RideWithGPS(Context *context) : CloudService(context), context(context), root_(NULL) {
|
|
|
|
if (context) {
|
|
nam = new QNetworkAccessManager(this);
|
|
connect(nam, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> & )), this, SLOT(onSslErrors(QNetworkReply*, const QList<QSslError> & )));
|
|
}
|
|
|
|
uploadCompression = none; // gzip
|
|
useMetric = true; // distance and duration metadata
|
|
|
|
// config
|
|
settings.insert(Username, GC_RWGPSUSER);
|
|
settings.insert(Password, GC_RWGPSPASS);
|
|
}
|
|
|
|
RideWithGPS::~RideWithGPS() {
|
|
if (context) delete nam;
|
|
}
|
|
|
|
void
|
|
RideWithGPS::onSslErrors(QNetworkReply *reply, const QList<QSslError>&)
|
|
{
|
|
reply->ignoreSslErrors();
|
|
}
|
|
|
|
bool
|
|
RideWithGPS::open(QStringList &errors)
|
|
{
|
|
printd("RideWithGPS::open\n");
|
|
QString username = getSetting(GC_RWGPSUSER).toString();
|
|
if (username == "") {
|
|
errors << tr("RideWithGPS account not configured.");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
RideWithGPS::close()
|
|
{
|
|
printd("RideWithGPS::close\n");
|
|
// nothing to do for now
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
RideWithGPS::writeFile(QByteArray &, QString remotename, RideFile *ride)
|
|
{
|
|
Q_UNUSED(ride);
|
|
|
|
printd("RideWithGPS::writeFile(%s)\n", remotename.toStdString().c_str());
|
|
|
|
// RIDE WITH GPS USES ITS OWN FORMAT, WE CONSTRUCT FROM THE RIDE
|
|
int prevSecs = 0;
|
|
long diffSecs = 0;
|
|
|
|
|
|
int size = 0;
|
|
int totalSize = ride->dataPoints().size();
|
|
QDateTime rideDateTime = ride->startTime();
|
|
QString out, data;
|
|
|
|
QString username = getSetting(GC_RWGPSUSER).toString();
|
|
QString password = getSetting(GC_RWGPSPASS).toString();
|
|
|
|
// application/json
|
|
out += "{\"apikey\": \"p24n3a9e\", ";
|
|
out += "\"email\": \""+username+"\", ";
|
|
out += "\"password\": \""+password+"\", ";
|
|
out += "\"track_points\": \"";
|
|
|
|
data += "\[";
|
|
foreach (const RideFilePoint *point, ride->dataPoints()) {
|
|
size++;
|
|
|
|
if (point->secs == 0.0)
|
|
continue;
|
|
|
|
diffSecs = point->secs - prevSecs;
|
|
prevSecs = point->secs;
|
|
rideDateTime = rideDateTime.addSecs(diffSecs);
|
|
|
|
data += "{\"x\": ";
|
|
data += QString("%1").arg(point->lon,0,'f',GPS_COORD_TO_STRING);
|
|
data += ", \"y\": ";
|
|
data += QString("%1").arg(point->lat,0,'f',GPS_COORD_TO_STRING);
|
|
data += ", \"t\": ";
|
|
data += QString("%1").arg(rideDateTime.toTime_t());
|
|
data += ", \"e\": ";
|
|
data += QString("%1").arg(point->alt);
|
|
data += ", \"p\": ";
|
|
data += QString("%1").arg(point->watts);
|
|
data += ", \"c\": ";
|
|
data += QString("%1").arg(point->cad);
|
|
data += ", \"h\": ";
|
|
data += QString("%1").arg(point->hr);
|
|
|
|
data += "}";
|
|
|
|
if(size < totalSize)
|
|
data += ",";
|
|
}
|
|
data += "]";
|
|
out += data.replace("\"","\\\"");
|
|
out += "\"}";
|
|
|
|
QUrl url = QUrl("http://ridewithgps.com/trips.json");
|
|
QNetworkRequest request = QNetworkRequest(url);
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
|
|
|
// this must be performed asyncronously and call made
|
|
// to notifyWriteCompleted(QString remotename, QString message) when done
|
|
reply = nam->post(request, out.toLatin1());
|
|
|
|
// catch finished signal
|
|
connect(reply, SIGNAL(finished()), this, SLOT(writeFileCompleted()));
|
|
|
|
// remember
|
|
mapReply(reply,remotename);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
RideWithGPS::writeFileCompleted()
|
|
{
|
|
printd("RideWithGPS::writeFileCompleted()\n");
|
|
|
|
QNetworkReply *reply = static_cast<QNetworkReply*>(QObject::sender());
|
|
|
|
printd("reply:%s\n", reply->readAll().toStdString().c_str());
|
|
|
|
bool uploadSuccessful = false;
|
|
QString uploadError;
|
|
//XXXint tripid = 0;
|
|
|
|
try {
|
|
|
|
// parse the response
|
|
QString response = reply->readAll();
|
|
MVJSONReader jsonResponse(string(response.toLatin1()));
|
|
|
|
// get values
|
|
uploadError = jsonResponse.root->getFieldString("error").c_str();
|
|
//XXXif (jsonResponse.root->hasField("trip")) {
|
|
//XXX tripid = jsonResponse.root->getField("trip")->getFieldInt("id");
|
|
//XXX}
|
|
|
|
} catch(...) {
|
|
|
|
// problem!
|
|
uploadError = "bad response or parser exception.";
|
|
}
|
|
|
|
// no error so clear
|
|
if (uploadError.toLower() == "none" || uploadError.toLower() == "null") uploadError = "";
|
|
|
|
// set tags if uploaded (XXX not supported after refactor)
|
|
if (uploadError.length()>0 || reply->error() != QNetworkReply::NoError) uploadSuccessful = false;
|
|
else {
|
|
//XXX ride->ride()->setTag("RideWithGPS tripid", QString("%1").arg(tripid));
|
|
//XXX ride->setDirty(true);
|
|
|
|
uploadSuccessful = true;
|
|
}
|
|
|
|
if (uploadSuccessful && reply->error() == QNetworkReply::NoError) {
|
|
notifyWriteComplete( replyName(static_cast<QNetworkReply*>(QObject::sender())), tr("Completed."));
|
|
} else {
|
|
notifyWriteComplete( replyName(static_cast<QNetworkReply*>(QObject::sender())), tr("Network Error - Upload failed."));
|
|
}
|
|
}
|
|
|
|
static bool addRideWithGPS() {
|
|
CloudServiceFactory::instance().addService(new RideWithGPS(NULL));
|
|
return true;
|
|
}
|
|
|
|
static bool add = addRideWithGPS();
|