Skip to content

Instantly share code, notes, and snippets.

@bendtherules
Last active July 23, 2023 06:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bendtherules/6f535f114e7ffda823e003dd4c4262be to your computer and use it in GitHub Desktop.
Save bendtherules/6f535f114e7ffda823e003dd4c4262be to your computer and use it in GitHub Desktop.
Control GFit Treadmills with BLE protocol - read and write
/**
* Returns hex command which can be sent to treadmill
* @param mode {int} Start = 1, Stop = 2, Speed = 3, Slope = 4, Pause = 5
* @param speed {int} Speed in Km/hr*10. Ex: 25 = 2.5 Km/hr
* @param slope {int} Slope number
* @returns {string} hex as string
*/
function getControlCommand(mode, speed = 0, slope = 0) {
const cmd = new Array(7);
cmd[0] = (mode & 255);
cmd[1] = (speed & 255);
cmd[2] = (slope & 255);
cmd[3] = 0;
cmd[4] = 0;
cmd[5] = (((cmd[0] + cmd[1]) ^ cmd[2]) + cmd[3] + 37);
cmd[6] = ((cmd[0] ^ cmd[1]) + cmd[2] + cmd[3] + 2);
return cmd.map(function (x) {
x = x + 0xFFFFFFFF + 1; // twos complement
x = x.toString(16); // to hex
x = ("00"+x).substr(-2); // zero-pad to 8-digits
return x;
}).join('');
}

Gfit treadmill BLE protocol

What is this?

GFit by FutureGo is an android/ios app to read and control supported BLE treadmills - usually made in China but white-labelled and sold under different names. This is an effort to document the Bluetooth protocol for it, only for personal use.

Sold under brands - Fitkit, Cultsport, Voit.

Not in scope - Elliptical treadmill, Rowers (also supported by Gfit app, but not documented here)

Resources

nRF Connect app on Android - use to send/receive values easily

Existing blog on sending commands - https://www.mertsarica.com/run-mert-run/, https://www.youtube.com/watch?v=o_elqOH75HM

To maintain connection

After connecting, the treadmill disconnects automatically after a few seconds unless you send this specific command.

CHARACTERISTIC = E54EAA55-371B-476C-99A3-74D267E3EDAE

METHOD = Write

Write hex value = 88 (hex) or -120 (byte)

Now, it will stay connected until you disconnect.

Read/notify value

CHARACTERISTIC = E54EAA56-371B-476C-99A3-74D267E3EDAE

METHOD = Read, Notify

Byte Length = 12

Note: Received bytes has to be decoded first byte-by-byte.
Decoded byte = (((byteVal - 37) ^ 2) - 38)

Example original hex data = 4D-6B-49-D6-49-F9-49-55-94-4F-6B-49

Explanation -

Byte number 1 2 3 4 5 6 7 8 9 10 11 12
Original hex 4D 6B 49 D6 49 F9 49 55 94 4F 6B 49
Original byte 77 107 73 214 73 249 73 85 148 79 107 73
Decoded byte 4 30 0 141 0 176 0 12 71 2 30 0
Used for - Current Speed (Kmph*10) Duration high (seconds) Duration low (seconds) Distance high (Km*100) Distance low (Km*100) Calories high Calories low Heart Rate (bpm) Slope Target Speed (Kmph*10) Status

Note: Some values (Duration, Duration, Distance) are broken into two bytes (high and low) because they can be >255 in value. To get total value, use -
total = (high * 256) + low

Status is usually 0.

Write

CHARACTERISTIC = e54eaa57-371b-476c-99a3-74d267e3edae

METHOD = Write, Read

Hex value - Logic implemented in code.js file in this gist (getControlCommand).

Actions -

  1. Start treadmill
    Value = 01000000002603
    Code = getControlCommand(1, 0, 0)
    Note: Can startTreadmill with slope, but not speed
  2. Pause
    Value = 05000000002a07
    Code = getControlCommand(5, 0, 0)
    Note: Use "Start treadmill" to resume
  3. Stop
    Value = 02000000002704
    Code = getControlCommand(2, 0, 0)
  4. Set speed
    Value = 035a000000825b (9 km/h), 03340000005c39 (5.2 km/h)
    Code = getControlCommand(3, <speed>, 0)
    Note: Slope value is ignored, <speed> = Kmph*10
  5. Set slope
    Value = 0400040000250a (<slope> = 2)
    Code = getControlCommand(4, 0, <slope>)
    Note: Speed value is ignored

Keywords

com.artiwares.treadmill, GFit, FutureGo, Cultsport, Fitkit, Voit Active treadmill, RunnerT, Runner 2.0, ZY-Format-BigBod, L.C. Hangzhou, Chinese treadmill, Bluetooth, BLE

Disclaimer

UNDER NO CIRCUMSTANCE SHALL I HAVE ANY LIABILITY TO YOU FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF THE SITE OR RELIANCE ON ANY INFORMATION PROVIDED ON THE SITE. YOUR USE OF THE SITE AND YOUR RELIANCE ON ANY INFORMATION ON THE SITE IS SOLELY AT YOUR OWN RISK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment