health 0.25: lib.read* methods now return correctly scaled movement

movement graph in app is now an average, not sum
      fix 11pm slot for daily HRM
pull/2951/head
Gordon Williams 2023-08-04 09:36:18 +01:00
parent b55d60befd
commit 31fb8f8d02
6 changed files with 28 additions and 16 deletions

View File

@ -23,3 +23,6 @@
0.22: Fix timeout for heartrate sensor on 3 minute setting (#2435)
0.23: Fix HRM logic
0.24: Correct daily health summary for movement (some logic errors resulted in garbage data being written)
0.25: lib.read* methods now return correctly scaled movement
movement graph in app is now an average, not sum
fix 11pm slot for daily HRM

View File

@ -59,7 +59,7 @@ function hrmPerHour() {
E.showMessage(/*LANG*/"Loading...");
current_selection = "hrmPerHour";
var data = new Uint16Array(24);
var cnt = new Uint8Array(23);
var cnt = new Uint8Array(24);
require("health").readDay(new Date(), h=>{
data[h.hr]+=h.bpm;
if (h.bpm) cnt[h.hr]++;
@ -87,7 +87,12 @@ function movementPerHour() {
E.showMessage(/*LANG*/"Loading...");
current_selection = "movementPerHour";
var data = new Uint16Array(24);
require("health").readDay(new Date(), h=>data[h.hr]+=h.movement);
var cnt = new Uint8Array(24);
require("health").readDay(new Date(), h=>{
data[h.hr]+=h.movement
cnt[h.hr]++;
});
data.forEach((d,i)=>data[i] = d/cnt[i]);
setButton(menuMovement);
barChart(/*LANG*/"HOUR", data);
}
@ -96,7 +101,12 @@ function movementPerDay() {
E.showMessage(/*LANG*/"Loading...");
current_selection = "movementPerDay";
var data = new Uint16Array(31);
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement);
var cnt = new Uint8Array(31);
require("health").readDailySummaries(new Date(), h=>{
data[h.hr]+=h.movement
cnt[h.hr]++;
});
data.forEach((d,i)=>data[i] = d/cnt[i]);
setButton(menuMovement);
barChart(/*LANG*/"DAY", data);
}

View File

@ -1,6 +1,5 @@
(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){var c=function(){Bangle.setHRMPower(1,"health");setTimeout(function(){return Bangle.setHRMPower(0,"health")},6E4*a);if(1==a){var b=function(){Bangle.setHRMPower(1,"health");setTimeout(function(){Bangle.setHRMPower(0,"health")},6E4)};setTimeout(b,2E5);setTimeout(b,4E5)}};Bangle.on("health",c);Bangle.on("HRM",function(b){90<b.confidence&&1>Math.abs(Bangle.getHealthStatus().bpm-b.bpm)&&Bangle.setHRMPower(0,"health")});
90<Bangle.getHealthStatus().bpmConfidence||c()}else Bangle.setHRMPower(!!a,"health")})();
Bangle.on("health",function(a){function c(g){return String.fromCharCode(g.steps>>8,g.steps&255,g.bpm,Math.min(g.movement,255))}var b=new Date(Date.now()-59E4);a&&0<a.steps&&q();var f=145*(b.getDate()-1)+6*b.getHours()+(0|6*b.getMinutes()/60);b="health-"+b.getFullYear()+"-"+(b.getMonth()+1)+".raw";var h=require("Storage").read(b);if(h){var e=h.substr(8+4*f,4);if("\xff\xff\xff\xff"!=e){print("HEALTH ERR: Already written!");return}}else require("Storage").write(b,"HEALTH1\x00",0,17988);var m=
8+4*f;a=Object.assign({},a);a.movement/=8;require("Storage").write(b,c(a),m,17988);if(143==f%145)if(f=m+4,"\xff\xff\xff\xff"!=h.substr(f,4))print("HEALTH ERR: Daily summary already written!");else{a={steps:0,bpm:0,movement:0,movCnt:0,bpmCnt:0};for(var n=0;144>n;n++){e=h.substr(m,4);if("\xff\xff\xff\xff"!=e){a.steps+=(e.charCodeAt(0)<<8)+e.charCodeAt(1);var p=e.charCodeAt(2);a.bpm+=p;a.movement+=e.charCodeAt(3);a.movCnt++;p&&a.bpmCnt++}m-=4}a.bpmCnt&&(a.bpm/=a.bpmCnt);a.movCnt&&(a.movement/=
a.movCnt);require("Storage").write(b,c(a),f,17988)}});
function q(){var a=require("Storage").readJSON("health.json",1)||{},c=Bangle.getHealthStatus("day").steps;a.stepGoalNotification&&0<a.stepGoal&&c>=a.stepGoal&&(c=(new Date(Date.now())).toISOString().split("T")[0],!a.stepGoalNotificationDate||a.stepGoalNotificationDate<c)&&(Bangle.buzz(200,.5),require("notify").show({title:a.stepGoal+" steps",body:"You reached your step goal!",icon:atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")}),a.stepGoalNotificationDate=c,require("Storage").writeJSON("health.json",a))}
function m(){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:a.stepGoal+" steps",body:"You reached your step goal!",icon:atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")}),a.stepGoalNotificationDate=d,require("Storage").writeJSON("health.json",
a))}(function(){var a=0|(require("Storage").readJSON("health.json",1)||{}).hrm;if(1==a||2==a){function d(){Bangle.setHRMPower(1,"health");setTimeout(()=>Bangle.setHRMPower(0,"health"),6E4*a);if(1==a){function b(){Bangle.setHRMPower(1,"health");setTimeout(()=>{Bangle.setHRMPower(0,"health")},6E4)}setTimeout(b,2E5);setTimeout(b,4E5)}}Bangle.on("health",d);Bangle.on("HRM",b=>{90<b.confidence&&1>Math.abs(Bangle.getHealthStatus().bpm-b.bpm)&&Bangle.setHRMPower(0,"health")});90<Bangle.getHealthStatus().bpmConfidence||
d()}else Bangle.setHRMPower(!!a,"health")})();Bangle.on("health",a=>{function d(c){return String.fromCharCode(c.steps>>8,c.steps&255,c.bpm,Math.min(c.movement,255))}var b=new Date(Date.now()-59E4);a&&0<a.steps&&m();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("\xff\xff\xff\xff"!=e){print("HEALTH ERR: Already written!");
return}}else require("Storage").write(b,"HEALTH1\x00",0,17988);var h=8+4*f;a=Object.assign({},a);a.movement/=8;require("Storage").write(b,d(a),h,17988);if(143==f%145)if(f=h+4,"\xff\xff\xff\xff"!=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);if("\xff\xff\xff\xff"!=e){a.steps+=(e.charCodeAt(0)<<8)+e.charCodeAt(1);var l=e.charCodeAt(2);a.bpm+=l;a.movement+=e.charCodeAt(3);a.movCnt++;
l&&a.bpmCnt++}h-=4}a.bpmCnt&&(a.bpm/=a.bpmCnt);a.movCnt&&(a.movement/=a.movCnt);require("Storage").write(b,d(a),f,17988)}})

