forked from FOSS/BangleApps
Merge pull request #337 from Purple-Tentacle/master
Active Pedometer 0.03 / Chrono Widget 0.03master
commit
4744b64a28
10
apps.json
10
apps.json
|
@ -1153,22 +1153,22 @@
|
||||||
"name": "Active Pedometer",
|
"name": "Active Pedometer",
|
||||||
"shortName":"Active Pedometer",
|
"shortName":"Active Pedometer",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.02",
|
"version":"0.03",
|
||||||
"description": "Pedometer that filters out arm movement and displays a step goal progress.",
|
"description": "Pedometer that filters out arm movement and displays a step goal progress. Steps are saved to a daily file and can be viewed as graph.",
|
||||||
"tags": "outdoors,widget",
|
"tags": "outdoors,widget",
|
||||||
"type":"widget",
|
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"activepedom.wid.js","url":"widget.js"},
|
{"name":"activepedom.wid.js","url":"widget.js"},
|
||||||
{"name":"activepedom.settings.js","url":"settings.js"},
|
{"name":"activepedom.settings.js","url":"settings.js"},
|
||||||
{"name":"activepedom.img","url":"app-icon.js","evaluate":true}
|
{"name":"activepedom.img","url":"app-icon.js","evaluate":true},
|
||||||
|
{"name":"activepedom.app.js","url":"app.js"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ "id": "chronowid",
|
{ "id": "chronowid",
|
||||||
"name": "Chrono Widget",
|
"name": "Chrono Widget",
|
||||||
"shortName":"Chrono Widget",
|
"shortName":"Chrono Widget",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.02",
|
"version":"0.03",
|
||||||
"description": "Chronometer (timer) which runs as widget.",
|
"description": "Chronometer (timer) which runs as widget.",
|
||||||
"tags": "tools,widget",
|
"tags": "tools,widget",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New Widget!
|
0.01: New Widget!
|
||||||
0.02: Distance calculation and display
|
0.02: Distance calculation and display
|
||||||
|
0.03: Data logging and display
|
|
@ -1,4 +1,4 @@
|
||||||
# Active Pedometer
|
# Active Pedometer
|
||||||
Pedometer that filters out arm movement and displays a step goal progress.
|
Pedometer that filters out arm movement and displays a step goal progress.
|
||||||
|
|
||||||
I changed the step counting algorithm completely.
|
I changed the step counting algorithm completely.
|
||||||
|
@ -6,6 +6,8 @@ Now every step is counted when in status 'active', if the time difference betwee
|
||||||
To get in 'active' mode, you have to reach the step threshold before the active timer runs out.
|
To get in 'active' mode, you have to reach the step threshold before the active timer runs out.
|
||||||
When you reach the step threshold, the steps needed to reach the threshold are counted as well.
|
When you reach the step threshold, the steps needed to reach the threshold are counted as well.
|
||||||
|
|
||||||
|
Steps are saved to a datafile every 5 minutes. You can watch a graph using the app.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
* 600 steps
|
* 600 steps
|
||||||

|

|
||||||
|
@ -30,6 +32,22 @@ When you reach the step threshold, the steps needed to reach the threshold are c
|
||||||
* Steps are saved to a file and read-in at start (to not lose step progress)
|
* Steps are saved to a file and read-in at start (to not lose step progress)
|
||||||
* Settings can be changed in Settings - App/widget settings - Active Pedometer
|
* Settings can be changed in Settings - App/widget settings - Active Pedometer
|
||||||
|
|
||||||
|
## Data storage
|
||||||
|
|
||||||
|
* Data is stored to a file
|
||||||
|
* Format: now,stepsCounted,active,stepsTooShort,stepsTooLong,stepsOutsideTime
|
||||||
|
* now is UNIX timestamp in ms
|
||||||
|
* You can chose the app to watch a steps graph
|
||||||
|
* You can import the file into Excel
|
||||||
|
* The file does not include a header
|
||||||
|
* You can convert UNIX timestamp to a date in Excel using this formula: =DATUM(1970;1;1)+(LINKS(A2;10)/86400)
|
||||||
|
* You have to format the cell with the formula to a date cell. Example: JJJJ-MM-TT-hh-mm-ss
|
||||||
|
|
||||||
|
## App
|
||||||
|
|
||||||
|
* The app accesses the data stored for the current day
|
||||||
|
* Timespan is choseable (1h, 4h, 8h, 12h, 16h, 20, 24h), standard is 24h, the whole current day
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
* Max time (ms): Maximum time between two steps in milliseconds, steps will not be counted if exceeded. Standard: 1100
|
* Max time (ms): Maximum time between two steps in milliseconds, steps will not be counted if exceeded. Standard: 1100
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
(() => {
|
||||||
|
|
||||||
|
//Graph module, as long as modules are not added by the app loader
|
||||||
|
Modules.addCached("graph",function(){exports.drawAxes=function(b,c,a){function h(a){return e+m*(a-t)/x}function l(a){return f+g-g*(a-n)/u}var k=a.padx||0,d=a.pady||0,t=-k,w=c.length+k-1,n=(void 0!==a.miny?a.miny:a.miny=c.reduce(function(a,b){return Math.min(a,b)},c[0]))-d;c=(void 0!==a.maxy?a.maxy:a.maxy=c.reduce(function(a,b){return Math.max(a,b)},c[0]))+d;a.gridy&&(d=a.gridy,n=d*Math.floor(n/d),c=d*Math.ceil(c/d));var e=a.x||0,f=a.y||0,m=a.width||b.getWidth()-(e+1),g=a.height||b.getHeight()-(f+1);a.axes&&(null!==a.ylabel&&
|
||||||
|
(e+=6,m-=6),null!==a.xlabel&&(g-=6));a.title&&(f+=6,g-=6);a.axes&&(b.drawLine(e,f,e,f+g),b.drawLine(e,f+g,e+m,f+g));a.title&&(b.setFontAlign(0,-1),b.drawString(a.title,e+m/2,f-6));var x=w-t,u=c-n;u||(u=1);if(a.gridx){b.setFontAlign(0,-1,0);var v=a.gridx;for(d=Math.ceil((t+k)/v)*v;d<=w-k;d+=v){var r=h(d),p=a.xlabel?a.xlabel(d):d;b.setPixel(r,f+g-1);var q=b.stringWidth(p)/2;null!==a.xlabel&&r>q&&b.getWidth()>r+q&&b.drawString(p,r,f+g+2)}}if(a.gridy)for(b.setFontAlign(0,0,1),d=n;d<=c;d+=a.gridy)k=l(d),
|
||||||
|
p=a.ylabel?a.ylabel(d):d,b.setPixel(e+1,k),q=b.stringWidth(p)/2,null!==a.ylabel&&k>q&&b.getHeight()>k+q&&b.drawString(p,e-5,k+1);b.setFontAlign(-1,-1,0);return{x:e,y:f,w:m,h:g,getx:h,gety:l}};exports.drawLine=function(b,c,a){a=a||{};a=exports.drawAxes(b,c,a);var h=!0,l;for(l in c)h?b.moveTo(a.getx(l),a.gety(c[l])):b.lineTo(a.getx(l),a.gety(c[l])),h=!1;return a};exports.drawBar=function(b,c,a){a=a||{};a.padx=1;a=exports.drawAxes(b,c,a);for(var h in c)b.fillRect(a.getx(h-.5)+1,a.gety(c[h]),a.getx(h+
|
||||||
|
.5)-1,a.gety(0));return a}});
|
||||||
|
|
||||||
|
const storage = require("Storage");
|
||||||
|
const SETTINGS_FILE = 'activepedom.settings.json';
|
||||||
|
var history = 86400000; // 28800000=8h 43200000=12h //86400000=24h
|
||||||
|
|
||||||
|
//return setting
|
||||||
|
function setting(key) {
|
||||||
|
//define default settings
|
||||||
|
const DEFAULTS = {
|
||||||
|
'cMaxTime' : 1100,
|
||||||
|
'cMinTime' : 240,
|
||||||
|
'stepThreshold' : 30,
|
||||||
|
'intervalResetActive' : 30000,
|
||||||
|
'stepSensitivity' : 80,
|
||||||
|
'stepGoal' : 10000,
|
||||||
|
'stepLength' : 75,
|
||||||
|
};
|
||||||
|
if (!settings) { loadSettings(); }
|
||||||
|
return (key in settings) ? settings[key] : DEFAULTS[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert ms to time
|
||||||
|
function getTime(t) {
|
||||||
|
date = new Date(t);
|
||||||
|
offset = date.getTimezoneOffset() / 60;
|
||||||
|
//var milliseconds = parseInt((t % 1000) / 100),
|
||||||
|
seconds = Math.floor((t / 1000) % 60);
|
||||||
|
minutes = Math.floor((t / (1000 * 60)) % 60);
|
||||||
|
hours = Math.floor((t / (1000 * 60 * 60)) % 24);
|
||||||
|
hours = hours - offset;
|
||||||
|
hours = (hours < 10) ? "0" + hours : hours;
|
||||||
|
minutes = (minutes < 10) ? "0" + minutes : minutes;
|
||||||
|
seconds = (seconds < 10) ? "0" + seconds : seconds;
|
||||||
|
return hours + ":" + minutes + ":" + seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDate(t) {
|
||||||
|
date = new Date(t*1);
|
||||||
|
year = date.getFullYear();
|
||||||
|
month = date.getMonth()+1; //month is zero-based
|
||||||
|
day = date.getDate();
|
||||||
|
month = (month < 10) ? "0" + month : month;
|
||||||
|
day = (day < 10) ? "0" + day : day;
|
||||||
|
return year + "-" + month + "-" + day;
|
||||||
|
}
|
||||||
|
|
||||||
|
//columns: 0=time, 1=stepsCounted, 2=active, 3=stepsTooShort, 4=stepsTooLong, 5=stepsOutsideTime
|
||||||
|
function getArrayFromCSV(file, column) {
|
||||||
|
i = 0;
|
||||||
|
array = [];
|
||||||
|
now = new Date();
|
||||||
|
while ((nextLine = file.readLine())) { //as long as there is a next line
|
||||||
|
if(nextLine) {
|
||||||
|
dataSplitted = nextLine.split(','); //split line,
|
||||||
|
diff = now - dataSplitted[0]; //calculate difference between now and stored time
|
||||||
|
if (diff <= history) { //only entries from the last x ms
|
||||||
|
array.push(dataSplitted[column]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGraph() {
|
||||||
|
//times
|
||||||
|
// actives = getArrayFromCSV(csvFile, 2);
|
||||||
|
// shorts = getArrayFromCSV(csvFile, 3);
|
||||||
|
// longs = getArrayFromCSV(csvFile, 4);
|
||||||
|
// outsides = getArrayFromCSV(csvFile, 5); //array.push(dataSplitted[5].slice(0,-1));
|
||||||
|
now = new Date();
|
||||||
|
month = now.getMonth() + 1;
|
||||||
|
if (month < 10) month = "0" + month;
|
||||||
|
filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data";
|
||||||
|
var csvFile = storage.open(filename, "r");
|
||||||
|
times = getArrayFromCSV(csvFile, 0);
|
||||||
|
first = getDate(times[0]) + " " + getTime(times[0]); //first entry in datafile
|
||||||
|
last = getDate (times[times.length-1]) + " " + getTime(times[times.length-1]); //last entry in datafile
|
||||||
|
//free memory
|
||||||
|
csvFile = undefined;
|
||||||
|
times = undefined;
|
||||||
|
|
||||||
|
//steps
|
||||||
|
var csvFile = storage.open(filename, "r");
|
||||||
|
steps = getArrayFromCSV(csvFile, 1);
|
||||||
|
first = first + " " + steps[0] + "/" + setting('stepGoal');
|
||||||
|
last = last + " " + steps[steps.length-1] + "/" + setting('stepGoal');
|
||||||
|
|
||||||
|
//define y-axis grid labels
|
||||||
|
stepsLastEntry = steps[steps.length-1];
|
||||||
|
if (stepsLastEntry < 1000) gridyValue = 100;
|
||||||
|
if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 1000;
|
||||||
|
if (stepsLastEntry > 10000) gridyValue = 5000;
|
||||||
|
|
||||||
|
//draw
|
||||||
|
drawMenu();
|
||||||
|
g.drawString("First: " + first, 10, 30);
|
||||||
|
g.drawString(" Last: " + last, 10, 40);
|
||||||
|
require("graph").drawLine(g, steps, {
|
||||||
|
//title: "Steps Counted",
|
||||||
|
axes : true,
|
||||||
|
gridy : gridyValue,
|
||||||
|
y : 60, //offset on screen
|
||||||
|
x : 5, //offset on screen
|
||||||
|
});
|
||||||
|
//free memory from big variables
|
||||||
|
allData = undefined;
|
||||||
|
allDataFile = undefined;
|
||||||
|
csvFile = undefined;
|
||||||
|
times = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawMenu () {
|
||||||
|
g.clear();
|
||||||
|
g.setFont("6x8", 1);
|
||||||
|
g.drawString("BTN1:Timespan | BTN2:Draw", 20, 10);
|
||||||
|
g.drawString("Timespan: " + history/1000/60/60 + " hours", 20, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
setWatch(function() { //BTN1
|
||||||
|
switch(history) {
|
||||||
|
case 3600000 : //1h
|
||||||
|
history = 14400000; //4h
|
||||||
|
break;
|
||||||
|
case 86400000 : //24
|
||||||
|
history = 3600000; //1h
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
history = history + 14400000; //4h
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drawMenu();
|
||||||
|
}, BTN1, {edge:"rising", debounce:50, repeat:true});
|
||||||
|
|
||||||
|
setWatch(function() { //BTN2
|
||||||
|
g.setFont("6x8", 2);
|
||||||
|
g.drawString ("Drawing...",30,60);
|
||||||
|
drawGraph();
|
||||||
|
}, BTN2, {edge:"rising", debounce:50, repeat:true});
|
||||||
|
|
||||||
|
setWatch(function() { //BTN3
|
||||||
|
}, BTN3, {edge:"rising", debounce:50, repeat:true});
|
||||||
|
|
||||||
|
setWatch(function() { //BTN4
|
||||||
|
}, BTN4, {edge:"rising", debounce:50, repeat:true});
|
||||||
|
|
||||||
|
setWatch(function() { //BTN5
|
||||||
|
}, BTN5, {edge:"rising", debounce:50, repeat:true});
|
||||||
|
|
||||||
|
//load settings
|
||||||
|
let settings;
|
||||||
|
function loadSettings() {
|
||||||
|
settings = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
drawMenu();
|
||||||
|
|
||||||
|
})();
|
|
@ -3,13 +3,14 @@
|
||||||
var startTimeStep = new Date(); //set start time
|
var startTimeStep = new Date(); //set start time
|
||||||
var stopTimeStep = 0; //Time after one step
|
var stopTimeStep = 0; //Time after one step
|
||||||
var timerResetActive = 0; //timer to reset active
|
var timerResetActive = 0; //timer to reset active
|
||||||
|
var timerStoreData = 0; //timer to store data
|
||||||
var steps = 0; //steps taken
|
var steps = 0; //steps taken
|
||||||
var stepsCounted = 0; //active steps counted
|
var stepsCounted = 0; //active steps counted
|
||||||
var active = 0; //x steps in y seconds achieved
|
var active = 0; //x steps in y seconds achieved
|
||||||
var stepGoalPercent = 0; //percentage of step goal
|
var stepGoalPercent = 0; //percentage of step goal
|
||||||
var stepGoalBarLength = 0; //length og progress bar
|
var stepGoalBarLength = 0; //length og progress bar
|
||||||
var lastUpdate = new Date(); //used to reset counted steps on new day
|
var lastUpdate = new Date(); //used to reset counted steps on new day
|
||||||
var width = 45; //width of widget
|
var width = 46; //width of widget
|
||||||
|
|
||||||
//used for statistics and debugging
|
//used for statistics and debugging
|
||||||
var stepsTooShort = 0;
|
var stepsTooShort = 0;
|
||||||
|
@ -18,13 +19,41 @@
|
||||||
|
|
||||||
var distance = 0; //distance travelled
|
var distance = 0; //distance travelled
|
||||||
|
|
||||||
|
const s = require('Storage');
|
||||||
const SETTINGS_FILE = 'activepedom.settings.json';
|
const SETTINGS_FILE = 'activepedom.settings.json';
|
||||||
const PEDOMFILE = "activepedom.steps.json";
|
const PEDOMFILE = "activepedom.steps.json";
|
||||||
|
var dataFile;
|
||||||
|
var storeDataInterval = 5*60*1000; //ms
|
||||||
|
|
||||||
let settings;
|
let settings;
|
||||||
//load settings
|
//load settings
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {};
|
settings = s.readJSON(SETTINGS_FILE, 1) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeData() {
|
||||||
|
now = new Date();
|
||||||
|
month = now.getMonth() + 1;
|
||||||
|
if (month < 10) month = "0" + month;
|
||||||
|
filename = filename = "activepedom" + now.getFullYear() + month + now.getDate() + ".data";
|
||||||
|
dataFile = s.open(filename,"a");
|
||||||
|
if (dataFile) {
|
||||||
|
if (dataFile.getLength() == 0) {
|
||||||
|
stepsToWrite = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stepsToWrite = stepsCounted;
|
||||||
|
}
|
||||||
|
dataFile.write([
|
||||||
|
now.getTime(),
|
||||||
|
stepsToWrite,
|
||||||
|
active,
|
||||||
|
stepsTooShort,
|
||||||
|
stepsTooLong,
|
||||||
|
stepsOutsideTime,
|
||||||
|
].join(",")+"\n");
|
||||||
|
}
|
||||||
|
dataFile = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
//return setting
|
//return setting
|
||||||
|
@ -77,20 +106,20 @@
|
||||||
|
|
||||||
//Remove step if time between first and second step is too long
|
//Remove step if time between first and second step is too long
|
||||||
if (stepTimeDiff >= setting('cMaxTime')) { //milliseconds
|
if (stepTimeDiff >= setting('cMaxTime')) { //milliseconds
|
||||||
stepsTooLong++; //count steps which are note counted, because time too long
|
stepsTooLong++; //count steps which are not counted, because time too long
|
||||||
steps--;
|
steps--;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove step if time between first and second step is too short
|
//Remove step if time between first and second step is too short
|
||||||
if (stepTimeDiff <= setting('cMinTime')) { //milliseconds
|
if (stepTimeDiff <= setting('cMinTime')) { //milliseconds
|
||||||
stepsTooShort++; //count steps which are note counted, because time too short
|
stepsTooShort++; //count steps which are not counted, because time too short
|
||||||
steps--;
|
steps--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Step threshold reached
|
||||||
if (steps >= setting('stepThreshold')) {
|
if (steps >= setting('stepThreshold')) {
|
||||||
if (active == 0) {
|
if (active == 0) {
|
||||||
stepsCounted = stepsCounted + (setting('stepThreshold') -1) ; //count steps needed to reach active status, last step is counted anyway, so treshold -1
|
stepsCounted = stepsCounted + (setting('stepThreshold') -1) ; //count steps needed to reach active status, last step is counted anyway, so treshold -1
|
||||||
stepsOutsideTime = stepsOutsideTime - 10; //substract steps needed to reac active status
|
stepsOutsideTime = stepsOutsideTime - 10; //substract steps needed to reach active status
|
||||||
}
|
}
|
||||||
active = 1;
|
active = 1;
|
||||||
clearInterval(timerResetActive); //stop timer which resets active
|
clearInterval(timerResetActive); //stop timer which resets active
|
||||||
|
@ -109,14 +138,17 @@
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
var height = 23; //width is deined globally
|
var height = 23; //width is deined globally
|
||||||
distance = (stepsCounted * setting('stepLength')) / 100 /1000 //distance in km
|
distance = (stepsCounted * setting('stepLength')) / 100 /1000; //distance in km
|
||||||
|
|
||||||
//Check if same day
|
//Check if same day
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
if (lastUpdate.getDate() == date.getDate()){ //if same day
|
if (lastUpdate.getDate() == date.getDate()){ //if same day
|
||||||
}
|
}
|
||||||
else {
|
else { //different day, set all steps to 0
|
||||||
stepsCounted = 1; //set stepcount to 1
|
stepsCounted = 0;
|
||||||
|
stepsTooShort = 0;
|
||||||
|
stepsTooLong = 0;
|
||||||
|
stepsOutsideTime = 0;
|
||||||
}
|
}
|
||||||
lastUpdate = date;
|
lastUpdate = date;
|
||||||
|
|
||||||
|
@ -166,7 +198,7 @@
|
||||||
stepsTooLong : stepsTooLong,
|
stepsTooLong : stepsTooLong,
|
||||||
stepsOutsideTime : stepsOutsideTime
|
stepsOutsideTime : stepsOutsideTime
|
||||||
};
|
};
|
||||||
require("Storage").write(PEDOMFILE,d); //write array to file
|
s.write(PEDOMFILE,d); //write array to file
|
||||||
});
|
});
|
||||||
|
|
||||||
//When Step is registered by firmware
|
//When Step is registered by firmware
|
||||||
|
@ -182,8 +214,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
//Read data from file and set variables
|
//Read data from file and set variables
|
||||||
let pedomData = require("Storage").readJSON(PEDOMFILE,1);
|
let pedomData = s.readJSON(PEDOMFILE,1);
|
||||||
|
|
||||||
if (pedomData) {
|
if (pedomData) {
|
||||||
if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate);
|
if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate);
|
||||||
stepsCounted = pedomData.stepsToday|0;
|
stepsCounted = pedomData.stepsToday|0;
|
||||||
|
@ -191,12 +222,10 @@
|
||||||
stepsTooLong = pedomData.stepsTooLong;
|
stepsTooLong = pedomData.stepsTooLong;
|
||||||
stepsOutsideTime = pedomData.stepsOutsideTime;
|
stepsOutsideTime = pedomData.stepsOutsideTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
pedomdata = 0; //reset pedomdata to save memory
|
pedomdata = 0; //reset pedomdata to save memory
|
||||||
|
|
||||||
setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive)
|
setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive)
|
||||||
|
timerStoreData = setInterval(storeData, storeDataInterval); //store data regularly
|
||||||
//Add widget
|
//Add widget
|
||||||
WIDGETS["activepedom"]={area:"tl",width:width,draw:draw};
|
WIDGETS["activepedom"]={area:"tl",width:width,draw:draw};
|
||||||
|
|
||||||
})();
|
})();
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New widget and app!
|
0.01: New widget and app!
|
||||||
0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme)
|
0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme)
|
||||||
|
0.03: Display only minutes:seconds when less than 1 hour left
|
|
@ -1,93 +1,93 @@
|
||||||
(() => {
|
(() => {
|
||||||
const storage = require('Storage');
|
const storage = require('Storage');
|
||||||
settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file
|
settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file
|
||||||
var height = 23;
|
var height = 23;
|
||||||
var width = 58;
|
var width = 58;
|
||||||
var interval = 0; //used for the 1 second interval timer
|
var interval = 0; //used for the 1 second interval timer
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
|
|
||||||
var time = 0;
|
var time = 0;
|
||||||
var diff = settingsChronowid.goal - now;
|
var diff = settingsChronowid.goal - now;
|
||||||
|
|
||||||
//Convert ms to time
|
//Convert ms to time
|
||||||
function getTime(t) {
|
function getTime(t) {
|
||||||
var milliseconds = parseInt((t % 1000) / 100),
|
var milliseconds = parseInt((t % 1000) / 100),
|
||||||
seconds = Math.floor((t / 1000) % 60),
|
seconds = Math.floor((t / 1000) % 60),
|
||||||
minutes = Math.floor((t / (1000 * 60)) % 60),
|
minutes = Math.floor((t / (1000 * 60)) % 60),
|
||||||
hours = Math.floor((t / (1000 * 60 * 60)) % 24);
|
hours = Math.floor((t / (1000 * 60 * 60)) % 24);
|
||||||
|
|
||||||
hours = (hours < 10) ? "0" + hours : hours;
|
hours = (hours < 10) ? "0" + hours : hours;
|
||||||
minutes = (minutes < 10) ? "0" + minutes : minutes;
|
minutes = (minutes < 10) ? "0" + minutes : minutes;
|
||||||
seconds = (seconds < 10) ? "0" + seconds : seconds;
|
seconds = (seconds < 10) ? "0" + seconds : seconds;
|
||||||
|
|
||||||
return hours + ":" + minutes + ":" + seconds;
|
return hours + ":" + minutes + ":" + seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
function printDebug() {
|
function printDebug() {
|
||||||
print ("Nowtime: " + getTime(now));
|
print ("Nowtime: " + getTime(now));
|
||||||
print ("Now: " + now);
|
print ("Now: " + now);
|
||||||
print ("Goaltime: " + getTime(settingsChronowid.goal));
|
print ("Goaltime: " + getTime(settingsChronowid.goal));
|
||||||
print ("Goal: " + settingsChronowid.goal);
|
print ("Goal: " + settingsChronowid.goal);
|
||||||
print("Difftime: " + getTime(diff));
|
print("Difftime: " + getTime(diff));
|
||||||
print("Diff: " + diff);
|
print("Diff: " + diff);
|
||||||
print ("Started: " + settingsChronowid.started);
|
print ("Started: " + settingsChronowid.started);
|
||||||
print ("----");
|
print ("----");
|
||||||
}
|
}
|
||||||
|
|
||||||
//counts down, calculates and displays
|
//counts down, calculates and displays
|
||||||
function countDown() {
|
function countDown() {
|
||||||
now = new Date();
|
now = new Date();
|
||||||
diff = settingsChronowid.goal - now; //calculate difference
|
diff = settingsChronowid.goal - now; //calculate difference
|
||||||
WIDGETS["chronowid"].draw();
|
WIDGETS["chronowid"].draw();
|
||||||
//time is up
|
//time is up
|
||||||
if (settingsChronowid.started && diff < 1000) {
|
if (settingsChronowid.started && diff < 1000) {
|
||||||
Bangle.buzz(1500);
|
Bangle.buzz(1500);
|
||||||
//write timer off to file
|
//write timer off to file
|
||||||
settingsChronowid.started = false;
|
settingsChronowid.started = false;
|
||||||
storage.writeJSON('chronowid.json', settingsChronowid);
|
storage.writeJSON('chronowid.json', settingsChronowid);
|
||||||
clearInterval(interval); //stop interval
|
clearInterval(interval); //stop interval
|
||||||
}
|
}
|
||||||
//printDebug();
|
//printDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw your widget
|
// draw your widget
|
||||||
function draw() {
|
function draw() {
|
||||||
if (!settingsChronowid.started) {
|
if (!settingsChronowid.started) {
|
||||||
width = 0;
|
width = 0;
|
||||||
return; //do not draw anything if timer is not started
|
return; //do not draw anything if timer is not started
|
||||||
}
|
}
|
||||||
g.reset();
|
g.reset();
|
||||||
if (diff >= 0) {
|
if (diff >= 0) {
|
||||||
if (diff < 600000) { //less than 1 hour left
|
if (diff < 3600000) { //less than 1 hour left
|
||||||
width = 58;
|
width = 58;
|
||||||
g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
||||||
g.setFont("6x8", 2);
|
g.setFont("6x8", 2);
|
||||||
g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00
|
g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00
|
||||||
}
|
}
|
||||||
if (diff >= 600000) { //one hour or more left
|
if (diff >= 3600000) { //one hour or more left
|
||||||
width = 48;
|
width = 48;
|
||||||
g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
||||||
g.setFont("6x8", 1);
|
g.setFont("6x8", 1);
|
||||||
g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00
|
g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed.
|
// not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed.
|
||||||
// else {
|
// else {
|
||||||
// width = 58;
|
// width = 58;
|
||||||
// g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
// g.clearRect(this.x,this.y,this.x+width,this.y+height);
|
||||||
// g.setFont("6x8", 2);
|
// g.setFont("6x8", 2);
|
||||||
// g.drawString("END", this.x+15, this.y+5);
|
// g.drawString("END", this.x+15, this.y+5);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second
|
if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second
|
||||||
|
|
||||||
// add the widget
|
// add the widget
|
||||||
WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() {
|
WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() {
|
||||||
reload();
|
reload();
|
||||||
Bangle.drawWidgets(); // relayout all widgets
|
Bangle.drawWidgets(); // relayout all widgets
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//printDebug();
|
//printDebug();
|
||||||
countDown();
|
countDown();
|
||||||
})();
|
})();
|
Loading…
Reference in New Issue