Skip to main content

KICKR Climb & Smart Trainer

Important!

These Bluetooth SIG documents offer greater insight into how this driver works then I can:

The KICKR's driver has three different functions - compared to the one function all other drivers have:

  1. Read speed, cadence & power data
  2. Control incline
  3. Control resistance

Data Reading

Data reading is achieved by enabling notification on the indoor_bike_data characteristic with UUID (INDOOR_BIKE_DATA_UUID). Once notification is enabled, when the characteristic updates the characteristic_value_updated method is called with the new value and the process_indoor_bike_data method is called to process the new data.

The data processing is complex and the linked Bluetooth SIG documents should be investigated to understand how it works.

Incline Control

As a quick note: the incline control does not follow the standards defined by Bluetooth SIG.

A new incline value can be set by writing to the custom_incline_characteristic characteristic - UUID.

The value must be between -10 and 19, and converted to a byte array using the convert_incline_to_op_value BLE helper function. The value must also be paired with the INCLINE_CONTROL_OP_CODE OP code.

The custom_control_point_set_target_inclination method can be passed the integer value to set the new incline.

Resistance Control

A new resistance value can be set by writing to the ftms_control_point characteristic - UUID.

The value must be an integer between 0 and 100 - representing a percentage - and converted to a byte array. It must be paired with the FTMS_SET_TARGET_RESISTANCE_LEVEL OP code.

The ftms_set_target_resistance_level method can be passed the integer value to set the new resistance.

MQTT Topics

Subscribed topics messages are processed by the custom MQTT client.

Data Topics

TopicData
bike/{DEVICE_ID}/speedSpeed data
bike/{DEVICE_ID/cadenceCadence data
bike/{DEVICE_ID}/powerPower data

This should be changed to conform to the MQTT Topics documents convention:

  • bike/{DEVICE_ID}/speed/report
  • bike/{DEVICE_ID/cadence/report
  • bike/{DEVICE_ID}/power/report

Incline Topic

The incline is controlled using the topic:

bike/{DEVICE_ID}/incline

With the package expected to be only an integer.

This should be changed to conform to the MQTT Topics documents convention:

bike/{DEVICE_ID}/incline/control

Resistance Topic

The resistance is controlled using the topic:

bike/{DEVICE_ID}/resistance

With the package expected to be only an integer.

This should be changed to conform to the MQTT Topics documents convention:

bike/{DEVICE_ID}/resistance/control

MQTT Payload

The data (speed, cadence, power) payload follows a JSON structure:

{
'value' : [cadence | speed | power]
'unitName' : [a unit metric relevent to the data type]
'timestamp' : [the time at publish]
'metadata' : {
'deviceName' : [some identifier of the publishing device]
}
}

Driver Location

This driver has two parts:

An Alternative Driver

Two alternative driver wahoo_controller.py and smartbike.py were developed to implement many of the above requirements. wahoo_controller.py works and has a starter wahoo_controller_starter.py. smartbike.py is an extension of wahoo_controller.py to cover all drivers but was developed late and is not functional (I would not recommand using it).

Important!

The VR game's incline control was developed to use the improved incline control payload used by the wahoo_controller.py driver. You should use the wahoo_controller.py driver over the kickr_climb_and_smart_trainer driver.

Location - Drivers/smartbike_driver/smartbike/