2022-01-10 15:10:42 +00:00
|
|
|
const Layout = require("Layout");
|
2022-01-10 18:02:39 +00:00
|
|
|
const heatshrink = require('heatshrink');
|
2022-01-11 15:18:10 +00:00
|
|
|
const storage = require('Storage');
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
let tStart;
|
2022-01-10 15:10:42 +00:00
|
|
|
let historyY = [];
|
|
|
|
let historyZ = [];
|
|
|
|
let historyAvgY = [];
|
|
|
|
let historyAvgZ = [];
|
|
|
|
let historySlopeY = [];
|
|
|
|
let historySlopeZ = [];
|
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
let lastZeroPassCameFromPositive;
|
2024-03-04 20:34:50 +00:00
|
|
|
//let lastZeroPassTime = 0;
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
let lastExerciseCompletionTime = 0;
|
|
|
|
let lastExerciseHalfCompletionTime = 0;
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
let exerciseType = {
|
2022-01-11 11:38:19 +00:00
|
|
|
"id": "",
|
2022-01-10 18:02:39 +00:00
|
|
|
"name": ""
|
|
|
|
};
|
2022-01-11 11:38:19 +00:00
|
|
|
|
|
|
|
// add new exercises here:
|
2022-01-10 18:02:39 +00:00
|
|
|
const exerciseTypes = [{
|
|
|
|
"id": "pushup",
|
2022-01-11 15:04:54 +00:00
|
|
|
"name": "push ups",
|
2022-01-14 08:47:26 +00:00
|
|
|
"useYaxis": true,
|
|
|
|
"useZaxis": false,
|
|
|
|
"threshold": 2500,
|
|
|
|
"thresholdMinTime": 800, // mininmal time between two push ups in ms
|
2022-01-11 15:04:54 +00:00
|
|
|
"thresholdMaxTime": 5000, // maximal time between two push ups in ms
|
2022-01-14 08:47:26 +00:00
|
|
|
"thresholdMinDurationTime": 600, // mininmal duration of half a push up in ms
|
2022-01-11 11:38:19 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"id": "curl",
|
2022-01-11 15:04:54 +00:00
|
|
|
"name": "curls",
|
2022-01-14 08:47:26 +00:00
|
|
|
"useYaxis": true,
|
|
|
|
"useZaxis": false,
|
|
|
|
"threshold": 2500,
|
|
|
|
"thresholdMinTime": 800, // mininmal time between two curls in ms
|
2022-01-11 15:04:54 +00:00
|
|
|
"thresholdMaxTime": 5000, // maximal time between two curls in ms
|
2022-01-14 08:47:26 +00:00
|
|
|
"thresholdMinDurationTime": 500, // mininmal duration of half a curl in ms
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"id": "situp",
|
|
|
|
"name": "sit ups",
|
|
|
|
"useYaxis": false,
|
|
|
|
"useZaxis": true,
|
|
|
|
"threshold": 3500,
|
|
|
|
"thresholdMinTime": 800, // mininmal time between two sit ups in ms
|
|
|
|
"thresholdMaxTime": 5000, // maximal time between two sit ups in ms
|
|
|
|
"thresholdMinDurationTime": 500, // mininmal duration of half a sit up in ms
|
2022-01-11 11:38:19 +00:00
|
|
|
}
|
2022-01-10 18:02:39 +00:00
|
|
|
];
|
|
|
|
let exerciseCounter = 0;
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
let layout;
|
2022-01-10 15:10:42 +00:00
|
|
|
let recordActive = false;
|
|
|
|
|
2022-01-11 11:38:19 +00:00
|
|
|
// Size of average window for data analysis
|
2022-01-10 18:02:39 +00:00
|
|
|
const avgSize = 6;
|
|
|
|
|
|
|
|
let hrtValue;
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
let settings = storage.readJSON("banglexercise.json", 1) || {
|
|
|
|
'buzz': true
|
|
|
|
};
|
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
function showMainMenu() {
|
2022-01-10 15:10:42 +00:00
|
|
|
let menu;
|
2022-01-10 18:02:39 +00:00
|
|
|
menu = {
|
|
|
|
"": {
|
2022-09-22 22:39:27 +00:00
|
|
|
title: "BanglExercise",
|
|
|
|
back: load
|
2022-01-10 18:02:39 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exerciseTypes.forEach(function(et) {
|
2022-01-14 08:47:26 +00:00
|
|
|
menu[et.name] = function() {
|
2022-01-10 18:02:39 +00:00
|
|
|
exerciseType = et;
|
|
|
|
E.showMenu();
|
2022-01-12 10:24:04 +00:00
|
|
|
startTraining();
|
2022-01-10 15:10:42 +00:00
|
|
|
};
|
2022-01-10 18:02:39 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if (exerciseCounter > 0) {
|
2022-01-11 15:04:54 +00:00
|
|
|
menu["--------"] = {
|
2022-01-11 11:38:19 +00:00
|
|
|
value: ""
|
|
|
|
};
|
2022-01-10 18:02:39 +00:00
|
|
|
menu["Last:"] = {
|
|
|
|
value: exerciseCounter + " " + exerciseType.name
|
2022-01-10 15:10:42 +00:00
|
|
|
};
|
|
|
|
}
|
2022-01-14 08:47:26 +00:00
|
|
|
menu.exit = function() {
|
|
|
|
load();
|
2022-01-12 09:27:39 +00:00
|
|
|
};
|
2022-01-10 18:02:39 +00:00
|
|
|
|
2022-01-10 15:10:42 +00:00
|
|
|
E.showMenu(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
function accelHandler(accel) {
|
2022-01-10 18:02:39 +00:00
|
|
|
if (!exerciseType) return;
|
2022-01-10 15:10:42 +00:00
|
|
|
const t = Math.round(new Date().getTime()); // time in ms
|
2022-01-14 08:47:26 +00:00
|
|
|
const y = exerciseType.useYaxis ? accel.y * 8192 : 0;
|
|
|
|
const z = exerciseType.useZaxis ? accel.z * 8192 : 0;
|
2022-01-10 15:10:42 +00:00
|
|
|
//console.log(t, y, z);
|
|
|
|
|
2022-01-14 08:47:26 +00:00
|
|
|
if (exerciseType.useYaxis) {
|
2022-01-10 18:02:39 +00:00
|
|
|
while (historyY.length > avgSize)
|
|
|
|
historyY.shift();
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
historyY.push(y);
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
if (historyY.length > avgSize / 2) {
|
|
|
|
const avgY = E.sum(historyY) / historyY.length;
|
|
|
|
historyAvgY.push([t, avgY]);
|
2022-01-11 15:04:54 +00:00
|
|
|
while (historyAvgY.length > avgSize)
|
|
|
|
historyAvgY.shift();
|
2022-01-10 18:02:39 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-14 08:47:26 +00:00
|
|
|
if (exerciseType.useZaxis) {
|
2022-01-10 18:02:39 +00:00
|
|
|
while (historyZ.length > avgSize)
|
|
|
|
historyZ.shift();
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
historyZ.push(z);
|
|
|
|
|
|
|
|
if (historyZ.length > avgSize / 2) {
|
|
|
|
const avgZ = E.sum(historyZ) / historyZ.length;
|
|
|
|
historyAvgZ.push([t, avgZ]);
|
2022-01-11 15:04:54 +00:00
|
|
|
while (historyAvgZ.length > avgSize)
|
|
|
|
historyAvgZ.shift();
|
2022-01-10 18:02:39 +00:00
|
|
|
}
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// slope for Y
|
2022-01-14 08:47:26 +00:00
|
|
|
if (exerciseType.useYaxis) {
|
2022-01-10 18:02:39 +00:00
|
|
|
let l = historyAvgY.length;
|
|
|
|
if (l > 1) {
|
|
|
|
const p1 = historyAvgY[l - 2];
|
|
|
|
const p2 = historyAvgY[l - 1];
|
2022-01-11 11:38:19 +00:00
|
|
|
const slopeY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000);
|
|
|
|
// we use this data for exercises which can be detected by using Y axis data
|
2022-01-14 08:47:26 +00:00
|
|
|
isValidExercise(slopeY, t);
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// slope for Z
|
2022-01-14 08:47:26 +00:00
|
|
|
if (exerciseType.useZaxis) {
|
2024-03-13 10:51:40 +00:00
|
|
|
let l = historyAvgZ.length;
|
2022-01-10 18:02:39 +00:00
|
|
|
if (l > 1) {
|
|
|
|
const p1 = historyAvgZ[l - 2];
|
|
|
|
const p2 = historyAvgZ[l - 1];
|
2022-01-14 08:47:26 +00:00
|
|
|
const slopeZ = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000);
|
|
|
|
// we use this data for some exercises which can be detected by using Z axis data
|
|
|
|
isValidExercise(slopeZ, t);
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-11 11:38:19 +00:00
|
|
|
}
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-11 11:38:19 +00:00
|
|
|
/*
|
2022-01-14 08:47:26 +00:00
|
|
|
* Check if slope value of Y-axis or Z-axis data (depending on exercise type) looks like an exercise
|
2022-01-11 11:38:19 +00:00
|
|
|
*
|
2022-01-14 08:47:26 +00:00
|
|
|
* In detail we look for slop values which are bigger than the configured threshold for the current exercise type
|
2022-01-11 11:38:19 +00:00
|
|
|
* Then we look for two consecutive slope values of which one is above 0 and the other is below zero.
|
|
|
|
* If we find one pair of these values this could be part of one exercise.
|
|
|
|
* Then we look for a pair of values which cross the zero from the otherwise direction
|
|
|
|
*/
|
2022-01-14 08:47:26 +00:00
|
|
|
function isValidExercise(slope, t) {
|
2022-01-11 11:38:19 +00:00
|
|
|
if (!exerciseType) return;
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-14 08:47:26 +00:00
|
|
|
const threshold = exerciseType.threshold;
|
|
|
|
const historySlopeValues = exerciseType.useYaxis ? historySlopeY : historySlopeZ;
|
2022-01-11 15:04:54 +00:00
|
|
|
const thresholdMinTime = exerciseType.thresholdMinTime;
|
|
|
|
const thresholdMaxTime = exerciseType.thresholdMaxTime;
|
|
|
|
const thresholdMinDurationTime = exerciseType.thresholdMinDurationTime;
|
2022-01-11 11:38:19 +00:00
|
|
|
const exerciseName = exerciseType.name;
|
|
|
|
|
|
|
|
|
2022-01-14 08:47:26 +00:00
|
|
|
if (Math.abs(slope) >= threshold) {
|
|
|
|
historySlopeValues.push([t, slope]);
|
|
|
|
//console.log(t, Math.abs(slope));
|
|
|
|
|
|
|
|
const lSlopeHistory = historySlopeValues.length;
|
|
|
|
if (lSlopeHistory > 1) {
|
|
|
|
const p1 = historySlopeValues[lSlopeHistory - 1][1];
|
|
|
|
const p2 = historySlopeValues[lSlopeHistory - 2][1];
|
2022-01-11 11:38:19 +00:00
|
|
|
if (p1 > 0 && p2 < 0) {
|
2022-01-11 15:04:54 +00:00
|
|
|
if (lastZeroPassCameFromPositive == false) {
|
|
|
|
lastExerciseHalfCompletionTime = t;
|
2022-01-14 08:47:26 +00:00
|
|
|
console.log(t, exerciseName + " half complete...");
|
2022-01-11 11:38:19 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
layout.progress.label = "½";
|
2022-01-14 08:47:26 +00:00
|
|
|
layout.recording.label = "TRAINING";
|
2022-01-12 09:27:39 +00:00
|
|
|
g.clear();
|
2022-01-11 11:38:19 +00:00
|
|
|
layout.render();
|
|
|
|
}
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
lastZeroPassCameFromPositive = true;
|
2024-03-04 20:34:50 +00:00
|
|
|
//lastZeroPassTime = t;
|
2022-01-11 11:38:19 +00:00
|
|
|
}
|
|
|
|
if (p2 > 0 && p1 < 0) {
|
2022-01-11 15:04:54 +00:00
|
|
|
if (lastZeroPassCameFromPositive == true) {
|
|
|
|
const tDiffLastExercise = t - lastExerciseCompletionTime;
|
2022-01-11 11:38:19 +00:00
|
|
|
const tDiffStart = t - tStart;
|
2022-01-14 08:47:26 +00:00
|
|
|
console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart));
|
2022-01-11 15:04:54 +00:00
|
|
|
|
|
|
|
// check minimal time between exercises:
|
|
|
|
if ((lastExerciseCompletionTime <= 0 && tDiffStart >= thresholdMinTime) || tDiffLastExercise >= thresholdMinTime) {
|
|
|
|
|
|
|
|
// check maximal time between exercises:
|
|
|
|
if (lastExerciseCompletionTime <= 0 || tDiffLastExercise <= thresholdMaxTime) {
|
|
|
|
|
|
|
|
// check minimal duration of exercise:
|
|
|
|
const tDiffExerciseHalfCompletion = t - lastExerciseHalfCompletionTime;
|
|
|
|
if (tDiffExerciseHalfCompletion > thresholdMinDurationTime) {
|
2022-01-12 09:31:05 +00:00
|
|
|
//console.log(t, exerciseName + " complete!!!");
|
2022-01-11 15:04:54 +00:00
|
|
|
|
|
|
|
lastExerciseCompletionTime = t;
|
|
|
|
exerciseCounter++;
|
|
|
|
|
|
|
|
layout.count.label = exerciseCounter;
|
|
|
|
layout.progress.label = "";
|
2022-01-14 08:47:26 +00:00
|
|
|
layout.recording.label = "Good!";
|
|
|
|
|
2022-01-12 09:27:39 +00:00
|
|
|
g.clear();
|
2022-01-11 15:04:54 +00:00
|
|
|
layout.render();
|
|
|
|
|
|
|
|
if (settings.buzz)
|
2022-01-14 08:47:26 +00:00
|
|
|
Bangle.buzz(200, 0.5);
|
2022-01-11 15:04:54 +00:00
|
|
|
} else {
|
2022-01-14 08:47:26 +00:00
|
|
|
console.log(t, exerciseName + " too quick for duration time threshold!"); // thresholdMinDurationTime
|
2022-01-11 15:04:54 +00:00
|
|
|
lastExerciseCompletionTime = t;
|
2022-01-14 08:47:26 +00:00
|
|
|
|
|
|
|
layout.recording.label = "Go slower!";
|
|
|
|
g.clear();
|
|
|
|
layout.render();
|
2022-01-11 15:04:54 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-01-14 08:47:26 +00:00
|
|
|
console.log(t, exerciseName + " top slow for time threshold!"); // thresholdMaxTime
|
2022-01-11 15:04:54 +00:00
|
|
|
lastExerciseCompletionTime = t;
|
2022-01-14 08:47:26 +00:00
|
|
|
|
|
|
|
layout.recording.label = "Go faster!";
|
|
|
|
g.clear();
|
|
|
|
layout.render();
|
2022-01-11 15:04:54 +00:00
|
|
|
}
|
2022-01-11 11:38:19 +00:00
|
|
|
} else {
|
2022-01-14 08:47:26 +00:00
|
|
|
console.log(t, exerciseName + " too quick for time threshold!"); // thresholdMinTime
|
2022-01-11 15:04:54 +00:00
|
|
|
lastExerciseCompletionTime = t;
|
2022-01-14 08:47:26 +00:00
|
|
|
|
|
|
|
layout.recording.label = "Go slower!";
|
|
|
|
g.clear();
|
|
|
|
layout.render();
|
2022-01-11 11:38:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-10 15:10:42 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
lastZeroPassCameFromPositive = false;
|
2024-03-04 20:34:50 +00:00
|
|
|
//lastZeroPassTime = t;
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-11 11:38:19 +00:00
|
|
|
|
2022-01-10 15:10:42 +00:00
|
|
|
function reset() {
|
|
|
|
historyY = [];
|
|
|
|
historyZ = [];
|
|
|
|
historyAvgY = [];
|
|
|
|
historyAvgZ = [];
|
|
|
|
historySlopeY = [];
|
|
|
|
historySlopeZ = [];
|
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
lastZeroPassCameFromPositive = undefined;
|
2024-03-04 20:34:50 +00:00
|
|
|
//lastZeroPassTime = 0;
|
2022-01-11 15:04:54 +00:00
|
|
|
lastExerciseHalfCompletionTime = 0;
|
|
|
|
lastExerciseCompletionTime = 0;
|
2022-01-10 18:02:39 +00:00
|
|
|
exerciseCounter = 0;
|
|
|
|
tStart = 0;
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-12 10:24:04 +00:00
|
|
|
function startTraining() {
|
2022-01-10 15:10:42 +00:00
|
|
|
if (recordActive) return;
|
|
|
|
g.clear(1);
|
|
|
|
reset();
|
2022-01-14 08:47:26 +00:00
|
|
|
Bangle.setLCDTimeout(0); // force LCD on
|
2022-01-10 18:02:39 +00:00
|
|
|
Bangle.setHRMPower(1, "banglexercise");
|
|
|
|
if (!hrtValue) hrtValue = "...";
|
|
|
|
|
2022-01-10 15:10:42 +00:00
|
|
|
layout = new Layout({
|
|
|
|
type: "v",
|
|
|
|
c: [{
|
|
|
|
type: "txt",
|
|
|
|
id: "type",
|
|
|
|
font: "6x8:2",
|
2022-01-10 18:02:39 +00:00
|
|
|
label: exerciseType.name,
|
2022-01-10 15:10:42 +00:00
|
|
|
pad: 5
|
|
|
|
},
|
|
|
|
{
|
2022-01-10 18:02:39 +00:00
|
|
|
type: "h",
|
|
|
|
c: [{
|
|
|
|
type: "txt",
|
|
|
|
id: "count",
|
2022-01-12 09:27:39 +00:00
|
|
|
font: exerciseCounter < 100 ? "6x8:9" : "6x8:8",
|
2022-01-14 08:47:26 +00:00
|
|
|
label: exerciseCounter,
|
2022-01-12 09:27:39 +00:00
|
|
|
pad: 5
|
2022-01-10 18:02:39 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "txt",
|
|
|
|
id: "progress",
|
|
|
|
font: "6x8:2",
|
|
|
|
label: "",
|
|
|
|
pad: 5
|
|
|
|
},
|
|
|
|
]
|
2022-01-10 15:10:42 +00:00
|
|
|
},
|
|
|
|
{
|
2022-01-10 18:02:39 +00:00
|
|
|
type: "h",
|
|
|
|
c: [{
|
|
|
|
type: "img",
|
|
|
|
pad: 4,
|
|
|
|
src: function() {
|
|
|
|
return heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM"));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "txt",
|
|
|
|
id: "hrtRate",
|
|
|
|
font: "6x8:2",
|
|
|
|
label: hrtValue,
|
|
|
|
pad: 5
|
|
|
|
},
|
|
|
|
]
|
2022-01-10 15:10:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "txt",
|
|
|
|
id: "recording",
|
|
|
|
font: "6x8:2",
|
2022-01-12 10:24:04 +00:00
|
|
|
label: "TRAINING",
|
2022-01-10 15:10:42 +00:00
|
|
|
bgCol: "#f00",
|
|
|
|
pad: 5,
|
|
|
|
fillx: 1
|
|
|
|
},
|
|
|
|
]
|
|
|
|
}, {
|
2022-01-11 11:38:19 +00:00
|
|
|
btns: [{
|
|
|
|
label: "STOP",
|
|
|
|
cb: () => {
|
2022-01-12 10:24:04 +00:00
|
|
|
stopTraining();
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
2022-01-11 11:38:19 +00:00
|
|
|
}],
|
2022-01-12 09:27:39 +00:00
|
|
|
lazy: false
|
2022-01-10 15:10:42 +00:00
|
|
|
});
|
|
|
|
layout.render();
|
|
|
|
|
|
|
|
Bangle.setPollInterval(80); // 12.5 Hz
|
2022-01-14 08:47:26 +00:00
|
|
|
|
2022-01-10 15:10:42 +00:00
|
|
|
tStart = new Date().getTime();
|
|
|
|
recordActive = true;
|
2022-01-11 15:04:54 +00:00
|
|
|
if (settings.buzz)
|
|
|
|
Bangle.buzz(200, 1);
|
2022-01-14 08:47:26 +00:00
|
|
|
|
|
|
|
// delay start a little bit
|
|
|
|
setTimeout(() => {
|
|
|
|
Bangle.on('accel', accelHandler);
|
|
|
|
}, 1000);
|
2022-01-10 15:10:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 10:24:04 +00:00
|
|
|
function stopTraining() {
|
2022-01-10 15:10:42 +00:00
|
|
|
if (!recordActive) return;
|
2022-01-10 18:02:39 +00:00
|
|
|
|
2022-01-11 15:04:54 +00:00
|
|
|
g.clear(1);
|
2022-01-10 15:10:42 +00:00
|
|
|
Bangle.removeListener('accel', accelHandler);
|
2022-01-11 15:04:54 +00:00
|
|
|
Bangle.setHRMPower(0, "banglexercise");
|
2022-01-10 18:02:39 +00:00
|
|
|
showMainMenu();
|
2022-01-10 15:10:42 +00:00
|
|
|
recordActive = false;
|
|
|
|
}
|
|
|
|
|
2022-01-10 18:02:39 +00:00
|
|
|
Bangle.on('HRM', function(hrm) {
|
|
|
|
hrtValue = hrm.bpm;
|
|
|
|
});
|
|
|
|
|
2022-01-10 15:10:42 +00:00
|
|
|
g.clear(1);
|
2022-09-22 22:53:45 +00:00
|
|
|
Bangle.loadWidgets();
|
2022-01-10 18:02:39 +00:00
|
|
|
showMainMenu();
|