i am experimenting in reading bluetooth characteristics values from my indoor bike trainer. I can connect and i get callbacks on the CharacteristicValueChanged but after a lot of trying i cannot retrieve meaningful data from the byte array the value holds.
I am aware there are bluetooth specifications but shoot me, i am unable to retrieve readable data.
Can anyone assist me how to get real values that are defined here https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.indoor_bike_data.xml from a byte array ?
Things i tried:
private static void Chars_CharacteristicValueChanged(object sender, GattCharacteristicValueChangedEventArgs e)
{
var flags = e.Value[0];
var test = BitConverter.ToSingle(e.Value, 4);
Console.WriteLine(flags);
Console.WriteLine(test);
Console.WriteLine(e.Value.GetValue(4));
//for (var i = 0; i < 13; i++)
//{
// Console.WriteLine(i + ": " + BitConverter.ToBoolean(e.Value, i));
//}
//Console.WriteLine("Instant Speed: " + BitConverter.ToUInt16(e.Value, 14));
//Console.WriteLine("Average Speed: " + BitConverter.ToUInt16(e.Value, 15));
//Console.WriteLine("Instantious Cadence: " + BitConverter.ToUInt16(e.Value, 16));
//Console.WriteLine("Average Cadence: " + BitConverter.ToUInt16(e.Value, 17));
//Console.WriteLine("Total Distance: " + BitConverter.ToInt32(e.Value, 18));
//Console.WriteLine("Resistance Level: " + BitConverter.ToUInt16(e.Value, 19));
//Console.WriteLine("Instantaneous Power: " + BitConverter.ToUInt16(e.Value, 20));
//Console.WriteLine("Average Power: " + BitConverter.ToUInt16(e.Value, 21));
//Console.WriteLine("Unknown22: " + BitConverter.ToUInt16(e.Value, 22));
//Console.WriteLine("Unknown23: " + BitConverter.ToUInt16(e.Value, 23));
//Console.WriteLine("Unknown24: " + BitConverter.ToUInt16(e.Value, 24));
//Console.WriteLine("Unknown25: " + BitConverter.ToUInt16(e.Value, 25));
//Console.WriteLine("Elapsed Time: " + BitConverter.ToUInt16(e.Value, 26));
//Console.WriteLine("Unknown27: " + BitConverter.ToUInt16(e.Value, 27));
//Console.WriteLine("Unknown28: " + BitConverter.ToUInt16(e.Value, 28));
//distance = Convert.ToUInt16(e.Value[10]);
//Console.WriteLine("Distance= " + distance);
But no data that looks real life...
For example:
e.Value.GetValue(0) returns 254 e.Value.GetValue(1) returns 31 the others mostly 0 ...
Already a big thanks upfront!
EDIT After searching and trying to convert other code samples in other languages I found, i came up with something like this:
private static void Chars_CharacteristicValueChanged(object sender, GattCharacteristicValueChangedEventArgs e)
{
byte[] distanceBytes = new byte[2];
Array.Copy(e.Value, 10, distanceBytes, 0, distanceBytes.Length);
distanceBytes = PadBytes(distanceBytes, 4);
var distance = Convert.ToDouble(BitConverter.ToUInt32(distanceBytes, 0).ToString());
Console.WriteLine("Real Trainer: " + distance + "m");
}
It looks like a realistic value and most importantly, it does not go back to zero after passing the 254 value.
It seems that because of the uint24 the data is, we should take two bytes of the complete byte array (starting from index position 10).
It feels like some kind of magic, so if someone can enlighten me how to do all this correctly, i would be very grateful