Bluetooth LE app for TomTom GPS watches: Runner, MultiSport, Cardio, Spark, Runner v2
Branch: master
Clone or download
Latest commit dc7536a Dec 8, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
gatt_list move gatt_list*.txt to subdir May 26, 2016
.travis.yml add Travis-CI Jan 19, 2018
LICENSE remove cruft, add usage message and LICENSE Jul 31, 2015
Makefile v2 credits Jul 5, 2018
bbatt.c factor out addr_type_name function May 13, 2016
bbatt.h update some links to Bluetooth develop docs Jul 3, 2018
ttops.c Merge pull request #15 from Grimler91/pairing_simplification Dec 7, 2018
ttops.h Use same authorization sequence for new pair and re-auth Dec 5, 2018
version.c parse firmware version correctly as tuple of integers May 13, 2016
version.h parse firmware version correctly as tuple of integers May 13, 2016

Build Status

Table of Contents


The TomTom Multi-Sport and Runner are nice GPS watches and quite affordable, but they suffer from subpar official software. There is no official desktop app for interfacing wirelessly with the TomTom GPS watches, (only for Android and iPhone).

Now you can use ttblue to download your activites wirelessly and keep the QuickFix GPS ephemeris data up-to-date.



You need to be running a recent Linux kernel, with a Bluetooth 4.0 adapter supporting Bluetooth Low Energy. Many newer PCs include built in Bluetooth 4.0 adapters; if you need one, I've had good success with this $6 dongle, which works out-of-the-box with the btusb driver from recent Linux kernels.

The libbluetooth (BlueZ), libcurl, and popt libraries are required. On Debian/Ubuntu-based systems, these can be installed with:

$ sudo apt-get install libbluetooth-dev libcurl4-gnutls-dev libpopt-dev


Compilation with gcc should be straightforward:

$ make
$ make setcap # requires sudo/root access

To fix the issue with very slow file transfers, the most secure solution I've been able to come up with so far is to give the binary elevated capabilities as discussed on StackExchange: make setcap will do this automatically or you can do it manually as follows:

sudo setcap 'cap_net_raw,cap_net_admin+eip' ttblue

(Note that this is more secure than giving the binary setuid root permissions, because it only allows root-like privileges for these specific capabilities.)

Use it

For initial pairing, you'll need to go to the Phone|Pair New menu on the watch.

For subsequent reconnection, ensure that Phone|Sync is enabled, and you may need to "wake up" the device's BLE radio by pressing a few buttons.

Try the following command line:

./ttblue -a [-d <bluetooth-address>] [-c <pairing-code>] [-s <activity-store>]
  • bluetooth-address is the MAC address of your TomTom GPS watch, for example E4:04:39:17:62:B1. If not specified, ttblue will attempt to scan for BLE devices, and try to connect to the first one matching TomTom's vendor ID (E4:04:39).

  • The pairing-code is a previously-used pairing code (can be from one of the "official" TomTom mobile apps). If left blank, ttblue will try to create a new pairing.

  • The -a/--auto option tells ttblue to download all activities and update QuickFixGPS.

  • The -s/--activity-store option specifies a location for .ttbin activity files to be output (current directory is the default).

As invoked above, ttblue will download your activity files (saved as 0091000n_YYYYMMDD_HHmmSS.ttbin), and attempt to download the QuickGPSFix update and send it to the watch. (You can then use ttbincnv to convert the TTBIN files to GPX/TCX format.)

$ ./ttblue -a -d E4:04:39:17:62:B1 -c 123456
Opening L2CAP LE connection on ATT channel:
	 src: 00:00:00:00:00:00
	dest: E4:04:39:17:62:B1
Connected to HC4354G00150.
  maker     : TomTom Fitness
  serial    : HC4354G00150
  user_name : Lenski
  model_name: Runner
  model_num : 1001
  firmware  : 1.8.42
  rssi      : -90 dB
Setting PHONE menu to 'dlenski-ultra-0'.
Found 1 activity files on watch.
  Reading activity file 00910000 ...
11: read 55000 bytes from watch (1807/sec)
    Saved 55000 bytes to ./00910000_20150801_123616.ttbin
    Deleting activity file 00910000 ...
Updating QuickFixGPS...
  Last update was at at Sat Aug 1 04:11:03 2015.
  Sending update to watch (32150 bytes)...
7: wrote 32150 bytes to watch (1891/sec)

There's also a fairly rudimentary "daemon" mode wherein ttblue just loops over and over (by default it waits an hour to retry after a successful connection, but only 10 seconds after a failed one), and a -p/--post option to specify a command to be run on each successfully downloaded .ttbin file (see for an example):

$ ./ttblue -a --daemon -d e4:04:39:17:62:b1 -c 123456 -s ~/ttbin -p

Why so slow?

By default, Linux (as of 3.19.0) specifies a very intermittent connection interval for BLE devices. This makes sense for things like beacons and thermometers, but it is bad for devices that use BLE to transfer large files because the transfer rate is directly limited by the BLE connection interval.

If you run as root or if you give the ttblue binary elevated capabilities, it will attempt to set the minimum connection interval (7.5 ms) and activity file downloads will proceed much faster (about 1800 B/s vs. 500 B/s for me).

Unfortunately, elevated permissions are required to configure this feature of a BLE connection. For gory details, see this thread on the BlueZ mailing list.


  • More command line options?
  • Real config file?
  • Better daemon mode that actually puts itself in the background and writes output to a log file?
  • Integrate with ttwatch which already does all these things, but over USB?

Protocol documentation

See for reverse-engineered protocol documentation.


@ryanbinns did a lot of the heavy lifting by writing his excellent ttwatch utility to sync with TomTom GPS watches over USB, and in the process documenting the ttbin binary format of the activity files, as well as many of the internal data structures of the units.

@Grimler91 for adding support for TomTom GPS watches using the "v2" protocol. (Spark, Runner v2, etc.)


I'd like to license it as GPLv3 or later, but it uses snippets from the BlueZ source which are GPLv2 so... let's call it GPLv2 or later?

By Dan Lenski <> © 2015