mirror of https://github.com/espruino/BangleApps
Add widhrzone
Widget that displays the current out of five heart rate zonespull/3091/head
parent
726a81d54f
commit
9aaa451c5e
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "widhrzone",
|
||||||
|
"name": "Heart rate zone widget",
|
||||||
|
"shortName": "HRzone widget",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Widget that displays the current out of five heart rate training zones 1. HEALTH (50-60% of max. HR, Recovery, grey), 2. FAT-B (60-70% of max. HR, burns fat, blue), 3. AROBIC (70-80% of max. HR, Endurance, green), 4. ANAROB (80-90% of max. HR, Speed, yellow), 5. MAX (90-100% of max. HR, red). Only visible when heart rate monitor is active and inside one of the zones. Requires to set the maximum heart rate in settings (if unsure set to 220-age).",
|
||||||
|
"icon": "widget.png",
|
||||||
|
"type": "widget",
|
||||||
|
"tags": "widget,health",
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"screenshots" : [ { "url":"screenshot.png" } ],
|
||||||
|
"storage": [
|
||||||
|
{"name":"widhrzone.wid.js","url":"widget.js"},
|
||||||
|
{"name":"widhrzone.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [{"name":"widhrzone.json"}]
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,26 @@
|
||||||
|
(function(back) {
|
||||||
|
const CONFIGFILE = "widhrzone.json";
|
||||||
|
// Load settings
|
||||||
|
const settings = Object.assign({
|
||||||
|
maxHrm: 200,
|
||||||
|
}, require("Storage").readJSON(CONFIGFILE,1) || {});
|
||||||
|
|
||||||
|
function writeSettings() {
|
||||||
|
require('Storage').writeJSON(CONFIGFILE, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the menu
|
||||||
|
E.showMenu({
|
||||||
|
"" : { "title" : "HRzone widget" },
|
||||||
|
"< Back" : () => back(),
|
||||||
|
/*LANG*/'HR max': {
|
||||||
|
format: v => v,
|
||||||
|
value: settings.maxHrm,
|
||||||
|
min: 30, max: 220,
|
||||||
|
onchange: v => {
|
||||||
|
settings.maxHrm = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,98 @@
|
||||||
|
(() => {
|
||||||
|
const config = Object.assign({
|
||||||
|
maxHrm: 200,
|
||||||
|
}, require("Storage").readJSON("widhrzone.json",1) || {});
|
||||||
|
|
||||||
|
require("FontTeletext5x9Ascii").add(Graphics);
|
||||||
|
|
||||||
|
const calczone = (bpm) => {
|
||||||
|
if (bpm <= config.maxHrm*0.5) {
|
||||||
|
return 0;
|
||||||
|
} else if (bpm <= config.maxHrm*0.60) {
|
||||||
|
return 1;
|
||||||
|
} else if (bpm <= config.maxHrm*0.70) {
|
||||||
|
return 2;
|
||||||
|
} else if (bpm <= config.maxHrm*0.80) {
|
||||||
|
return 3;
|
||||||
|
} else if (bpm <= config.maxHrm*0.90) {
|
||||||
|
return 4;
|
||||||
|
} else { // > 0.9
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const zoneToText = (zone) => {
|
||||||
|
switch(zone) {
|
||||||
|
case 1:
|
||||||
|
return "HEALTH";
|
||||||
|
case 2:
|
||||||
|
return "FAT-B";
|
||||||
|
case 3:
|
||||||
|
return "AROBIC";
|
||||||
|
case 4:
|
||||||
|
return "ANAROB";
|
||||||
|
default:
|
||||||
|
return "MAX";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const zoneToColor = (zone) => {
|
||||||
|
switch(zone) {
|
||||||
|
case 1:
|
||||||
|
return ["#888888", "#000000"]; // bg, fg
|
||||||
|
case 2:
|
||||||
|
return ["#0000ff", "#ffffff"];
|
||||||
|
case 3:
|
||||||
|
return ["#00ff00", "#000000"];
|
||||||
|
case 4:
|
||||||
|
return ["#ffff00", "#000000"];
|
||||||
|
default:
|
||||||
|
return ["#ff0000", "#ffffff"];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Bangle.on('HRM', function(hrm) {
|
||||||
|
if (hrm.confidence >= 90) {
|
||||||
|
const zone = calczone(hrm.bpm);
|
||||||
|
if (WIDGETS.widhrzone.zone != zone) {
|
||||||
|
WIDGETS.widhrzone.zone = zone;
|
||||||
|
WIDGETS.widhrzone.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
WIDGETS.widhrzone = {
|
||||||
|
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
|
||||||
|
width: 0, // default hide, only show for valid hrm
|
||||||
|
draw: function() {
|
||||||
|
if (this.zone > 0 && Bangle.isHRMOn()) {
|
||||||
|
if (this.width === 0) {
|
||||||
|
this.width = 6*6;
|
||||||
|
// width changed, re-layout
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
}
|
||||||
|
// https://icons8.com/icon/set/heart/color 12x12, compression, transparency, inverted
|
||||||
|
g.reset();
|
||||||
|
// background
|
||||||
|
const colors = zoneToColor(this.zone);
|
||||||
|
g.setColor(colors[0]).fillRect(this.x, this.y, this.x+this.width, this.y+24);
|
||||||
|
// icon
|
||||||
|
const icon = require("heatshrink").decompress(atob("hkMgIFCv/m/1D8EGgFhjkXwHwBwQ"));
|
||||||
|
g.setColor(colors[1]).setBgColor(colors[0]).drawImage(icon, this.x, this.y);
|
||||||
|
// number upper right
|
||||||
|
g.setBgColor(colors[0]).setColor(colors[1]);
|
||||||
|
g.setFont("4x6:2x2").drawString(this.zone, this.x+18, this.y);
|
||||||
|
// text bottom
|
||||||
|
g.setFont("Teletext5x9Ascii:1x1").drawString(zoneToText(this.zone), this.x, this.y+12);
|
||||||
|
g.setColor(g.theme.fg).setBgColor(g.theme.bg); // restore
|
||||||
|
} else {
|
||||||
|
if (this.width !== 0) {
|
||||||
|
this.width = 0;
|
||||||
|
// width changed, re-layout
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
zone: 0
|
||||||
|
};
|
||||||
|
})();
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in New Issue