Skip to content

Commit 28fe2e1

Browse files
committed
Merge remote-tracking branch 'origin/codex/remove-loop.exec-from-ftmsbike-class' into Lukas-Baum
2 parents 664502d + 9442fcd commit 28fe2e1

2 files changed

Lines changed: 96 additions & 44 deletions

File tree

src/devices/ftmsbike/ftmsbike.cpp

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,20 @@ ftmsbike::ftmsbike(bool noWriteResistance, bool noHeartService, int8_t bikeResis
5757
ergModeSupported = true; // by default ftms devices SHOULD have ergMode supported
5858
connect(refresh, &QTimer::timeout, this, &ftmsbike::update);
5959
refresh->start(settings.value(QZSettings::poll_device_time, QZSettings::default_poll_device_time).toInt());
60+
61+
writeTimeoutTimer = new QTimer(this);
62+
writeTimeoutTimer->setSingleShot(true);
63+
connect(writeTimeoutTimer, &QTimer::timeout, this, [this]() {
64+
qDebug() << QStringLiteral("writeCharacteristic timeout - processing next in queue");
65+
completeCurrentWrite();
66+
});
67+
6068
wheelCircumference::GearTable g;
6169
g.printTable();
6270
}
6371

6472
void ftmsbike::writeCharacteristicZwiftPlay(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log,
6573
bool wait_for_response) {
66-
QEventLoop loop;
67-
QTimer timeout;
6874
QSettings settings;
6975
bool gears_zwift_ratio = settings.value(QZSettings::gears_zwift_ratio, QZSettings::default_gears_zwift_ratio).toBool();
7076

@@ -73,37 +79,12 @@ void ftmsbike::writeCharacteristicZwiftPlay(uint8_t *data, uint8_t data_len, con
7379
return;
7480
}
7581

76-
if (wait_for_response) {
77-
connect(zwiftPlayService, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit);
78-
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
79-
} else {
80-
connect(zwiftPlayService, &QLowEnergyService::characteristicWritten, &loop, &QEventLoop::quit);
81-
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
82-
}
83-
84-
if (writeBuffer) {
85-
delete writeBuffer;
86-
}
87-
writeBuffer = new QByteArray((const char *)data, data_len);
88-
89-
if (zwiftPlayWriteChar.properties() & QLowEnergyCharacteristic::WriteNoResponse) {
90-
zwiftPlayService->writeCharacteristic(zwiftPlayWriteChar, *writeBuffer,
91-
QLowEnergyService::WriteWithoutResponse);
92-
} else {
93-
zwiftPlayService->writeCharacteristic(zwiftPlayWriteChar, *writeBuffer);
94-
}
95-
96-
if (!disable_log) {
97-
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
98-
}
99-
100-
loop.exec();
82+
enqueueWrite(zwiftPlayService, zwiftPlayWriteChar, data, data_len, info, disable_log, wait_for_response,
83+
zwiftPlayWriteChar.properties() & QLowEnergyCharacteristic::WriteNoResponse);
10184
}
10285

10386
bool ftmsbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log,
10487
bool wait_for_response) {
105-
QEventLoop loop;
106-
QTimer timeout;
10788
QSettings settings;
10889
bool gears_zwift_ratio = settings.value(QZSettings::gears_zwift_ratio, QZSettings::default_gears_zwift_ratio).toBool();
10990

@@ -117,33 +98,74 @@ bool ftmsbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QStrin
11798
return false;
11899
}
119100

120-
if (wait_for_response) {
121-
connect(gattFTMSService, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit);
122-
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
123-
} else {
124-
connect(gattFTMSService, &QLowEnergyService::characteristicWritten, &loop, &QEventLoop::quit);
125-
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
101+
return enqueueWrite(gattFTMSService, gattWriteCharControlPointId, data, data_len, info, disable_log,
102+
wait_for_response,
103+
gattWriteCharControlPointId.properties() & QLowEnergyCharacteristic::WriteNoResponse &&
104+
!DOMYOS);
105+
}
106+
107+
bool ftmsbike::enqueueWrite(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, uint8_t *data,
108+
uint8_t data_len, const QString &info, bool disable_log, bool wait_for_response,
109+
bool write_without_response) {
110+
if (!service || !characteristic.isValid()) {
111+
qDebug() << QStringLiteral("writeCharacteristic error because service/characteristic is invalid");
112+
return false;
113+
}
114+
115+
WriteRequest request;
116+
request.data = QByteArray((const char *)data, data_len);
117+
request.info = info;
118+
request.disable_log = disable_log;
119+
request.wait_for_response = wait_for_response;
120+
request.service = service;
121+
request.characteristic = characteristic;
122+
request.write_without_response = write_without_response;
123+
124+
writeQueue.enqueue(request);
125+
processWriteQueue();
126+
return true;
127+
}
128+
129+
void ftmsbike::processWriteQueue() {
130+
if (isWriting || writeQueue.isEmpty()) {
131+
return;
132+
}
133+
134+
WriteRequest request = writeQueue.dequeue();
135+
if (!request.service || request.service->state() != QLowEnergyService::ServiceDiscovered) {
136+
qDebug() << QStringLiteral("writeCharacteristic error because the connection is closed");
137+
writeQueue.clear();
138+
return;
126139
}
127140

128141
if (writeBuffer) {
129142
delete writeBuffer;
130143
}
131-
writeBuffer = new QByteArray((const char *)data, data_len);
144+
writeBuffer = new QByteArray(request.data);
145+
146+
isWriting = true;
147+
currentWriteWaitingForResponse = request.wait_for_response;
148+
currentWriteService = request.service;
132149

133-
if (gattWriteCharControlPointId.properties() & QLowEnergyCharacteristic::WriteNoResponse && !DOMYOS) {
134-
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer,
135-
QLowEnergyService::WriteWithoutResponse);
150+
if (request.write_without_response) {
151+
request.service->writeCharacteristic(request.characteristic, *writeBuffer, QLowEnergyService::WriteWithoutResponse);
136152
} else {
137-
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer);
153+
request.service->writeCharacteristic(request.characteristic, *writeBuffer);
138154
}
139155

