activepedom 0.03

master
Purple-Tentacle 2020-04-20 17:34:33 +02:00 committed by GitHub
parent af0ac4041c
commit 4b512af0e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 190 additions and 17 deletions

View File

@ -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

View File

@ -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
![](600.png) ![](600.png)
@ -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

133
apps/activepedom/app.js Normal file
View File

@ -0,0 +1,133 @@
(() => {
const storage = require("Storage");
var history = 86400000; // 28800000=8h 43200000=12h //86400000=24h
//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]);
last = getDate (times[times.length-1]) + " " + getTime(times[times.length-1]);
//free memory
csvFile = undefined;
times = undefined;
//steps
var csvFile = storage.open(filename, "r");
steps = getArrayFromCSV(csvFile, 1);
//define y-axis grid labels
stepsLastEntry = steps[steps.length-1];
if (stepsLastEntry < 1000) gridyValue = 100;
if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 500;
if (stepsLastEntry > 10000) gridyValue = 5000;
//draw
drawMenu();
g.drawString("First: " + first, 40, 30);
g.drawString(" Last: " + last, 40, 40);
require("graph").drawLine(g, steps, {
//title: "Steps Counted",
axes : true,
gridy : gridyValue,
y : 50, //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});
drawMenu();
})();

View File

@ -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,33 @@
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) dataFile.write([
now.getTime(),
stepsCounted,
active,
stepsTooShort,
stepsTooLong,
stepsOutsideTime,
].join(",")+"\n");
dataFile = undefined;
} }
//return setting //return setting
@ -77,20 +98,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 +130,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 +190,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 +206,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 +214,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};
})(); })();