Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kettler serial connection fixes #2191

Closed
wants to merge 100 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
30b5612
fix docs in serial device selection regex
joekearney Nov 19, 2016
b12ef59
Fix commands sent to Kettler serial devices
joekearney Nov 19, 2016
2dea386
Fixup to enable build on QT 5.8 and Xcode 8.1
liversedge Nov 20, 2016
830500d
Splash screen size
liversedge Nov 20, 2016
fd487e4
VERSION 3.4 SIERRA BUILD
liversedge Nov 20, 2016
8d2b5ce
Undo accidental edit in src.pro
liversedge Nov 20, 2016
b059179
Edit Italian Translation
Nov 20, 2016
3e21619
Update FitRideFile.cpp
hunnymonster Nov 21, 2016
bd9d205
DataFilter : Match exact name for XDATA series
grauser Nov 21, 2016
19c76cd
CI Deprecate support for QT4 on Mac
liversedge Nov 22, 2016
c485e40
Merge pull request #2194 from UgoBor/master
amtriathlon Nov 23, 2016
a275396
Merge pull request #2196 from hunnymonster/patch-1
grauser Nov 23, 2016
8abbf99
Fit : Add some Garmin products
grauser Nov 23, 2016
1237953
Fixed SML lap swimming files import when using drill mode
amtriathlon Nov 24, 2016
3b09402
Merge pull request #2203 from amtriathlon/master
amtriathlon Nov 24, 2016
0c25841
Cosmetic - adding/maintaining consistency
hunnymonster Nov 24, 2016
1ab2bf5
Merge pull request #2205 from hunnymonster/patch-2
grauser Nov 24, 2016
6fc0c08
Added swim XData for SML lap swimming files
amtriathlon Nov 24, 2016
b7c65f1
Merge pull request #2206 from amtriathlon/SMLswimXdata
amtriathlon Nov 25, 2016
654de7a
Added Swedish translation
amtriathlon Nov 25, 2016
424f9ea
Merge pull request #2212 from amtriathlon/Swedish
amtriathlon Nov 25, 2016
42a13f1
MainWindow showhideToolbar always on Mac now
liversedge Nov 26, 2016
8a77973
Fixed metric formatting in Compare Pane
amtriathlon Nov 26, 2016
22733cd
Merge pull request #2217 from amtriathlon/master
amtriathlon Nov 26, 2016
5716234
Aerolab: Save parameters in MetaData
grauser Nov 26, 2016
749ba20
Fit: Add Wahoo ELEMNT in Device Name
grauser Nov 26, 2016
5128b72
Deprecate Mac Native Buttons
liversedge Nov 27, 2016
6ba6d07
Deprecate TrainingPeaks
liversedge Nov 27, 2016
f3e377b
Fix creation of qwkcode from fractional seconds.
bgrabow Nov 29, 2016
e03c28d
Fix display of fractional seconds in block hover cursor.
bgrabow Nov 29, 2016
3182028
Merge pull request #2221 from bgrabow/issue#2175
liversedge Nov 29, 2016
1baa7b2
Updated Swedish Translation
amtriathlon Nov 30, 2016
b17c1af
Axure Design Concepts for V4
liversedge Dec 2, 2016
ef73196
Update UX4 Design Doc
liversedge Dec 2, 2016
18f4606
Update UX4 design doc
liversedge Dec 3, 2016
8996d46
Udated Spanish Translation
amtriathlon Dec 5, 2016
e874f7f
Update UX4 design doc
liversedge Dec 5, 2016
a14d95c
Edraw Navigation Flow for UX4
liversedge Dec 6, 2016
1631813
Fix typo
kootox Dec 6, 2016
fa87d58
Merge pull request #2236 from kootox/master
liversedge Dec 6, 2016
4007d1f
Updates to User Flow
liversedge Dec 6, 2016
b682689
R GC.season.MeanMax includes Dates
liversedge Dec 7, 2016
0cbe495
Update User Flow UX4
liversedge Dec 7, 2016
ef0debe
Fix crash when merging activities.
bgrabow Dec 7, 2016
82a6ea1
Remove unused header reference.
bgrabow Dec 8, 2016
c75092d
Merge pull request #2241 from bgrabow/issue#2192-Prevent-crash-when-c…
liversedge Dec 8, 2016
4673566
User Personas Document - Athlete
liversedge Dec 8, 2016
e32c0ed
Train : Record load in XData TRAIN
grauser Dec 8, 2016
9c0f928
CSV : No value for temperature is not 0°
grauser Dec 8, 2016
ec1169b
Small compile nit fix
liversedge Dec 9, 2016
10ee4e0
CloudDB Upload/Download improvements
Joern-R Dec 10, 2016
02f0db2
Merge pull request #2243 from Joern-R/CDB-BlockCharts
Joern-R Dec 10, 2016
06244f4
Delayed preset charts loading to wait for custom metrics initialization
amtriathlon Dec 11, 2016
2a695b8
Merge pull request #2244 from amtriathlon/master
liversedge Dec 11, 2016
bc84b5d
Correction : Efficiency Factor by XPace if no Power
grauser Dec 11, 2016
89e43f4
Today's Plan API documentation
liversedge Dec 14, 2016
6a97652
User Flow Doc Update
liversedge Dec 17, 2016
56c9eb3
Training Planning Development Starts
liversedge Dec 17, 2016
7745666
TAU override ignored for integral method
liversedge Dec 18, 2016
19aebac
Save Start Date when HR/Pace Zones are updated
amtriathlon Dec 19, 2016
1bfa302
Train view : add web page (not enabled)
grauser Dec 17, 2016
fed0faa
RideFileCache : Add aPower/kg
grauser Dec 20, 2016
4e4949f
CPPlot : Add aPower/Kg serie
grauser Dec 20, 2016
9fe7f7a
Correct page for win build
grauser Dec 20, 2016
1f49789
Correct copy-paste
grauser Dec 20, 2016
5ff1515
Remove onError
grauser Dec 20, 2016
cc8e2dd
Update Web Browser Chart
liversedge Dec 21, 2016
639e7f3
Browser Download WIP
liversedge Dec 21, 2016
32d8275
Web Page Experiments to Fixup
liversedge Dec 22, 2016
3826f75
WebPage add http:// if no scheme present
liversedge Dec 23, 2016
1550cab
Deprecate GoogleMap and BingMap
grauser Dec 23, 2016
5edb26e
Minor translation related fix on LTMPlot
amtriathlon Dec 23, 2016
0bb79de
Google Drive Auth - more diags
liversedge Dec 24, 2016
b2f53c5
OAUTH ignore handshake "errors"
liversedge Dec 24, 2016
b72a3ee
Ignore SSL errors during reply processing
liversedge Dec 24, 2016
d70ad04
More SSL handshaking with GoogleDrive
liversedge Dec 25, 2016
11340b2
Monotonic timer for ANT sensors
dresco Dec 26, 2016
2141239
Blacklist S&C sensor if also Tacx FE-C device
dresco Dec 26, 2016
4787172
Less FE-C debug noise
dresco Dec 26, 2016
0ce7040
Ensure FE-C device is visible in pairing dialog
dresco Dec 26, 2016
8c1bcd1
Merge pull request #2263 from dresco/ANT
liversedge Dec 26, 2016
1819ba0
CloudDB - Chart Caching
Joern-R Dec 28, 2016
1375119
Merge pull request #2266 from Joern-R/CloudDB-Cache
Joern-R Dec 28, 2016
a0474bc
Fix FileSyncDialog SEGV on Synchronise
liversedge Dec 28, 2016
55a2c83
Monark: Add support for Monark 839E
erikboto Dec 7, 2016
2b5f13c
Monark: Fix issue on windows computer
erikboto Dec 29, 2016
cc70b9d
Merge pull request #2269 from erikboto/monark-updates
liversedge Dec 29, 2016
a88bbf9
Today's Plan integration (first part : auth + upload)
grauser Dec 30, 2016
d503b7b
Add Today's Plan client id
grauser Dec 30, 2016
9618418
Compress files for Today's Plan
grauser Dec 30, 2016
33c39b1
Today's Plan filename with extension
grauser Dec 30, 2016
e054c4d
Today's Plan display error message
grauser Dec 30, 2016
9d42ba8
Today's Plan support GC json !
grauser Dec 31, 2016
cae8666
Today's Plan : stop using staging
grauser Dec 31, 2016
8755705
Add LMFit optional dependency
liversedge Dec 31, 2016
7747121
Add LMFit to About > Version Dialog
liversedge Dec 31, 2016
a185ef9
ShareDialog : ignore ignoreSslErrors
grauser Dec 31, 2016
0b49596
fix docs in serial device selection regex
joekearney Nov 19, 2016
174244d
Fix commands sent to Kettler serial devices
joekearney Nov 19, 2016
7404bd9
Merge branch 'kettler-serial-fixes' of github.com:joekearney/GoldenCh…
joekearney Jan 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Expand Up @@ -7,7 +7,6 @@ compiler:
- gcc
env:
matrix:
- BRANCH=master QT=qt4 QT_PATH=qt
- BRANCH=master QT=qt5 QT_PATH=qt5 QT_VER=5.5.1
global:
- secure: iqYW7f3//ZkMVzeCEarYn0S0DqKjFU9juBh0KF6WTlUsKX902Jtsk7dFoJlNDYBf63HLgV+wW2Hc6MxI9sGiUkom0gY9/To/aeGIJFGEX2sLm/e0Ok3qN521FA0Q/OiCFsD0RC6J+yrHxzI+rf8Z1rujceUsz2KgsrfAjYYv+BY=
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added doc/contrib/Todays Plan API.docx
Binary file not shown.
Binary file added doc/design/Flow UX4.eddx
Binary file not shown.
Binary file added doc/design/GC Personas.odt
Binary file not shown.
Binary file added doc/design/GoldenCheetah v4.rp
Binary file not shown.
Binary file added doc/design/Training Themes v1.1.odt
Binary file not shown.
31 changes: 31 additions & 0 deletions src/ANT/ANT.cpp
Expand Up @@ -120,6 +120,11 @@ ANT::ANT(QObject *parent, DeviceConfiguration *devConf, QString athlete) : QThre
currentRollingResistance = rollingResistance = 0.004; // typical for road
gradient = 0.1;

