Skip to content

Commit 11ac7fe

Browse files
cagnuleinclaude
andcommitted
Add Freebeat Fit bike support via USB serial (issue #4822)
- New FreebeatUSB QThread: opens /dev/ttyS4 at 9600 baud 8N1 (internal UART), handles binary protocol decoded from APK reverse engineering: - 5-byte commands [startCode, action, data, checksum, 0xA0] - 13-byte telemetry packets with speed, RPM and resistance - LED heartbeat to keep bike awake - New freebeatbike device class extending bike, with virtual bike support - New QZSettings::freebeat_serialport setting - QML accordion "Freebeat Bike Options" with serial port field - Wired into bluetooth.cpp instantiation, destructor and device getter - Added to qdomyos-zwift.pri and settings-catalog.json Fixes #4822 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 48946cf commit 11ac7fe

11 files changed

Lines changed: 1037 additions & 38 deletions

src/devices/bluetooth.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
623623
settings.value(QZSettings::computrainer_serialport, QZSettings::default_computrainer_serialport).toString();
624624
QString kettlerUsbSerialPort =
625625
settings.value(QZSettings::kettler_usb_serialport, QZSettings::default_kettler_usb_serialport).toString();
626+
QString freebeatSerialPort =
627+
settings.value(QZSettings::freebeat_serialport, QZSettings::default_freebeat_serialport).toString();
626628
QString csaferowerSerialPort = settings.value(QZSettings::csafe_rower, QZSettings::default_csafe_rower).toString();
627629
QString csafeellipticalSerialPort =
628630
settings.value(QZSettings::csafe_elliptical_port, QZSettings::default_csafe_elliptical_port).toString();
@@ -949,6 +951,19 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
949951
emit searchingStop();
950952
}
951953
this->signalBluetoothDeviceConnected(kettlerUsbBike);
954+
} else if (!freebeatSerialPort.isEmpty() && !freebeatBike) {
955+
this->stopDiscovery();
956+
freebeatBike =
957+
new freebeatbike(noWriteResistance, noHeartService, bikeResistanceOffset, bikeResistanceGain);
958+
emit deviceConnected(b);
959+
connect(freebeatBike, &bluetoothdevice::connectedAndDiscovered, this,
960+
&bluetooth::connectedAndDiscovered);
961+
connect(freebeatBike, &freebeatbike::debug, this, &bluetooth::debug);
962+
freebeatBike->deviceDiscovered(b);
963+
if (this->discoveryAgent && !this->discoveryAgent->isActive()) {
964+
emit searchingStop();
965+
}
966+
this->signalBluetoothDeviceConnected(freebeatBike);
952967
} else if (!csaferowerSerialPort.isEmpty() && !csafeRower) {
953968
this->stopDiscovery();
954969
csafeRower = new csaferower(noWriteResistance, noHeartService, false);
@@ -4196,6 +4211,11 @@ void bluetooth::restart() {
41964211
delete kettlerUsbBike;
41974212
kettlerUsbBike = nullptr;
41984213
}
4214+
if (freebeatBike) {
4215+
4216+
delete freebeatBike;
4217+
freebeatBike = nullptr;
4218+
}
41994219
if (csafeRower) {
42004220

42014221
delete csafeRower;
@@ -4563,6 +4583,8 @@ bluetoothdevice *bluetooth::device() {
45634583
return computrainerBike;
45644584
} else if (kettlerUsbBike) {
45654585
return kettlerUsbBike;
4586+
} else if (freebeatBike) {
4587+
return freebeatBike;
45664588
} else if (csafeRower) {
45674589
return csafeRower;
45684590
} else if (csafeElliptical) {

src/devices/bluetooth.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#ifndef Q_OS_IOS
3737
#include "devices/computrainerbike/computrainerbike.h"
3838
#include "devices/kettlerusbbike/kettlerusbbike.h"
39+
#include "devices/freebeatbike/freebeatbike.h"
3940
#include "devices/csaferower/csaferower.h"
4041
#include "devices/csafeelliptical/csafeelliptical.h"
4142
#endif
@@ -202,6 +203,7 @@ class bluetooth : public QObject, public SignalHandler {
202203
#ifndef Q_OS_IOS
203204
computrainerbike *computrainerBike = nullptr;
204205
kettlerusbbike *kettlerUsbBike = nullptr;
206+
freebeatbike *freebeatBike = nullptr;
205207
csaferower *csafeRower = nullptr;
206208
csafeelliptical *csafeElliptical = nullptr;
207209
#endif

0 commit comments

Comments
 (0)