Add settings for buzz; more timeouts to better detect activities; reduce memory usage

pull/1270/head
Marco Heiming 2022-01-11 16:04:54 +01:00
parent 83aa32ee84
commit a3ada12a92
3 changed files with 92 additions and 34 deletions

View File

@ -5518,7 +5518,11 @@
"readme": "README.md",
"storage": [
{"name":"banglexercise.app.js","url":"app.js"},
{"name":"banglexercise.img","url":"app-icon.js","evaluate":true}
{"name":"banglexercise.img","url":"app-icon.js","evaluate":true},
{"name":"banglexercise.settings.js","url":"settings.js"}
],
"data": [
{"name":"banglexercise.json"}
]
}
]

View File

@ -9,10 +9,11 @@ let historyAvgZ = [];
let historySlopeY = [];
let historySlopeZ = [];
let lastZeroPassType;
let lastZeroPassCameFromPositive;
let lastZeroPassTime = 0;
let lastExerciseCmpltTime = 0;
let lastExerciseCompletionTime = 0;
let lastExerciseHalfCompletionTime = 0;
let exerciseType = {
"id": "",
@ -22,19 +23,23 @@ let exerciseType = {
// add new exercises here:
const exerciseTypes = [{
"id": "pushup",
"name": "Push ups",
"name": "push ups",
"useYaxe": true,
"useZaxe": false,
"thresholdY": 2500,
"thresholdTime": 1400 // mininmal time between two push ups
"thresholdMinTime": 1400, // mininmal time between two push ups in ms
"thresholdMaxTime": 5000, // maximal time between two push ups in ms
"thresholdMinDurationTime": 700, // mininmal duration of half a push ups in ms
},
{
"id": "curl",
"name": "Curls",
"name": "curls",
"useYaxe": true,
"useZaxe": false,
"thresholdY": 2500,
"thresholdTime": 1000 // mininmal time between two curls
"thresholdMinTime": 1000, // mininmal time between two curls in ms
"thresholdMaxTime": 5000, // maximal time between two curls in ms
"thresholdMinDurationTime": 500, // mininmal duration of half a push ups in ms
}
];
let exerciseCounter = 0;
@ -47,6 +52,10 @@ const avgSize = 6;
let hrtValue;
let settings = storage.readJSON("banglexercise.json", 1) || {
'buzz': true
};
function showMainMenu() {
let menu;
menu = {
@ -64,7 +73,7 @@ function showMainMenu() {
});
if (exerciseCounter > 0) {
menu["----"] = {
menu["--------"] = {
value: ""
};
menu["Last:"] = {
@ -91,6 +100,8 @@ function accelHandler(accel) {
if (historyY.length > avgSize / 2) {
const avgY = E.sum(historyY) / historyY.length;
historyAvgY.push([t, avgY]);
while (historyAvgY.length > avgSize)
historyAvgY.shift();
}
}
@ -103,6 +114,8 @@ function accelHandler(accel) {
if (historyZ.length > avgSize / 2) {
const avgZ = E.sum(historyZ) / historyZ.length;
historyAvgZ.push([t, avgZ]);
while (historyAvgZ.length > avgSize)
historyAvgZ.shift();
}
}
@ -113,7 +126,6 @@ function accelHandler(accel) {
const p1 = historyAvgY[l - 2];
const p2 = historyAvgY[l - 1];
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
switch (exerciseType.id) {
case "pushup":
@ -154,7 +166,9 @@ function isValidYAxisExercise(slopeY, t) {
if (!exerciseType) return;
const thresholdY = exerciseType.thresholdY;
const thresholdTime = exerciseType.thresholdTime;
const thresholdMinTime = exerciseType.thresholdMinTime;
const thresholdMaxTime = exerciseType.thresholdMaxTime;
const thresholdMinDurationTime = exerciseType.thresholdMinDurationTime;
const exerciseName = exerciseType.name;
if (Math.abs(slopeY) >= thresholdY) {
@ -164,43 +178,61 @@ function isValidYAxisExercise(slopeY, t) {
const lSlopeY = historySlopeY.length;
if (lSlopeY > 1) {
const p1 = historySlopeY[lSlopeY - 2][1];
const p2 = historySlopeY[lSlopeY - 1][1];
const p1 = historySlopeY[lSlopeY - 1][1];
const p2 = historySlopeY[lSlopeY - 2][1];
if (p1 > 0 && p2 < 0) {
if (lastZeroPassType == "-+") {
if (lastZeroPassCameFromPositive == false) {
lastExerciseHalfCompletionTime = t;
console.log(t, exerciseName + " half complete...");
layout.progress.label = "*";
layout.progress.label = "½";
layout.render();
}
lastZeroPassType = "+-";
lastZeroPassCameFromPositive = true;
lastZeroPassTime = t;
}
if (p2 > 0 && p1 < 0) {
if (lastZeroPassType == "+-") {
// potential complete exercise. Let's check the time difference...
const tDiffLastPushUp = t - lastExerciseCmpltTime;
if (lastZeroPassCameFromPositive == true) {
const tDiffLastExercise = t - lastExerciseCompletionTime;
const tDiffStart = t - tStart;
console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart));
console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart));
if ((lastExerciseCmpltTime <= 0 && tDiffStart >= thresholdTime) || tDiffLastPushUp >= thresholdTime) {
// 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) {
console.log(t, exerciseName + " complete!!!");
lastExerciseCmpltTime = t;
lastExerciseCompletionTime = t;
exerciseCounter++;
layout.count.label = exerciseCounter;
layout.progress.label = "";
layout.render();
Bangle.buzz(100, 0.4); // TODO make configurable
if (settings.buzz)
Bangle.buzz(100, 0.4);
} else {
console.log(t, exerciseName + " to quick for duration time threshold!");
lastExerciseCompletionTime = t;
}
} else {
console.log(t, exerciseName + " to slow for time threshold!");
lastExerciseCompletionTime = t;
}
} else {
console.log(t, exerciseName + " to quick for time threshold!");
lastExerciseCompletionTime = t;
}
}
lastZeroPassType = "-+";
lastZeroPassCameFromPositive = false;
lastZeroPassTime = t;
}
}
@ -216,9 +248,10 @@ function reset() {
historySlopeY = [];
historySlopeZ = [];
lastZeroPassType = "";
lastZeroPassCameFromPositive = undefined;
lastZeroPassTime = 0;
lastExerciseCmpltTime = 0;
lastExerciseHalfCompletionTime = 0;
lastExerciseCompletionTime = 0;
exerciseCounter = 0;
tStart = 0;
}
@ -300,18 +333,18 @@ function startRecording() {
Bangle.setPollInterval(80); // 12.5 Hz
Bangle.on('accel', accelHandler);
Bangle.buzz(200, 1);
tStart = new Date().getTime();
recordActive = true;
if (settings.buzz)
Bangle.buzz(200, 1);
}
function stopRecording() {
if (!recordActive) return;
g.clear(1);
Bangle.setHRMPower(0, "banglexercise");
Bangle.removeListener('accel', accelHandler);
Bangle.setHRMPower(0, "banglexercise");
showMainMenu();
recordActive = false;
}

View File

@ -0,0 +1,21 @@
(function(back) {
const SETTINGS_FILE = "banglexercise.json";
const storage = require('Storage');
let settings = storage.readJSON(SETTINGS_FILE, 1) || {};
function save(key, value) {
settings[key] = value;
storage.write(SETTINGS_FILE, settings);
}
E.showMenu({
'': { 'title': 'BanglExercise' },
'< Back': back,
'Buzz': {
value: "buzz" in settings ? settings.buzz : false,
format: () => (settings.buzz ? 'Yes' : 'No'),
onchange: () => {
settings.buzz = !settings.buzz;
save('buzz', settings.buzz);
}
}
});
});