// elapsed time reference
elapsedTimer.start();
if (!elapsedTimer.isMonotonic())
qDebug() << "Caution: ANT timer is not monotonic";

// state machine
state = ST_WAIT_FOR_SYNC;
length = bytes = 0;
Expand Down Expand Up @@ -1297,3 +1302,29 @@ void ANT::setControlChannel(int channel)
{
controlChannel = channel;
}

qint64 ANT::getElapsedTime()
{
return elapsedTimer.elapsed();
}

// blacklist a specific sensor
void ANT::blacklistSensor(int device_number, int device_id)
{
for (int i=0; i<channels; i++) {
if ((antChannel[i]->device_number == device_number) && (antChannel[i]->device_id == device_id)) {
if (!antChannel[i]->blacklisted) {
char *name = NULL;
for (int i=0; ant_sensor_types[i].suffix != '\0'; i++) {
if (ant_sensor_types[i].device_id == device_id)
name = (char*)ant_sensor_types[i].descriptive_name;
}

if (name)
qDebug() << "*** Blacklisting" << name << "sensor id" << device_number;

antChannel[i]->blacklisted = 1;
}
}
}
}
6 changes: 6 additions & 0 deletions src/ANT/ANT.h
Expand Up @@ -37,6 +37,7 @@
#include <QStringList>
#include <QTime>
#include <QTimer>
#include <QElapsedTimer>
#include <QProgressDialog>
#include <QFile>

