diff --git a/apps.json b/apps.json index 4bc4f802a..024fb1d54 100644 --- a/apps.json +++ b/apps.json @@ -49,7 +49,7 @@ { "id": "health", "name": "Health Tracking", - "version": "0.01", + "version": "0.02", "description": "Logs health data and provides an app to view it (BETA - requires firmware 2v11)", "icon": "app.png", "tags": "tool,system", @@ -61,36 +61,7 @@ {"name":"health.boot.js","url":"boot.js"}, {"name":"health","url":"lib.js"} ], - "sortorder": -8 - }, - { - "id": "moonphase", - "name": "Moonphase", - "version": "0.02", - "description": "Shows current moon phase. Now with GPS function.", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "allow_emulator": true, - "storage": [ - {"name":"moonphase.app.js","url":"app.js"}, - {"name":"moonphase.img","url":"app-icon.js","evaluate":true} - ] - }, - { - "id": "daysl", - "name": "Days left", - "version": "0.03", - "description": "Shows you the days left until a certain date. Date can be set with a settings app and is written to a file.", - "icon": "app.png", - "tags": "", - "supports": ["BANGLEJS"], - "allow_emulator": false, - "storage": [ - {"name":"daysl.app.js","url":"app.js"}, - {"name":"daysl.img","url":"app-icon.js","evaluate":true}, - {"name":"daysl.wid.js","url":"widget.js"} - ] + "sortorder": -2 }, { "id": "launch", @@ -108,6 +79,22 @@ ], "sortorder": -10 }, + { + "id": "setting", + "name": "Settings", + "version": "0.31", + "description": "A menu for setting up Bangle.js", + "icon": "settings.png", + "tags": "tool,system", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"setting.app.js","url":"settings.js"}, + {"name":"setting.img","url":"settings-icon.js","evaluate":true} + ], + "data": [{"name":"setting.json","url":"settings.min.json","evaluate":true}], + "sortorder": -5 + }, { "id": "about", "name": "About", @@ -123,6 +110,24 @@ {"name":"about.img","url":"app-icon.js","evaluate":true} ] }, + { + "id": "alarm", + "name": "Default Alarm & Timer", + "shortName": "Alarms", + "version": "0.13", + "description": "Set and respond to alarms and timers", + "icon": "app.png", + "tags": "tool,alarm,widget", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"alarm.app.js","url":"app.js"}, + {"name":"alarm.boot.js","url":"boot.js"}, + {"name":"alarm.js","url":"alarm.js"}, + {"name":"alarm.img","url":"app-icon.js","evaluate":true}, + {"name":"alarm.wid.js","url":"widget.js"} + ], + "data": [{"name":"alarm.json"}] + }, { "id": "locale", "name": "Languages", @@ -240,38 +245,33 @@ "sortorder": -9 }, { - "id": "setting", - "name": "Settings", - "version": "0.31", - "description": "A menu for setting up Bangle.js", - "icon": "settings.png", - "tags": "tool,system", - "supports": ["BANGLEJS","BANGLEJS2"], - "readme": "README.md", + "id": "moonphase", + "name": "Moonphase", + "version": "0.02", + "description": "Shows current moon phase. Now with GPS function.", + "icon": "app.png", + "tags": "", + "supports": ["BANGLEJS"], + "allow_emulator": true, "storage": [ - {"name":"setting.app.js","url":"settings.js"}, - {"name":"setting.img","url":"settings-icon.js","evaluate":true} - ], - "data": [{"name":"setting.json","url":"settings.min.json","evaluate":true}], - "sortorder": -2 + {"name":"moonphase.app.js","url":"app.js"}, + {"name":"moonphase.img","url":"app-icon.js","evaluate":true} + ] }, { - "id": "alarm", - "name": "Default Alarm & Timer", - "shortName": "Alarms", - "version": "0.13", - "description": "Set and respond to alarms and timers", + "id": "daysl", + "name": "Days left", + "version": "0.03", + "description": "Shows you the days left until a certain date. Date can be set with a settings app and is written to a file.", "icon": "app.png", - "tags": "tool,alarm,widget", - "supports": ["BANGLEJS","BANGLEJS2"], + "tags": "", + "supports": ["BANGLEJS"], + "allow_emulator": false, "storage": [ - {"name":"alarm.app.js","url":"app.js"}, - {"name":"alarm.boot.js","url":"boot.js"}, - {"name":"alarm.js","url":"alarm.js"}, - {"name":"alarm.img","url":"app-icon.js","evaluate":true}, - {"name":"alarm.wid.js","url":"widget.js"} - ], - "data": [{"name":"alarm.json"}] + {"name":"daysl.app.js","url":"app.js"}, + {"name":"daysl.img","url":"app-icon.js","evaluate":true}, + {"name":"daysl.wid.js","url":"widget.js"} + ] }, { "id": "wclock", diff --git a/apps/health/ChangeLog b/apps/health/ChangeLog index 5560f00bc..acf786e65 100644 --- a/apps/health/ChangeLog +++ b/apps/health/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Modified data format to include daily summaries diff --git a/apps/health/README.md b/apps/health/README.md index 0ba0d8228..456143844 100644 --- a/apps/health/README.md +++ b/apps/health/README.md @@ -28,7 +28,6 @@ to grab historical health info. ## TODO -* **Extend file format to include combined data for each day (to make graphs faster)** * `interface` page for desktop to allow data to be viewed and exported in common formats * More features in app: * Step counting goal (ensure pedometers use this) diff --git a/apps/health/app.js b/apps/health/app.js index f2df52972..e6fea91b2 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -11,7 +11,8 @@ function menuStepCount() { E.showMenu({ "":{title:"Step Counting"}, "< Back":()=>menuMain(), - "per hour":()=>stepsPerHour() + "per hour":()=>stepsPerHour(), + "per day":()=>stepsPerDay() }); } @@ -19,7 +20,8 @@ function menuMovement() { E.showMenu({ "":{title:"Movement"}, "< Back":()=>menuMain(), - "per hour":()=>movementPerHour() + "per hour":()=>movementPerHour(), + "per day":()=>movementPerDay(), }); } @@ -40,6 +42,23 @@ function stepsPerHour() { Bangle.setUI("updown", ()=>menuStepCount()); } +function stepsPerDay() { + E.showMessage("Loading..."); + var data = new Uint16Array(24); + require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps); + 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()); +} + function movementPerHour() { E.showMessage("Loading..."); var data = new Uint16Array(24); @@ -57,6 +76,23 @@ function movementPerHour() { Bangle.setUI("updown", ()=>menuStepCount()); } +function movementPerDay() { + E.showMessage("Loading..."); + var data = new Uint16Array(24); + require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement); + 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", ()=>menuStepCount()); +} + Bangle.loadWidgets(); Bangle.drawWidgets(); menuMain(); diff --git a/apps/health/boot.js b/apps/health/boot.js index d6b84ce98..0da4af086 100644 --- a/apps/health/boot.js +++ b/apps/health/boot.js @@ -4,7 +4,7 @@ Bangle.on("health", health => { const DB_RECORD_LEN = 4; const DB_RECORDS_PER_HR = 6; - const DB_RECORDS_PER_DAY = DB_RECORDS_PER_HR*24; + 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; const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN; @@ -17,6 +17,12 @@ Bangle.on("health", health => { (DB_RECORDS_PER_HR*d.getHours()) + (0|(d.getMinutes()*DB_RECORDS_PER_HR/60)); } + function getRecordData(health) { + return String.fromCharCode( + health.steps>>8,health.steps&255, // 16 bit steps + health.bpm, // 8 bit bpm + Math.min(health.movement / 8, 255)); // movement + } var rec = getRecordIdx(d); var fn = getRecordFN(d); @@ -30,9 +36,30 @@ Bangle.on("health", health => { } else { require("Storage").write(fn, "HEALTH1\0", 0, DB_FILE_LEN); // header } - var recordData = String.fromCharCode( - health.steps>>8,health.steps&255, // 16 bit steps - health.bpm, // 8 bit bpm - Math.min(health.movement / 8, 255)); // movement - require("Storage").write(fn, recordData, DB_HEADER_LEN+(rec*DB_RECORD_LEN), DB_FILE_LEN); + var recordPos = DB_HEADER_LEN+(rec*DB_RECORD_LEN); + require("Storage").write(fn, getRecordData(health), recordPos, DB_FILE_LEN); + if (rec%DB_RECORDS_PER_DAY != DB_RECORDS_PER_DAY-1) 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 + DB_RECORD_LEN; // record after the current one is the sum + if (f.substr(sumPos, DB_RECORD_LEN)!="\xFF\xFF\xFF\xFF") { + print("HEALTH ERR: Daily summary already written!"); + return; + } + health = { steps:0, bpm:0, movement:0, records:0}; + var records = DB_RECORDS_PER_HR*24; + for (var i=0;i