Skip to content

Instantly share code, notes, and snippets.

@deltam
Last active November 30, 2020 02:59
Show Gist options
  • Save deltam/2bfa7248052fc913ae3db3a0df17ec58 to your computer and use it in GitHub Desktop.
Save deltam/2bfa7248052fc913ae3db3a0df17ec58 to your computer and use it in GitHub Desktop.
// switch record
var jsonName = 'sleeprec.settings.json';
var settings = require("Storage").readJSON(jsonName,1)||{};
function init() {
if (settings.isRecording == undefined)
settings.isRecording = false;
if (settings.lastAverage == undefined)
settings.lastAverage = -1;
if (settings.lastRecordedAt == undefined)
settings.lastRecordedAt = 0;
setWatch(toggle, BTN2);
}
function show() {
if (settings.isRecording)
E.showMessage('recording on', 'sleeprec');
else
E.showMessage('recording off', 'sleeprec');
}
function toggle() {
settings.isRecording = !settings.isRecording;
settings.lastAverage = -1;
settings.lastRecordedAt = 0;
require('Storage').writeJSON(jsonName, settings);
show();
setWatch(toggle, BTN2);
}
init();
show();
// record heart rate while sleeping
function Recorder() {}
(() => {
const MEASURE_PERIOD = 15*60*1000; // every 15 min
const SAMPLE_TIME = 3*60*1000; // 3 min
const DISPOSE_TIME = 30*1000; // 30 sec
var sumBPM;
var sumCount;
var sumAccelDiff;
var countAccelDiff;
var maxAccelDiff;
var csvFile;
Recorder.prototype.init = (csvFilename) => {
if (csvFilename == '') {
d = new Date();
loc = require('locale');
locTime = `${loc.date(d)}_${loc.time(d)}`.trim().split(/[\/:]/).join('');
csvFilename = `sleeprec.bpm.${locTime}.csv`;
}
csvFile = require("Storage").open(csvFilename, 'a');
console.log('length', csvFile.getLength());
if (csvFile.getLength() == 0) {
csvFile.write(`time, locale_date, locale_time, bpm_avg, accel_diff_avg, accel_diff_max\n`);
}
};
Recorder.prototype.stop = () => {
console.log('stop');
Bangle.removeListener('HRM', onHRM);
Bangle.setHRMPower(0);
Bangle.removeListener('accel', onAccel);
Bangle.setPollInterval(80);
};
function delay(msec) {
return new Promise((resolve) => {
setTimeout(resolve, msec);
});
}
Recorder.prototype.measure = (lastRecordedAt) => {
return new Promise((resolve, reject) => {
if (Date.now() - lastRecordedAt < MEASURE_PERIOD) {
reject();
return;
}
console.log('measure start');
Bangle.setHRMPower(1);
Bangle.on('HRM', onHRM);
Bangle.on('accel', onAccel);
return delay(DISPOSE_TIME).then(() => { // dispose first N sec bpm
reset();
console.log('record start');
}).then(
() => delay(SAMPLE_TIME) // sampling time
).then(() => {
console.log('record end');
Bangle.removeListener('HRM', onHRM);
Bangle.setHRMPower(0);
Bangle.removeListener('accel', onAccel);
resolve(record());
});
});
};
function reset() {
sumBPM = 0;
sumCount = 0;
sumAccelDiff = 0;
countAccelDiff = 0;
maxAccelDiff = -1;
}
function onHRM(hrm) {
if (hrm.confidence < 100)
return;
sumBPM += hrm.bpm;
sumCount++;
console.log(`hrme ${hrm.bpm} , ${hrm.confidence}`);
}
function onAccel(acc) {
sumAccelDiff += acc.diff;
countAccelDiff++;
maxAccelDiff = Math.max(maxAccelDiff, acc.diff);
}
function record() {
avg = Math.floor(sumBPM/sumCount + 0.5);
avgDiff = Math.floor(1000*sumAccelDiff/countAccelDiff + 0.5);
d = new Date();
loc = require('locale');
rec = [
Math.floor(d.getTime()),
loc.date(d),
loc.time(d).trim(),
avg,
avgDiff,
Math.floor(maxAccelDiff*1000)
];
csvFile.write(rec.join(',') + '\n');
console.log(`sum ${sumBPM}, cnt ${sumCount}, avg ${avg}, ${sumAccelDiff}, ${countAccelDiff}, accelDiffAvg ${avgDiff}, max ${maxAccelDiff}`);
return rec;
}
})();
// Draw Widget
(() => {
var DRAW_PERIOD = 1*60*1000; // 1 min
var recorder;
var settings;
var isMesure;
var width = 24; // width of the widget
var height = 22; // height of tha widget
function draw() {
if (!settings.isRecording) return;
g.reset();
if (settings.lastAverage == -1){
g.setColor(1,0,0);
drawStr('rec', this.x, this.y);
} else {
g.setColor(0,1,0);
drawStr(settings.lastAverage, this.x, this.y);
}
}
function drawStr(s, x, y) {
g.setFontAlign(0,0); // center fonts
g.clearRect(x, y, x+width-1, y+height-1);
g.drawRect(x, y, x+width-1, y+height-1); // check the bounds!
g.setFont("6x8");
g.drawString(s, x+width/2, y+11);
}
function init() {
recorder = new Recorder();
recorder.init('sleeprec.bpm.2.csv');
}
function reload() {
settings = require('Storage').readJSON('sleeprec.settings.json',1)||{};
if (settings.lastAverage == undefined)
settings.lastAverage = -1;
if (settings.lastRecordedAt == undefined)
settings.lastRecordedAt = 0;
if (settings.isRecording == undefined)
settings.isRecording = false;
if (!settings.isRecording)
recorder.stop();
console.log('reload', settings);
}
// add your widget
WIDGETS.sleeprec={
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
width: width, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
draw:draw, // called to draw the widget
reload: () => {
reload();
Bangle.drawWidgets();
}
};
init();
reload();
setInterval(function() {
if (!settings.isRecording) return;
WIDGETS.sleeprec.draw(WIDGETS.sleeprec);
// console.log('draw interval', settings.lastRecordedAt);
let lastRecordedAt = settings.lastRecordedAt;
settings.lastRecordedAt = Date.now();
recorder.measure(lastRecordedAt).then(rec => {
settings.lastAverage = rec[3];
require('Storage').writeJSON('sleeprec.settings.json', settings);
Bangle.drawWidgets();
console.log('handler', settings);
}, () => {
settings.lastRecordedAt = lastRecordedAt;
// console.log('reject', settings.lastRecordedAt);
});
}, DRAW_PERIOD);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment