mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
3 Commits
master
...
build-1238
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f0b02ff3d | ||
|
|
62f4425a20 | ||
|
|
adb9efee23 |
@@ -4579,7 +4579,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -4780,7 +4780,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
@@ -5017,7 +5017,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -5113,7 +5113,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
@@ -5205,7 +5205,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -5321,7 +5321,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
@@ -5431,7 +5431,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = QZWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -5522,7 +5522,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = QZWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1237;
|
||||
CURRENT_PROJECT_VERSION = 1238;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
||||
@@ -73,50 +73,98 @@ domyostreadmill::domyostreadmill(uint32_t pollDeviceTime, bool noConsole, bool n
|
||||
initDone = false;
|
||||
connect(refresh, &QTimer::timeout, this, &domyostreadmill::update);
|
||||
refresh->start(pollDeviceTime);
|
||||
|
||||
// Initialize write timeout timer
|
||||
writeTimeoutTimer = new QTimer(this);
|
||||
writeTimeoutTimer->setSingleShot(true);
|
||||
connect(writeTimeoutTimer, &QTimer::timeout, this, [this]() {
|
||||
qDebug() << QStringLiteral("writeCharacteristic timeout - processing next in queue");
|
||||
isWriting = false;
|
||||
currentWriteWaitingForResponse = false;
|
||||
processWriteQueue();
|
||||
});
|
||||
|
||||
// Connect packetReceived signal to handle wait_for_response = true case
|
||||
connect(this, &domyostreadmill::packetReceived, this, [this]() {
|
||||
// Only process if we were waiting for a response
|
||||
if (currentWriteWaitingForResponse && isWriting) {
|
||||
// Stop timeout timer
|
||||
writeTimeoutTimer->stop();
|
||||
|
||||
// Mark writing as complete and process next item in queue
|
||||
isWriting = false;
|
||||
currentWriteWaitingForResponse = false;
|
||||
processWriteQueue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void domyostreadmill::writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log,
|
||||
bool wait_for_response) {
|
||||
QEventLoop loop;
|
||||
QTimer timeout;
|
||||
// Create write request and add to queue
|
||||
WriteRequest request;
|
||||
request.data = QByteArray((const char *)data, data_len);
|
||||
request.info = info;
|
||||
request.disable_log = disable_log;
|
||||
request.wait_for_response = wait_for_response;
|
||||
|
||||
if (wait_for_response) {
|
||||
connect(this, &domyostreadmill::packetReceived, &loop, &QEventLoop::quit);
|
||||
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
|
||||
} else {
|
||||
connect(gattCommunicationChannelService, &QLowEnergyService::characteristicWritten, &loop, &QEventLoop::quit);
|
||||
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
|
||||
writeQueue.enqueue(request);
|
||||
|
||||
// Start processing if not already writing
|
||||
processWriteQueue();
|
||||
}
|
||||
|
||||
void domyostreadmill::processWriteQueue() {
|
||||
// If already writing or queue is empty, do nothing
|
||||
if (isWriting || writeQueue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gattCommunicationChannelService->state() != QLowEnergyService::ServiceState::ServiceDiscovered ||
|
||||
// Check connection state
|
||||
if (!gattCommunicationChannelService ||
|
||||
gattCommunicationChannelService->state() != QLowEnergyService::ServiceState::ServiceDiscovered ||
|
||||
m_control->state() == QLowEnergyController::UnconnectedState) {
|
||||
qDebug() << QStringLiteral("writeCharacteristic error because the connection is closed");
|
||||
|
||||
// Clear the queue on disconnection
|
||||
writeQueue.clear();
|
||||
isWriting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gattWriteCharacteristic.isValid()) {
|
||||
qDebug() << QStringLiteral("gattWriteCharacteristic is invalid");
|
||||
// Clear the queue on invalid characteristic
|
||||
writeQueue.clear();
|
||||
isWriting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get next request from queue
|
||||
WriteRequest request = writeQueue.dequeue();
|
||||
isWriting = true;
|
||||
currentWriteWaitingForResponse = request.wait_for_response;
|
||||
|
||||
// Update write buffer
|
||||
if (writeBuffer) {
|
||||
delete writeBuffer;
|
||||
}
|
||||
writeBuffer = new QByteArray((const char *)data, data_len);
|
||||
writeBuffer = new QByteArray(request.data);
|
||||
|
||||
// Write the characteristic
|
||||
gattCommunicationChannelService->writeCharacteristic(gattWriteCharacteristic, *writeBuffer);
|
||||
|
||||
if (!disable_log) {
|
||||
if (!request.disable_log) {
|
||||
qDebug() << QStringLiteral(" >> ") + writeBuffer->toHex(' ')
|
||||
<< QStringLiteral(" // ") + info;
|
||||
<< QStringLiteral(" // ") + request.info;
|
||||
}
|
||||
|
||||
loop.exec();
|
||||
// Start timeout timer (300ms as before)
|
||||
writeTimeoutTimer->start(300);
|
||||
|
||||
if (timeout.isActive() == false) {
|
||||
qDebug() << QStringLiteral(" exit for timeout");
|
||||
}
|
||||
// Note: The actual completion will be signaled by:
|
||||
// - characteristicWritten (if wait_for_response = false)
|
||||
// - packetReceived (if wait_for_response = true)
|
||||
// which will call processWriteQueue() again to process the next item
|
||||
}
|
||||
|
||||
void domyostreadmill::updateDisplay(uint16_t elapsed) {
|
||||
@@ -823,6 +871,17 @@ void domyostreadmill::characteristicWritten(const QLowEnergyCharacteristic &char
|
||||
const QByteArray &newValue) {
|
||||
Q_UNUSED(characteristic);
|
||||
emit debug(QStringLiteral("characteristicWritten ") + newValue.toHex(' '));
|
||||
|
||||
// If the current write is NOT waiting for a response, we can process the next one
|
||||
if (!currentWriteWaitingForResponse) {
|
||||
// Stop timeout timer
|
||||
writeTimeoutTimer->stop();
|
||||
|
||||
// Mark writing as complete and process next item in queue
|
||||
isWriting = false;
|
||||
processWriteQueue();
|
||||
}
|
||||
// Otherwise, we need to wait for packetReceived signal
|
||||
}
|
||||
|
||||
void domyostreadmill::serviceScanDone(void) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
#include <QtCore/qqueue.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
@@ -43,6 +44,13 @@ class domyostreadmill : public treadmill {
|
||||
bool changeFanSpeed(uint8_t speed) override;
|
||||
|
||||
private:
|
||||
// Structure for async write queue
|
||||
struct WriteRequest {
|
||||
QByteArray data;
|
||||
QString info;
|
||||
bool disable_log;
|
||||
bool wait_for_response;
|
||||
};
|
||||
bool sendChangeFanSpeed(uint8_t speed);
|
||||
double GetSpeedFromPacket(const QByteArray &packet);
|
||||
double GetInclinationFromPacket(const QByteArray &packet);
|
||||
@@ -53,6 +61,7 @@ class domyostreadmill : public treadmill {
|
||||
void btinit(bool startTape);
|
||||
void writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log = false,
|
||||
bool wait_for_response = false);
|
||||
void processWriteQueue();
|
||||
void startDiscover();
|
||||
volatile bool incompletePackets = false;
|
||||
bool noConsole = false;
|
||||
@@ -75,6 +84,12 @@ class domyostreadmill : public treadmill {
|
||||
bool initDone = false;
|
||||
bool initRequest = false;
|
||||
|
||||
// Async write queue management
|
||||
QQueue<WriteRequest> writeQueue;
|
||||
bool isWriting = false;
|
||||
bool currentWriteWaitingForResponse = false;
|
||||
QTimer *writeTimeoutTimer = nullptr;
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
lockscreen *h = 0;
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,17 @@ wahookickrsnapbike::wahookickrsnapbike(bool noWriteResistance, bool noHeartServi
|
||||
connect(refresh, &QTimer::timeout, this, &wahookickrsnapbike::update);
|
||||
QSettings settings;
|
||||
refresh->start(settings.value(QZSettings::poll_device_time, QZSettings::default_poll_device_time).toInt());
|
||||
|
||||
// Initialize write timeout timer
|
||||
writeTimeoutTimer = new QTimer(this);
|
||||
writeTimeoutTimer->setSingleShot(true);
|
||||
connect(writeTimeoutTimer, &QTimer::timeout, this, [this]() {
|
||||
qDebug() << QStringLiteral("writeCharacteristic timeout - processing next in queue");
|
||||
isWriting = false;
|
||||
currentWriteWaitingForResponse = false;
|
||||
processWriteQueue();
|
||||
});
|
||||
|
||||
wheelCircumference::GearTable g;
|
||||
g.printTable();
|
||||
}
|
||||
@@ -47,47 +58,69 @@ void wahookickrsnapbike::restoreDefaultWheelDiameter() {
|
||||
|
||||
bool wahookickrsnapbike::writeCharacteristic(uint8_t *data, uint8_t data_len, QString info, bool disable_log,
|
||||
bool wait_for_response) {
|
||||
#ifndef Q_OS_IOS
|
||||
QEventLoop loop;
|
||||
QTimer timeout;
|
||||
// Create write request and add to queue
|
||||
WriteRequest request;
|
||||
request.data = QByteArray((const char *)data, data_len);
|
||||
request.info = info;
|
||||
request.disable_log = disable_log;
|
||||
request.wait_for_response = wait_for_response;
|
||||
|
||||
if (gattPowerChannelService == nullptr) {
|
||||
writeQueue.enqueue(request);
|
||||
|
||||
// Start processing if not already writing
|
||||
processWriteQueue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wahookickrsnapbike::processWriteQueue() {
|
||||
// If already writing or queue is empty, do nothing
|
||||
if (isWriting || writeQueue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check connection state
|
||||
if (!gattPowerChannelService) {
|
||||
qDebug() << QStringLiteral("gattPowerChannelService not found, write skipping...");
|
||||
return false;
|
||||
// Clear the queue on disconnection
|
||||
writeQueue.clear();
|
||||
isWriting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (wait_for_response) {
|
||||
connect(gattPowerChannelService, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), &loop,
|
||||
SLOT(quit()));
|
||||
timeout.singleShot(1000, &loop, SLOT(quit()));
|
||||
} else {
|
||||
connect(gattPowerChannelService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), &loop,
|
||||
SLOT(quit()));
|
||||
timeout.singleShot(1000, &loop, SLOT(quit()));
|
||||
if (!gattWriteCharacteristic.isValid()) {
|
||||
qDebug() << QStringLiteral("gattWriteCharacteristic is invalid");
|
||||
// Clear the queue on invalid characteristic
|
||||
writeQueue.clear();
|
||||
isWriting = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get next request from queue
|
||||
WriteRequest request = writeQueue.dequeue();
|
||||
isWriting = true;
|
||||
currentWriteWaitingForResponse = request.wait_for_response;
|
||||
|
||||
// Update write buffer
|
||||
if (writeBuffer) {
|
||||
delete writeBuffer;
|
||||
}
|
||||
writeBuffer = new QByteArray((const char *)data, data_len);
|
||||
writeBuffer = new QByteArray(request.data);
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
#ifndef IO_UNDER_QT
|
||||
iOS_wahooKickrSnapBike->writeCharacteristic((unsigned char*)writeBuffer->data(), data_len);
|
||||
#endif
|
||||
#else
|
||||
// Write the characteristic
|
||||
gattPowerChannelService->writeCharacteristic(gattWriteCharacteristic, *writeBuffer);
|
||||
#endif
|
||||
|
||||
if (!disable_log)
|
||||
debug(" >> " + writeBuffer->toHex(' ') + " // " + info);
|
||||
if (!request.disable_log) {
|
||||
debug(" >> " + writeBuffer->toHex(' ') + " // " + request.info);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
loop.exec();
|
||||
#endif
|
||||
// Start timeout timer (1000ms as before, longer than domyostreadmill)
|
||||
writeTimeoutTimer->start(1000);
|
||||
|
||||
return true;
|
||||
// Note: The actual completion will be signaled by:
|
||||
// - characteristicWritten (if wait_for_response = false)
|
||||
// - characteristicChanged (if wait_for_response = true)
|
||||
// which will call processWriteQueue() again to process the next item
|
||||
}
|
||||
|
||||
QByteArray wahookickrsnapbike::unlockCommand() {
|
||||
@@ -192,12 +225,10 @@ QByteArray wahookickrsnapbike::setWheelCircumference(double millimeters) {
|
||||
}
|
||||
|
||||
void wahookickrsnapbike::update() {
|
||||
#ifndef Q_OS_IOS
|
||||
if (m_control->state() == QLowEnergyController::UnconnectedState) {
|
||||
if (m_control && m_control->state() == QLowEnergyController::UnconnectedState) {
|
||||
emit disconnected();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSettings settings;
|
||||
bool wahooWithoutWheelDiameter = settings.value(QZSettings::wahoo_without_wheel_diameter, QZSettings::default_wahoo_without_wheel_diameter).toBool();
|
||||
@@ -231,13 +262,8 @@ void wahookickrsnapbike::update() {
|
||||
Resistance = 0;
|
||||
emit resistanceRead(Resistance.value());
|
||||
initRequest = false;
|
||||
} else if (
|
||||
#ifndef Q_OS_IOS
|
||||
bluetoothDevice.isValid() &&
|
||||
m_control->state() == QLowEnergyController::DiscoveredState
|
||||
#else
|
||||
1
|
||||
#endif
|
||||
} else if (m_control &&
|
||||
(bluetoothDevice.isValid() && m_control->state() == QLowEnergyController::DiscoveredState)
|
||||
//&&
|
||||
// gattCommunicationChannelService &&
|
||||
// gattWriteCharacteristic.isValid() &&
|
||||
@@ -439,6 +465,17 @@ void wahookickrsnapbike::characteristicChanged(const QLowEnergyCharacteristic &c
|
||||
void wahookickrsnapbike::handleCharacteristicValueChanged(const QBluetoothUuid &uuid, const QByteArray &newValue) {
|
||||
// qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length();
|
||||
|
||||
// Handle async write queue - if we were waiting for a response, process next item
|
||||
if (currentWriteWaitingForResponse && isWriting) {
|
||||
// Stop timeout timer
|
||||
writeTimeoutTimer->stop();
|
||||
|
||||
// Mark writing as complete and process next item in queue
|
||||
isWriting = false;
|
||||
currentWriteWaitingForResponse = false;
|
||||
processWriteQueue();
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
QString heartRateBeltName =
|
||||
settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString();
|
||||
@@ -654,11 +691,9 @@ void wahookickrsnapbike::handleCharacteristicValueChanged(const QBluetoothUuid &
|
||||
emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs));
|
||||
emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime));
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
if (m_control->error() != QLowEnergyController::NoError) {
|
||||
if (m_control && m_control->error() != QLowEnergyController::NoError) {
|
||||
qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void wahookickrsnapbike::stateChanged(QLowEnergyService::ServiceState state) {
|
||||
@@ -667,7 +702,6 @@ void wahookickrsnapbike::stateChanged(QLowEnergyService::ServiceState state) {
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<QLowEnergyService::ServiceState>();
|
||||
emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state)));
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
for (QLowEnergyService *s : qAsConst(gattCommunicationChannelService)) {
|
||||
qDebug() << QStringLiteral("stateChanged") << s->serviceUuid() << s->state();
|
||||
if (s->state() != QLowEnergyService::ServiceDiscovered && s->state() != QLowEnergyService::InvalidService) {
|
||||
@@ -746,7 +780,6 @@ void wahookickrsnapbike::stateChanged(QLowEnergyService::ServiceState state) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ******************************************* virtual bike init *************************************
|
||||
if (!firstStateChanged && !this->hasVirtualDevice()
|
||||
@@ -806,6 +839,17 @@ void wahookickrsnapbike::characteristicWritten(const QLowEnergyCharacteristic &c
|
||||
const QByteArray &newValue) {
|
||||
Q_UNUSED(characteristic);
|
||||
emit debug(QStringLiteral("characteristicWritten ") + newValue.toHex(' '));
|
||||
|
||||
// If the current write is NOT waiting for a response, we can process the next one
|
||||
if (!currentWriteWaitingForResponse) {
|
||||
// Stop timeout timer
|
||||
writeTimeoutTimer->stop();
|
||||
|
||||
// Mark writing as complete and process next item in queue
|
||||
isWriting = false;
|
||||
processWriteQueue();
|
||||
}
|
||||
// Otherwise, we need to wait for characteristicChanged signal
|
||||
}
|
||||
|
||||
void wahookickrsnapbike::characteristicRead(const QLowEnergyCharacteristic &characteristic,
|
||||
@@ -824,7 +868,6 @@ void wahookickrsnapbike::serviceScanDone(void) {
|
||||
m_control->requestConnectionUpdate(c);
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
auto services_list = m_control->services();
|
||||
zwift_found = false;
|
||||
wahoo_found = false;
|
||||
@@ -839,8 +882,7 @@ void wahookickrsnapbike::serviceScanDone(void) {
|
||||
wahoo_found = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
qDebug() << "zwift service found " << zwift_found << "wahoo service found" << wahoo_found;
|
||||
|
||||
if(zwift_found && !wahoo_found) {
|
||||
@@ -926,10 +968,6 @@ void wahookickrsnapbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
|
||||
// Modified connected method to handle iOS
|
||||
bool wahookickrsnapbike::connected() {
|
||||
#ifdef Q_OS_IOS
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (!m_control) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
#include <QtCore/qqueue.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
@@ -69,6 +70,13 @@ class wahookickrsnapbike : public bike {
|
||||
void handleCharacteristicValueChanged(const QBluetoothUuid &uuid, const QByteArray &newValue);
|
||||
|
||||
private:
|
||||
// Structure for async write queue
|
||||
struct WriteRequest {
|
||||
QByteArray data;
|
||||
QString info;
|
||||
bool disable_log;
|
||||
bool wait_for_response;
|
||||
};
|
||||
QByteArray unlockCommand();
|
||||
QByteArray setResistanceMode(double resistance);
|
||||
QByteArray setStandardMode(uint8_t level);
|
||||
@@ -82,6 +90,7 @@ class wahookickrsnapbike : public bike {
|
||||
|
||||
bool writeCharacteristic(uint8_t *data, uint8_t data_len, QString info, bool disable_log = false,
|
||||
bool wait_for_response = false);
|
||||
void processWriteQueue();
|
||||
uint16_t wattsFromResistance(double resistance);
|
||||
metric ResistanceFromFTMSAccessory;
|
||||
void startDiscover();
|
||||
@@ -90,11 +99,16 @@ class wahookickrsnapbike : public bike {
|
||||
QTimer *refresh;
|
||||
virtualbike *virtualBike = nullptr;
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
// Bluetooth LE services and characteristics (unified for all platforms)
|
||||
QList<QLowEnergyService *> gattCommunicationChannelService;
|
||||
QLowEnergyService *gattPowerChannelService = nullptr;
|
||||
QLowEnergyCharacteristic gattWriteCharacteristic;
|
||||
#endif
|
||||
|
||||
// Async write queue management
|
||||
QQueue<WriteRequest> writeQueue;
|
||||
bool isWriting = false;
|
||||
bool currentWriteWaitingForResponse = false;
|
||||
QTimer *writeTimeoutTimer = nullptr;
|
||||
|
||||
uint8_t sec1Update = 0;
|
||||
QByteArray lastPacket;
|
||||
|
||||
Reference in New Issue
Block a user