KICKR Climb & Smart Trainer
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:
- Read speed, cadence & power data
- Control incline
- 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
Topic | Data |
---|---|
bike/{DEVICE_ID}/speed | Speed data |
bike/{DEVICE_ID/cadence | Cadence data |
bike/{DEVICE_ID}/power | Power 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:
- Core driver code - Drivers/kickr_climb_and_smart_trainer/wahoo_device.py
- Driver starter - Drivers/kickr_climb_and_smart_trainer/incline_and_resistance_control.py
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).
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/