Remove WFAPI support

This commit is contained in:
Arto Jantunen
2016-04-21 20:09:33 +03:00
parent 6b12547e27
commit 4024d84a67
17 changed files with 13 additions and 1532 deletions

View File

@@ -63,10 +63,6 @@
#include "kqoauthmanager.h"
#endif
#ifdef GC_HAVE_WFAPI
#include "WFApi.h"
#endif
#ifdef GC_HAVE_SAMPLERATE
#include <samplerate.h>
#endif
@@ -266,12 +262,6 @@ QString GcCrashDialog::versionHTML()
vlc = "yes";
#endif
#ifdef GC_HAVE_WFAPI
QString wfapi = WFApi::getInstance()->apiVersion();
#else
QString wfapi = QString("none");
#endif
#ifdef GC_HAVE_SAMPLERATE
QString src = QString(src_get_version()).mid(14,6);
#else
@@ -332,7 +322,6 @@ QString GcCrashDialog::versionHTML()
.arg(ical)
.arg(usbxpress)
.arg(libusb)
.arg(wfapi)
.arg(vlc)
#if defined GC_VIDEO_QUICKTIME
.arg("quicktime")

View File

@@ -108,10 +108,6 @@
// LTM CHART DRAG/DROP PARSE
#include "LTMChartParser.h"
#ifdef GC_HAVE_WFAPI
#include "WFApi.h"
#endif
// CloudDB
#ifdef GC_HAS_CLOUD_DB
#include "CloudDBCommon.h"
@@ -155,10 +151,6 @@ MainWindow::MainWindow(const QDir &home)
setContentsMargins(0,0,0,0);
setAcceptDrops(true);
#ifdef GC_HAVE_WFAPI
WFApi *w = WFApi::getInstance(); // ensure created on main thread
w->apiVersion();//shutup compiler
#endif
Library::initialise(context->athlete->home->root());
QNetworkProxyQuery npq(QUrl("http://www.google.com"));
QList<QNetworkProxy> listOfProxies = QNetworkProxyFactory::systemProxyForQuery(npq);

View File

