BangleApps/apps/health/boot.js

116 lines
4.2 KiB
JavaScript

(function() {
var settings = require("Storage").readJSON("health.json", 1) || {};
var hrm = 0|settings.hrm;
if (hrm == 1 || hrm == 2) {
function onHealth() {
Bangle.setHRMPower(1, "health");
setTimeout(() => Bangle.setHRMPower(0, "health"), hrm * 60000); // give it 1 minute detection time for 3 min setting and 2 minutes for 10 min setting
if (hrm == 1) {
function startMeasurement() {
Bangle.setHRMPower(1, "health");
setTimeout(() => {
Bangle.setHRMPower(0, "health");
}, 60000);
}
setTimeout(startMeasurement, 200000);
setTimeout(startMeasurement, 400000);
}
}
Bangle.on("health", onHealth);
Bangle.on("HRM", (h) => {
if (h.confidence > 90 && Math.abs(Bangle.getHealthStatus().bpm - h.bpm) < 1) Bangle.setHRMPower(0, "health");
});
if (Bangle.getHealthStatus().bpmConfidence > 90) return;
onHealth();
} else Bangle.setHRMPower(!!hrm, "health");
})();
Bangle.on("health", health => {
(Bangle.getPressure?Bangle.getPressure():Promise.resolve({})).then(pressure => {
Object.assign(health, pressure); // add temperature/pressure/altitude
// ensure we write health info for *last* block
var d = new Date(Date.now() - 590000);
const DB_RECORDS_PER_HR = 6;
const DB_RECORDS_PER_DAY = DB_RECORDS_PER_HR*24 + 1/*summary*/;
const DB_RECORDS_PER_MONTH = DB_RECORDS_PER_DAY*31;
const DB_HEADER_LEN = 8;
if (health && health.steps > 0) { // Show step goal notification
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 : settings.stepGoal + /*LANG*/ " steps",
body : /*LANG*/ "You reached your step goal!",
icon : atob("DAyBABmD6BaBMAsA8BCBCBCBCA8AAA==")
});
settings.stepGoalNotificationDate = now;
require("Storage").writeJSON("health.json", settings);
}
}
}
function getRecordFN(d) {
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
}
function getRecordIdx(d) {
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
(DB_RECORDS_PER_HR*d.getHours()) +
(0|(d.getMinutes()*DB_RECORDS_PER_HR/60));
}
var rec = getRecordIdx(d);
var fn = getRecordFN(d);
var inf, f = require("Storage").read(fn);
if (f!==undefined) {
inf = require("health").getDecoder(f);
var dt = f.substr(DB_HEADER_LEN+(rec*inf.r), inf.r);
if (dt!=inf.clr) {
print("HEALTH ERR: Already written!");
return;
}
} else {
inf = require("health").getDecoder("HEALTH2");
require("Storage").write(fn, "HEALTH2\0", 0, DB_HEADER_LEN + DB_RECORDS_PER_MONTH*inf.r); // header (and allocate full new file)
}
var recordPos = DB_HEADER_LEN+(rec*inf.r);
// scale down reported movement value in order to fit it within a
// uint8 DB field
health = Object.assign({}, health);
health.movement /= 8;
require("Storage").write(fn, inf.encode(health), recordPos);
if (rec%DB_RECORDS_PER_DAY != DB_RECORDS_PER_DAY-2) return;
// we're at the end of the day. Read in all of the data for the day and sum it up
var sumPos = recordPos + inf.r; // record after the current one is the sum
if (f.substr(sumPos, inf.r)!=inf.clr) {
print("HEALTH ERR: Daily summary already written!");
return;
}
health = { steps:0, bpm:0, movement:0, movCnt:0, bpmCnt:0};
var records = DB_RECORDS_PER_HR*24;
for (var i=0;i<records;i++) {
var dt = f.substr(recordPos, inf.r);
if (dt!=inf.clr) {
var h = inf.decode(dt);
health.steps += h.steps
health.bpm += h.bpm;
health.movement += h.movement;
health.movCnt++;
if (h.bpm) health.bpmCnt++;
}
recordPos -= inf.r;
}
if (health.bpmCnt)
health.bpm /= health.bpmCnt;
if (health.movCnt)
health.movement /= health.movCnt;
require("Storage").write(fn, inf.encode(health), sumPos);
})});