Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

recorder: resume logs recorded within 4 hours #3136

Closed
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/recorder/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@
0.36: When recording with 1 second periods, log time with one decimal.
0.37: 1 second periods + gps log => log when gps event is received, not with
setInterval.
0.38: Resume previous recorder logs, if within four hours - regardless of date
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to clarify that the previous recorder log is only resumed on append

2 changes: 1 addition & 1 deletion apps/recorder/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "recorder",
"name": "Recorder",
"shortName": "Recorder",
"version": "0.37",
"version": "0.38",
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
"icon": "app.png",
"tags": "tool,outdoors,gps,widget,clkinfo",
Expand Down
143 changes: 143 additions & 0 deletions apps/recorder/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
let writes = {};
let testDate, now;
let files;

const testDateStamp = () => `${testDate.getYear() + 1900}${testDate.getMonth() + 1}${testDate.getDate()}`;

const mockStorage = {
readJSON(f, err) {
if(f === "recorder.json"){
return {};
}
throw new Error(`unimplemented readJSON(${args})`);
},
writeJSON(fname, json) {
if(!writes[fname])
writes[fname] = [];
writes[fname].push(json);
},
list(re) {
let files = [
"recorder.json",
"recorder.log20230802a.csv\1",
`recorder.log${testDateStamp()}a.csv\x01`,
"recorder.log20181219a.csv\1",
"abc",
];

if (re)
files = files.filter(f => re.test ? re.test(f) : re === f);
return files;
},
read(...args) {
throw new Error(`unimplemented read(${args})`);
},
write(...args) {
throw new Error(`unimplemented write(${args})`);
},
open(f, mode) {
f = f.replace(/\1$/, "");

const lines = files[f] || [];

return {
readLine() {
return lines.shift() || "";
}
}
},
};

const assertEq = (a, b) => {
if(typeof a !== typeof b)
throw new Error("type mismatch");
if(typeof a !== "string")
throw new Error("unimplemented");
if(a !== b)
throw new Error(`string mismatch, ${JSON.stringify(a)} != ${JSON.stringify(b)}`);
}

require = (origRequire => req => {
if (req === "Storage") {
return mockStorage;
}
return origRequire(req);
})(require);

Date = (OrigDate => function(...args) {
if (args.length === 0) {
// new Date(), pretend the time is what we're testing
return new OrigDate(now);
}
return new OrigDate(...args);
})(Date);

Bangle = {
removeListener(){},
drawWidgets(){},
}
WIDGETS = {};
const w = require("fs").readFileSync("./widget.js", "utf8");
eval(w);

let file;

/*
* if it's almost midnight but we have a recording
* from ~15 mins ago, we select it
*/
testDate = new Date("2023-11-23T23:45:00.000Z");
now = new Date("2023-11-23T23:59:00.000Z");
files = {
[`recorder.log${testDateStamp()}a.csv`]: [
"Time,Steps",
"2023-12-20T19:27:45.000Z,9",
testDate.toISOString() + ",21",
],
};
writes = {};

WIDGETS["recorder"].setRecording(true);

file = writes["recorder.json"][0].file;
assertEq(file, `recorder.log20231123a.csv`);

/*
* if it's past midnight but we have a recording
* from ~15 mins ago, we select it
*/
testDate = new Date("2023-11-23T23:45:00.000Z");
now = new Date("2023-11-24T00:01:00.000Z");
files = {
[`recorder.log${testDateStamp()}a.csv`]: [
"Time,Steps",
"2023-12-20T19:27:45.000Z,9",
testDate.toISOString() + ",21",
],
};
writes = {};

WIDGETS["recorder"].setRecording(true);

file = writes["recorder.json"][0].file;
assertEq(file, `recorder.log20231123a.csv`);

/*
* if it's a fair bit after the last recording,
* we pick a new one
*/
testDate = new Date("2023-11-23T23:45:00.000Z");
now = new Date("2023-11-24T03:45:00.000Z"); // just over the 4 hour limit
files = {
[`recorder.log${testDateStamp()}a.csv`]: [
"Time,Steps",
"2023-12-20T19:27:45.000Z,9",
testDate.toISOString() + ",21",
],
};
writes = {};

WIDGETS["recorder"].setRecording(true);

file = writes["recorder.json"][0].file;
assertEq(file, `recorder.log20231124a.csv`);
34 changes: 29 additions & 5 deletions apps/recorder/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,34 @@
options = options||{};
if (isOn && !settings.recording) {
var date=(new Date()).toISOString().substr(0,10).replace(/-/g,""), trackNo=10;
function getTrackFilename() { return "recorder.log" + date + trackNo.toString(36) + ".csv"; }
if (!settings.file || !settings.file.startsWith("recorder.log" + date)) {
// if no filename set or date different, set up a new filename
settings.file = getTrackFilename();
function nextTrackFilename() { return "recorder.log" + date + trackNo.toString(36) + ".csv"; }
function mostRecentFile() {
const logs = require("Storage").list(/^recorder\.log/);

if(logs.length > 0){
logs.sort();
const latest = logs[logs.length-1].replace("\1", "");
const f = require("Storage").open(latest, "r");
const timeIdx = f.readLine().replace("\n", "").split(",").indexOf("Time");
if(timeIdx >= 0){
let last, tmp;
while(tmp = f.readLine())

Check warning on line 270 in apps/recorder/widget.js

View workflow job for this annotation

GitHub Actions / build

Expected a conditional expression and instead saw an assignment
bobrippling marked this conversation as resolved.
Show resolved Hide resolved
last = tmp;

const when = new Date(last.replace("\n", "").split(",")[timeIdx]);
const now = new Date;
const age = now.getTime() - when.getTime();
if (age < 14400000) { // 4 hours
return latest;
}
}
}
}
const recentlyRecorded = mostRecentFile();
if (recentlyRecorded) {
settings.file = recentlyRecorded;
} else if (!settings.file) {
settings.file = nextTrackFilename();
}
var headers = require("Storage").open(settings.file,"r").readLine();
if (headers){ // if file exists
Expand Down Expand Up @@ -289,7 +313,7 @@
// new file - use the current date
var newFileName;
do { // while a file exists, add one to the letter after the date
newFileName = getTrackFilename();
newFileName = nextTrackFilename();
trackNo++;
} while (require("Storage").list(newFileName).length);
settings.file = newFileName;
Expand Down