forked from FOSS/BangleApps
Merge pull request #2442 from myxor/health_step_goal_notification
Health: Step goal reached notificationmaster
commit
059a2e7af7
|
@ -17,3 +17,4 @@
|
||||||
0.16: Code tidyup, add back button in top left of health app graphs
|
0.16: Code tidyup, add back button in top left of health app graphs
|
||||||
0.17: Add automatic translation of bar chart labels
|
0.17: Add automatic translation of bar chart labels
|
||||||
0.18: Show step goal in daily step chart
|
0.18: Show step goal in daily step chart
|
||||||
|
0.19: Can show notification when daily step goal is reached
|
||||||
|
|
|
@ -25,7 +25,8 @@ Stores:
|
||||||
* **3 Min** - Turn HRM on every 3 minutes (for each heath entry) and turn it off after 1 minute, or when a good reading is found
|
* **3 Min** - Turn HRM on every 3 minutes (for each heath entry) and turn it off after 1 minute, or when a good reading is found
|
||||||
* **10 Min** - Turn HRM on every 10 minutes (for each heath entry) and turn it off after 2 minutes, or when a good reading is found
|
* **10 Min** - Turn HRM on every 10 minutes (for each heath entry) and turn it off after 2 minutes, or when a good reading is found
|
||||||
* **Always** - Keep HRM on all the time (more accurate recording, but reduces battery life to ~36 hours)
|
* **Always** - Keep HRM on all the time (more accurate recording, but reduces battery life to ~36 hours)
|
||||||
* **Daily Step Goal** - Default 10000, daily step goal for pedometer apps to use
|
* **Daily Step Goal** - Default 10000, daily step goal for pedometer apps to use and for the step goal notification
|
||||||
|
* **Step Goal Notification** - True if you want a notification when the daily step goal is reached
|
||||||
|
|
||||||
|
|
||||||
## Technical Info
|
## Technical Info
|
||||||
|
|
|
@ -36,6 +36,10 @@ Bangle.on("health", health => {
|
||||||
const DB_HEADER_LEN = 8;
|
const DB_HEADER_LEN = 8;
|
||||||
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||||
|
|
||||||
|
if (health && health.steps > 0) {
|
||||||
|
handleStepGoalNotification();
|
||||||
|
}
|
||||||
|
|
||||||
function getRecordFN(d) {
|
function getRecordFN(d) {
|
||||||
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
|
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
|
||||||
}
|
}
|
||||||
|
@ -92,3 +96,21 @@ Bangle.on("health", health => {
|
||||||
health.movement /= health.movCnt;
|
health.movement /= health.movCnt;
|
||||||
require("Storage").write(fn, getRecordData(health), sumPos, DB_FILE_LEN);
|
require("Storage").write(fn, getRecordData(health), sumPos, DB_FILE_LEN);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleStepGoalNotification() {
|
||||||
|
var settings = require("Storage").readJSON("health.json",1)||{};
|
||||||
|
const steps = Bangle.getHealthStatus("day").steps;
|
||||||
|
if (settings.stepGoalNotification && settings.stepGoal > 0 && steps >= settings.stepGoal) {
|
||||||
|
const now = new Date(Date.now()).toISOString().split('T')[0]; // yyyy-mm-dd
|
||||||
|
if (!settings.stepGoalNotificationDate || settings.stepGoalNotificationDate < now) { // notification not yet shown today?
|
||||||
|
Bangle.buzz(200, 0.5);
|
||||||
|
require("notify").show({
|
||||||
|
title : /*LANG*/ settings.stepGoal + " steps",
|
||||||
|
body : /*LANG*/ "You reached your step goal!",
|
||||||
|
icon : atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")
|
||||||
|
});
|
||||||
|
settings.stepGoalNotificationDate = now;
|
||||||
|
require("Storage").writeJSON("health.json", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){function f(){Bangle.setHRMPower(1,"health");setTimeout(()=>Bangle.setHRMPower(0,"health"),6E4*a);if(1==a)for(var b=1;2>=b;b++)setTimeout(()=>{Bangle.setHRMPower(1,"health");setTimeout(()=>{Bangle.setHRMPower(0,"health")},2E5*b+6E4)},2E5*b)}Bangle.on("health",f);Bangle.on("HRM",b=>{80<b.confidence&&Bangle.setHRMPower(0,"health")});Bangle.getHealthStatus().bpmConfidence||f()}else Bangle.setHRMPower(0!=
|
function l(){var a=require("Storage").readJSON("health.json",1)||{},d=Bangle.getHealthStatus("day").steps;a.stepGoalNotification&&0<a.stepGoal&&d>=a.stepGoal&&(d=(new Date(Date.now())).toISOString().split("T")[0],!a.stepGoalNotificationDate||a.stepGoalNotificationDate<d)&&(Bangle.buzz(200,.5),require("notify").show({title:"8000 steps",body:"You reached your step goal!",icon:atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")}),a.stepGoalNotificationDate=d,require("Storage").writeJSON("health.json",
|
||||||
a,"health")})();Bangle.on("health",a=>{function f(c){return String.fromCharCode(c.steps>>8,c.steps&255,c.bpm,Math.min(c.movement/8,255))}var b=new Date(Date.now()-59E4),e=function(c){return 145*(c.getDate()-1)+6*c.getHours()+(0|6*c.getMinutes()/60)}(b);b=function(c){return"health-"+c.getFullYear()+"-"+(c.getMonth()+1)+".raw"}(b);var g=require("Storage").read(b);if(g){var d=g.substr(8+4*e,4);if("\u00ff\u00ff\u00ff\u00ff"!=d){print("HEALTH ERR: Already written!");return}}else require("Storage").write(b,
|
a))}(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){var d=function(){Bangle.setHRMPower(1,"health");setTimeout(function(){return Bangle.setHRMPower(0,"health")},6E4*a);if(1==a)for(var b=1;2>=b;b++)setTimeout(function(){Bangle.setHRMPower(1,"health");setTimeout(function(){Bangle.setHRMPower(0,"health")},2E5*b+6E4)},2E5*b)};Bangle.on("health",d);Bangle.on("HRM",function(b){80<b.confidence&&Bangle.setHRMPower(0,"health")});Bangle.getHealthStatus().bpmConfidence||
|
||||||
"HEALTH1\x00",0,17988);var h=8+4*e;require("Storage").write(b,f(a),h,17988);if(143==e%145)if(e=h+4,"\u00ff\u00ff\u00ff\u00ff"!=g.substr(e,4))print("HEALTH ERR: Daily summary already written!");else{a={steps:0,bpm:0,movement:0,movCnt:0,bpmCnt:0};for(var k=0;144>k;k++)d=g.substr(h,4),"\u00ff\u00ff\u00ff\u00ff"!=d&&(a.steps+=(d.charCodeAt(0)<<8)+d.charCodeAt(1),a.movement+=d.charCodeAt(2),a.movCnt++,d=d.charCodeAt(2),a.bpm+=d,d&&a.bpmCnt++),h-=4;a.bpmCnt&&(a.bpm/=a.bpmCnt);a.movCnt&&(a.movement/=a.movCnt);
|
d()}else Bangle.setHRMPower(0!=a,"health")})();Bangle.on("health",function(a){function d(c){return String.fromCharCode(c.steps>>8,c.steps&255,c.bpm,Math.min(c.movement/8,255))}var b=new Date(Date.now()-59E4);a&&0<a.steps&&l();var f=function(c){return 145*(c.getDate()-1)+6*c.getHours()+(0|6*c.getMinutes()/60)}(b);b=function(c){return"health-"+c.getFullYear()+"-"+(c.getMonth()+1)+".raw"}(b);var g=require("Storage").read(b);if(g){var e=g.substr(8+4*f,4);if("\u00ff\u00ff\u00ff\u00ff"!=e){print("HEALTH ERR: Already written!");
|
||||||
require("Storage").write(b,f(a),e,17988)}})
|
return}}else require("Storage").write(b,"HEALTH1\x00",0,17988);var h=8+4*f;require("Storage").write(b,d(a),h,17988);if(143==f%145)if(f=h+4,"\u00ff\u00ff\u00ff\u00ff"!=g.substr(f,4))print("HEALTH ERR: Daily summary already written!");else{a={steps:0,bpm:0,movement:0,movCnt:0,bpmCnt:0};for(var k=0;144>k;k++)e=g.substr(h,4),"\u00ff\u00ff\u00ff\u00ff"!=e&&(a.steps+=(e.charCodeAt(0)<<8)+e.charCodeAt(1),a.movement+=e.charCodeAt(2),a.movCnt++,e=e.charCodeAt(2),a.bpm+=e,e&&a.bpmCnt++),h-=4;a.bpmCnt&&(a.bpm/=
|
||||||
|
a.bpmCnt);a.movCnt&&(a.movement/=a.movCnt);require("Storage").write(b,d(a),f,17988)}})
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
"shortName": "Health",
|
"shortName": "Health",
|
||||||
"version": "0.18",
|
"version": "0.19",
|
||||||
"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",
|
||||||
|
@ -16,5 +16,6 @@
|
||||||
{"name":"health","url":"lib.min.js"},
|
{"name":"health","url":"lib.min.js"},
|
||||||
{"name":"health.settings.js","url":"settings.js"}
|
{"name":"health.settings.js","url":"settings.js"}
|
||||||
],
|
],
|
||||||
"data": [{"name":"health.json"}]
|
"data": [{"name":"health.json"}],
|
||||||
|
"dependencies": {"notify":"type"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
(function (back) {
|
(function (back) {
|
||||||
var settings = Object.assign({
|
var settings = Object.assign({
|
||||||
hrm: 0,
|
hrm: 0,
|
||||||
stepGoal: 10000
|
stepGoal: 10000,
|
||||||
|
stepGoalNotification: false
|
||||||
}, require("Storage").readJSON("health.json", true) || {});
|
}, require("Storage").readJSON("health.json", true) || {});
|
||||||
|
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
|
@ -34,6 +35,14 @@
|
||||||
settings.stepGoal = v;
|
settings.stepGoal = v;
|
||||||
setSettings(settings);
|
setSettings(settings);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
/*LANG*/"Step Goal Notification": {
|
||||||
|
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
|
||||||
|
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
|
||||||
|
onchange: () => {
|
||||||
|
settings.stepGoalNotification = !settings.stepGoalNotification;
|
||||||
|
setSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue