Level Up Your Desk Workout: Hacking an Under Desk Bike for Desktop Fitness Tracking

alt: Person pedaling on an under desk bike while working at a computer, illustrating a desk workout setup.

Like many others navigating the realities of remote work, my regular exercise routine took a hit this year due to COVID. To counter the sedentary nature of my work-from-home setup, I decided to try an Under The Desk Bike. I opted for a model that seemed promising: it offered adjustable resistance, remained stable during use, operated quietly, and included Bluetooth connectivity for workout data tracking.

If you’re thinking about incorporating an under the desk bike into your workspace, it’s worth considering whether it will truly fit your needs. For standard desks, you might find your knees colliding with the desk itself. However, my desk has a design intended for a keyboard tray – an accessory I’ve never used. Instead, I position my keyboard directly on the desktop, elevate my chair, and use a footrest. This configuration creates an ideal height for comfortable pedaling with an under the desk bike.

Bluetooth connectivity was a key feature for me; the ability to monitor and log speed and distance serves as significant motivation. As expected, the under the desk bike came with its own mobile app. However, the app left much to be desired. It felt underdeveloped, received lukewarm reviews, required account creation, and aggressively pushed a subscription service for workout classes. While I could look past these shortcomings, the idea of constantly reaching for my phone and navigating through menus just to start a workout at my desk felt cumbersome. Leaving my phone screen on and propped up on my desk for extended periods wasn’t appealing either. Furthermore, I wasn’t thrilled about having my workout data confined to yet another proprietary app ecosystem.

The solution became clear: I needed to develop my own desktop application to interface with the under the desk bike.

The Project: Building a Custom Desktop App for Your Under Desk Bike

My project drew inspiration from an article detailing the “unbricking” of a high-end bike using a Raspberry Pi. It sparked the idea that my under the desk bike likely operated on similar principles. If I could establish a connection from my desktop, I could create a tailored application to meet my specific needs.

Project Goals:

  • Real-time display of workout metrics in a compact desktop window.
  • Recording of workout data to a local SQLite database for progress tracking, goal setting, and enhanced motivation.
  • Automatic app start and stop functionality synchronized with pedaling activity, if technically feasible.

Challenges Encountered:

  • My desktop computer lacked built-in Bluetooth capabilities.
  • I had no prior experience working with Bluetooth Low Energy (BLE) technology.

The first challenge was easily overcome with the purchase of a USB Bluetooth dongle from Amazon. The second challenge, the intricacies of Bluetooth LE, would be addressed directly through the project itself – a learning-by-doing approach.

Step 1: In-Depth Research into Under Desk Bike Communication Protocols

The initial step involved comprehensive research to gather as much information as possible. This led me to discover nRF Connect, a powerful Android application. nRF Connect provides detailed insights into nearby Bluetooth devices, enabling connection, profile exploration, and data logging. Using nRF Connect, I discovered that my under the desk bike utilizes a Nordic UART (Universal Asynchronous Receiver/Transmitter) chip. Nordic UART essentially establishes a serial communication channel over Bluetooth. This was excellent news, suggesting that the bike was likely streaming raw data bytes.

However, simply connecting with nRF Connect didn’t immediately yield workout data. While I could establish a connection and subscribe to notifications, no data was being transmitted. This required further investigation into the communication patterns of the under the desk bike.

The next phase involved capturing and analyzing the Bluetooth traffic generated by the bike’s official app to understand its communication protocol. I found a helpful article detailing how to enable Bluetooth logging on an Android phone and retrieve the logs for analysis. I activated both screen recording and Bluetooth logging on my phone, performed several workout sessions on the under the desk bike, and then downloaded the captured logs.

By using Wireshark to examine the Bluetooth logs in conjunction with my screen recordings, I successfully deciphered the communication method employed by the app and the under the desk bike. The app initiates communication by sending a command packet, to which the bike responds with one or more data packets. During a workout, the app repeatedly transmits a specific command, prompting the bike to respond with real-time workout data.

Step 2: Establishing a Bluetooth Connection with the Under Desk Bike

Through log analysis and Wireshark examination, I identified six distinct command packets sent by the official app to the under the desk bike. My next objective was to develop a basic console application capable of connecting to the bike, transmitting these commands, and processing the responses. This step aimed to validate whether I could replicate the app’s behavior directly from my desktop environment.

For this project, I chose the .NET 5.0 framework on Windows, as it offers seamless access to the Windows Runtime Bluetooth API. Integrating this API for Bluetooth communication in a .NET desktop application is a relatively straightforward process.

Step 3: Decoding and Interpreting Workout Data from the Under Desk Bike

The first command sent by the app, which I labeled the “Connect” command, is crucial and must be sent before any subsequent commands. After initiating the connection with this command, it’s essential to send further commands at intervals of no more than one second to maintain the Bluetooth connection with the under the desk bike.

