Schwinn IC4 / IC8 and Bowflex C6 support
Nov 13, 2020
I mentioned in my Track My Indoor Workout introductory blog post that I planned to support more fitness machines.
My original inspiration was a Precor Spinner® Chrono™ Power machine, however I was not able to find any information about the details of its communication protocol. First - wiretap perspective approach: I knew Wahoo Fitness app supported it (except the most important ones: power meter and cadence readings) so while exercising on the machine I turned on bluetooth snooping and basically wire sharked the traffic. I could only analyze the yielded HCI snoop CFA files with a Windows software and the results were too mirky.
So I switched tactics and prepared modified versions of the flutter_blue and flutter_ble example applications. The idea was that I’ll use one of these plugins anyway so I can accustom myself to their details while gathering data at the same time.
I gathered data in four exercise forms:
- pedaling normally
- pedaling with very high resistance but very low cadence
- pedaling with very high cadence but low resistance
- idling (stopped pedaling).
I was making snapshots of the data and also screenshots of the bike’s console so later I can correlate the information and decipher what bytes belong to what data. The various modes would help separate the different measurements. My plan paid off and with tireless work I isolated the most important Bluetooth GATT Services and GATT Characteristics. I finally honed in on a single characteristic which supplied enough data to calculate everything. I’d say the protocol is proprietary, because I haven’t found a standard description anywhere.
I had way more trouble with the Schwinn IC4. I knew if I could add Schwinn IC4 (US version of the bike) then technically I’d cover Schwinn IC8 (UK version of the same bike) as well as Bowflex C6. These machines are all produced by Nautilus Inc. I reached out to Schwinn, Bowflex, and Nautilus (the reason my app is not open source yet is if I’d receive any proprietary information) with no result, so I started on my reverse engineering journey again - this time with more struggle. I practiced my 4 exercise forms but I was not able to sort out the data as clearly as I could with the Precor equipment. I started to cherish Precor’s proprietary protocol.
I went back to the drawing board and after some more research I realized that Schwinn actually is following Bluetooth Low Energy standard GATT Services and Characteristics. For example it supplied wheel and crank revolution data through 0x1816 Service 0x2A5B characteristic. That data does not tell you the immediate rpm (rotation per minute) but only the cumulative revolution and related time stamps. This tripped other developers (see also): it would require maintaining a dynamic ring buffer and calculating the rpm over a time window ourselves.
Fortunately one of the many other sources the bike offers is GATT Service 0x1826 Characteristic 0x2AD2. These characteristics were available on bluetooth.com in 2017, however today they are not. You either have to use the wayback machine or later I found this GitHub repository. With the XML definitions I could decipher the protocol: one of the measurements was 24 bits (not 16 or 32 as I expected), that threw me off before I saw the XML, or the fact that the cadence data has 0.5 precision or the times had 1/1024 seconds resolution. On top of that the indoor_bike_data.xml has an error which made me miss that Schwinn IC4 actually provided the cadence here as well. Schwinn IC4 also supplies the heart rate in a different GATT service and characteristic, but having everything (except cumulative energy expense) under the hood of the 0x2AD2 makes the support less complex.
I still had to go through a bunch of hoops and the calorie counting seems to lag, but the support’s minimum viable version is released.
Besides that major feature I also improved the UI in several ways:
- Introduced configurable training zones. While exercising the measurements and icons are clickable and then the track progress visualization would switch to a corresponding zone colored rolling graph of power, speed, cadence, or heart rate. (Only exceptions are old phones where I turn off the extra visualization, but that can be turned back on by a configuration option).
- The Activity details page has also colored graphs and pie charts depicting the training zones as well.
- I started to use a circular floating action button on the start screen and more colors.
- Many small UX enhancements like spinner feedback while the uploading to Strava is in progress.
I’ll enhance the UX further: the activity list and details page will match the measurement screen better (I’ll employ the same icon and the 7 segment and 14 segment fonts). I’m also working on fixing crucial bugs (for example Strava authentication issues). I don’t have a timeline for an iOS release yet, but it’s constantly in the back of my mind how I could pull that off.