Skip to content

doudar/grupetto

 
 

Repository files navigation

grupetto: workout data for Gen 2 Peloton Bikes Dougmeister

 

grupetto is an app that creates a system-wide overlay with live statistics about your ride, and transmits the metrics as a BLE power meter.

Dougmeister

You can use it to watch media from sources like Netflix and Youtube while viewing your current power output, cadence, resistance, and speed.

Note: This project is wholly unaffiliated with Peloton. Please do not approach them for support with this app. It relies on undocumented interfaces that are subject to change with any update.

For developers: When forking this project, be sure to update the ReleaseChecker to point to your repository


Installation

grupetto must be side-loaded onto the Peloton, The easiest way is to use OpenPelo. You can either watch this video , or follow the steps below to learn how to sideload an APK.

  1. Enable USB debugging on your Peloton:
    • Make sure your bike sensor cable is connected to the Peloton Tablet.
    • Go to Settings, system menu and perform a Firmware Reset.
    • Select your language on the setup screen, but don't go any further.
    • Go to Settings.
    • Go to Device Preferences.
    • Tap 7 times on Build Number to enable Developer Options.
    • Go back to Settings.
    • Go To Developer Options.
    • Enable USB debugging.
    • Disable Verify apps over USB.
    • Enable Gabeldorsche (if availiable).
    • Plug your computer into the Peloton using a micro USB-B cable.
    • Select "always allow this computer" and allow USB debugging.
  2. Run OpenPelo:
    • Double-click the downloaded executable.
    • The installer will automatically check for your device.
    • Wait for the "✅ Device connected" status.
    • Select the apps you want to install by checking the boxes (grupetto is one of the options).
    • Click "Install Selected Apps" and wait for the installation to complete.

After following those steps, the APK for grupetto can be found on the Releases tab above.

Usage

  • When first run, grupetto will ask for permission to draw over other apps. This permission is required for the app to function.

Permissions Screenshot

  • By default the overlay is shown in its expanded form.

    Pressing and holding on power graph will shrink it, and the overlay be dragged around the screen to position it:

Example of Dragging Overlay

  • Clicking once on either edge of the overlay enters minimized mode. In this mode the overlay can no longer be relocated, but it continues to show updated values. Click on it again to re-enter the exapnded mode

Minimized Mode Gif Minimized Mode Static

  • The timer can only be controlled in expanded mode. Click once on the timer to start it. Click again to pause, and hold down for 3 seconds to restart it. There is a configuration option on the main screen to show or hide the timer when minimized

Shows Timer Operation

Implementation

Getting access to sensor data

Exploring SerialPort

This project was greatly helped by the work done by @ihaque on the Pelomon project: https://ihaque.org/tag/pelomon.html

My initial attempt was to directly interface with the serial port via the SerialPort API (which would rely on reflection). But the OS is locked down quite extensively, and there was no clear way for a non-system app to access the serial port directly. Additionally there is no (known) way to get a system application onto the bike, which heavily limits our options, as many permissions used internally are marked as system level permissions.

I explored trying to leverage the built-in updater services, but it seems unlikely that there is no verification of installed packages, and they are also likely behind similar system level permissions to the serial port.

Establishing system service connection

After establishing the direct-access method was a non-starter, there I pulled APKs from my production Generation 2 bike and decompiled them via JADX. They were heavily obfuscated, but using the Pelomon project as a reference, I was able to track down an internal system service that provides communication with a Generation 2 bike.

By leveraging that system service, we're able to "leapfrog" the restriction on direct access, since technically the internal system service is accessing the Serial Port, not our application.

This also provides an ergonomic interface to build against (all the serial port resource handling is done for us), but drastically increases the odds of this being broken by an update.


I also explored a backup approach by using reflection to instantiate internal classes and manipulate their APIs, but it's a much tricker approach since we're running any code found under the current app's UID (meaning anything that was locked off to system-apps

Android App Architecture

Grupetto is an example of implementing a system service with a rich UI. Jetpack Compose was leveraged for rapid iteration.

A service acts as a LifecycleOwner to provide the scaffolding Compose expects outside of a normal activity (see LifecycleEnabledService.kt)

Due to the nature of this project relying on an undocumented interface that may break without notice, effort that has been put into organization of the composables themselves is somewhat limited, and I would not use them as a reference for what a well-built Compose app looks like

However, the patterns used to provide them with data are generally sound, and could be used as a reference for how a Service can provide data for a complex UI

Other hardware

The app is intentionally designed to not necessarily rely on data from the Peloton. The app could be expanded to support other tablets and sensor sources, such as ANT+ power meters.

Reporting Issues

Please do not approach Peloton with issues related to this. They have no duty to support a reverse engineered service.

Please use the Github issue tab, and mention which version of the OS you're running if possible ( this is displayed at the bottom of screen before the overlay is started)

Unimplemented features

I've limited this project's scope due to the fact it could easily be broken by an update.

Features I would consider out-of-scope are mostly related to workout session tracking, and interfacing directly with other apps.

What's with the name?

https://en.wikipedia.org/wiki/Autobus_(cycling)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Kotlin 92.3%
  • Java 7.7%