Read heart rate
C11 · Teslasuit v. 4.7+ · SDK 2.5.1+
Read live heart rate from a Teslasuit photoplethysmography (PPG) node: start raw streaming and print the heart rate as each reading arrives.
Code for heart rate data#
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ts_api/ts_types.h>
#ifdef _WIN32
#include <Windows.h>
#elif defined(__APPLE__) || defined(__linux__)
#include <dlfcn.h>
#include <unistd.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define API_FUNCTION_NAME(name) name##_func_t
#define DECLARE_API_FUNCTION(ret, name, args) \
typedef ret(*API_FUNCTION_NAME(name)) args; \
static API_FUNCTION_NAME(name) name
#define LOAD_API_FUNCTION(lib, name) \
do { \
name = (API_FUNCTION_NAME(name))api_library_get_function(lib, #name); \
if (name == NULL) \
return false; \
} while (0)
typedef void *SharedLibrary;
static void *api_library_get_function(SharedLibrary lib,
const char *function_name) {
#ifdef _WIN32
return (void *)GetProcAddress((HMODULE)lib, function_name);
#elif defined(__APPLE__) || defined(__linux__)
return dlsym(lib, function_name);
#endif
}
static void sleep_ms(int ms) {
#ifdef _WIN32
Sleep(ms);
#elif defined(__APPLE__) || defined(__linux__)
usleep(ms * 1000);
#endif
}
// device/session
DECLARE_API_FUNCTION(TsStatusCode, ts_initialize, ());
DECLARE_API_FUNCTION(void, ts_uninitialize, ());
DECLARE_API_FUNCTION(TsStatusCode, ts_get_device_list,
(TsDevice *, uint32_t *));
DECLARE_API_FUNCTION(TsDeviceHandle *, ts_device_open, (TsDevice *));
DECLARE_API_FUNCTION(const char *, ts_device_get_name, (TsDeviceHandle *));
DECLARE_API_FUNCTION(void, ts_device_close, (TsDeviceHandle *));
DECLARE_API_FUNCTION(const char *, ts_get_status_code_message, (TsStatusCode));
// ppg
DECLARE_API_FUNCTION(TsStatusCode, ts_ppg_set_update_callback,
(TsDeviceHandle *, TsPpgUpdatedCallback, void *));
DECLARE_API_FUNCTION(TsStatusCode, ts_ppg_start_streaming, (TsDeviceHandle *));
DECLARE_API_FUNCTION(TsStatusCode, ts_ppg_stop_streaming, (TsDeviceHandle *));
DECLARE_API_FUNCTION(TsStatusCode, ts_ppg_get_heart_rate,
(const TsPpgData, uint8_t, uint32_t *));
static bool load_api_functions(SharedLibrary lib) {
// device/session
LOAD_API_FUNCTION(lib, ts_initialize);
LOAD_API_FUNCTION(lib, ts_uninitialize);
LOAD_API_FUNCTION(lib, ts_get_device_list);
LOAD_API_FUNCTION(lib, ts_device_open);
LOAD_API_FUNCTION(lib, ts_device_get_name);
LOAD_API_FUNCTION(lib, ts_device_close);
LOAD_API_FUNCTION(lib, ts_get_status_code_message);
// ppg
LOAD_API_FUNCTION(lib, ts_ppg_set_update_callback);
LOAD_API_FUNCTION(lib, ts_ppg_start_streaming);
LOAD_API_FUNCTION(lib, ts_ppg_stop_streaming);
LOAD_API_FUNCTION(lib, ts_ppg_get_heart_rate);
return true;
}
static bool check_code(TsStatusCode code) {
if (code != 0) {
printf("Error: %s\n", ts_get_status_code_message(code));
return false;
}
return true;
}
static void heart_rate_callback(TsDeviceHandle *dev, const TsPpgData ppg_data,
void *user_data) {
(void)dev;
(void)user_data;
uint32_t heart_rate = 0;
// Node 0: this device has one PPG sensor node, so it's always the suit
// itself.
if (check_code(ts_ppg_get_heart_rate(ppg_data, 0, &heart_rate))) {
printf("Heart rate: %u\n", heart_rate);
}
}
static void run(TsDeviceHandle *dev) {
check_code(ts_ppg_set_update_callback(dev, heart_rate_callback, NULL));
if (check_code(ts_ppg_start_streaming(dev))) {
printf("Press any key to end\n");
(void)getchar();
ts_ppg_stop_streaming(dev);
}
}
#ifdef __cplusplus
}
#endif
int main() {
const char *api_path = getenv("TESLASUIT_API_LIB_PATH");
if (api_path == NULL) {
printf("Error: environment variable TESLASUIT_API_LIB_PATH not set\n");
return 0;
}
#ifdef _WIN32
SharedLibrary lib = (SharedLibrary)LoadLibraryEx(
api_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#elif defined(__APPLE__) || defined(__linux__)
SharedLibrary lib = (SharedLibrary)dlopen(api_path, RTLD_NOW | RTLD_LOCAL);
#endif
if (lib == NULL) {
printf("Error: library was not found\n");
return 0;
}
if (!load_api_functions(lib)) {
printf("Error: failed to load library functions\n");
goto unload;
}
if (!check_code(ts_initialize())) {
printf("Error: failed to initialize API\n");
// Nothing to uninitialize: it never successfully initialized.
goto unload;
}
TsDevice device;
uint32_t device_count = 0;
while (device_count == 0) {
printf("Waiting for a device...\n");
device_count = 1;
ts_get_device_list(&device, &device_count);
sleep_ms(100);
}
TsDeviceHandle *dev = ts_device_open(&device);
if (dev == NULL) {
printf("Error: failed to get device\n");
goto deinitialize;
}
printf("Using device: %s\n", ts_device_get_name(dev));
run(dev);
ts_device_close(dev);
deinitialize:
ts_uninitialize();
unload:
#ifdef _WIN32
FreeLibrary((HMODULE)lib);
#elif defined(__APPLE__) || defined(__linux__)
dlclose(lib);
#endif
return 0;
}Expected output#
Waiting for a device...
Using device: Teslasuit XR-5
Press any key to end
Heart rate: 72
Heart rate: 74
...What to read next#
Explore these references and guides to build on this example and get the most out of Teslasuit PPG features:
Essential API references#
- Biometry API Reference: Full reference for
ts_ppg_set_update_callbackandts_ppg_get_heart_rateused in this example. - Common Types — PPG: Reference for the raw, HRV, and heart-rate data types.
Practical guides & examples#
- Measure HRV: The companion PPG example for reading heart rate variability.
- Examples Overview: Browse the full set of runnable examples.
Deeper dives & broader concepts#
- PPG Main Concept: The conceptual background behind the photoplethysmography subsystem.
- Teslasuit Main Concepts: Fundamental articles explaining Teslasuit technology and how PPG fits within the larger suite of subsystems.
