ppg-js docs

Quick start with ppg-js

Start ppg-js with a script tag, npm, or a reusable React hook.

Quick start

Choose the setup that matches your app. In every case, call start() from a button click or tap.

<script src="https://unpkg.com/@sontakey/ppg-js/dist/index.global.js"></script>
<script>
  const ppg = new PPG.PPG();
  ppg.addEventListener('metrics', (e) => {
    console.log(e.detail.heartRate, e.detail.quality);
  });
  // Camera permission needs a user gesture.
  document.querySelector('#start').onclick = () => ppg.start();
</script>
import { PPG } from '@sontakey/ppg-js';

const ppg = new PPG();

ppg.addEventListener('state', (e) => {
  // NO_FINGER -> SETTLING -> MEASURING
  console.log(e.detail.state, e.detail.reason);
});

ppg.addEventListener('metrics', (e) => {
  const m = e.detail;
  if (!m.quality.good) {
    console.log('not ready:', m.quality.reason, m.guidanceMessage);
    return;
  }
  console.log(`${m.heartRate} bpm, RMSSD ${m.rmssd.toFixed(0)} ms`);
});

// Camera, wake lock, and motion permission need a user gesture.
button.onclick = () => ppg.start();
import { useEffect, useRef, useState } from 'react';
import { PPG } from '@sontakey/ppg-js';

export function usePulse() {
  const ppgRef = useRef<PPG | null>(null);
  const [bpm, setBpm] = useState(0);
  const [status, setStatus] = useState('Tap start, then cover the camera');

  useEffect(() => {
    const ppg = new PPG();
    ppgRef.current = ppg;
    ppg.addEventListener('metrics', (e) => {
      const m = e.detail;
      if (m.quality.good) setBpm(m.heartRate);
      else setStatus(m.guidanceMessage);
    });
    return () => ppg.destroy();
  }, []);

  // Call from a button's onClick.
  const start = () => ppgRef.current?.start();
  return { bpm, status, start };
}

After a session

import { hrv } from '@sontakey/ppg-js';

const beats = ppg.getTachogram({ goodOnly: true, hrvOnly: true })
  .filter((beat) => beat.valid);
const report = hrv.analyzeHRV(beats, {
  rmssdFloorMs: ppg.getMetrics().rmssdFloorMs,
});