09-15-2025 04:07
09-15-2025 04:07
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 Answer09-15-2025 13:04
Gold Fitbit Product Experts share support knowledge on the forums and advocate for the betterment of Fitbit products and services. Learn more
09-15-2025 13:04
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.
09-16-2025 03:59
09-16-2025 03:59
Thank you very much.. I'll try
Best Answer