diff --git a/src/devices/treadmill.cpp b/src/devices/treadmill.cpp index e89c4fc053..65cb493789 100644 --- a/src/devices/treadmill.cpp +++ b/src/devices/treadmill.cpp @@ -612,11 +612,31 @@ bool treadmill::cadenceFromAppleWatch() { .startsWith(QStringLiteral("Disabled"))) { long appleWatchCadence = h.stepCadence(); qDebug() << QStringLiteral("Current Cadence: ") << QString::number(appleWatchCadence); + // Slow-jogging mode: derive Speed from Apple Watch cadence when running on Fake + // Treadmill. Gated on both toggles so this only runs in the explicit Fake Treadmill + // use case and does not affect normal treadmill users by default. + const bool appleWatchTreadmillSpeed = + settings.value(QZSettings::applewatch_as_treadmill_speed, + QZSettings::default_applewatch_as_treadmill_speed).toBool() && + settings.value(QZSettings::fakedevice_treadmill, + QZSettings::default_fakedevice_treadmill).toBool(); if (appleWatchCadence > 0) { evaluateStepCount(); Cadence = appleWatchCadence; + if (appleWatchTreadmillSpeed) { + const double ratio = + settings.value(QZSettings::cadence_sensor_speed_ratio, + QZSettings::default_cadence_sensor_speed_ratio).toDouble(); + Speed = appleWatchCadence * (ratio > 0.0 ? ratio : 0.0); + } return true; } + if (appleWatchCadence == 0 && appleWatchTreadmillSpeed) { + // Cadence reported as exactly zero (user stopped); zero Speed too so the virtual + // treadmill broadcast doesn't ghost the previous value. Negative values are + // treated as "no fresh sample" and leave Speed unchanged. + Speed = 0; + } return false; } #endif diff --git a/src/qzsettings.cpp b/src/qzsettings.cpp index 1d8cc0c12f..02e1f0096f 100644 --- a/src/qzsettings.cpp +++ b/src/qzsettings.cpp @@ -1086,9 +1086,10 @@ const QString QZSettings::step_gain = QStringLiteral("step_gain"); const QString QZSettings::proform_carbon_tlx_treadmill = QStringLiteral("proform_carbon_tlx_treadmill"); const QString QZSettings::proform_carbon_tlx_v84_314_treadmill = QStringLiteral("proform_carbon_tlx_v84_314_treadmill"); const QString QZSettings::proform_carbon_tl_PFTL59723_6 = QStringLiteral("proform_carbon_tl_PFTL59723_6"); +const QString QZSettings::applewatch_as_treadmill_speed = QStringLiteral("applewatch_as_treadmill_speed"); -const uint32_t allSettingsCount = 887; +const uint32_t allSettingsCount = 888; QVariant allSettings[allSettingsCount][2] = { {QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles}, @@ -1999,6 +2000,7 @@ QVariant allSettings[allSettingsCount][2] = { {QZSettings::proform_carbon_tlx_treadmill, QZSettings::default_proform_carbon_tlx_treadmill}, {QZSettings::proform_carbon_tlx_v84_314_treadmill, QZSettings::default_proform_carbon_tlx_v84_314_treadmill}, {QZSettings::proform_carbon_tl_PFTL59723_6, QZSettings::default_proform_carbon_tl_PFTL59723_6}, + {QZSettings::applewatch_as_treadmill_speed, QZSettings::default_applewatch_as_treadmill_speed}, }; void QZSettings::qDebugAllSettings(bool showDefaults) { diff --git a/src/qzsettings.h b/src/qzsettings.h index 549acf6227..e81da19ad0 100644 --- a/src/qzsettings.h +++ b/src/qzsettings.h @@ -2989,6 +2989,15 @@ class QZSettings { static const QString proform_carbon_tl_PFTL59723_6; static constexpr bool default_proform_carbon_tl_PFTL59723_6 = false; + /** + * @brief When enabled together with fakedevice_treadmill, derives treadmill Speed from + * Apple Watch step cadence using cadence_sensor_speed_ratio. Lets users do indoor walking + * or slow jogging without a physical treadmill, broadcasting cadence-driven speed via + * the existing virtual treadmill / RSC pipeline. Default off; iOS-only effect. + */ + static const QString applewatch_as_treadmill_speed; + static constexpr bool default_applewatch_as_treadmill_speed = false; + /** * @brief Write the QSettings values using the constants from this namespace. * @param showDefaults Optionally indicates if the default should be shown with the key. diff --git a/src/settings.qml b/src/settings.qml index bb47b8d099..18b2a9afd5 100644 --- a/src/settings.qml +++ b/src/settings.qml @@ -1312,12 +1312,13 @@ import Qt.labs.platform 1.1 property double power_sensor_speed_inclination_coeff_a: 0.0 property double power_sensor_speed_inclination_coeff_b: 0.0 - property bool proform_carbon_tlx_v84_314_treadmill: false + property bool proform_carbon_tlx_v84_314_treadmill: false property bool cscbike_custom_resistance_power_table: false property real cscbike_custom_resistance_level_1: 1 property real cscbike_custom_watt_1: 100 property real cscbike_custom_resistance_level_2: 15 property real cscbike_custom_watt_2: 300 + property bool applewatch_as_treadmill_speed: false } @@ -14634,6 +14635,34 @@ import Qt.labs.platform 1.1 color: Material.color(Material.Lime) } + IndicatorOnlySwitch { + id: appleWatchAsTreadmillSpeedDelegate + text: qsTr("Use Apple Watch Cadence for Fake Treadmill Speed") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.applewatch_as_treadmill_speed + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.applewatch_as_treadmill_speed = checked; window.settings_restart_to_apply = true; } + } + + Label { + text: qsTr("iOS only. For Fake Treadmill mode: when no physical treadmill is connected, derives Speed from Apple Watch step cadence using the Wheel Ratio under Accessories > Cadence Sensor Options. The cycling default is far too high for running - try 0.04-0.15 depending on pace, from walking to running, and tune to taste. Useful with apps like Kinomap or Zwift. Default is off.") + font.bold: true + font.italic: true + font.pixelSize: Qt.application.font.pixelSize - 2 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + IndicatorOnlySwitch { id: fakeEllipticalDelegate text: qsTr("Fake Elliptical")