140-
if (!disable_log) {
141-
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
156+
if (!request.disable_log) {
157+
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + request.info);
142158
}
143159

144-
loop.exec();
160+
writeTimeoutTimer->start(300);
161+
}
145162

146-
return true;
163+
void ftmsbike::completeCurrentWrite() {
164+
writeTimeoutTimer->stop();
165+
isWriting = false;
166+
currentWriteWaitingForResponse = false;
167+
currentWriteService = nullptr;
168+
processWriteQueue();
147169
}
148170

149171
void ftmsbike::init() {
@@ -657,6 +679,10 @@ bool ftmsbike::shouldUseCalculatedResistanceFallback(const QDateTime &now) {
657679
}
658680

659681
void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) {
682+
if (isWriting && currentWriteWaitingForResponse && sender() == currentWriteService) {
683+
completeCurrentWrite();
684+
}
685+
660686
QDateTime now = QDateTime::currentDateTime();
661687
// qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length();
662688
Q_UNUSED(characteristic);
@@ -1907,6 +1933,10 @@ void ftmsbike::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByt
19071933
}
19081934

19091935
void ftmsbike::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) {
1936+
if (isWriting && !currentWriteWaitingForResponse && sender() == currentWriteService) {
1937+
completeCurrentWrite();
1938+
}
1939+
19101940
Q_UNUSED(characteristic);
19111941
emit debug(QStringLiteral("characteristicWritten ") + newValue.toHex(' '));
19121942
}

src/devices/ftmsbike/ftmsbike.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <QtBluetooth/qlowenergyservice.h>
1212
#include <QtBluetooth/qlowenergyservicedata.h>
1313
#include <QtCore/qbytearray.h>
14+
#include <QtCore/qqueue.h>
1415

1516
#ifndef Q_OS_ANDROID
1617
#include <QtCore/qcoreapplication.h>
@@ -89,10 +90,25 @@ class ftmsbike : public bike {
8990
bool inclinationAvailableBySoftware() override { return !resistance_lvl_mode; }
9091

9192
private:
93+
struct WriteRequest {
94+
QByteArray data;
95+
QString info;
96+
bool disable_log = false;
97+
bool wait_for_response = false;
98+
QLowEnergyService *service = nullptr;
99+
QLowEnergyCharacteristic characteristic;
100+
bool write_without_response = false;
101+
};
102+
92103
bool writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log = false,
93104
bool wait_for_response = false);
94105
void writeCharacteristicZwiftPlay(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log = false,
95106
bool wait_for_response = false);
107+
bool enqueueWrite(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, uint8_t *data,
108+
uint8_t data_len, const QString &info, bool disable_log, bool wait_for_response,
109+
bool write_without_response);
110+
void processWriteQueue();
111+
void completeCurrentWrite();
96112
void zwiftPlayInit();
97113
void startDiscover();
98114
void setWheelDiameter(double diameter);
@@ -205,6 +221,12 @@ class ftmsbike : public bike {
205221
bool wattReceived = false;
206222
bool gearInclinationSent = false;
207223

224+
QQueue<WriteRequest> writeQueue;
225+
bool isWriting = false;
226+
bool currentWriteWaitingForResponse = false;
227+
QLowEnergyService *currentWriteService = nullptr;
228+
QTimer *writeTimeoutTimer = nullptr;
229+
208230
uint16_t oldLastCrankEventTime = 0;
209231
uint16_t oldCrankRevs = 0;
210232
QDateTime lastGoodCadence = QDateTime::currentDateTime();

0 commit comments

Comments
 (0)