A Bluetooth bridge for First Degree Fitness (FDF) rower consoles that enables wireless connectivity to fitness applications like Kinomap using the Bluetooth Fitness Machine Service (FTMS) protocol.
This project creates an ESP32-S3 firmware that acts as a USB-to-Bluetooth bridge, reading rowing data from the FDF console's USB interface and broadcasting it via Bluetooth FTMS for compatibility with modern fitness applications.
- ESP32-S3-DevKitC-1 or ESP32-S3-USB-OTG development board (with native USB OTG support)
- USB OTG cable/adapter to connect FDF console to ESP32-S3
- First Degree Fitness rower console with USB interface
- USB Host Communication: Connects directly to FDF console via USB CDC-ACM
- Bluetooth FTMS: Implements Fitness Machine Service for indoor rowing
- Real-time Data: Transmits stroke rate, distance, power, calories, and timing data
- Compatible Apps: Works with Kinomap, Zwift, and other FTMS-compatible applications
All FTMS Indoor Rower Data fields are transmitted:
Timing & Stroke Data:
- Stroke count and rate (current and average)
- Elapsed time (seconds)
- Average stroke rate
Distance & Pace:
- Total distance (meters)
- Instantaneous pace per 500m
- Average pace per 500m
Power & Energy:
- Instantaneous power (watts)
- Average power (watts)
- Total energy (calories)
- Energy per hour (calories)
-
Install ESP-IDF v5.0 (recommended stable version):
# Install ESP-IDF v5.0 git clone -b v5.0 --recursive https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh esp32s3 . ./export.sh
Note: ESP-IDF v5.5+ and master branch have USB Host API changes that may cause compatibility issues. v5.0 is the most stable version for this project.
-
Clone this repository:
git clone https://github.com/avilleret/fdf-ftms-esp32 cd fdf-ftms-esp32
-
Build the project:
idf.py build
-
Flash to ESP32-S3:
idf.py flash monitor
✅ Project builds successfully with ESP-IDF v5.0
✅ USB Host functionality fully implemented with CDC-ACM support
✅ FDF protocol parser complete with rowing metrics extraction
✅ Bluetooth FTMS fully implemented with Indoor Rower Data notifications
- ✅ USB Host CDC-ACM driver initialization and automatic device detection
- ✅ Real-time data reception from FDF console via USB serial
- ✅ FDF protocol parser extracting all rowing metrics (strokes, distance, rate, power, calories, pace)
- ✅ Bluetooth controller and Bluedroid stack initialization
- ✅ GAP and GATTS callbacks registered
- ✅ FTMS service (UUID 0x1826) with Indoor Rower Data characteristic (UUID 0x2AD1)
- ✅ BLE advertising with device name "FDF Rower"
- ✅ GATT notifications with properly formatted Indoor Rower Data packets
- ✅ Connection management and subscription handling
- ✅ Complete data flow from USB to Bluetooth FTMS
The project is now fully functional and ready for hardware testing:
- USB Communication: Reads data from FDF console via USB CDC-ACM
- Protocol Parsing: Extracts rowing metrics from serial data stream
- Bluetooth FTMS: Broadcasts Indoor Rower Data via Bluetooth LE
- GATT Notifications: Sends real-time updates to connected clients
- Error Handling: Comprehensive error handling and connection management
The implementation includes:
- USB Host CDC-ACM with automatic device detection and data streaming
- FDF protocol parser with support for all standard rowing metrics
- Complete Bluetooth FTMS GATT server with Indoor Rower Data characteristic
- Proper GATT notification handling with connection and subscription management
- Indoor Rower Data packet formatting according to FTMS specification
-
Connect FDF Console: Use a USB OTG cable to connect your FDF console to the ESP32-S3's USB port (not the UART port)
-
Power: Connect the ESP32-S3 to power via USB or external power supply
-
LED Indicators: The ESP32-S3 will show connection status via built-in LEDs
- Power On: Connect power to the ESP32-S3 via USB-C port
- Connect FDF Console: Plug in your FDF console to the ESP32-S3 via USB OTG cable
- Wait for Connection: ESP32-S3 will automatically detect the FDF console and start receiving data
- Bluetooth Advertising: Device will advertise as "FDF Rower" and start BLE scanning
- Pair Device: Open your fitness app (Kinomap, Zwift, etc.) and connect to "FDF Rower"
- Enable Notifications: The app will automatically enable FTMS notifications
- Start Rowing: Begin your rowing session - data will be transmitted in real-time via Bluetooth
- Kinomap: Full compatibility with indoor rowing workouts
- Zwift: Connect as indoor rowing machine
- Concept2 Utility: Monitor and log workouts
- Any FTMS-compatible app: Generic Bluetooth fitness machine support
- Ensure USB OTG cable is properly connected
- Check that FDF console is powered on
- Verify USB port on ESP32-S3 (use USB port, not UART port)
- Check console logs for USB connection errors
- Ensure device is advertising as "FDF Rower" (check logs for "Advertising started")
- Try restarting the ESP32-S3
- Clear Bluetooth cache on your device
- Check that FTMS service is properly initialized (look for "FTMS service started" in logs)
- Verify client connects and enables notifications (check logs for "Client connected" and "Notifications enabled")
- Ensure you're connecting from an FTMS-compatible app (Kinomap, Zwift, etc.)
- Verify FDF console is sending data (check logs)
- Ensure rowing session is active
- Check protocol parser is receiving data
- Monitor FTMS notifications in logs
- Buffer size: 1024 bytes (RX and TX)
- CDC-ACM driver enabled
- USB host library configured for ESP32-S3
- Automatic device detection and connection
- Data callback for real-time processing
- Device name: "FDF Rower"
- Service: Fitness Machine Service (UUID 0x1826)
- Characteristic: Indoor Rower Data (UUID 0x2AD1)
- Advertising type: Connectable Undirected
- Advertising interval: 32-64ms (0x20-0x40)
- Channel map: All channels
- Power optimization: Classic BT memory released
The FDF protocol parser expects data in the format:
STROKES:123 TIME:12:34 DISTANCE:5000 RATE:24 POWER:150 CALORIES:200
main/
├── main.c # Main application entry point
├── usb_host_handler.c/h # USB host and CDC-ACM communication
├── fdf_protocol.c/h # FDF console protocol parser
├── ble_ftms.c/h # Bluetooth FTMS service implementation
└── CMakeLists.txt # Build configuration
To add support for additional rowing metrics:
- Update
fdf_rowing_data_tstructure infdf_protocol.h - Add parsing logic in
fdf_protocol.c - Update FTMS data packet in
ble_ftms.c - Add appropriate FTMS flags
Enable debug logging by setting log level to DEBUG in sdkconfig:
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
- FDF Console Recorder - FDF protocol reference
- Open Rowing Monitor - FTMS implementation reference
- ESP-IDF USB Host Documentation
- Bluetooth FTMS Specification
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
For support and questions:
- Open an issue on GitHub
- Check the troubleshooting section above
- Review ESP-IDF documentation for USB host and Bluetooth issues