Skip to content

Commit 11992fc

Browse files
authored
Merge pull request #1 from Decathlon/feature/new-example-treadmill
Add a new example for treadmill
2 parents 0295fcf + 201ffcc commit 11992fc

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ You can contribute by sharing new example, please refer to our [Contributing](co
1313

1414
Display an overlay on Decathlon Training Plus website with live data from you Fitness Machine connected by Bluetooth to your browser.
1515

16+
## [ftms-treadmill-web-console](ftms-treadmill-web-console/)
17+
18+
Connect to a treadmill Fitness Machine by Bluetooth to your browser. Collect some values from the treadmill data in the browser console.
1619

1720

1821
# Domyos brand guidelines
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<html>
2+
<head>
3+
<title>Demo FTMS Treadmill Web Console</title>
4+
</head>
5+
6+
<body>
7+
<h1>Web Bluetooth / FTMS BLE Treadmill</h1>
8+
9+
<h2>Connection</h2>
10+
<button id="bleConnectionButton">Connect FTMS BLE Treadmill</button>
11+
<br />
12+
<span>Open the Web brower console to see the result.</span>
13+
</body>
14+
15+
<script>
16+
const serviceFTMS = 0x1826;
17+
const treadmillData = 0x2acd;
18+
19+
document.querySelector('#bleConnectionButton').addEventListener('click', function() {
20+
if (isWebBluetoothEnabled()) {
21+
connect();
22+
}
23+
});
24+
25+
26+
27+
function isWebBluetoothEnabled() {
28+
if (navigator.bluetooth) {
29+
return true;
30+
} else {
31+
ChromeSamples.setStatus('Web Bluetooth API is not available.\n' +
32+
'Please make sure the "Experimental Web Platform features" flag is enabled.');
33+
return false;
34+
}
35+
}
36+
37+
38+
39+
function connect() {
40+
console.log('Requesting FTMS Bluetooth Device...');
41+
navigator.bluetooth.requestDevice({
42+
filters:[{
43+
services: [serviceFTMS],
44+
}]})
45+
.then(device => {
46+
console.log('Connecting to GATT Server...');
47+
return device.gatt.connect();
48+
})
49+
.then(server => {
50+
console.log('Getting Service...');
51+
return server.getPrimaryService(serviceFTMS);
52+
})
53+
.then(service => {
54+
console.log('Getting Characteristic...');
55+
return service.getCharacteristic(treadmillData);
56+
})
57+
.then(characteristic => {
58+
var treadmillDataCharacteristic = characteristic;
59+
return treadmillDataCharacteristic.startNotifications().then(_ => {
60+
console.log('> Notifications started');
61+
treadmillDataCharacteristic.addEventListener('characteristicvaluechanged', handleNotifications);
62+
});
63+
})
64+
.catch(error => {
65+
console.log('Argh! ' + error);
66+
});
67+
}
68+
69+
70+
71+
72+
function handleNotifications(event) {
73+
let value = event.target.value;
74+
let a = [];
75+
// Convert raw data bytes to hex values in order to console log each notification.
76+
for (let i = 0; i < value.byteLength; i++)
77+
{
78+
a.push('0x' + ('00' + value.getUint8(i).toString(16)).slice(-2));
79+
}
80+
console.log('> ' + a.join(' '));
81+
82+
var flags = value.getUint16(0, /*littleEndian=*/true);
83+
// 2octets for flags, 2octets for instant speed, nextPosition is incremented following the number of octets for each value
84+
var nextPosition = 4;
85+
86+
87+
if ((flags & (1 << 1)) != 0) {posAvgSpeed=nextPosition; nextPosition+=2;}
88+
if ((flags & (1 << 2)) != 0) {posTotDistance=nextPosition; nextPosition+=3;}//4
89+
if ((flags & (1 << 3)) != 0) {posInclination=nextPosition; nextPosition+=4;}//8
90+
if ((flags & (1 << 4)) != 0) {posElevGain=nextPosition; nextPosition+=4;}
91+
if ((flags & (1 << 5)) != 0) {posInsPace=nextPosition; nextPosition+=1;}
92+
if ((flags & (1 << 6)) != 0) {posAvgPace=nextPosition; nextPosition+=1;}
93+
if ((flags & (1 << 7)) != 0) {posKcal=nextPosition; nextPosition+=5;}
94+
if ((flags & (1 << 8)) != 0) {posHR=nextPosition; nextPosition+=1;}
95+
if ((flags & (1 << 9)) != 0) {posMET=nextPosition; nextPosition+=1;}
96+
if ((flags & (1 << 10)) != 0) {posElaspedTime=nextPosition; nextPosition+=2;}
97+
if ((flags & (1 << 11)) != 0) {posRemainTime=nextPosition; nextPosition+=2;}
98+
if ((flags & (1 << 12)) != 0) {posForceBelt=nextPosition; nextPosition+=4;}
99+
100+
// instantaneous speed
101+
speed = value.getUint16(2, /*littleEndian=*/true)/100;
102+
console.log('> Speed ' + speed);
103+
104+
//distance
105+
distance = value.getUint16(posTotDistance, /*littleEndian=*/true);
106+
distance_complement = value.getUint8(posTotDistance + 2, /*littleEndian=*/true);
107+
distance_complement = distance_complement << 16;
108+
distance = distance + distance_complement;
109+
console.log('> Distance ' + distance);
110+
111+
if (typeof posInclination != "undefined")
112+
{
113+
inclination = (value.getInt16(posInclination, /*littleEndian=*/true)/10);
114+
console.log('> Inclinaison % ' + inclination );
115+
}
116+
117+
if (typeof posKcal != "undefined")
118+
{
119+
kcal = (value.getUint16(posKcal, /*littleEndian=*/true));
120+
console.log('> Kcal ' + kcal);
121+
}
122+
123+
if (typeof posHR != "undefined")
124+
{
125+
console.log('> HR ' + (value.getUint8(posHR, /*littleEndian=*/true)));
126+
}
127+
128+
if (typeof posElaspedTime != "undefined")
129+
{
130+
console.log('> Elapsed time ' + (value.getUint16(posElaspedTime, /*littleEndian=*/true)));
131+
}
132+
}
133+
134+
135+
136+
</script>
137+
</html>

0 commit comments

Comments
 (0)