Start Command: f9 d0 00 c9 Response: f9 e0 00 d9

The subsequent command, termed the “Hold” command, appears to function as a keep-alive signal, ensuring the connection remains active. The under the desk bike responds with two identical packets each time this command is sent.

Hold Command: f9 d1 05 02 00 00 00 00 d1 Response #1: f9 e1 10 07 00 00 00 00 00 00 02 00 03 37 00 00 2a Response #2: f9 e2 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 eb

Following these, there were two one-time commands, which I named “Info1” and “Info2.” These commands likely serve to retrieve model-specific information or calibration data from the under the desk bike.

Info1 Command: f9 d3 0d 01 00 00 2c 00 00 3c 00 a0 00 00 00 00 e2 00 00 00 Response #1: f9 e3 01 00 dd Response #2: f9 e3 0c 00 00 00 00 00 00 00 00 00 00 00 00 e8 Info2 Command: f9 d4 0f 02 00 00 00 00 00 00 00 00 00 00 00 00 1f 0f 0c 00 Response: f9 e4 02 00 00 df

At this point, a consistent pattern in the command and response structure emerged. Every command and response packet begins with the byte F9. The subsequent byte indicates the command or response type; the high nibble is D for commands and E for responses. The byte after that specifies the length of the packet, excluding the header. The byte following the length appears to be some form of checksum for data integrity.

The most crucial commands for real-time workout data retrieval are the “Start Workout” and “Continue Workout” commands. The “Start Workout” command is sent when a workout session begins. Subsequently, the app continuously sends the “Continue Workout” command to sample and receive workout data from the under the desk bike at regular intervals.

Start Cmd: f9 d5 0d 01 00 00 00 00 00 00 00 00 00 00 00 00 dc 00 00 00 Response #1: f9 e5 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ef Response #2: f9 e6 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ef Response #3: f9 e7 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f0 Continue Cmd: f9 d5 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 db 00 00 00 Response #1: f9 e5 10 00 09 00 03 00 07 00 00 00 99 00 00 53 00 00 01 ee Response #2: f9 e6 10 00 00 00 00 00 06 00 00 00 00 00 00 00 00 00 2f 24 Response #3: f9 e7 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f0

With a solid understanding of the communication protocol, I could now begin assembling and interpreting the workout data transmitted by the under the desk bike. My initial step was to concatenate all the workout result packets and remove the header information. Subsequently, I performed a 10-minute workout session on the under the desk bike, collecting the raw data.

00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EF 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 01 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EF 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 02 00 00 00 00 00 00 00 00 00 00 00 00 00 01 F1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EF 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 03 00 00 00 01 00 00 00 BC 00 00 66 00 00 01 15 00 00 00 00 07 00 00 00 00 00 00 00 00 00 19 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 03 00 01 00 01 00 00 00 BB 00 00 65 00 00 01 14 00 00 00 00 07 00 00 00 00 00 00 00 00 00 19 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 04 00 01 00 02 00 00 00 BE 00 00 67 00 00 01 1B 00 00 00 00 07 00 00 00 00 00 00 00 00 00 25 1B 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 05 00 01 00 03 00 00 00 C1 00 00 69 00 00 01 22 00 00 00 00 07 00 00 00 00 00 00 00 00 00 2D 23 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 06 00 02 00 04 00 00 00 C3 00 00 6A 00 00 01 28 00 00 00 00 07 00 00 00 00 00 00 00 00 00 32 28 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 07 00 02 00 06 00 00 00 C1 00 00 69 00 00 01 28 00 00 00 00 07 00 00 00 00 00 00 00 00 00 36 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 07 00 03 00 06 00 00 00 C1 00 00 69 00 00 01 29 00 00 00 00 07 00 00 00 00 00 00 00 00 00 36 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 08 00 03 00 07 00 00 00 BE 00 00 67 00 00 01 26 00 00 00 00 07 00 00 00 00 00 00 00 00 00 39 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 09 00 03 00 08 00 00 00 BA 00 00 65 00 00 01 22 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3B 31 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0A 00 04 00 09 00 00 00 B0 00 00 5F 00 00 01 15 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3C 32 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0B 00 04 00 0A 00 00 00 B5 00 00 63 00 00 01 20 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3D 33 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0B 00 05 00 0A 00 00 00 B8 00 00 64 00 00 01 25 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3D 33 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0C 00 05 00 0C 00 00 00 BB 00 00 66 00 00 01 2D 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3E 34 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0D 00 06 00 0D 00 00 00 BF 00 00 68 00 00 01 36 00 00 00 00 07 00 00 00 00 00 00 00 00 00 3F 35 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0E 00 06 00 0E 00 00 00 BF 00 00 68 00 00 01 38 00 00 00 00 07 00 00 00 00 00 00 00 00 00 40 36 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0F 00 06 00 0F 00 00 00 BF 00 00 68 00 00 01 3A 00 00 00 00 07 00 00 00 00 00 00 00 00 00 41 37 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 0F 00 07 00 0F 00 00 00 BE 00 00 67 00 00 01 39 00 00 00 00 07 00 00 00 00 00 00 00 00 00 41 37 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 ...