Expand Down Expand Up @@ -476,6 +477,7 @@ public slots:
int removeDevice(int device_number, int channel_type);
ANTChannel *findDevice(int device_number, int channel_type);
int startWaitingSearch();
void blacklistSensor(int device_number, int channel_type);

// transmission
void sendMessage(ANTMessage);
Expand Down Expand Up @@ -564,6 +566,8 @@ public slots:
void setTrainerReady(bool status) { telemetry.setTrainerReady(status); }
void setTrainerRunning(bool status) { telemetry.setTrainerRunning(status); }

qint64 getElapsedTime();

private:

void run();
Expand Down Expand Up @@ -609,6 +613,8 @@ public slots:
int powerchannels; // how many power channels do we have?
QDateTime lastCadenceMessage;

QElapsedTimer elapsedTimer;

QQueue<setChannelAtom> channelQueue; // messages for configuring channels from controller

// generic trainer settings
Expand Down
108 changes: 60 additions & 48 deletions src/ANT/ANTChannel.cpp
Expand Up @@ -59,7 +59,8 @@ ANTChannel::init()
status = Closed;
fecPrevRawDistance=0;
fecCapabilities=0;
lastMessageTimestamp = lastMessageTimestamp2 = QTime::currentTime();
lastMessageTimestamp = lastMessageTimestamp2 = parent->getElapsedTime();
blacklisted=0;
}

