forked from GoldenCheetah/GoldenCheetah
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGoldenClient.h
161 lines (140 loc) · 6.04 KB
/
GoldenClient.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
* Copyright (c) 2009 Steve Gribble (gribble [at] cs.washington.edu) and
* Mark Liversedge ([email protected])
*
* 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
*/
#ifndef _GC_GoldenClient_h
#define _GC_GoldenClient_h 1
#include "GoldenCheetah.h"
#include <QString>
#include <QDebug>
#include <QMap>
#include <QQueue>
#include <QTcpSocket>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "ProtocolHandler.h"
typedef struct {
QString rider_name;
QString rider_id;
int ftp_watts;
float weight_kg;
int power_watts;
int cadence_rpm;
float distance_km;
int heartrate_bpm;
float speed_kph;
int place;
} RiderData;
typedef struct {
QString race_id;
float race_distance_km;
bool race_finished;
bool membership_changed;
QMap<QString,RiderData> riders_status;
} RaceStatus;
// This class manages the binding of the GoldenCheetah client with
// a GoldenServer. When connected, an instance of this class spawns
// a thread to manage reading and writing data from/to the server.
class GoldenClient : public QThread {
public:
GoldenClient() : running(false), connected(false), kill_signal(false) { }
~GoldenClient() { }
// Forge the connection to the GoldenServer and perform the initial
// handshake. If the handshake works, set up the cache of rider
// performance (initially empty). Returns true on success, in which
// case a thread has been spawned to manage the connection. Returns
// false on failure.
//
// raceid is the raceid to connect to, ridername is the name of
// the local rider. the rest should be self-explanatory. :)
bool connect(QString server_hostname, quint16 server_port,
QString raceid, QString ridername, int ftp_watts,
float weight_kg);
// Sever the connection with the server and kill off the thread that
// was spawned to manage it. Note that this MUST be called before
// the instance is destroyed, or the thread will be orphaned.
void closeAndExit();
// Send a telemetry update to the server.
//
// Note that we haven't yet figured out which telemetry data the
// server should use when calculating race updates. For example,
// one possibility is that the server just uses watts to calculate
// each rider's speed normalized to FTP, as a way of having a handicapped
// race. As another example, the server could use reported speed
// or reported distance. [For now, the server just uses the
// reported speed of the client, and ignores watts and distance.]
void sendTelemetry(int power_watts, int cadence_rpm,
float distance_km, int heartrate_bpm,
float speed_kph);
// Get a copy of the current race standings. Note that
// race_finished is set to true if the race is over (for any
// reason). Also note that membership_changed is set to true if the
// race membership has been updated since the last time anybody
// invoked getStandings().
RaceStatus getStandings();
// The client's particulars, exchanged with the server on session
// establishment. [Is just a cached copy of what's passed to me in
// connect().]
QString remote_host;
quint16 remote_port;
QString rider_raceid;
QString rider_name;
int rider_ftp_watts;
float rider_weight_kg;
// The race metadata, returned during the server handshake.
QString rider_id;
float race_distance_km;
private:
// For coordinating between the caller and the embedded thread.
QMutex client_lock;
QWaitCondition client_cond;
bool running; // thread running? controlled by the child thread
bool connected; // socket connected? controlled by the child thread
bool kill_signal; // controlled by caller via closeAndExit()
// The current race status/standings
RaceStatus race_status;
// The client can enqueue a message to be sent to the server
// on here by calling sendTelemetry().
QQueue<QSharedPointer<ProtocolMessage> > write_queue;
// connect() will spawn a child thread when it successfully
// connects to a server. The child thread will enter this
// private method.
void run();
// read a line of text from the socket; returns true on success,
// and includes the newline at the end of the string. since
// a read might block, we'll pass in a locker to release.
// "block" says whether to loop forever waiting for data.
bool read_line(QMutexLocker &locker, QTcpSocket &server,
bool block, QString &read_into_me);
// write a line of text to the socket; returns true on success,
// false if the write failed. since a write might block, we'll
// pass in a locker to release.
bool write_line(QMutexLocker &locker, QTcpSocket &server,
QString line_to_write);
// handle various messages from the server. returns false if things
// go wrong, in which case caller should bork out.
bool handle_message(QMutexLocker &locker, QTcpSocket &server,
QSharedPointer<ProtocolMessage> msg);
bool handle_clientlist(QMutexLocker &locker, QTcpSocket &server,
QSharedPointer<ClientListMessage> msg);
bool handle_standings(QMutexLocker &locker, QTcpSocket &server,
QSharedPointer<StandingsMessage> msg);
bool handle_raceconcluded(QMutexLocker &locker, QTcpSocket &server,
QSharedPointer<RaceConcludedMessage> msg);
};
#endif // _GC_GoldenClient_h