View File

@ -29,7 +29,7 @@ exports.readAllRecords = function(d, cb) {
day:day+1, hr : hr, min:m*10,
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
bpm : h.charCodeAt(2),
movement : h.charCodeAt(3)
movement : h.charCodeAt(3)*8
});
}
idx += DB_RECORD_LEN;
@ -53,7 +53,7 @@ exports.readDailySummaries = function(d, cb) {
day:day+1,
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
bpm : h.charCodeAt(2),
movement : h.charCodeAt(3)
movement : h.charCodeAt(3)*8
});
}
idx += DB_RECORDS_PER_DAY*DB_RECORD_LEN;
@ -75,7 +75,7 @@ exports.readDay = function(d, cb) {
hr : hr, min:m*10,
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
bpm : h.charCodeAt(2),
movement : h.charCodeAt(3)
movement : h.charCodeAt(3)*8
});
}
idx += DB_RECORD_LEN;

View File

@ -1,3 +1,3 @@
function h(a){return"health-"+a.getFullYear()+"-"+(a.getMonth()+1)+".raw"}function k(a){return 145*(a.getDate()-1)+6*a.getHours()+(0|6*a.getMinutes()/60)}exports.readAllRecords=function(a,f){a=h(a);a=require("Storage").read(a);if(void 0!==a)for(var c=8,d=0;31>d;d++){for(var b=0;24>b;b++)for(var e=0;6>e;e++){var g=a.substr(c,4);"\u00ff\u00ff\u00ff\u00ff"!=g&&f({day:d+1,hr:b,min:10*e,steps:g.charCodeAt(0)<<8|g.charCodeAt(1),bpm:g.charCodeAt(2),movement:g.charCodeAt(3)});c+=
4}c+=4}};exports.readDailySummaries=function(a,f){k(a);a=h(a);a=require("Storage").read(a);if(void 0!==a)for(var c=584,d=0;31>d;d++){var b=a.substr(c,4);"\u00ff\u00ff\u00ff\u00ff"!=b&&f({day:d+1,steps:b.charCodeAt(0)<<8|b.charCodeAt(1),bpm:b.charCodeAt(2),movement:b.charCodeAt(3)});c+=580}};exports.readDay=function(a,f){k(a);var c=h(a);c=require("Storage").read(c);if(void 0!==c){a=8+580*(a.getDate()-1);for(var d=0;24>d;d++)for(var b=0;6>b;b++){var e=c.substr(a,4);"\u00ff\u00ff\u00ff\u00ff"!=e&&f({hr:d,
min:10*b,steps:e.charCodeAt(0)<<8|e.charCodeAt(1),bpm:e.charCodeAt(2),movement:e.charCodeAt(3)});a+=4}}}
function h(a){return"health-"+a.getFullYear()+"-"+(a.getMonth()+1)+".raw"}function k(a){return 145*(a.getDate()-1)+6*a.getHours()+(0|6*a.getMinutes()/60)}exports.readAllRecords=function(a,f){a=h(a);a=require("Storage").read(a);if(void 0!==a)for(var c=8,d=0;31>d;d++){for(var b=0;24>b;b++)for(var e=0;6>e;e++){var g=a.substr(c,4);"\xff\xff\xff\xff"!=g&&f({day:d+1,hr:b,min:10*e,steps:g.charCodeAt(0)<<8|g.charCodeAt(1),bpm:g.charCodeAt(2),movement:8*g.charCodeAt(3)});c+=
4}c+=4}};exports.readDailySummaries=function(a,f){k(a);a=h(a);a=require("Storage").read(a);if(void 0!==a)for(var c=584,d=0;31>d;d++){var b=a.substr(c,4);"\xff\xff\xff\xff"!=b&&f({day:d+1,steps:b.charCodeAt(0)<<8|b.charCodeAt(1),bpm:b.charCodeAt(2),movement:8*b.charCodeAt(3)});c+=580}};exports.readDay=function(a,f){k(a);var c=h(a);c=require("Storage").read(c);if(void 0!==c){a=8+580*(a.getDate()-1);for(var d=0;24>d;d++)for(var b=0;6>b;b++){var e=c.substr(a,4);"\xff\xff\xff\xff"!=e&&
f({hr:d,min:10*b,steps:e.charCodeAt(0)<<8|e.charCodeAt(1),bpm:e.charCodeAt(2),movement:8*e.charCodeAt(3)});a+=4}}}

View File

@ -2,7 +2,7 @@
"id": "health",
"name": "Health Tracking",
"shortName": "Health",
"version": "0.24",
"version": "0.25",
"description": "Logs health data and provides an app to view it",
"icon": "app.png",
"tags": "tool,system,health",