Developing a CIQ BLE Client for Treadmill and Fitness Equipment

I want to run on my smart treadmill and get EXACT speed and grade information via BLE.  Previously, I created an Arduino ESP-32 solution running as a BLE server that runs on the treadmill.  This server works well with Zwift etc, so I know it works.  Now the plan is to create a CLIENT on my fenix-5.  Eventually, I want to save and thereafter load my treadmill runs into Strava.  In the far away future, I would like to control my treadmill from the fenix-5 (using watch buttons to speed-up, tilt up etc) .  In the far,far,far away future, I would like to automatically adjust treadmill speed and grade based on complicated pre-planned-workouts (intervals, hill repeat etc).



Plan to read data from:

  • Fitness Machine Service UUID: 0x1826
    • Fitness Machine Feature Characteristic 0x2acc 
    • Treadmill Data Characteristic 0x2acd
      • 2902 Enable Notify Descriptor 0x2902
        • This is required so client gets more than one data point.
    • Supported Speed Range Characteristic 0x2ad4
    • Supported Incline Range Characteristic 0x2ad5
  • Keep Alive UUID

Long Form "standard" UUIDs take the form of 

where xxxxxxxx is the zero-padded short-form uuid (see above)
E.G. Fitness Machine Service long UUID would be 00001826-0000-1000-8000-00805F9B34FB

  • So how far have you gotten?  If you're doing BLE, you probably want to be able to use the sim vs side loading all the time.  To do that you need a nordic nNF52-dk or a nordic nRF52840 dongle, and load some FW on those. (the dongle is about $10US, and the nRF52-DK, about $40US if I recall.  There's info on the BLW setup in the Programmer's guide.  Also, you want to watch the presentation from the CIQ Summit on BLE:

    You can start with the nordicThingy52 sample in the SDK, as it's got the basic structure you'll need.

    Here's the info on the thingy52, as it will probably help in seeing what the code does as far as services and characteristics:

    When I first used it, in the BLE delegate, the "contains" function is really helpful, as there you can see what UUIDs are seen when scanning (add a println).  Once you find what you want, pair it, and then it's time for data...

  • Good Video!   Thanks for the link.   Gonna side-load for now, but with a lot of debug messages on the front screen.  Will see how it goes today.   The example code is really well written, self explanatory.   My MacBook 64 Bit upgrade arduino.. not so much.  I spent yesterday working through the Catalina update.   More later...

  • After about a dozen sideloads, it could get old!  As I said, the nRF52840 is about $10US, so might be worth looking into. It makes life much easier!

    Here's one:

    At the Summit they handed out the dongle and the nRf52-DK (along with a Thingy52) at the session in the video.  While I've used both, I pretty much just use the dongle right now.

  • Danger Will Robinson!

    I just noticed you mentioned a Fenix5 in your first post.  I don't think CIQ BLE is supported on the f5.  The f5 plus, yes...

    Check out the BLE section in this Blog Post:

    It's from before things like the f6 and va4 were announced so you won't see them, but the f5 is an older device and not listed.

  • My bad.  i have a f5+.  

    So far, the treadmill client app scans, filters-out all the other devices and successfully displays my treadmill in the pairing list.  But, when I pair, it only pulls down one set of speed/incline data.  Then the app disconnects and errors-out.

    Here what's weird.  I wrote the server firmware and the server pushes data ALL THE TIME.  I purposely never need to enable notifications, using the 0x2902 descriptor (ccc) like with other devices.

    I'll keep plugging.  But this Catalina upgrade is killing me, sucking time away from fun stuff.

  • First thing I'd try is slowing down how often you send data.  Maybe try every second or something.  You could be dropping the connection on the watch side because of the speed of the transmissions.

  • Something else.

    In my apps, when I get a scan result for the device I want, I just go ahead and do the pair.  It removes a step.  But something else I do is check the signal strength before I do that.  In my case, I'm looking for -85db or greater, as I found below that the connection could be unreliable.

  • Great Idea.  I love the autoconnect feature!!  I'm close to getting the treadmill Client BLE app up and running.  I solved the Catalina 64bit OS issue, by moving the BLE Server portion of the app to a Windows Laptop.  It's klunky, but at least the Windows 64bit UART drivers work.  

    For me, having the Server send-out debugging messages, really helps a lot.  So I'm refining the Server and the Garmin Client in parallel.  For example, during scan, the Garmin watch returns null as the name of the server.  Yet, it returns the name of my heart rate monitor, and stryd sensor.  Why is that?  Maybe I need to advertise more info in the Server app.  etc...

    The Client App now connects and pulls data.  Whoot!  But, because the Treadmill Data Characteristic is rather complicated, (the offsets of particular fields depends on if the Server is even sending the data) so parsing it is gonna be a pain-- little endian conversion and all that.  But that's just tedius, not difficult.  And coffee helps.

  • One thing I may not have mentioned here, is with autoconnect, I also check the RSSI and if it's below -85db, I don't connect (the signal was too flaky). 

    For the blog post I did on interfacing to a raspberry pi, it was nice as I could add debug info on the server by just turning my chair and typing, and watch things on the server and in the CIQ app at the same time, and also used some spare GPIO pins if I wanted to add something like an LED to show a specific state.  I didn't send debug info over BLE.

    As far as decoding the data, decodeNumber() works well, where you can specify the starting byte, the number of bytes as well as the endian.  I developed a function of my own with the thingy52 for things like 6Q10 fixed point on the thingy52.

    The nice thing with having control of the server is you can format the data in a way where's it's easy for the app to use

  • IT WORKS!  Thanks for all you help!  Next step is to integrate speed and elevation and display distance travelled and feet (or meters) climbed.