FTMS-Rower/js/ftms-rower.js

135 lines
4.2 KiB
JavaScript
Raw Permalink Normal View History

// UUID list
// https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/uuids/characteristic_uuids.yaml
const serviceFTMS = 0x1826;
const rowerData = 0x2ad1;
function connect() {
console.log('Requesting FTMS Bluetooth Device...');
return navigator.bluetooth.requestDevice({
filters: [{
services: [serviceFTMS],
}]
})
.then(device => {
// Human-readable name of the device.
console.log('Device name: ' + device.name);
console.log('Connecting to GATT Server...');
return device.gatt.connect();
})
.then(server => {
console.log('Getting Service...');
return server.getPrimaryService(serviceFTMS);
})
.then(service => {
console.log('Getting Characteristic...');
return service.getCharacteristic(rowerData);
})
.then(characteristic => {
characteristic.startNotifications().then(_ => {
console.log('> Notifications started');
document.querySelector(".btButton").style.display="none"; //todo show device name div instead (and later on add reconnect button if connection fails)
document.querySelector(".setupinfo").style.display="none";
document.querySelector(".training").style.display="block";
});
return characteristic;
})
.catch(error => {
console.log('Argh! ' + error);
});
}
// Field descriptions and lengths:
// https://bitbucket.org/bluetooth-SIG/public/src/main/gss/org.bluetooth.characteristic.rower_data.yaml
function parseRowerData(value) {
let a = [];
// Convert raw data bytes to hex values in order to console log each notification.
for (let i = 0; i < value.byteLength; i++) {
a.push('0x' + ('00' + value.getUint8(i).toString(16)).slice(-2));
}
console.log('> ' + a.join(' '));
var flags = value.getUint16(0, littleEndian = true);
let byteIndex = 2;
var data = [];
if ((flags & (1 << 0)) == 0) {
data['Stroke Rate'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex += 1;
data['Stroke Count'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 1)) != 0) {
data['Average Stroke Rate'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex += 1;
}
if ((flags & (1 << 2)) != 0) {
data['Total Distance'] = value.getUint16(byteIndex, littleEndian = true) + (value.getUint8(byteIndex + 2, littleEndian = true) << 16);
byteIndex += 3;
}
if ((flags & (1 << 3)) != 0) {
data['Instantaneous Pace'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 4)) != 0) {
data['Average Pace'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 5)) != 0) {
data['Instantaneous Power'] = value.getInt16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 6)) != 0) {
data['Average Power'] = value.getInt16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 7)) != 0) {
data['Resistance Level'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex++;
}
if ((flags & (1 << 8)) != 0) {
data['Total Energy'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
data['Energy Per Hour'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
data['Energy Per Minute'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex += 1;
}
if ((flags & (1 << 9)) != 0) {
data['Heart Rate'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex += 1;
}
if ((flags & (1 << 10)) != 0) {
data['Metabolic Equivalent'] = value.getUint8(byteIndex, littleEndian = true);
byteIndex += 1;
}
if ((flags & (1 << 11)) != 0) {
data['Elapsed Time'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
}
if ((flags & (1 << 12)) != 0) {
data['Remaining Time'] = value.getUint16(byteIndex, littleEndian = true);
byteIndex += 2;
}
return data;
}