//
Expand Down Expand Up @@ -342,6 +343,12 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
product_id=MANUFACTURER_MODEL_NUMBER_ID(message);
checkCinqo();

// If we are a Tacx FE-C trainer then blacklist the Speed and Cadence channel
// on the same device, as known to cause problems due to poor quality data
// (multiple unchanged messages between valid updates)
if (is_fec && manufacturer_id == 0x59)
parent->blacklistSensor(device_number, ANT_SPORT_SandC_TYPE);

} else if (MESSAGE_IS_BATTERY_VOLTAGE(message)) {
// todo: push battery status up to train view when we have a means to display notifications
}
Expand Down Expand Up @@ -631,9 +638,9 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
if (time) {
rpm = 1024*60*revs / time;
last_measured_rpm = rpm;
lastMessageTimestamp = QTime::currentTime();
lastMessageTimestamp = parent->getElapsedTime();
} else {
int ms = lastMessageTimestamp.msecsTo(QTime::currentTime());
qint64 ms = parent->getElapsedTime() - lastMessageTimestamp;
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getCadence());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < last_measured_rpm / 2.0)
Expand All @@ -649,43 +656,48 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
{
float rpm;
static float last_measured_rpm;
// cadence first...
uint16_t time = antMessage.crankMeasurementTime - lastMessage.crankMeasurementTime;
uint16_t revs = antMessage.crankRevolutions - lastMessage.crankRevolutions;
if (time) {
rpm = 1024*60*revs / time;
last_measured_rpm = rpm;

if (is_moxy) /* do nothing for now */ ; //XXX fixme when moxy arrives XXX
else parent->setCadence(rpm);
lastMessageTimestamp = QTime::currentTime();
} else {
int ms = lastMessageTimestamp.msecsTo(QTime::currentTime());
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getCadence());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < last_measured_rpm / 2.0)
rpm = 0.0; // if rpm is less than half previous cadence we consider that we are stopped
parent->setCadence(rpm);
}
value = rpm;

// now speed ...
time = antMessage.wheelMeasurementTime - lastMessage.wheelMeasurementTime;
revs = antMessage.wheelRevolutions - lastMessage.wheelRevolutions;
if (time) {
rpm = 1024*60*revs / time;
if (is_moxy) /* do nothing for now */ ; //XXX fixme when moxy arrives XXX
else parent->setWheelRpm(rpm);
lastMessageTimestamp2 = QTime::currentTime();
} else {
int ms = lastMessageTimestamp2.msecsTo(QTime::currentTime());
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getWheelRpm());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < (float) 15.0)
rpm = 0.0; // if rpm is less than 15rpm (=4s) then we consider that we are stopped
parent->setWheelRpm(rpm);
if (!blacklisted) {
// cadence first...
uint16_t time = antMessage.crankMeasurementTime - lastMessage.crankMeasurementTime;
uint16_t revs = antMessage.crankRevolutions - lastMessage.crankRevolutions;
if (time) {
rpm = 1024*60*revs / time;
last_measured_rpm = rpm;

if (is_moxy) /* do nothing for now */ ; //XXX fixme when moxy arrives XXX
else parent->setCadence(rpm);
lastMessageTimestamp = parent->getElapsedTime();
} else {
qint64 ms = parent->getElapsedTime() - lastMessageTimestamp;
//qDebug() << "cadence ms:" << ms;
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getCadence());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < last_measured_rpm / 2.0)
rpm = 0.0; // if rpm is less than half previous cadence we consider that we are stopped
parent->setCadence(rpm);
}
value = rpm;

// now speed ...
time = antMessage.wheelMeasurementTime - lastMessage.wheelMeasurementTime;
revs = antMessage.wheelRevolutions - lastMessage.wheelRevolutions;
if (time) {
rpm = 1024*60*revs / time;
if (is_moxy) /* do nothing for now */ ; //XXX fixme when moxy arrives XXX
else parent->setWheelRpm(rpm);
lastMessageTimestamp2 = parent->getElapsedTime();
} else {
qint64 ms = parent->getElapsedTime() - lastMessageTimestamp2;
//qDebug() << "speed ms:" << ms;
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getWheelRpm());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < (float) 15.0)
rpm = 0.0; // if rpm is less than 15rpm (=4s) then we consider that we are stopped
parent->setWheelRpm(rpm);
}
value2 = rpm;
}
value2 = rpm;
}
break;

Expand All @@ -697,9 +709,9 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
uint16_t revs = antMessage.wheelRevolutions - lastMessage.wheelRevolutions;
if (time) {
rpm = 1024*60*revs / time;
lastMessageTimestamp = QTime::currentTime();
lastMessageTimestamp = parent->getElapsedTime();
} else {
int ms = lastMessageTimestamp.msecsTo(QTime::currentTime());
qint64 ms = parent->getElapsedTime() - lastMessageTimestamp;
rpm = qMin((float)(1000.0*60.0*1.0) / ms, parent->getWheelRpm());
// If we received a message but timestamp remain unchanged then we know that sensor have not detected magnet thus we deduct that rpm cannot be higher than this
if (rpm < (float) 15.0)
Expand Down Expand Up @@ -748,14 +760,14 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
parent->setTrainerStatusAvailable(true);
// temporarily disabled until calibration included in the code / TODO : remove && false
parent->setTrainerCalibRequired((antMessage.fecPowerCalibRequired || antMessage.fecResisCalibRequired) && false);
if (antMessage.fecPowerCalibRequired)
qDebug() << "Trainer calibration required (power)";
if (antMessage.fecResisCalibRequired)
qDebug() << "Trainer calibration required (resistance)";
//if (antMessage.fecPowerCalibRequired)
// qDebug() << "Trainer calibration required (power)";
//if (antMessage.fecResisCalibRequired)
// qDebug() << "Trainer calibration required (resistance)";
// temporarily disabled until calibration included in the code / TODO : remove && false
parent->setTrainerConfigRequired(antMessage.fecUserConfigRequired && false);
if (antMessage.fecUserConfigRequired)
qDebug() << "Trainer configuration required";
//if (antMessage.fecUserConfigRequired)
// qDebug() << "Trainer configuration required";
parent->setTrainerBrakeFault(antMessage.fecPowerOverLimits==FITNESS_EQUIPMENT_POWER_NOK_LOWSPEED
|| antMessage.fecPowerOverLimits==FITNESS_EQUIPMENT_POWER_NOK_HIGHSPEED
|| antMessage.fecPowerOverLimits==FITNESS_EQUIPMENT_POWER_NOK);
Expand Down Expand Up @@ -823,8 +835,8 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
// just process strides for now
if (antMessage.fpodInstant == false) {

QTime now=QTime::currentTime();
int ms = lastMessageTimestamp.msecsTo(now);
qint64 now = parent->getElapsedTime();
qint64 ms = now - lastMessageTimestamp;
lastMessageTimestamp = now;

// how many strides since last ?
Expand Down
11 changes: 6 additions & 5 deletions src/ANT/ANTChannel.h
Expand Up @@ -102,10 +102,10 @@ class ANTChannel : public QObject {
char id[10]; // short identifier
ANTChannelInitialisation mi;

int messages_received; // for signal strength metric
int messages_dropped;
QTime lastMessageTimestamp;
QTime lastMessageTimestamp2;
int messages_received; // for signal strength metric
int messages_dropped;
qint64 lastMessageTimestamp; // for time comparisons
qint64 lastMessageTimestamp2;

unsigned char rx_burst_data[RX_BURST_DATA_LEN];
int rx_burst_data_index;
Expand All @@ -114,9 +114,9 @@ class ANTChannel : public QObject {
void (*tx_ack_disposition)(struct ant_channel *);

// what we got
int manufacturer_id;
int product_id;
int product_version;
int manufacturer_id;

public:

Expand Down Expand Up @@ -153,6 +153,7 @@ class ANTChannel : public QObject {
int device_number;
int channel_type_flags;
int device_id;
int blacklisted;

// special cases
bool is_kickr;
Expand Down