1
0
Fork 0

Merge pull request #881 from hughbarney/master

Health: added bar charts
master
Gordon Williams 2021-11-16 08:53:12 +00:00 committed by GitHub
commit 30a51228ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 53 deletions

View File

@ -82,7 +82,7 @@
{
"id": "health",
"name": "Health Tracking",
"version": "0.06",
"version": "0.07",
"description": "Logs health data and provides an app to view it (BETA - requires firmware 2v11)",
"icon": "app.png",
"tags": "tool,system,health",
@ -3467,7 +3467,7 @@
"id": "widgps",
"name": "GPS Widget",
"version": "0.03",
"description": "Tiny widget to show the power on/off status of the GPS. Require firmware v2.08.167 or later",
"description": "Tiny widget to show the power on/off status of the GPS",
"icon": "widget.png",
"type": "widget",
"tags": "widget,gps",
@ -3481,7 +3481,7 @@
"id": "widhrt",
"name": "HRM Widget",
"version": "0.03",
"description": "Tiny widget to show the power on/off status of the Heart Rate Monitor. Requires firmware v2.08.167 or later",
"description": "Tiny widget to show the power on/off status of the Heart Rate Monitor",
"icon": "widget.png",
"type": "widget",
"tags": "widget,hrm",
@ -3524,7 +3524,7 @@
"id": "widcom",
"name": "Compass Widget",
"version": "0.02",
"description": "Tiny widget to show the power on/off status of the Compass. Requires firmware v2.08.167 or later",
"description": "Tiny widget to show the power on/off status of the Compass",
"icon": "widget.png",
"type": "widget",
"tags": "widget,compass",
@ -3665,7 +3665,7 @@
"id": "kitchen",
"name": "Kitchen Combo",
"version": "0.13",
"description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'. Requires firmware v2.08.167 or later",
"description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'",
"icon": "kitchen.png",
"type": "clock",
"tags": "tool,outdoors,gps",

View File

@ -5,3 +5,4 @@
Don't restart HRM when changing apps if we've already got a good BPM value
0.05: Fix daily summary calculation
0.06: Fix daily health summary for movement (a line got deleted!)
0.07: Added coloured bar charts

View File

@ -7,6 +7,8 @@ function setSettings(s) {
}
function menuMain() {
swipe_enabled = false;
clearButton();
E.showMenu({
"":{title:"Health Tracking"},
"< Back":()=>load(),
@ -18,6 +20,8 @@ function menuMain() {
}
function menuSettings() {
swipe_enabled = false;
clearButton();
var s=getSettings();
E.showMenu({
"":{title:"Health Tracking"},
@ -32,6 +36,8 @@ function menuSettings() {
}
function menuStepCount() {
swipe_enabled = false;
clearButton();
E.showMenu({
"":{title:"Step Counting"},
"< Back":()=>menuMain(),
@ -41,6 +47,8 @@ function menuStepCount() {
}
function menuMovement() {
swipe_enabled = false;
clearButton();
E.showMenu({
"":{title:"Movement"},
"< Back":()=>menuMain(),
@ -50,6 +58,8 @@ function menuMovement() {
}
function menuHRM() {
swipe_enabled = false;
clearButton();
E.showMenu({
"":{title:"Heart Rate"},
"< Back":()=>menuMain(),
@ -66,14 +76,8 @@ function stepsPerHour() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawBar(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 6,
gridy : 500
});
Bangle.setUI("updown", ()=>menuStepCount());
setButton(menuStepCount);
barChart("HOUR", data);
}
function stepsPerDay() {
@ -83,14 +87,8 @@ function stepsPerDay() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawBar(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 5,
gridy : 2000
});
Bangle.setUI("updown", ()=>menuStepCount());
setButton(menuStepCount);
barChart("DAY", data);
}
function hrmPerHour() {
@ -105,14 +103,8 @@ function hrmPerHour() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawBar(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 6,
gridy : 20
});
Bangle.setUI("updown", ()=>menuHRM());
setButton(menuHRM);
barChart("HOUR", data);
}
function hrmPerDay() {
@ -127,14 +119,8 @@ function hrmPerDay() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawBar(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 5,
gridy : 20
});
Bangle.setUI("updown", ()=>menuHRM());
setButton(menuHRM);
barChart("DAY", data);
}
function movementPerHour() {
@ -144,14 +130,8 @@ function movementPerHour() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawLine(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 6,
ylabel : null
});
Bangle.setUI("updown", ()=>menuMovement());
setButton(menuMovement);
barChart("HOUR", data);
}
function movementPerDay() {
@ -161,14 +141,112 @@ function movementPerDay() {
g.clear(1);
Bangle.drawWidgets();
g.reset();
require("graph").drawBar(g, data, {
y:24,
miny: 0,
axes : true,
gridx : 5,
ylabel : null
});
Bangle.setUI("updown", ()=>menuMovement());
setButton(menuMovement);
barChart("DAY", data);
}
// Bar Chart Code
const w = g.getWidth();
const h = g.getHeight();
var data_len;
var chart_index;
var chart_max_datum;
var chart_label;
var chart_data;
var swipe_enabled = false;
var btn;
// find the max value in the array, using a loop due to array size
function max(arr) {
var m = -Infinity;
for(var i=0; i< arr.length; i++)
if(arr[i] > m) m = arr[i];
return m;
}
// find the end of the data, the array might be for 31 days but only have 2 days of data in it
function get_data_length(arr) {
var nlen = arr.length;
for(var i = arr.length - 1; i > 0 && arr[i] == 0; i--)
nlen--;
return nlen;
}
function barChart(label, 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_max_datum = max(dt); // find highest bar, for scaling
chart_label = label;
chart_data = dt;
drawBarChart();
swipe_enabled = true;
}
function drawBarChart() {
const bar_bot = 140;
const bar_width = (w - 2) / 9; // we want 9 bars, bar 5 in the centre
var bar_top;
var bar;
g.setColor(g.theme.bg);
g.fillRect(0,24,w,h);
for (bar = 1; bar < 10; bar++) {
if (bar == 5) {
g.setFont('6x8', 2);
g.setFontAlign(0,-1)
g.setColor(g.theme.fg);
g.drawString(chart_label + " " + (chart_index + bar -1) + " " + chart_data[chart_index + bar - 1], g.getWidth()/2, 150);
g.setColor("#00f");
} else {
g.setColor("#0ff");
}
// draw a fake 0 height bar if chart_index is outside the bounds of the array
if ((chart_index + bar - 1) >= 0 && (chart_index + bar - 1) < data_len)
bar_top = bar_bot - 100 * (chart_data[chart_index + bar - 1]) / chart_max_datum;
else
bar_top = bar_bot;
g.fillRect( 1 + (bar - 1)* bar_width, bar_bot, 1 + bar*bar_width, bar_top);
g.setColor(g.theme.fg);
g.drawRect( 1 + (bar - 1)* bar_width, bar_bot, 1 + bar*bar_width, bar_top);
}
}
function next_bar() {
chart_index = Math.min(data_len - 5, chart_index + 1);
}
function prev_bar() {
// HOUR data starts at index 0, DAY data starts at index 1
chart_index = Math.max((chart_label == "DAY") ? -3 : -4, chart_index - 1);
}
Bangle.on('swipe', dir => {
if (!swipe_enabled) return;
if (dir == 1) prev_bar(); else next_bar();
drawBarChart();
});
// use setWatch() as Bangle.setUI("updown",..) interacts with swipes
function setButton(fn) {
if (process.env.HWVERSION == 1)
btn = setWatch(fn, BTN2);
else
btn = setWatch(fn, BTN1);
}
function clearButton() {
if (btn !== undefined) {
clearWatch(btn);
btn = undefined;
}
}
Bangle.loadWidgets();