From 0545e6d9f33dd9add25620ebdf3359f71199e5d3 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 9 Jan 2024 15:20:07 +0100 Subject: [PATCH 1/3] adding helper functions --- src/qdomyos-zwift.pri | 2 + src/zwift-api/MapCoordinate.h | 21 +++++++ src/zwift-api/PlayerStateWrapper.h | 87 +++++++++++++++++++++++++++++ src/zwift-api/ZwiftWorldConstants.h | 25 +++++++++ 4 files changed, 135 insertions(+) create mode 100644 src/zwift-api/MapCoordinate.h create mode 100644 src/zwift-api/ZwiftWorldConstants.h diff --git a/src/qdomyos-zwift.pri b/src/qdomyos-zwift.pri index 28334c405..dd2b89e68 100644 --- a/src/qdomyos-zwift.pri +++ b/src/qdomyos-zwift.pri @@ -291,7 +291,9 @@ HEADERS += \ $$PWD/proformtelnetbike.h \ $$PWD/windows_zwift_workout_paddleocr_thread.h \ $$PWD/fakerower.h \ + $$PWD/zwift-api/MapCoordinate.h \ $$PWD/zwift-api/PlayerStateWrapper.h \ + $$PWD/zwift-api/ZwiftWorldConstants.h \ $$PWD/zwift-api/zwift_client_auth.h \ virtualdevice.h \ $$PWD/androidactivityresultreceiver.h \ diff --git a/src/zwift-api/MapCoordinate.h b/src/zwift-api/MapCoordinate.h new file mode 100644 index 000000000..2208a2456 --- /dev/null +++ b/src/zwift-api/MapCoordinate.h @@ -0,0 +1,21 @@ +#ifndef MAPCOORDINATE_H +#define MAPCOORDINATE_H + +#include "ZwiftWorldConstants.h" + +class MapCoordinate { +public: + double X; + double Y; + double Altitude; + double WorldId; + + MapCoordinate(double X, double Y, double Altitude, double WorldID) { + this->X = X; + this->Y = Y; + this->Altitude = Altitude; + this->WorldId = WorldID; + }; +}; + +#endif // MAPCOORDINATE_H diff --git a/src/zwift-api/PlayerStateWrapper.h b/src/zwift-api/PlayerStateWrapper.h index 06c0c93b9..93f08d655 100644 --- a/src/zwift-api/PlayerStateWrapper.h +++ b/src/zwift-api/PlayerStateWrapper.h @@ -10,6 +10,9 @@ #include #include +#include "MapCoordinate.h" +#include "ZwiftWorldConstants.h" + class ZwiftRequest: public QObject { Q_OBJECT @@ -52,10 +55,94 @@ class ZwiftRequest: public QObject { return reply->readAll(); } + MapCoordinate* ToMapCoordinate(int worldId, double Longitude, double Latitude, double Altitude) + { + ZwiftWorldConstants* worldConstants; + + switch (worldId) + { + case _Watopia: + worldConstants = Watopia; + break; + case _MakuriIslands: + worldConstants = MakuriIslands; + break; + case _Richmond: + worldConstants = Richmond; + break; + case _London: + worldConstants = London; + break; + case _NewYork: + worldConstants = NewYork; + break; + case _Innsbruck: + worldConstants = Innsbruck; + break; + case _Bologna: + worldConstants = Bologna; + break; + case _Yorkshire: + worldConstants = Yorkshire; + break; + case _CritCity: + worldConstants = CritCity; + break; + case _France: + worldConstants = France; + break; + case _Paris: + worldConstants = Paris; + break; + default: + return new MapCoordinate(0,0,0,0); + } + + // NOTE: The coordinates in Zwift itself are flipped which + // is why you see longitude used to calculate latitude + // and negative latitude to calculate longitude. + double latitudeAsCentimetersFromOrigin = (Longitude * worldConstants->MetersBetweenLatitudeDegree * 100); + double latitudeOffsetCentimeters = latitudeAsCentimetersFromOrigin - worldConstants->CenterLatitudeFromOrigin; + + double longitudeAsCentimetersFromOrigin = -Latitude * worldConstants->MetersBetweenLongitudeDegree * 100; + double longitudeOffsetCentimeters = longitudeAsCentimetersFromOrigin - worldConstants->CenterLongitudeFromOrigin; + + return new MapCoordinate(latitudeOffsetCentimeters, longitudeOffsetCentimeters, Altitude, worldId); + } + private: QNetworkAccessManager manager; const QString BASE_URL = "https://us-or-rly101.zwift.com"; const QString getAccessToken; + + enum ZwiftWorldId + { + _Unknown = -1, + _Watopia = 1, + _Richmond = 2, + _London = 3, + _NewYork = 4, + _Innsbruck = 5, + _Bologna = 6, + _Yorkshire = 7, + _CritCity = 8, + _MakuriIslands = 9, + _France = 10, + _Paris = 11 + }; + + // https://github.com/sandermvanvliet/RoadCaptain/blob/d8ec891349212d2a8ef2691925376712680e0bc4/src/RoadCaptain/TrackPoint.cs#L256 + ZwiftWorldConstants* Watopia = new ZwiftWorldConstants(110614.71, 109287.52, -11.644904f, 166.95293); + ZwiftWorldConstants* Richmond = new ZwiftWorldConstants(110987.82, 88374.68, 37.543f, -77.4374f); + ZwiftWorldConstants* London = new ZwiftWorldConstants(111258.3, 69400.28, 51.501705f, -0.16794094f); + ZwiftWorldConstants* NewYork = new ZwiftWorldConstants(110850.0, 84471.0, 40.76723f, -73.97667f); + ZwiftWorldConstants* Innsbruck = new ZwiftWorldConstants(111230.0, 75027.0, 47.2728f, 11.39574f); + ZwiftWorldConstants* Bologna = new ZwiftWorldConstants(111230.0, 79341.0, 44.49477f, 11.34324f); + ZwiftWorldConstants* Yorkshire = new ZwiftWorldConstants(111230.0, 65393.0, 53.991127f, -1.541751f); + ZwiftWorldConstants* CritCity = new ZwiftWorldConstants(110614.71, 109287.52, -10.3844f, 165.8011f); + ZwiftWorldConstants* MakuriIslands = new ZwiftWorldConstants(110614.71, 109287.52, -10.749806f, 165.83644f); + ZwiftWorldConstants* France = new ZwiftWorldConstants(110726.0, 103481.0, -21.695074f, 166.19745f); + ZwiftWorldConstants* Paris = new ZwiftWorldConstants(111230.0, 73167.0, 48.86763f, 2.31413f); }; class World { diff --git a/src/zwift-api/ZwiftWorldConstants.h b/src/zwift-api/ZwiftWorldConstants.h new file mode 100644 index 000000000..661159fdd --- /dev/null +++ b/src/zwift-api/ZwiftWorldConstants.h @@ -0,0 +1,25 @@ +#ifndef ZWIFTWORLDCONSTANTS_H +#define ZWIFTWORLDCONSTANTS_H + +class ZwiftWorldConstants +{ +public: + double MetersBetweenLatitudeDegree; + double MetersBetweenLongitudeDegree; + double MetersBetweenLatitudeDegreeMul; + double MetersBetweenLongitudeDegreeMul; + double CenterLatitudeFromOrigin; + double CenterLongitudeFromOrigin; + + ZwiftWorldConstants(double metersBetweenLatitudeDegree, double metersBetweenLongitudeDegree, double centerLatitudeFromOrigin, double centerLongitudeFromOrigin) + { + MetersBetweenLatitudeDegree = metersBetweenLatitudeDegree; + MetersBetweenLongitudeDegree = metersBetweenLongitudeDegree; + MetersBetweenLatitudeDegreeMul = 1 / metersBetweenLatitudeDegree; + MetersBetweenLongitudeDegreeMul = 1 / metersBetweenLongitudeDegree; + CenterLatitudeFromOrigin = centerLatitudeFromOrigin * metersBetweenLatitudeDegree * 100; + CenterLongitudeFromOrigin = centerLongitudeFromOrigin * metersBetweenLongitudeDegree * 100; + } +}; + +#endif // ZWIFTWORLDCONSTANTS_H From c3bbacc8aa40b15e66c8c042117cac180d25000d Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 9 Jan 2024 17:02:06 +0100 Subject: [PATCH 2/3] Update trainprogram.cpp --- src/trainprogram.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/trainprogram.cpp b/src/trainprogram.cpp index 2fbdecf05..658cb3590 100644 --- a/src/trainprogram.cpp +++ b/src/trainprogram.cpp @@ -621,6 +621,14 @@ void trainprogram::scheduler() { static int zwift_counter = 5; if(zwift_counter++ >= 4) { zwift_counter = 0; + + QString id = zwift_world->player_id(); + QJsonParseError parseError; + QJsonDocument document = QJsonDocument::fromJson(id.toLocal8Bit(), &parseError); + QJsonObject ride = document.object(); + qDebug() << "zwift api player" << ride; + int worldId = ride[QStringLiteral("worldId")].toInt(); + QByteArray bb = zwift_world->playerStatus(zwift_player_id); #ifdef Q_OS_IOS #ifndef IO_UNDER_QT From eae374ba544a556e5ceb2d93e96e2b5265a32414 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 9 Jan 2024 17:14:05 +0100 Subject: [PATCH 3/3] should be ok --- src/trainprogram.cpp | 19 ++++++++++- src/zwift-api/PlayerStateWrapper.h | 54 +++++++++++++++--------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/trainprogram.cpp b/src/trainprogram.cpp index 658cb3590..d857ddd6b 100644 --- a/src/trainprogram.cpp +++ b/src/trainprogram.cpp @@ -635,9 +635,13 @@ void trainprogram::scheduler() { h->zwift_api_decodemessage_player(bb.data(), bb.length()); float alt = h->zwift_api_getaltitude(); float distance = h->zwift_api_getdistance(); + float lat = h->zwift_api_getlatitude(); + float lon = h->zwift_api_getlongitude(); #else float alt = 0; float distance = 0; + float lat = 0; + float lon = 0; #endif #elif defined(Q_OS_ANDROID) QAndroidJniEnvironment env; @@ -656,11 +660,24 @@ void trainprogram::scheduler() { #else float alt = 0; float distance = 0; + float lat = 0; + float lon = 0; #endif static float old_distance = 0; static float old_alt = 0; - qDebug() << "zwift api incline1" << old_distance << old_alt << distance << alt; + qDebug() << "zwift api incline1" << old_distance << old_alt << distance << alt << lat << lon; + + MapCoordinate* coord = zwift_world->ToMapCoordinate(worldId, lon, lat, alt); + if(coord) { + qDebug() << "zwift coordinate" << coord->X << coord->Y; + QGeoCoordinate p; + p.setLatitude(coord->X); + p.setLongitude(coord->Y); + p.setAltitude(coord->Altitude); + emit changeGeoPosition(p, 0, 0); + delete coord; + } if(old_distance > 0) { float delta = distance - old_distance; diff --git a/src/zwift-api/PlayerStateWrapper.h b/src/zwift-api/PlayerStateWrapper.h index 93f08d655..bf16cd58b 100644 --- a/src/zwift-api/PlayerStateWrapper.h +++ b/src/zwift-api/PlayerStateWrapper.h @@ -55,6 +55,16 @@ class ZwiftRequest: public QObject { return reply->readAll(); } +private: + QNetworkAccessManager manager; + const QString BASE_URL = "https://us-or-rly101.zwift.com"; + const QString getAccessToken; +}; + +class World { +public: + World(int worldId, const QString& getAccessToken) : worldId(worldId), request(getAccessToken) {} + MapCoordinate* ToMapCoordinate(int worldId, double Longitude, double Latitude, double Altitude) { ZwiftWorldConstants* worldConstants; @@ -110,12 +120,24 @@ class ZwiftRequest: public QObject { return new MapCoordinate(latitudeOffsetCentimeters, longitudeOffsetCentimeters, Altitude, worldId); } + QString getPlayers() { + return request.json("/relay/worlds/" + QString::number(worldId)); + } + + QByteArray playerStatus(int playerId) { + QByteArray buffer = request.protobuf("/relay/worlds/" + QString::number(worldId) + "/players/" + QString::number(playerId)); + return buffer; + } + + QString player_id() { + return request.json("/api/profiles/me"); + } + private: - QNetworkAccessManager manager; - const QString BASE_URL = "https://us-or-rly101.zwift.com"; - const QString getAccessToken; + int worldId; + ZwiftRequest request; - enum ZwiftWorldId + enum ZwiftWorldId { _Unknown = -1, _Watopia = 1, @@ -142,29 +164,7 @@ class ZwiftRequest: public QObject { ZwiftWorldConstants* CritCity = new ZwiftWorldConstants(110614.71, 109287.52, -10.3844f, 165.8011f); ZwiftWorldConstants* MakuriIslands = new ZwiftWorldConstants(110614.71, 109287.52, -10.749806f, 165.83644f); ZwiftWorldConstants* France = new ZwiftWorldConstants(110726.0, 103481.0, -21.695074f, 166.19745f); - ZwiftWorldConstants* Paris = new ZwiftWorldConstants(111230.0, 73167.0, 48.86763f, 2.31413f); -}; - -class World { -public: - World(int worldId, const QString& getAccessToken) : worldId(worldId), request(getAccessToken) {} - - QString getPlayers() { - return request.json("/relay/worlds/" + QString::number(worldId)); - } - - QByteArray playerStatus(int playerId) { - QByteArray buffer = request.protobuf("/relay/worlds/" + QString::number(worldId) + "/players/" + QString::number(playerId)); - return buffer; - } - - QString player_id() { - return request.json("/api/profiles/me"); - } - -private: - int worldId; - ZwiftRequest request; + ZwiftWorldConstants* Paris = new ZwiftWorldConstants(111230.0, 73167.0, 48.86763f, 2.31413f); }; class PlayerStateWrapper {