Key Data Observations:

  • Significant portions of the data consisted of constant zeros and a few constant values, which could be disregarded for workout metrics.
  • Some data values were single bytes, while others were two-byte words (integers).
  • Certain values incremented continuously over time, while others directly reflected my pedaling speed, registering as zero when I stopped pedaling on the under the desk bike.

Based on these observations, I developed code to parse the data into nine distinct fields, differentiating between byte and word values. I then re-ran my console application during another workout session to collect these parsed values into a CSV (Comma Separated Values) file. Importing this CSV data into Excel enabled visual analysis and clearer interpretation of each data field. Most of the values became readily understandable through this analysis. The most time-consuming aspect was realizing that the under the desk bike reports measurements in imperial units (miles, miles per hour) rather than metric units (kilometers, kilometers per hour).

The nine data fields, in the order they appear in the data stream, are:

  1. Workout Second: The current second within the minute of the workout. This value cycles from 0 to 59 repeatedly. If data is sampled at a rate faster than once per second, this value may remain constant across multiple samples.
  2. Distance (hundredths of a mile): Accumulated distance traveled in hundredths of a mile units.
  3. Workout Time (seconds): Total elapsed workout time in seconds, starting from zero and increasing as long as pedaling continues on the under the desk bike. This value pauses when pedaling stops.
  4. Speed (tenths of a mile per hour): Current speed in tenths of a mile per hour.
  5. RPM (Rotations Per Minute): Cadence or pedaling rate in rotations per minute.
  6. Unknown Byte 1: Appears related to workout intensity or speed, but its exact meaning is unclear. When not pedaling, it increments by one each second and periodically resets to a specific value before continuing to count up.
  7. Speed Level (0-9): A discrete speed level value ranging from 0 to 9.
  8. Unknown Byte 2 & 9. Unknown Byte 3: Both appear to be average speed-related values calculated over the entire workout duration. However, their precise representation remains undetermined.

From these data insights, I concluded that only three commands were strictly necessary for my desktop application: the “Connect” command, the “Start Workout” command, and the “Continue Workout” command. Furthermore, a deep understanding of the intricacies of each command was not essential; simply sending the identified byte sequences in the correct order would suffice to replicate the necessary communication for data acquisition from the under the desk bike.

Step 4: Integrating Components and Building the Desktop Application

The final phase involved structuring my findings into a cohesive API (Application Programming Interface) and developing a user-friendly WPF (Windows Presentation Foundation) application for the graphical interface. WPF’s MVVM (Model-View-ViewModel) architectural pattern is ideally suited for this type of application, promoting separation of concerns and maintainability. I leveraged Entity Framework Core to quickly implement SQLite database storage for workout data persistence.

alt: Screenshot of the custom desktop application displaying workout metrics from the under desk bike, including time, speed, distance, and RPM.

Final Application Features for Enhanced Under Desk Bike Workouts:

  • Real-time Workout Metrics: Displays workout duration, current speed, distance covered, and RPM in real-time during your under the desk bike session.
  • Post-Workout Averages: Upon workout completion, the display transitions to show average workout values for a summary of your session.
  • Automatic Workout Detection: Intelligently detects Bluetooth activation on the under the desk bike (triggered by pedaling). This automatically initiates the workout tracking and displays the application window.
  • Workout Pause Functionality: Pauses workout tracking when pedaling stops. The workout timer display blinks during paused periods. Workout automatically ends after one minute of inactivity.
  • Manual Workout Controls: Start and Stop buttons provide manual control over workout sessions for user flexibility.
  • Daily Distance Tracking: Displays daily accumulated distance for goal setting and progress monitoring.
  • System Tray Minimization: Closing the application window minimizes it to the system tray for unobtrusive background operation.
  • System Tray Icon with Context Menu: Provides a system tray icon with a context menu for quick access to application functions.
  • Always-on-Top Option: Window can be set to remain always on top of other windows via a right-click context menu for constant visibility.
  • Automatic Startup: Option to configure the application to launch automatically upon system login for seamless integration into your workflow.
  • Workout Data Logging: Saves detailed workout information and all sampled data points from the under the desk bike to a local SQLite database for historical analysis and record-keeping.

Conclusion: A Customized Desktop Fitness Solution

The custom desktop application for my under the desk bike has proven to be highly effective and fulfills all my initial objectives. It has seamlessly integrated fitness tracking into my workday. Now, the only remaining challenge is to see just how far I can pedal while working!

View this project on Github

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *