Skip to content

Commit abacbf2

Browse files
authored
Fanatics S8 Bike (#4555)
* Fanatics S8 Bike * Update devicediscoveryinfo.cpp * fs test fixed * test fixed * Update ftmsbike.cpp * ignoring HR * Remove unused variable in ftmsbike.h Removed unused variable 'usdc_d700_ftms_frames_received'. * 2ad9 as well * Remove characteristic filtering for USDC_D700 Removed specific characteristic checks for USDC_D700.
1 parent e78ce79 commit abacbf2

8 files changed

Lines changed: 111 additions & 51 deletions

File tree

src/devices/bluetooth.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
19241924
(b.name().toUpper().startsWith("B94")) || (b.name().toUpper().startsWith("STAGES BIKE")) ||
19251925
(b.name().toUpper().startsWith("SUITO")) || (b.name().toUpper().startsWith("D2RIDE")) ||
19261926
(b.name().toUpper().startsWith("DIRETO X")) || (b.name().toUpper().startsWith("MERACH-667-")) ||
1927+
(b.name().toUpper().startsWith("USDC-D700-")) ||
19271928
!b.name().compare(ftms_bike, Qt::CaseInsensitive) || (b.name().toUpper().startsWith("SMB1")) ||
19281929
(b.name().toUpper().startsWith("UBIKE FTMS")) || (b.name().toUpper().startsWith("INRIDE")) ||
19291930
(b.name().toUpper().startsWith("INCONDI")) || // inCondi S150i

src/devices/ftmsbike/ftmsbike.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,15 @@ void ftmsbike::init() {
140140

141141
uint8_t write[] = {FTMS_REQUEST_CONTROL};
142142
bool ret = writeCharacteristic(write, sizeof(write), "requestControl", false, true);
143-
write[0] = {FTMS_START_RESUME};
144-
ret = writeCharacteristic(write, sizeof(write), "start simulation", false, true);
143+
if (USDC_D700) {
144+
// Kinomap keeps this bike streaming by following request-control with STOP/PAUSE(0x01)
145+
// instead of the usual START/RESUME opcode.
146+
uint8_t usdcStart[] = {FTMS_STOP_PAUSE, 0x01};
147+
ret = writeCharacteristic(usdcStart, sizeof(usdcStart), "usdc d700 start workaround", false, true);
148+
} else {
149+
write[0] = {FTMS_START_RESUME};
150+
ret = writeCharacteristic(write, sizeof(write), "start simulation", false, true);
151+
}
145152

146153
if(ret) {
147154
initDone = true;
@@ -265,7 +272,7 @@ void ftmsbike::forceResistance(resistance_t requestResistance) {
265272
if(SL010 || SPORT01)
266273
Resistance = requestResistance;
267274

268-
if(JFBK5_0 || DIRETO_XR || YPBM || FIT_BK || ZIPRO_RAVE || SPEEDRACEX || MRK_S28) {
275+
if(JFBK5_0 || DIRETO_XR || YPBM || FIT_BK || ZIPRO_RAVE || SPEEDRACEX || MRK_S28 || USDC_D700) {
269276
uint8_t write[] = {FTMS_SET_TARGET_RESISTANCE_LEVEL, 0x00, 0x00};
270277
write[1] = ((uint16_t)requestResistance * 10) & 0xFF;
271278
write[2] = ((uint16_t)requestResistance * 10) >> 8;
@@ -415,7 +422,7 @@ void ftmsbike::update() {
415422
<< "elapsedMs:" << sinceLastDomyosResistance;
416423
deferResistanceRequest = true;
417424
}
418-
}
425+
}
419426

420427
if (deferResistanceRequest) {
421428
requestResistance = rR;
@@ -697,7 +704,6 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
697704
}
698705

699706
if (characteristic.uuid() == QBluetoothUuid((quint16)0x2AD2)) {
700-
701707
union flags {
702708
struct {
703709
uint16_t moreData : 1;
@@ -1529,7 +1535,7 @@ void ftmsbike::stateChanged(QLowEnergyService::ServiceState state) {
15291535
}
15301536
}
15311537

1532-
if (settings.value(QZSettings::hammer_racer_s, QZSettings::default_hammer_racer_s).toBool() || SCH_190U || SCH_290R || DOMYOS || SMB1 || FIT_BK) {
1538+
if (settings.value(QZSettings::hammer_racer_s, QZSettings::default_hammer_racer_s).toBool() || SCH_190U || SCH_290R || DOMYOS || SMB1 || FIT_BK || USDC_D700) {
15331539
QBluetoothUuid ftmsService((quint16)0x1826);
15341540
if (s->serviceUuid() != ftmsService) {
15351541
qDebug() << QStringLiteral("hammer racer bike wants to be subscribed only to FTMS service in order "
@@ -2026,6 +2032,10 @@ void ftmsbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
20262032
ergModeSupported = false;
20272033
max_resistance = 32;
20282034
_ergTable.loadDefaultData(kSpeedRaceXDefaultErgData);
2035+
} else if (device.name().toUpper().startsWith("USDC-D700-")) {
2036+
qDebug() << QStringLiteral("USDC-D700 found");
2037+
USDC_D700 = true;
2038+
resistance_lvl_mode = true;
20292039
}
20302040

20312041

src/devices/ftmsbike/ftmsbike.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class ftmsbike : public bike {
183183
bool S18 = false;
184184
bool ZIPRO_RAVE = false;
185185
bool SPEEDRACEX = false;
186+
bool USDC_D700 = false;
186187

187188
uint8_t secondsToResetTimer = 5;
188189

tst/Devices/bluetoothdevicetestsuite.cpp

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -191,39 +191,54 @@ void BluetoothDeviceTestSuite::test_deviceDetection_invalidNames_enabled()
191191
this->test_deviceDetection(false, true);
192192
}
193193

194-
void BluetoothDeviceTestSuite::test_deviceDetection_exclusions() {
195-
auto testData = this->testParam;
196-
197-
auto exclusionNames = testData->Exclusions();
198-
199-
if(exclusionNames.size()==0)
200-
GTEST_SKIP() << "No exclusions defined for this device: " << testData->Name().toStdString();
201-
202-
// Only take the first for each type of exclusion
203-
std::vector<const BluetoothDeviceTestData*> exclusions;
204-
std::unordered_set<int> exclusionTypeIds;
205-
for(auto exclusionName : exclusionNames)
206-
{
207-
auto deviceTestData = DeviceTestDataIndex::GetTestData(exclusionName);
208-
if(exclusionTypeIds.count(deviceTestData->ExpectedDeviceType()))
209-
continue;
210-
exclusions.push_back(deviceTestData);
211-
exclusionTypeIds.insert(deviceTestData->ExpectedDeviceType());
212-
}
213-
214-
bluetooth bt(this->defaultDiscoveryOptions);
215-
216-
// Test that it doesn't detect this device if its higher priority "namesakes" are already detected.
217-
for(auto exclusion : exclusions) {
218-
219-
// For each name that would otherwise result in the device being detected
220-
for(QString deviceName : this->names)
221-
{
222-
// Get the enabling configurations
223-
auto enablingConfigurations = this->getConfigurations(testData, deviceName, true);
224-
225-
for(size_t i=0; i<enablingConfigurations.size(); i++) {
226-
DeviceDiscoveryInfo enablingDiscoveryInfo = enablingConfigurations[i];
194+
void BluetoothDeviceTestSuite::test_deviceDetection_exclusions() {
195+
auto testData = this->testParam;
196+
197+
auto exclusionNames = testData->Exclusions();
198+
199+
if(exclusionNames.size()==0)
200+
GTEST_SKIP() << "No exclusions defined for this device: " << testData->Name().toStdString();
201+
202+
bluetooth bt(this->defaultDiscoveryOptions);
203+
204+
// Test that it doesn't detect this device if its higher priority "namesakes" are already detected.
205+
for(QString deviceName : this->names)
206+
{
207+
// Prefer exclusions that actually collide with the specific bluetooth name being tested.
208+
std::vector<const BluetoothDeviceTestData*> exclusions;
209+
std::unordered_set<int> exclusionTypeIds;
210+
211+
for(auto exclusionName : exclusionNames)
212+
{
213+
auto candidate = DeviceTestDataIndex::GetTestData(exclusionName);
214+
auto typeId = candidate->ExpectedDeviceType();
215+
216+
if(exclusionTypeIds.count(typeId))
217+
continue;
218+
219+
const BluetoothDeviceTestData *selected = candidate;
220+
for(auto alternativeName : exclusionNames)
221+
{
222+
auto alternative = DeviceTestDataIndex::GetTestData(alternativeName);
223+
if(alternative->ExpectedDeviceType() != typeId)
224+
continue;
225+
226+
if(alternative->NamePatternGroup()->DeviceNames().contains(deviceName)) {
227+
selected = alternative;
228+
break;
229+
}
230+
}
231+
232+
exclusions.push_back(selected);
233+
exclusionTypeIds.insert(typeId);
234+
}
235+
236+
for(auto exclusion : exclusions) {
237+
// Get the enabling configurations
238+
auto enablingConfigurations = this->getConfigurations(testData, deviceName, true);
239+
240+
for(size_t i=0; i<enablingConfigurations.size(); i++) {
241+
DeviceDiscoveryInfo enablingDiscoveryInfo = enablingConfigurations[i];
227242

228243
// get an enabling configuration for the exclusion
229244
DeviceDiscoveryInfo exclusionDiscoveryInfo(true);
@@ -253,9 +268,8 @@ void BluetoothDeviceTestSuite::test_deviceDetection_exclusions() {
253268

254269
failMessage = QString("Detected the %1 from %2 with valid config %3 in spite of exclusion by %4")
255270
.arg(testData->Name()).arg(deviceName).arg(i).arg(exclusion->Name());
256-
this->testDeviceDetection(testData, bt, *enablingDiscoveryInfo.DeviceInfo(), false, true, failMessage);
257-
}
258-
259-
}
260-
}
261-
}
271+
this->testDeviceDetection(testData, bt, *enablingDiscoveryInfo.DeviceInfo(), false, true, failMessage);
272+
}
273+
}
274+
}
275+
}

tst/Devices/devicediscoveryinfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ void InitializeTrackedSettings()
2929
trackedSettings.insert(QZSettings::ftms_accessory_name, QZSettings::default_ftms_accessory_name);
3030
trackedSettings.insert(QZSettings::ftms_bike, QZSettings::default_ftms_bike);
3131
trackedSettings.insert(QZSettings::ftms_treadmill, QZSettings::default_ftms_treadmill);
32+
trackedSettings.insert(QZSettings::gymstick_gx6_0_elliptical, QZSettings::default_gymstick_gx6_0_elliptical);
3233
trackedSettings.insert(QZSettings::hammer_racer_s, QZSettings::default_hammer_racer_s);
3334
trackedSettings.insert(QZSettings::horizon_treadmill_force_ftms, QZSettings::default_horizon_treadmill_force_ftms);
3435
trackedSettings.insert(QZSettings::iconcept_elliptical, QZSettings::default_iconcept_elliptical);
@@ -52,6 +53,7 @@ void InitializeTrackedSettings()
5253
trackedSettings.insert(QZSettings::toorx_bike, QZSettings::default_toorx_bike);
5354
trackedSettings.insert(QZSettings::toorx_ftms, QZSettings::default_toorx_ftms);
5455
trackedSettings.insert(QZSettings::toorx_ftms_treadmill, QZSettings::default_toorx_ftms_treadmill);
56+
trackedSettings.insert(QZSettings::virtufit_etappe, QZSettings::default_virtufit_etappe);
5557
};
5658

5759
static void AssertKeyIsTracked(const QString& key) {

tst/Devices/deviceindex.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ DEFINE_DEVICE(FitPlusBike_MRK_NoSettings, "FitPlus Bike (MRK, no settings)");
7878
DEFINE_DEVICE(FitPlusF5, "FitPlus F5");
7979
DEFINE_DEVICE(FitShowBF, "FitShow BF");
8080
DEFINE_DEVICE(FitShowFS, "FitShow FS");
81+
DEFINE_DEVICE(FitShowTR510T, "FitShow TR510-T");
8182
DEFINE_DEVICE(FitShowSW, "FitShow SW");
8283
DEFINE_DEVICE(FlywheelBike, "Flywheel Bike");
8384
DEFINE_DEVICE(FlywheelLifeFitnessIC8, "Flywheel Life Fitness IC8");

tst/Devices/deviceindex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class DeviceIndex
8383
DEFINE_DEVICE(FitPlusF5, "FitPlus F5");
8484
DEFINE_DEVICE(FitShowBF, "FitShow BF");
8585
DEFINE_DEVICE(FitShowFS, "FitShow FS");
86+
DEFINE_DEVICE(FitShowTR510T, "FitShow TR510-T");
8687
DEFINE_DEVICE(FitShowSW, "FitShow SW");
8788
DEFINE_DEVICE(FlywheelBike, "Flywheel Bike");
8889
DEFINE_DEVICE(FlywheelLifeFitnessIC8, "Flywheel Life Fitness IC8");

tst/Devices/devicetestdataindex.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@ void DeviceTestDataIndex::Initialize() {
399399
RegisterNewDeviceTestData(DeviceIndex::FitShowFS)
400400
->expectDevice<fitshowtreadmill>()
401401
->acceptDeviceName("FS-", DeviceNameComparison::StartsWith)
402-
->acceptDeviceName("TR510-T", DeviceNameComparison::StartsWithIgnoreCase)
403402
->configureSettingsWith(
404403
[](const DeviceDiscoveryInfo& info, bool enable, std::vector<DeviceDiscoveryInfo>& configurations) -> void
405404
{
@@ -408,17 +407,48 @@ void DeviceTestDataIndex::Initialize() {
408407
if(enable){
409408
config.setValue(QZSettings::snode_bike, false);
410409
config.setValue(QZSettings::fitplus_bike, false);
410+
config.setValue(QZSettings::hammer_racer_s, false);
411+
config.setValue(QZSettings::iconsole_elliptical, false);
412+
config.setValue(QZSettings::gymstick_gx6_0_elliptical, false);
413+
config.setValue(QZSettings::virtufit_etappe, false);
411414
configurations.push_back(config);
412415
} else {
413-
for(int i=1; i<4; i++) {
414-
config.setValue(QZSettings::snode_bike, i&1);
415-
config.setValue(QZSettings::fitplus_bike, i&2);
416-
configurations.push_back(config);
417-
}
416+
config.setValue(QZSettings::snode_bike, true);
417+
config.setValue(QZSettings::fitplus_bike, false);
418+
config.setValue(QZSettings::hammer_racer_s, false);
419+
config.setValue(QZSettings::iconsole_elliptical, false);
420+
config.setValue(QZSettings::gymstick_gx6_0_elliptical, false);
421+
config.setValue(QZSettings::virtufit_etappe, false);
422+
configurations.push_back(config);
423+
424+
config.setValue(QZSettings::snode_bike, false);
425+
config.setValue(QZSettings::fitplus_bike, true);
426+
configurations.push_back(config);
427+
428+
config.setValue(QZSettings::fitplus_bike, false);
429+
config.setValue(QZSettings::virtufit_etappe, true);
430+
configurations.push_back(config);
431+
432+
config.setValue(QZSettings::virtufit_etappe, false);
433+
config.setValue(QZSettings::hammer_racer_s, true);
434+
configurations.push_back(config);
435+
436+
config.setValue(QZSettings::hammer_racer_s, false);
437+
config.setValue(QZSettings::iconsole_elliptical, true);
438+
configurations.push_back(config);
439+
440+
config.setValue(QZSettings::iconsole_elliptical, false);
441+
config.setValue(QZSettings::gymstick_gx6_0_elliptical, true);
442+
configurations.push_back(config);
418443
}
419444
})
420445
->excluding<ftmsbike>();
421446

447+
// FitShow TR510-T
448+
RegisterNewDeviceTestData(DeviceIndex::FitShowTR510T)
449+
->expectDevice<fitshowtreadmill>()
450+
->acceptDeviceName("TR510-T", DeviceNameComparison::StartsWithIgnoreCase);
451+
422452

423453
// FitShow SW
424454
RegisterNewDeviceTestData(DeviceIndex::FitShowSW)

0 commit comments

Comments
 (0)