Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Getting real-time Heart Rate Variability (HRV) from FitBit Versa2 in addition to (BPM)

Hello, 

I've implemented a custom app for FitBit Versa2 to send real-time heart rate from the watch to my local server.. It seems that the kind of data I got now is beats per minute (BPM).. I want Heart Rate Variability (HRV) as well, which is expressed in milliseconds, for research purposes.. 

Would you please help?

This is my app (.js):

import { me as appbit } from "appbit";
import { HeartRateSensor } from "heart-rate";
import * as messaging from "messaging";
import { display } from "display"; 
import document from "document"; 

appbit.appTimeoutEnabled = false; 
display.autoOff = false; // keep screen on
console.log("APP STARTED");

// --------- Bouncing dot setup  ----------
const dot = document.getElementById("dot");
let x = 10;
let direction = 1;

if (dot) {
setInterval(() => {
// Move dot back and forth
x += direction * 4; //it was 2 but i want it faster i put 4
if (x > 140 || x < 0) direction *= -1;
dot.cx = x;
}, 1000 / 30); // ~30 FPS
} else {
console.log("Dot element not found in index.gui");
}

// --------- Heart rate setup ----------
if (appbit.permissions.granted("access_heart_rate")) {
const hrm = new HeartRateSensor();

hrm.addEventListener("reading", () => {
console.log(`HR: ${hrm.heartRate}`);

if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
messaging.peerSocket.send({
heartRate: hrm.heartRate,
timestamp: Date.now()
});
}
});

hrm.start();
} else {
console.log("No heart rate permission");
}

This is my server code .js:

const WebSocket = require("ws");
const fs = require("fs");
const path = require("path");

const server = new WebSocket.Server({ port: 9090 });

// Folder for all CSV files
const dataFolder = "HeartRateData";
if (!fs.existsSync(dataFolder)) {
fs.mkdirSync(dataFolder);
}

function getCsvFileName(date) {
// Format: HeartRateData/hr_log_YYYY-MM-DD.csv
const yyyy = date.getFullYear();
const mm = String(date.getMonth() + 1).padStart(2, "0");
const dd = String(date.getDate()).padStart(2, "0");
return path.join(dataFolder, `hr_log_${yyyy}-${mm}-${dd}.csv`);
}

server.on("connection", (ws) => {
console.log("PC Server: client connected");

ws.on("message", (msg) => {
let dataString = msg.toString();
let dataObj = JSON.parse(dataString);

const { heartRate, timestamp } = dataObj;

const date = new Date(timestamp);
const formattedTime = `${date.getDate().toString().padStart(2, "0")}/` +
`${(date.getMonth() + 1).toString().padStart(2, "0")}/` +
`${date.getFullYear()} ` +
`${date.getHours().toString().padStart(2, "0")}:` +
`${date.getMinutes().toString().padStart(2, "0")}:` +
`${date.getSeconds().toString().padStart(2, "0")}`;

const csvFile = getCsvFileName(date);

// Write header if file doesn't exist
if (!fs.existsSync(csvFile)) {
fs.writeFileSync(csvFile, "time,timestamp,heartrate\n");
}

// Append new line
fs.appendFileSync(csvFile, `"${formattedTime}",${timestamp},${heartRate}\n`);

console.log(`Logged: ${formattedTime}, ${timestamp}, ${heartRate} -> ${csvFile}`);
});
});

Best Answer
0 Votes
2 REPLIES 2

The SDK doesn't provide HRV. I think you can get it from the Web API, but not in real time.

You may be able to fudge something similar by converting HR to ms/beat, and then comparing sequences of values.

Peter McLennan
Gondwana Software
Best Answer

Thank you very much.. I'll try

Best Answer
0 Votes