1
0
Fork 0

edited app.js

master
Elfreda Kwawu 2024-04-15 23:08:51 -04:00
parent 3fb9e3fd50
commit fb29c3d378
1 changed files with 90 additions and 32 deletions

View File

@ -1,8 +1,15 @@
let isMeasuring = false; var isMeasuring = false;
let currentHeartRate = null; var currentHeartRate = null;
let lcdTimeout; var lcdTimeout;
let logData = []; var bpmValues = [];
var logData = [];
var lastHeartRateLogTimestamp = 0;
// HRV calculation variables
var hrvSlots = [10, 20, 30, 60, 120, 300];
var hrvValues = {};
// Heart rate monitor functions
function startMeasure() { function startMeasure() {
isMeasuring = true; isMeasuring = true;
Bangle.setLCDTimeout(0); Bangle.setLCDTimeout(0);
@ -13,7 +20,7 @@ function startMeasure() {
setTimeout(() => { setTimeout(() => {
Bangle.setHRMPower(1); Bangle.setHRMPower(1);
Bangle.on('HRM', handleHeartRate); Bangle.on('HRM', handleHeartRate);
Bangle.beep(400, 1000); // Buzz to indicate measurement start Bangle.buzz(500, 20);
drawScreen(); drawScreen();
}, 500); }, 500);
} }
@ -24,25 +31,10 @@ function stopMeasure() {
Bangle.setLCDTimeout(10); Bangle.setLCDTimeout(10);
Bangle.setHRMPower(0); Bangle.setHRMPower(0);
Bangle.removeAllListeners('HRM'); Bangle.removeAllListeners('HRM');
saveDataToCSV(); // Save data to CSV when measurement stops Bangle.buzz(500, 20);
Bangle.beep(400, 800); // Buzz to indicate measurement stop
drawScreen(); drawScreen();
} }
function handleHeartRate(hrm) {
if (hrm.confidence > 90) {
currentHeartRate = hrm.bpm;
let date = new Date();
let dateStr = require("locale").date(date);
let timeStr = require("locale").time(date, 1);
let seconds = date.getSeconds();
let timestamp = `${dateStr} ${timeStr}:${seconds}`; // Concatenate date, time, and seconds
logData.push({ timestamp: timestamp, heartRate: currentHeartRate });
drawScreen();
}
}
function drawScreen(message) { function drawScreen(message) {
g.clear(); // Clear the display g.clear(); // Clear the display
@ -65,9 +57,9 @@ function drawScreen(message) {
g.setFont('6x8', 2); g.setFont('6x8', 2);
g.drawString('Measuring...', g.getWidth() / 2, g.getHeight() / 2 - 10); g.drawString('Measuring...', g.getWidth() / 2, g.getHeight() / 2 - 10);
// Draw current heart rate if available // Draw current heart rate if available and not zero
if (currentHeartRate !== null && currentHeartRate > 0) {
g.setFont('6x8', 4); g.setFont('6x8', 4);
if (currentHeartRate !== null) {
g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 20); g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 20);
g.setFont('6x8', 1.6); g.setFont('6x8', 1.6);
g.drawString(' BPM', g.getWidth() / 2 + 42, g.getHeight() / 2 + 20); g.drawString(' BPM', g.getWidth() / 2 + 42, g.getHeight() / 2 + 20);
@ -83,6 +75,8 @@ function drawScreen(message) {
if (currentHeartRate !== null && currentHeartRate > 0) { if (currentHeartRate !== null && currentHeartRate > 0) {
g.setFont('6x8', 4); g.setFont('6x8', 4);
g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 10); g.drawString(currentHeartRate.toString(), g.getWidth() / 2, g.getHeight() / 2 + 10);
g.setFont('6x8', 1.6);
g.drawString(' BPM', g.getWidth() / 2 + 42, g.getHeight() / 2 + 12);
} else { } else {
g.setFont('6x8', 2); g.setFont('6x8', 2);
g.drawString('No data', g.getWidth() / 2, g.getHeight() / 2 + 10); g.drawString('No data', g.getWidth() / 2, g.getHeight() / 2 + 10);
@ -96,14 +90,78 @@ function drawScreen(message) {
} }
function saveDataToCSV() { function saveDataToCSV() {
let csvContent = "Timestamp,Heart Rate\n"; let date = new Date();
let dateStr = require("locale").date(date);
let timeStr = require("locale").time(date, 1);
let seconds = date.getSeconds();
let timestamp = `${dateStr} ${timeStr}:${seconds}`;
// Check if 10 seconds have passed since the last heart rate log
if (date.getTime() - lastHeartRateLogTimestamp >= 10 * 1000) {
logData.push({ timestamp: timestamp, heartRate: currentHeartRate });
lastHeartRateLogTimestamp = date.getTime(); // Update the last heart rate log timestamp
// Log data to CSV
let csvContent = "Timestamp,Heart Rate,HRV (ms)\n";
logData.forEach(entry => { logData.forEach(entry => {
csvContent += `${entry.timestamp},${entry.heartRate}\n`; if (entry.heartRate > 0) {
let hrv = hrvValues[entry.timestamp] || ""; // Get HRV value for the timestamp
csvContent += `${entry.timestamp},${entry.heartRate},${hrv}\n`;
}
}); });
require("Storage").write("heart_rate_data.csv", csvContent); require("Storage").write("heart_rate_data.csv", csvContent);
}
} }
setWatch(function() { function handleHeartRate(hrm) {
if (isMeasuring) {
currentHeartRate = hrm.bpm;
drawScreen();
// Log data to CSV
saveDataToCSV();
// Estimate RR intervals
let rrIntervals = estimateRRIntervals(bpmValues);
// Calculate HRV
calculateHRV(rrIntervals);
}
}
function estimateRRIntervals(rawData) {
let rrIntervals = [];
for (let i = 1; i < rawData.length; i++) {
let rrInterval = rawData[i] - rawData[i - 1];
rrIntervals.push(rrInterval);
}
return rrIntervals;
}
function calculateHRV(rawData) {
// Calculate HRV with SDNN method for each slot in hrvSlots
let sdnn = calcSDNN(rawData);
hrvValues[Date.now()] = sdnn; // Store HRV value with current timestamp
// Log HRV data if 5 minutes have elapsed
if (Date.now() - lastHeartRateLogTimestamp >= 5 * 60 * 1000) {
console.log("Recalculating HRV...");
saveDataToCSV(); // Save both heart rate and HRV data to the CSV file
lastHeartRateLogTimestamp = Date.now(); // Update the timestamp
}
}
function calcSDNN(rrIntervals) {
let sumOfDifferencesSquared = 0;
let meanRRInterval = rrIntervals.reduce((acc, val) => acc + val, 0) / rrIntervals.length;
rrIntervals.forEach(rr => {
sumOfDifferencesSquared += Math.pow(rr - meanRRInterval, 2);
});
let meanOfDifferencesSquared = sumOfDifferencesSquared / (rrIntervals.length - 1);
return Math.sqrt(meanOfDifferencesSquared);
}
setWatch(function () {
if (!isMeasuring) { if (!isMeasuring) {
startMeasure(); startMeasure();
} else { } else {