@@ -153,12 +153,6 @@ DeviceScanner::run()
active = true;
bool result = false;
#ifdef GC_HAVE_WFAPI
void *pool;
// get an autorelease pool for this thread!
if (wizard->deviceTypes.Supported[wizard->current].connector == DEV_BTLE) pool = WFApi::getInstance()->getPool();
#endif
for (int i=0; active && !result && i<10; i++) { // search for longer
// better to wait a while, esp. if its just a USB device
@@ -170,10 +164,6 @@ DeviceScanner::run()
result = quickScan(false);
}
if (active) emit finished(result); // only signal if we weren't aborted!
#ifdef GC_HAVE_WFAPI
WFApi::getInstance()->freePool(pool);
#endif
}
void
@@ -208,8 +198,7 @@ DeviceScanner::quickScan(bool deep) // scan quickly or if true scan forever, as
#endif
case DEV_NULL : wizard->controller = new NullController(NULL, NULL); break;
case DEV_ANTLOCAL : wizard->controller = new ANTlocalController(NULL, NULL); break;
#ifdef GC_HAVE_WFAPI
case DEV_KICKR : wizard->controller = new KickrController(NULL, NULL); break;
#ifdef QT_BLUETOOTH_LIB
case DEV_BT40 : wizard->controller = new BT40Controller(NULL, NULL); break;
#endif
@@ -260,12 +249,6 @@ DeviceScanner::quickScan(bool deep) // scan quickly or if true scan forever, as
} while (!isfound && deep && count++ < 2);
#ifdef GC_HAVE_WFAPI
// save away the device UUID, so we can choose it when connecting.
if (isfound && wizard->deviceTypes.Supported[wizard->current].connector == DEV_BTLE)
wizard->portSpec = ((KickrController*)(wizard->controller))->id();
#endif
return isfound;
}
@@ -453,7 +436,6 @@ AddSearch::nextId() const
case DEV_ANTLOCAL : return 50; break; // pair
case DEV_BT40 : return 55; break; // pair BT devices
default:
case DEV_KICKR :
case DEV_CT : return 60; break; // confirm and add
case DEV_MONARK : return 60; break; // confirm and add
case DEV_KETTLER : return 60; break; // confirm and add
@@ -887,10 +869,6 @@ AddPairBTLE::cleanupPage()
void
AddPairBTLE::initializePage()
{
#ifdef GC_HAVE_WFAPI
qDebug()<<"found this many devices:"<<WFApi::getInstance()->deviceCount();
#endif
// setup the controller and start it off so we can
// manipulate it
if (wizard->controller) delete wizard->controller;

View File

@@ -24,8 +24,7 @@
#include "DeviceTypes.h"
#include "Serial.h"
#include "RealtimeController.h"
#ifdef GC_HAVE_WFAPI
#include "KickrController.h"
#ifdef QT_BLUETOOTH_LIB
#include "BT40Controller.h"
#endif
#ifdef GC_HAVE_LIBUSB

View File

@@ -1,276 +0,0 @@
/*
* Copyright (c) 2013 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 "BT40.h"
BT40::BT40(QObject *parent, DeviceConfiguration *devConf) : QThread(parent)
{
this->parent = parent;
this->devConf = devConf;
scanned = false;
mode = -1;
load = 100;
slope = 1.0;
connect(WFApi::getInstance(), SIGNAL(discoveredDevices(int,bool)), this, SLOT(discoveredDevices(int,bool)));
}
BT40::~BT40()
{
stop();
}
// not required
void BT40::setDevice(QString) { }
void BT40::setMode(int mode, double load, double gradient)
{
pvars.lock();
this->mode = mode;
this->load = load;
this->slope = gradient;
pvars.unlock();
}
void BT40::setLoad(double load)
{
pvars.lock();
if (load > 1500) load = 1500;
if (load < 50) load = 50;
this->load = load;
pvars.unlock();
}
void BT40::setGradient(double gradient)
{
pvars.lock();
this->slope = gradient;
pvars.unlock();
}
int BT40::getMode()
{
int tmp;
pvars.lock();
tmp = mode;
pvars.unlock();
return tmp;
}
double BT40::getLoad()
{
double tmp;
pvars.lock();
tmp = load;
pvars.unlock();
return tmp;
}
double BT40::getGradient()
{
double tmp;
pvars.lock();
tmp = slope;
pvars.unlock();
return tmp;
}
void
BT40::getRealtimeData(RealtimeData &rtData)
{
pvars.lock();
rtData = rt;
pvars.unlock();
}
int
BT40::start()
{
QThread::start();
return 0;
}
// does nothing - neither does pause
int BT40::restart() { return 0; }
int BT40::pause() { return 0; }
int BT40::stop()
{
running = false;
return 0;
}
// used by thread to set variables and emit event if needed
// on unexpected exit
int BT40::quit(int code)
{
// event code goes here!
exit(code);
return 0; // never gets here obviously but shuts up the compiler!
}
/*----------------------------------------------------------------------
* MAIN THREAD - READS TELEMETRY AND UPDATES LOAD/GRADIENT ON KICKR
*----------------------------------------------------------------------*/
void BT40::run()
{
int currentmode = -1;
int currentload = -1;
double currentslope= -1;
// Connect to the device
if (connectBT40()) {
quit(2);
return; // open failed!
}
running = true;
while(running) {
// only get busy if we're actually connected
if (WFApi::getInstance()->isConnected(sd)) {
// We ALWAYS set load for each loop. This is because
// even though the device reports as connected we need
// to wait before it really is. So we just keep on
// sending the current mode/load. It doesn't cost us
// anything since all devices are powered.
// it does generate a few error messages though..
// and the connection takes about 25 secs to get
// up to speed.
// set load - reset it if generated watts don't match ..
if (mode == RT_MODE_ERGO) {
WFApi::getInstance()->setErgoMode(sd);
WFApi::getInstance()->setLoad(sd, load);
currentload = load;
currentmode = mode;
}
// set slope
if (mode == RT_MODE_SLOPE && currentslope) {
WFApi::getInstance()->setSlopeMode(sd);
WFApi::getInstance()->setSlope(sd, slope);
currentslope = slope;
currentmode = mode;
}
}
if (WFApi::getInstance()->hasData(sd)) {
pvars.lock();
WFApi::getInstance()->getRealtimeData(sd, &rt);
// set speed from wheelRpm and configured wheelsize
double x = rt.getWheelRpm();
if (devConf) rt.setSpeed(x * devConf->wheelSize / 1000 * 60 / 1000);
else rt.setSpeed(x * 2.10 * 60 / 1000);
pvars.unlock();
}
// lets not hog cpu
msleep(100);
}
disconnectBT40();
quit(0);
}
void
BT40::discoveredDevices(int n, bool finished)
{
WFApi *w = WFApi::getInstance();
// need to emit signal with device uuid and type
// this is used by the add device wizard.
// but only emit as they are found, not at the end
// when search times out -- we want them as they
// arrive.
if (!finished && w->deviceSubType(n-1) != WFApi::WF_SENSOR_SUBTYPE_BIKE_POWER_KICKR) {
for(int i=0; i<n; i++) {
qDebug()<<this<<"BT40 discovered a bluetooth device.."<<i
<<w->deviceUUID(i)
<<w->deviceType(i);
emit foundDevice(w->deviceUUID(i), w->deviceType(i));
}
}
}
bool
BT40::find()
{
WFApi *w = WFApi::getInstance();
// do we even have BTLE hardware available?
if (w->isBTLEEnabled() ==false) {
// lets try and enable it
// won't complete for a while but hopefully before next attempt to find is made
// by user or device scanner in AddDeviceWizard
w->enableBTLE(true, false);
return false;
}
// can we kick off a search?
if (w->discoverDevicesOfType(WFApi::WF_SENSORTYPE_NONE) == false) return false;
// wait for it to return something, anything
QEventLoop loop;
connect(w, SIGNAL(discoverFinished()), &loop, SLOT(quit()));
loop.exec();
scanned = true;
// what did we get?
if (w->deviceCount()) {
deviceUUID = w->deviceUUID(0);
return true;
} else return false;
}
int
BT40::connectBT40()
{
// get a pool for this thread
pool = WFApi::getInstance()->getPool();
sd = WFApi::getInstance()->connectDevice(devConf->portSpec);
return 0;
}
int
BT40::disconnectBT40()
{
// disconnect
WFApi::getInstance()->disconnectDevice(sd);
connected = false;
// clear that pool now we're done
WFApi::getInstance()->freePool(pool);
return 0;
}
// check to see of there is a port at the device specified
// returns true if the device exists and false if not
bool BT40::discover(QString)
{
return false;
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (c) 2013 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
*/
#ifndef _GC_BT40_h
#define _GC_BT40_h 1
#include "GoldenCheetah.h"
#include <QString>
#include <QDebug>
#include <QThread>
#include <QMutex>
#include <QFile>
#include "RealtimeController.h"
#include "TrainSidebar.h"
#include "DeviceConfiguration.h"
#include "WFApi.h"
class BT40 : public QThread
{
Q_OBJECT
public:
BT40(QObject *parent=0, DeviceConfiguration * devConf=0); // pass device
~BT40();
QObject *parent;
// HIGH-LEVEL FUNCTIONS
int start(); // Calls QThread to start
int restart(); // restart after paused
int pause(); // pauses data collection, inbound telemetry is discarded
int stop(); // stops data collection thread
int quit(int error); // called by thread before exiting
bool discover(QString deviceFilename); // confirm CT is attached to device
// SET
void setDevice(QString deviceFilename); // setup the device filename
void setLoad(double load); // set the load to generate in ERGOMODE
void setGradient(double gradient); // set the load to generate in SSMODE
void setMode(int mode,
double load=100, // set mode to CT_ERGOMODE or CT_SSMODE
double gradient=1);
bool find();
int connectBT40();
int disconnectBT40();
int getMode();
double getGradient();
double getLoad();
void getRealtimeData(RealtimeData &rtData);
QString id() { return deviceUUID; }
signals:
void foundDevice(QString uuid, int type);
private slots:
void discoveredDevices(int,bool);
private:
void run(); // called by start to kick off the CT comtrol thread
// device configuration
DeviceConfiguration *devConf;
// Mutex for controlling accessing private data
QMutex pvars;
bool scanned, running, connected;
volatile int mode;
volatile double load;
volatile double slope;
QString deviceUUID;
int sd; // sensor descriptor aka an index into the connections array
// mimics the fd index used by open/close syscalls.
RealtimeData rt;
void *pool;
};
#endif // _GC_BT40_h

View File

@@ -42,15 +42,10 @@ DeviceTypes::DeviceTypes()
"speed or cadence meters via a Garmin ANT+ USB1 or USB2 stick") ,
":images/devices/garminusb.png" },
#endif
#ifdef GC_HAVE_WFAPI
#if 0 //!!! Deferred until v3.1 or as an update to v3.0 when Wahoo support ANT+
{ DEV_BT40, DEV_BTLE, (char *) "Bluetooth 4.0", true, false,
tr("Bluetooth Low Energy devices such as KK Inride, Stages PM, Blue HR and Blue SC"),
":images/devices/btle.png" },
#endif
{ DEV_KICKR, DEV_BTLE, (char *) "Wahoo Kickr", true, false,
tr("The Wahoo Fitness Kickr cycling trainer via its Bluetooth smart interface. "),
":images/devices/kickr.png" },
#endif
{ DEV_CT, DEV_SERIAL, (char *) "Racermate Computrainer",true, false,
tr("Racermate Computrainer Lab or Pro bike trainer with the handlebar controller "

View File

@@ -34,8 +34,7 @@
#define DEV_GSERVER 0x0100 // NOT IMPLEMENTED IN THIS RELEASE XXX
#define DEV_GCLIENT 0x0200 // NOT IMPLEMENTED IN THIS RELEASE XXX
#define DEV_FORTIUS 0x0800 // Tacx Fortius
#define DEV_KICKR 0x1000 // Wahoo Kickr
#define DEV_BT40 0x2000 // Wahoo Kickr
#define DEV_BT40 0x2000 // QT Bluetooth support
#define DEV_MONARK 0x4000 // Monark USB
#define DEV_KETTLER 0x8000 // Kettler Serial

View File

@@ -1,274 +0,0 @@
/*
* Copyright (c) 2013 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 "Kickr.h"
Kickr::Kickr(QObject *parent, DeviceConfiguration *devConf) : QThread(parent)
{
this->parent = parent;
this->devConf = devConf;
scanned = false;
mode = -1;
load = 100;
slope = 1.0;
connect(WFApi::getInstance(), SIGNAL(discoveredDevices(int,bool)), this, SLOT(discoveredDevices(int,bool)));
}
Kickr::~Kickr()
{
}
// not required
void Kickr::setDevice(QString) { }
void Kickr::setMode(int mode, double load, double gradient)
{
pvars.lock();
this->mode = mode;
this->load = load;
this->slope = gradient;
pvars.unlock();
}
void Kickr::setLoad(double load)
{
pvars.lock();
if (load > 1500) load = 1500;
if (load < 50) load = 50;
this->load = load;
pvars.unlock();
}
void Kickr::setGradient(double gradient)
{
pvars.lock();
this->slope = gradient;
pvars.unlock();
}
int Kickr::getMode()
{
int tmp;
pvars.lock();
tmp = mode;
pvars.unlock();
return tmp;
}
double Kickr::getLoad()
{
double tmp;
pvars.lock();
tmp = load;
pvars.unlock();
return tmp;
}
double Kickr::getGradient()
{
double tmp;
pvars.lock();
tmp = slope;
pvars.unlock();
return tmp;
}
void
Kickr::getRealtimeData(RealtimeData &rtData)
{
pvars.lock();
rtData = rt;
pvars.unlock();
}
int
Kickr::start()
{
QThread::start();
return 0;
}
// does nothing - neither does pause
int Kickr::restart() { return 0; }
int Kickr::pause() { return 0; }
int Kickr::stop()
{
running = false;
return 0;
}
// used by thread to set variables and emit event if needed
// on unexpected exit
int Kickr::quit(int code)
{
// event code goes here!
exit(code);
return 0; // never gets here obviously but shuts up the compiler!
}
/*----------------------------------------------------------------------
* MAIN THREAD - READS TELEMETRY AND UPDATES LOAD/GRADIENT ON KICKR
*----------------------------------------------------------------------*/
void Kickr::run()
{
int currentmode = -1;
int currentload = -1;
double currentslope= -1;
// Connect to the device
if (connectKickr()) {
quit(2);
return; // open failed!
}
int connectionloops =0;
running = true;
while(running) {
// only get busy if we're actually connected
if (WFApi::getInstance()->isConnected(sd)) {
connectionloops = 0;
// We ALWAYS set load for each loop. This is because
// even though the device reports as connected we need
// to wait before it really is. So we just keep on
// sending the current mode/load. It doesn't cost us
// anything since all devices are powered.
// it does generate a few error messages though..
// and the connection takes about 25 secs to get
// up to speed.
// set load - reset it if generated watts don't match ..
if (mode == RT_MODE_ERGO) {
WFApi::getInstance()->setErgoMode(sd);
WFApi::getInstance()->setLoad(sd, load);
currentload = load;
currentmode = mode;
}
// set slope
if (mode == RT_MODE_SLOPE && currentslope) {
WFApi::getInstance()->setSlopeMode(sd);
WFApi::getInstance()->setSlope(sd, slope);
currentslope = slope;
currentmode = mode;
}
// get telemetry
if (WFApi::getInstance()->hasData(sd)) {
pvars.lock();
WFApi::getInstance()->getRealtimeData(sd, &rt);
// set speed from wheelRpm and configured wheelsize
double x = rt.getWheelRpm();
if (devConf) rt.setSpeed(x * devConf->wheelSize / 1000 * 60 / 1000);
else rt.setSpeed(x * 2.10 * 60 / 1000);
pvars.unlock();
}
} else {
// 100ms in each loop, 30secs is 300 loops
if (++connectionloops > 300) {
// give up waiting for connection
quit(-1);
}
}
// lets not hog cpu
msleep(100);
}
disconnectKickr();
quit(0);
}
void
Kickr::discoveredDevices(int n, bool finished)
{
WFApi *w = WFApi::getInstance();
// need to emit signal with device uuid and type
// this is used by the add device wizard.
// but only emit as they are found, not at the end
// when search times out -- we want them as they
// arrive.
if (!finished && w->deviceSubType(n-1) == WFApi::WF_SENSOR_SUBTYPE_BIKE_POWER_KICKR) {
qDebug()<<"KIKCR? discovered a device.."
<<w->deviceUUID(n-1)
<<w->deviceType(n-1);
emit foundDevice(w->deviceUUID(n-1), w->deviceType(n-1));
}
}
bool
Kickr::find()
{
WFApi *w = WFApi::getInstance();
if (w->discoverDevicesOfType(WFApi::WF_SENSORTYPE_BIKE_POWER) == false) return false;
QEventLoop loop;
connect(w, SIGNAL(discoveredDevices(int,bool)), &loop, SLOT(quit()));
loop.exec();
scanned = true;
if (w->deviceCount()) {
deviceUUID = w->deviceUUID(0);
return true;
} else return false;
}
int
Kickr::connectKickr()
{
// is BTLE even enabled?
if (WFApi::getInstance()->isBTLEEnabled() == false) return -1;
// get a pool for this thread
pool = WFApi::getInstance()->getPool();
// kick off connection and assume it is gonna be ok
sd = WFApi::getInstance()->connectDevice(devConf->portSpec);
return 0;
}
int
Kickr::disconnectKickr()
{
// disconnect
WFApi::getInstance()->disconnectDevice(sd);
connected = false;
// clear that pool now we're done
WFApi::getInstance()->freePool(pool);
return 0;
}
// check to see of there is a port at the device specified
// returns true if the device exists and false if not
bool Kickr::discover(QString)
{
return false;
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (c) 2013 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
*/
#ifndef _GC_Kickr_h
#define _GC_Kickr_h 1
#include "GoldenCheetah.h"
#include <QString>
#include <QDebug>
#include <QThread>
#include <QMutex>
#include <QFile>
#include "RealtimeController.h"
#include "TrainSidebar.h"
#include "DeviceConfiguration.h"
#include "WFApi.h"
class Kickr : public QThread
{
Q_OBJECT
public:
Kickr(QObject *parent=0, DeviceConfiguration * devConf=0); // pass device
~Kickr();
QObject *parent;
// HIGH-LEVEL FUNCTIONS
int start(); // Calls QThread to start
int restart(); // restart after paused
int pause(); // pauses data collection, inbound telemetry is discarded
int stop(); // stops data collection thread
int quit(int error); // called by thread before exiting
bool discover(QString deviceFilename); // confirm CT is attached to device
// SET
void setDevice(QString deviceFilename); // setup the device filename
void setLoad(double load); // set the load to generate in ERGOMODE
void setGradient(double gradient); // set the load to generate in SSMODE
void setMode(int mode,
double load=100, // set mode to CT_ERGOMODE or CT_SSMODE
double gradient=1);
bool find();
int connectKickr();
int disconnectKickr();
int getMode();
double getGradient();
double getLoad();
void getRealtimeData(RealtimeData &rtData);
QString id() { return deviceUUID; }
signals:
void foundDevice(QString uuid, int type);
private slots:
void discoveredDevices(int,bool);
private:
void run(); // called by start to kick off the CT comtrol thread
// device configuration
DeviceConfiguration *devConf;
// Mutex for controlling accessing private data
QMutex pvars;
bool scanned, running, connected;
volatile int mode;
volatile double load;
volatile double slope;
QString deviceUUID;
int sd; // sensor descriptor aka an index into the connections array
// mimics the fd index used by open/close syscalls.
RealtimeData rt;
void *pool;
};
#endif // _GC_Kickr_h

View File

@@ -1,103 +0,0 @@
/*
* Copyright (c) 2013 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 <QProgressDialog>
#include "KickrController.h"
#include "RealtimeData.h"
KickrController::KickrController(TrainSidebar *parent, DeviceConfiguration *dc) : RealtimeController(parent, dc)
{
myKickr = new Kickr(parent, dc);
connect(myKickr, SIGNAL(foundDevice(QString,int)), this, SIGNAL(foundDevice(QString,int)));
}
void
KickrController::setDevice(QString)
{
// not required
}
int
KickrController::start()
{
myKickr->start();
return 0;
}
int
KickrController::restart()
{
return myKickr->restart();
}
int
KickrController::pause()
{
return myKickr->pause();
}
int
KickrController::stop()
{
return myKickr->stop();
}
bool
KickrController::find()
{
return myKickr->find();
}
bool
KickrController::discover(QString name)
{
return myKickr->discover(name);
}
bool KickrController::doesPush() { return false; }
bool KickrController::doesPull() { return true; }
bool KickrController::doesLoad() { return true; }
/*
* gets called from the GUI to get updated telemetry.
* so whilst we are at it we check button status too and
* act accordingly.
*
*/
void
KickrController::getRealtimeData(RealtimeData &rtData)
{
if(!myKickr->isRunning())
{
QMessageBox msgBox;
msgBox.setText(tr("Cannot Connect to Kickr"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
parent->Stop(1);
return;
}
// get latest telemetry
myKickr->getRealtimeData(rtData);
processRealtimeData(rtData);
}
void KickrController::pushRealtimeData(RealtimeData &) { } // update realtime data with current values

View File

@@ -1,65 +0,0 @@
/*
* Copyright (c) 2011 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 "GoldenCheetah.h"
#include "RealtimeController.h"
#include "DeviceConfiguration.h"
#include "ConfigDialog.h"
#include "Kickr.h"
#ifndef _GC_KickrController_h
#define _GC_KickrController_h 1
class KickrController : public RealtimeController
{
Q_OBJECT
public:
KickrController (TrainSidebar *parent =0, DeviceConfiguration *dc =0);
Kickr *myKickr; // the device itself
int start();
int restart(); // restart after paused
int pause(); // pauses data collection, inbound telemetry is discarded
int stop(); // stops data collection thread
bool find();
bool discover(QString name);
void setDevice(QString);
// telemetry push pull
bool doesPush(), doesPull(), doesLoad();
void getRealtimeData(RealtimeData &rtData);
void pushRealtimeData(RealtimeData &rtData);
void setLoad(double x) { myKickr->setLoad(x); }
void setGradient(double x) { myKickr->setGradient(x); }
void setMode(int x) { myKickr->setMode(x); }
QString id() { return myKickr->id(); }
signals:
void foundDevice(QString uuid, int type);
private:
};
#endif // _GC_KickrController_h

View File

@@ -46,8 +46,8 @@
#endif
#include "ANTlocalController.h"
#include "NullController.h"
#ifdef GC_HAVE_WFAPI
#include "KickrController.h"
#ifdef QT_BLUETOOTH_LIB
#include "BT40Controller.h"
#endif
#ifdef GC_HAVE_LIBUSB
#include "FortiusController.h"
@@ -641,9 +641,9 @@ TrainSidebar::configChanged(qint32)
Devices[i].controller = new ANTlocalController(this, &Devices[i]);
// connect slot for receiving remote control commands
connect(Devices[i].controller, SIGNAL(remoteControl(uint16_t)), this, SLOT(remoteControl(uint16_t)));
#ifdef GC_HAVE_WFAPI
} else if (Devices.at(i).type == DEV_KICKR) {
Devices[i].controller = new KickrController(this, &Devices[i]);
#ifdef QT_BLUETOOTH_LIB
} else if (Devices.at(i).type == DEV_BT40) {
Devices[i].controller = new BT40Controller(this, &Devices[i]);
#endif
}
}

View File

@@ -1,226 +0,0 @@
/*
* Copyright (c) 2013 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 WARRWFApiY; without even the implied warranty of MERCHWFApiABILITY 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_WFApi_h
#define gc_WFApi_h
// GC
#include "GoldenCheetah.h"
#include "Settings.h"
#include "RealtimeData.h"
#include "DeviceConfiguration.h"
#include "RealtimeData.h"
// QT
#include <QPointer>
#include <QObject>
// global singleton
class WFApi;
extern WFApi *_gc_wfapi;
// declare the provate implementation for objc
#ifdef __OBJC__
@class WFBridge;
#else
// irritating dependencies
#endif
class WFApi : public QObject // QOBject for signals
{
Q_OBJECT
public:
WFApi(); // single instance
~WFApi();
static WFApi *getInstance() { if (_gc_wfapi) return _gc_wfapi;
else return (_gc_wfapi = new WFApi); } // singleton
// what version?
QString apiVersion();
// status of BTLE
bool hasBTLESupport();
bool isBTLEEnabled();
bool enableBTLE(bool enable, bool bondingmode);
bool isCommunicationHWReady();
// we don't use the WF API header "hardware_connector_types.h" because it
// references Objc types (NSUInteger) that fail when compiling C++.
// Instead we redeclare them here, but only the ones we absolutely need
// and hopefully they won't change too often
// current state
typedef enum {
WFAPI_HWCONN_STATE_NOT_CONNECTED = 0,
WFAPI_HWCONN_STATE_CONNECTED = 0x01,
WFAPI_HWCONN_STATE_ACTIVE = 0x02,
WFAPI_HWCONN_STATE_RESET = 0x04,
WFAPI_HWCONN_STATE_BT40_ENABLED = 0x08,
WFAPI_HWCONN_STATE_BT_BONDING_MODE = 0x10 } _state;
int currentState();
// connection state
typedef enum {
WF_SENSOR_CONNECTION_STATUS_IDLE = 0,
WF_SENSOR_CONNECTION_STATUS_CONNECTING = 1,
WF_SENSOR_CONNECTION_STATUS_CONNECTED = 2,
WF_SENSOR_CONNECTION_STATUS_INTERRUPTED = 3,
WF_SENSOR_CONNECTION_STATUS_DISCONNECTING = 4 } _connstate;
int connectionStatus(int sd);
bool isConnected(int sd);
// all the sensor types just the types we need
enum {
WF_SENSORTYPE_NONE = 0,
WF_SENSORTYPE_BIKE_POWER = 0x00000001, // kickr, inride etc
WF_SENSORTYPE_BIKE_SPEED = 0x00000002,
WF_SENSORTYPE_BIKE_CADENCE = 0x00000004,
WF_SENSORTYPE_BIKE_SPEED_CADENCE = 0x00000008,
WF_SENSORTYPE_FOOTPOD = 0x00000010,
WF_SENSORTYPE_HEARTRATE = 0x00000020,
WF_SENSORTYPE_WEIGHT_SCALE = 0x00000040,
WF_SENSORTYPE_ANT_FS = 0x00000080,
WF_SENSORTYPE_LOCATION = 0x00000100,
WF_SENSORTYPE_CALORIMETER = 0x00000200,
WF_SENSORTYPE_GEO_CACHE = 0x00000400,
WF_SENSORTYPE_FITNESS_EQUIPMENT = 0x00000800,
WF_SENSORTYPE_MULTISPORT_SPEED_DISTANCE = 0x00001000,
WF_SENSORTYPE_PROXIMITY = 0x00002000,
WF_SENSORTYPE_HEALTH_THERMOMETER = 0x00004000,
WF_SENSORTYPE_BLOOD_PRESSURE = 0x00008000,
WF_SENSORTYPE_BTLE_GLUCOSE = 0x00010000,
WF_SENSORTYPE_GLUCOSE = 0x00020000,
WF_SENSORTYPE_DISPLAY = 0x00800000 } _sensortypes; // rflkt
const QString sensorDescription(int id, int sub) const {
QString returning(tr("Unknown"));
switch (id) {
case 0x0 : returning = tr("None"); break;
case 0x1 :
{
switch(sub) {
case 0:
default:
returning = tr("Power Meter");
break;
case 1:
returning = tr("Wahoo KICKR trainer");
break;
case 2:
returning = tr("Stage ONE Crank Power Meter");
break;
case 3:
returning = tr("Kurt Kinetic InRide Power Meter");
break;
}
}
break;
case 0x2 : returning = tr("Bike Speed"); break;
case 0x4 : returning = tr("Bike Cadence"); break;
case 0x8 : returning = tr("Speed and Cadence"); break;
case 0x10 : returning = tr("FootPod"); break;
case 0x20 : returning = tr("Heart Rate"); break;
case 0x800000 : returning = tr("RFKLT Display"); break;
}
return returning;
}
// subtypes -- esp. power
enum {
WF_SENSOR_SUBTYPE_UNSPECIFIED = 0,
WF_SENSOR_SUBTYPE_BIKE_POWER_KICKR = 1,
WF_SENSOR_SUBTYPE_BIKE_POWER_STAGE_ONE = 2,
WF_SENSOR_SUBTYPE_BIKE_POWER_IN_RIDE = 3 } _sensorsubtype;
// scan
bool discoverDevicesOfType(int eSensorType);
int deviceCount();
QString deviceUUID(int); // return the UUID for device n
int deviceType(int); // return the device type
int deviceSubType(int); // return the subtype found
// connect and disconnect
int connectDevice(QString uuid); // connect the device n
bool disconnectDevice(int sd); // disconnect
// has data?
bool hasData(int sd);
void getRealtimeData(int sd, RealtimeData *p);
// set slope or ergo mode
void setSlopeMode(int sd);
void setErgoMode(int sd);
// set resistance slope or load
void setSlope(int sd, double slope);
void setLoad(int sd, int watts);
// NOTE: There is an application wide NSAutoreleasePool maintained
// in cocoa initialiser, but it is only to support activity on
// the main thread.
// The application code (e.g. Kickr.cpp) needs to get and free a
// pool for each thread, this is why we have a getPool/freePool
// method in WFApi, but never allocate a pool ourselves.
void *getPool();
void freePool(void*);
signals:
void currentStateChanged(int); // hardware conncector state changed
void connectionStateChanged(int status);
void discoveredDevices(int,bool);
void discoverFinished();
void connectionHasData();
public slots:
// connecting...
void stateChanged();
void connectionState(int status);
void connectionTimeout();
void connectedSensor(void*);
void didDiscoverDevices(int count, bool finished);
void disconnectedSensor(void*);
void hasFirmwareUpdateAvalableForConnection();
void connectorHasData();
signals:
public slots:
public:
// the native api bridge -- private implementation in
// WFApi.mm -- bridge between the QT/C++ world and the
// WF/Objc world
#ifdef __OBJC__
WFBridge *wf; // when included in objc sources
#else /* __OBJC__ */
void *wf; // when included in C++ sources
#endif /* __OBJC__ */
QVector <void *> connections;
};
#endif

View File

@@ -1,327 +0,0 @@
/*
* Copyright (c) 2013 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 WARRWFApiY; without even the implied warranty of MERCHWFApiABILITY 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 "WFApi.h"
// WF API Headers
#import <WFConnector/WFHardwareConnector.h>
#import <WFConnector/WFConnectionParams.h>
#import <WFConnector/WFDeviceParams.h>
#import <WFConnector/WFSensorConnection.h>
#import <WFConnector/WFSensorData.h>
#import <WFConnector/WFBikePowerData.h>
#import <WFConnector/WFBikePowerConnection.h>
#import <WFConnector/hardware_connector_types.h>
// Utility
static QString toQString(const NSString *nsstr)
{
NSRange range;
range.location = 0;
range.length = [nsstr length];
QString result(range.length, QChar(0));
unichar *chars = new unichar[range.length];
[nsstr getCharacters:chars range:range];
result = QString::fromUtf16(chars, range.length);
delete[] chars;
return result;
}
static inline NSString* fromQString(const QString &string)
{
const QByteArray utf8 = string.toUtf8();
const char* cString = utf8.constData();
return [[NSString alloc] initWithUTF8String:cString];
}
// Thi source file contains the private objc interface (WFBridge) that
// sits atop the Wahoo Fitness APIs at the top of the source file.
//
// This is then follwoed by the C++ public interface implementation that
// sits atop that private interface (WFBridge)
//----------------------------------------------------------------------
// Objective C -- Private interface
//----------------------------------------------------------------------
@interface WFBridge : NSObject <WFHardwareConnectorDelegate, WFSensorConnectionDelegate> {
@public
QPointer<WFApi> qtw; // the QT QObject public class
NSMutableArray *discoveredSensors;
}
@end
@implementation WFBridge
//============================================================================
// Hardware Connector Methods
//============================================================================
// retreive the API version
-(NSString *) apiVersion { return [[WFHardwareConnector sharedConnector] apiVersion]; }
// BTLE state and enablement
-(BOOL)hasBTLESupport { return [[WFHardwareConnector sharedConnector] hasBTLESupport]; }
-(BOOL)isBTLEEnabled { return [[WFHardwareConnector sharedConnector] isBTLEEnabled]; }
-(BOOL)enableBTLE:(BOOL)bEnable inBondingMode:(BOOL)bBondingMode {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
bool result = [[WFHardwareConnector sharedConnector] enableBTLE:bEnable inBondingMode:bBondingMode];
[pool drain];
return result;
}
-(BOOL)isCommunicationHWReady { return [[WFHardwareConnector sharedConnector] isCommunicationHWReady]; }
-(int)currentState { return [[WFHardwareConnector sharedConnector] currentState]; }
// Initialise the WFBridge singleton
-(id)init
{
// initialise
discoveredSensors = [[NSMutableArray alloc] init];
[[WFHardwareConnector sharedConnector] setDelegate:self];
[self enableBTLE:TRUE inBondingMode:false];
return self;
}
// scan for devices and stored details
-(BOOL)discoverDevicesOfType:(WFSensorType_t)eSensorType onNetwork:(WFNetworkType_t)eNetworkType searchTimeout:(NSTimeInterval)timeout
{
// get rid of past scans / stop any in progress
[discoveredSensors removeAllObjects];
[[WFHardwareConnector sharedConnector] cancelDiscoveryOnNetwork:WF_NETWORKTYPE_BTLE];
// go looking
[[WFHardwareConnector sharedConnector] discoverDevicesOfType:eSensorType onNetwork:eNetworkType searchTimeout:timeout]; //XXX ignoringreturn
return true;
}
-(int)deviceCount { return [discoveredSensors count]; }
-(NSString*)deviceUUID:(int)n
{
WFConnectionParams* connParams = (WFConnectionParams*)[discoveredSensors objectAtIndex:n];
return connParams.device1.deviceUUIDString;
}
-(int)deviceType:(int)n
{
WFConnectionParams* connParams = (WFConnectionParams*)[discoveredSensors objectAtIndex:n];
return (int)connParams.sensorType;
}
-(int)deviceSubType:(int)n
{
WFConnectionParams* connParams = (WFConnectionParams*)[discoveredSensors objectAtIndex:n];
return (int)connParams.sensorSubType;
}
//============================================================================
// Sensor Connection Methods
//============================================================================
// connect and disconnect a device
-(WFSensorConnection *)connectDevice: (NSString *)uuid
{
// just in case there is a discovery in action, lets cancel it...
[[WFHardwareConnector sharedConnector] cancelDiscoveryOnNetwork:WF_NETWORKTYPE_BTLE];
WFDeviceParams* dev = [[WFDeviceParams alloc] init];
dev.deviceUUIDString = uuid;
dev.networkType = WF_NETWORKTYPE_BTLE;
WFConnectionParams* params = [[WFConnectionParams alloc] init];
params.sensorType = WF_SENSORTYPE_BIKE_POWER;
params.networkType = WF_NETWORKTYPE_BTLE;
params.sensorSubType = WF_SENSOR_SUBTYPE_BIKE_POWER_KICKR;
params.searchTimeout = 5;
params.device1 = dev;
// request the sensor connection.
WFSensorConnection *sensorConnection = (WFBikePowerConnection*)[[WFHardwareConnector sharedConnector] requestSensorConnection:params];
// set delegate to receive connection status changes.
sensorConnection.delegate = self;
return sensorConnection;
}
-(int)connectionStatus:(WFSensorConnection*)sensorConnection { return (int)[sensorConnection connectionStatus]; }
- (BOOL)disconnectDevice:(WFSensorConnection*)sensorConnection { [sensorConnection disconnect]; return true; }
- (BOOL)isConnected:(WFSensorConnection*)sensorConnection { return [sensorConnection isConnected]; }
// get telemetry
- (WFBikePowerData*) getData:(WFSensorConnection*)sensorConnection { return (WFBikePowerData*)[sensorConnection getData]; }
// trainer setup / load
- (void) setSlopeMode:(WFBikePowerConnection*)sensorConnection { [sensorConnection trainerSetSimMode:85 rollingResistance:0.0004 windResistance:0.6]; }
- (void) setErgoMode:(WFBikePowerConnection*)sensorConnection { [sensorConnection trainerSetErgMode:100]; }
- (void) setSlope:(WFBikePowerConnection*)sensorConnection slope:(double)slope { [sensorConnection trainerSetGrade:slope]; }
- (void) setLoad:(WFBikePowerConnection*)sensorConnection load:(int)load { [sensorConnection trainerSetErgMode:load]; }
//============================================================================
// Sensor connection updates (delegate methods)
//============================================================================
// state changed
- (void)connection:(WFSensorConnection*)connectionInfo stateChanged:(WFSensorConnectionStatus_t)connState
{ Q_UNUSED(connectionInfo);
qtw->connectionState(connState);
}
// timed out
- (void)connectionDidTimeout:(WFSensorConnection*)connectionInfo
{ Q_UNUSED(connectionInfo);
qtw->connectionTimeout();
}
// telemetry available
- (BOOL) hasData:(WFSensorConnection*)sensorConnection { return [sensorConnection hasData]; }
// firmware available for this sensor
-(void) hardwareConnector:(WFHardwareConnector*)hwConnector hasFirmwareUpdateAvailableForConnection:(WFSensorConnection*)connectionInfo required:(BOOL)required withWahooUtilityAppURL:(NSURL *)wahooUtilityAppURL
{ Q_UNUSED(hwConnector);
Q_UNUSED(connectionInfo);
Q_UNUSED(required);
Q_UNUSED(wahooUtilityAppURL);
qtw->hasFirmwareUpdateAvalableForConnection(); //XXX do what?
}
//============================================================================
// Hardware connector updates (delegate methods)
//============================================================================
// state changed on connector
-(void)hardwareConnector:(WFHardwareConnector*)hwConnector stateChanged:(WFHardwareConnectorState_t)currentState
{ Q_UNUSED(hwConnector);
Q_UNUSED(currentState);
qtw->stateChanged();
}
// connection established
-(void)hardwareConnector:(WFHardwareConnector*)hwConnector connectedSensor:(WFSensorConnection*)connectionInfo
{ Q_UNUSED(hwConnector);
qtw->connectedSensor(connectionInfo);
}
// data has arrived on connector
-(void)hardwareConnectorHasData { qtw->connectorHasData(); }
// a sensor was disconnected
-(void)hardwareConnector:(WFHardwareConnector*)hwConnector disconnectedSensor:(WFSensorConnection*)connectionInfo
{ Q_UNUSED(hwConnector);
qtw->disconnectedSensor(connectionInfo);
}
// devices discovered
-(void)hardwareConnector:(WFHardwareConnector*)hwConnector didDiscoverDevices:(NSSet*)connectionParams searchCompleted:(BOOL)bCompleted
{ Q_UNUSED(hwConnector);
if (!bCompleted) {
// add discovered devices -- as they are discovered, not at the end.
for (WFConnectionParams* connParams in connectionParams) {
[discoveredSensors addObject:connParams];
}
}
qtw->didDiscoverDevices([discoveredSensors count], bCompleted);
}
-(NSAutoreleasePool*) getPool { return [[NSAutoreleasePool alloc] init]; }
-(void) freePool:(NSAutoreleasePool*)pool { [pool release]; }
@end
//----------------------------------------------------------------------
// C++ PUBLIC Interface
//----------------------------------------------------------------------
// Singleton API class
WFApi *_gc_wfapi = NULL;
WFApi::WFApi()
{
wf = [[WFBridge alloc] init];
wf->qtw = this;
}
WFApi::~WFApi() { [wf release]; }
//============================================================================
// wrappers for methods in private implementation above
//============================================================================
QString WFApi::apiVersion() { return toQString([wf apiVersion]); }
bool WFApi::isBTLEEnabled() { return [wf isBTLEEnabled]; }
bool WFApi::hasBTLESupport() { return [wf hasBTLESupport]; }
bool WFApi::isCommunicationHWReady() { return [wf isCommunicationHWReady]; }
bool WFApi::enableBTLE(bool enable, bool bondingmode) {
return [wf enableBTLE:enable inBondingMode:bondingmode];
}
int WFApi::currentState() { return [wf currentState]; }
bool
WFApi::discoverDevicesOfType(int eSensorType)
{
// ignore ehat was passed for now...
return [wf discoverDevicesOfType:(WFSensorType_t)eSensorType onNetwork:WF_NETWORKTYPE_BTLE searchTimeout:15.00];
}
QString WFApi::deviceUUID(int n)
{
if (n>=0 && n<deviceCount()) return toQString([wf deviceUUID:n]);
else return "";
}
int WFApi::deviceType(int n)
{
if (n>=0 && n<deviceCount()) return (int)[wf deviceType:n];
else return -1;
}
int WFApi::deviceSubType(int n)
{
if (n>=0 && n<deviceCount()) return (int)[wf deviceSubType:n];
else return -1;
}
int WFApi::connectionStatus(int sd) { return [wf connectionStatus:(WFSensorConnection*)connections.at(sd)]; }
bool WFApi::isConnected(int sd) { return [wf isConnected:(WFSensorConnection*)connections.at(sd)]; }
bool WFApi::hasData(int sd) { return [wf hasData:(WFSensorConnection*)connections.at(sd)]; }
int WFApi::connectDevice(QString uuid) {
void *conn = (void*)[wf connectDevice: fromQString(uuid)];
connections.append(conn);
return (connections.count()-1);
}
bool WFApi::disconnectDevice(int sd) { return [wf disconnectDevice:(WFSensorConnection*)connections.at(sd)]; }
int WFApi::deviceCount() { return [wf deviceCount]; }
// set slope or ergo mode
void WFApi::setSlopeMode(int sd) { [wf setSlopeMode:(WFBikePowerConnection*)connections.at(sd)]; }
void WFApi::setErgoMode(int sd) { [wf setErgoMode:(WFBikePowerConnection*)connections.at(sd)]; }
void WFApi::setSlope(int sd, double n) { [wf setSlope:(WFBikePowerConnection*)connections.at(sd) slope:n]; }
void WFApi::setLoad(int sd, int n) { [wf setLoad:(WFBikePowerConnection*)connections.at(sd) load:n]; }
//============================================================================
// methods called by delegate on updates
//============================================================================
void WFApi::connectedSensor(void*) { }
void WFApi::didDiscoverDevices(int count, bool finished) { if (finished) emit discoverFinished();
else emit discoveredDevices(count,finished); }
void WFApi::disconnectedSensor(void*) { }
void WFApi::hasFirmwareUpdateAvalableForConnection() { }
void WFApi::stateChanged() { emit currentStateChanged(currentState()); }
void WFApi::connectionState(int status) { emit connectionStateChanged(status); }
void WFApi::connectionTimeout() { }
void WFApi::connectorHasData() { emit connectionHasData(); }
void WFApi::getRealtimeData(int sd, RealtimeData *rt) {
WFBikePowerData *data = [wf getData:(WFSensorConnection*)connections.at(sd)];
rt->setWatts((int)[data instantPower]);
rt->setCadence((int)[data instantCadence]);
rt->setWheelRpm((int)[data instantWheelRPM]);
}
void * WFApi::getPool() { return (void*)[wf getPool]; }
void WFApi::freePool(void *pool) { [wf freePool:(NSAutoreleasePool*)pool]; }

View File

@@ -244,9 +244,6 @@ macx {
# Uncomment this line if you have SDK 10.7 or higher
#DEFINES += GC_HAVE_LION
# Uncomment this line if you have the Mac OSX Wahoo API installed (Kickr)
#HAVE_WFAPI = true
#uncomment below if you are running on the 10.9 developer preview
#INCLUDEPATH += /Library/Developer/CommandLineTools/SDKs/MacOSX10.9.sdk/usr/include/
}

View File

@@ -74,6 +74,11 @@ lessThan(QT_MAJOR_VERSION, 5) {
} else {
QT += multimedia multimediawidgets
}
greaterThan(QT_MINOR_VERSION, 3) {
QT += bluetooth
HEADERS += Train/BT40Controller.h
SOURCES += Train/BT40Controller.cpp
}
}
###=======================================================================