health: calculate distance from steps
- multiplies step counts with stride length - distance menu under step counting is only available if stride length is setmaster
parent
4f38e475a8
commit
dbf8995b14
|
|
@ -29,3 +29,4 @@
|
||||||
0.26: Implement API for activity fetching
|
0.26: Implement API for activity fetching
|
||||||
0.27: Fix typo in daily summary graph code causing graph not to load
|
0.27: Fix typo in daily summary graph code causing graph not to load
|
||||||
Fix daily summaries for 31st of the month
|
Fix daily summaries for 31st of the month
|
||||||
|
0.28: Calculate distance from steps if new stride length setting is set
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
let settings;
|
||||||
|
|
||||||
function menuMain() {
|
function menuMain() {
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
"": { title: /*LANG*/"Health Tracking" },
|
"": { title: /*LANG*/"Health Tracking" },
|
||||||
|
|
@ -5,16 +7,30 @@ function menuMain() {
|
||||||
/*LANG*/"Step Counting": () => menuStepCount(),
|
/*LANG*/"Step Counting": () => menuStepCount(),
|
||||||
/*LANG*/"Movement": () => menuMovement(),
|
/*LANG*/"Movement": () => menuMovement(),
|
||||||
/*LANG*/"Heart Rate": () => menuHRM(),
|
/*LANG*/"Heart Rate": () => menuHRM(),
|
||||||
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>menuMain())
|
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>{loadSettings();menuMain();})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function menuStepCount() {
|
function menuStepCount() {
|
||||||
E.showMenu({
|
const menu = {
|
||||||
"": { title:/*LANG*/"Steps" },
|
"": { title:/*LANG*/"Steps" },
|
||||||
/*LANG*/"< Back": () => menuMain(),
|
/*LANG*/"< Back": () => menuMain(),
|
||||||
/*LANG*/"per hour": () => stepsPerHour(),
|
/*LANG*/"per hour": () => stepsPerHour(menuStepCount),
|
||||||
/*LANG*/"per day": () => stepsPerDay()
|
/*LANG*/"per day": () => stepsPerDay(menuStepCount)
|
||||||
|
};
|
||||||
|
if (settings.strideLength) {
|
||||||
|
menu[/*LANG*/"distance"] = () => menuDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function menuDistance() {
|
||||||
|
E.showMenu({
|
||||||
|
"": { title:/*LANG*/"Distance" },
|
||||||
|
/*LANG*/"< Back": () => menuStepCount(),
|
||||||
|
/*LANG*/"per hour": () => stepsPerHour(menuDistance, settings.strideLength),
|
||||||
|
/*LANG*/"per day": () => stepsPerDay(menuDistance, settings.strideLength)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,23 +52,23 @@ function menuHRM() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepsPerHour() {
|
function stepsPerHour(back, mult) {
|
||||||
E.showMessage(/*LANG*/"Loading...");
|
E.showMessage(/*LANG*/"Loading...");
|
||||||
current_selection = "stepsPerHour";
|
current_selection = "stepsPerHour";
|
||||||
var data = new Uint16Array(24);
|
var data = new Uint16Array(24);
|
||||||
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
|
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
|
||||||
setButton(menuStepCount);
|
setButton(back, mult);
|
||||||
barChart(/*LANG*/"HOUR", data);
|
barChart(/*LANG*/"HOUR", data, mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepsPerDay() {
|
function stepsPerDay(back, mult) {
|
||||||
E.showMessage(/*LANG*/"Loading...");
|
E.showMessage(/*LANG*/"Loading...");
|
||||||
current_selection = "stepsPerDay";
|
current_selection = "stepsPerDay";
|
||||||
var data = new Uint16Array(32);
|
var data = new Uint16Array(32);
|
||||||
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
|
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
|
||||||
setButton(menuStepCount);
|
setButton(back, mult);
|
||||||
barChart(/*LANG*/"DAY", data);
|
barChart(/*LANG*/"DAY", data, mult);
|
||||||
drawHorizontalLine(settings.stepGoal);
|
drawHorizontalLine(settings.stepGoal * (mult || 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function hrmPerHour() {
|
function hrmPerHour() {
|
||||||
|
|
@ -139,7 +155,11 @@ function get_data_length(arr) {
|
||||||
return nlen;
|
return nlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
function barChart(label, dt) {
|
function barChart(label, dt, mult) {
|
||||||
|
if (mult !== undefined) {
|
||||||
|
// Calculate distance from steps
|
||||||
|
dt.forEach((val, i) => dt[i] = val*mult);
|
||||||
|
}
|
||||||
data_len = get_data_length(dt);
|
data_len = get_data_length(dt);
|
||||||
chart_index = Math.max(data_len - 5, -5); // choose initial index that puts the last day on the end
|
chart_index = Math.max(data_len - 5, -5); // choose initial index that puts the last day on the end
|
||||||
chart_max_datum = max(dt); // find highest bar, for scaling
|
chart_max_datum = max(dt); // find highest bar, for scaling
|
||||||
|
|
@ -180,7 +200,7 @@ function drawHorizontalLine(value) {
|
||||||
g.setColor(g.theme.fg).drawLine(0, top ,g.getWidth(), top);
|
g.setColor(g.theme.fg).drawLine(0, top ,g.getWidth(), top);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setButton(fn) {
|
function setButton(fn, mult) {
|
||||||
Bangle.setUI({mode:"custom",
|
Bangle.setUI({mode:"custom",
|
||||||
back:fn,
|
back:fn,
|
||||||
swipe:(lr,ud) => {
|
swipe:(lr,ud) => {
|
||||||
|
|
@ -194,12 +214,16 @@ function setButton(fn) {
|
||||||
}
|
}
|
||||||
drawBarChart();
|
drawBarChart();
|
||||||
if (current_selection == "stepsPerDay") {
|
if (current_selection == "stepsPerDay") {
|
||||||
drawHorizontalLine(settings.stepGoal);
|
drawHorizontalLine(settings.stepGoal * (mult || 1));
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadSettings() {
|
||||||
|
settings = require("Storage").readJSON("health.json",1)||{};
|
||||||
|
}
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
var settings = require("Storage").readJSON("health.json",1)||{};
|
loadSettings();
|
||||||
menuMain();
|
menuMain();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
"shortName": "Health",
|
"shortName": "Health",
|
||||||
"version": "0.27",
|
"version": "0.28",
|
||||||
"description": "Logs health data and provides an app to view it",
|
"description": "Logs health data and provides an app to view it",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,health",
|
"tags": "tool,system,health",
|
||||||
|
|
|
||||||
|
|
@ -8,44 +8,85 @@
|
||||||
function setSettings() {
|
function setSettings() {
|
||||||
require("Storage").writeJSON("health.json", settings);
|
require("Storage").writeJSON("health.json", settings);
|
||||||
}
|
}
|
||||||
E.showMenu({
|
|
||||||
"": { title: /*LANG*/"Health Tracking" },
|
|
||||||
|
|
||||||
/*LANG*/"< Back": () => back(),
|
function settingsMenu() {
|
||||||
|
E.showMenu({
|
||||||
|
"": { title: /*LANG*/"Health Tracking" },
|
||||||
|
|
||||||
/*LANG*/"HRM Interval": {
|
/*LANG*/"< Back": () => back(),
|
||||||
value: settings.hrm,
|
|
||||||
min: 0,
|
|
||||||
max: 3,
|
|
||||||
format: v => [
|
|
||||||
/*LANG*/"Off",
|
|
||||||
/*LANG*/"3 min",
|
|
||||||
/*LANG*/"10 min",
|
|
||||||
/*LANG*/"Always"
|
|
||||||
][v],
|
|
||||||
onchange: v => {
|
|
||||||
settings.hrm = v;
|
|
||||||
setSettings();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*LANG*/"Daily Step Goal": {
|
/*LANG*/"HRM Interval": {
|
||||||
value: settings.stepGoal,
|
value: settings.hrm,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 20000,
|
max: 3,
|
||||||
step: 250,
|
format: v => [
|
||||||
onchange: v => {
|
/*LANG*/"Off",
|
||||||
settings.stepGoal = v;
|
/*LANG*/"3 min",
|
||||||
|
/*LANG*/"10 min",
|
||||||
|
/*LANG*/"Always"
|
||||||
|
][v],
|
||||||
|
onchange: v => {
|
||||||
|
settings.hrm = v;
|
||||||
|
setSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/"Daily Step Goal": {
|
||||||
|
value: settings.stepGoal,
|
||||||
|
min: 0,
|
||||||
|
max: 20000,
|
||||||
|
step: 250,
|
||||||
|
onchange: v => {
|
||||||
|
settings.stepGoal = v;
|
||||||
|
setSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/"Step Goal Notification": {
|
||||||
|
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
|
||||||
|
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
|
||||||
|
onchange: () => {
|
||||||
|
settings.stepGoalNotification = !settings.stepGoalNotification;
|
||||||
|
setSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/"Stride length": () => strideLengthMenu()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function strideLengthMenu() {
|
||||||
|
const menu = {
|
||||||
|
"" : { title : /*LANG*/"Stride length" },
|
||||||
|
|
||||||
|
"< Back" : () => {
|
||||||
setSettings();
|
setSettings();
|
||||||
}
|
settingsMenu();
|
||||||
},
|
},
|
||||||
/*LANG*/"Step Goal Notification": {
|
|
||||||
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
|
"x 0.01" : {
|
||||||
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
|
value : settings.strideLength === undefined ? 0 : settings.strideLength,
|
||||||
onchange: () => {
|
min:0,
|
||||||
settings.stepGoalNotification = !settings.stepGoalNotification;
|
step:0.01,
|
||||||
setSettings();
|
format: v => require("locale").distance(v, 2),
|
||||||
}
|
onchange : v => {
|
||||||
}
|
settings.strideLength=v;
|
||||||
});
|
menu["x 0.1"].value = v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"x 0.1" : {
|
||||||
|
value : settings.strideLength === undefined ? 0 : settings.strideLength,
|
||||||
|
min:0,
|
||||||
|
step:0.1,
|
||||||
|
format: v => require("locale").distance(v, 2),
|
||||||
|
onchange : v => {
|
||||||
|
settings.strideLength=v;
|
||||||
|
menu["x 0.01"].value = v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsMenu();
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue