1. Home
  2. Dashboard
  3. Create
  4. Questionnaires
  5. Advanced Items
  6. Wearables (Garmin Direct Integration)
  1. Home
  2. Cool stuff
  3. Wearables (Garmin Direct Integration)

Wearables (Garmin Direct Integration)

The Direct Garmin integration in m-Path enables researchers to collect continuous physiological measurements directly from participants’ Garmin smartwatches. Unlike the standard wearable integration, this feature provides direct communication between the m-Path Sense app and Garmin devices, allowing for higher-resolution data collection and trigger-based interventions.

The Direct Garmin integration is available as an add-on. Contact us to enable this feature

Key Features

  • Raw data collection with customizable sampling rates (measure and device dependent).
  • Privacy-friendly: Participant data is transferred directly from the watch to the m-Path Sense app, no third-party integrations or apps required.
  • Trigger-based interventions: Enables you to create conditions that trigger notifications or questionnaires based on Garmin data.

If you need high-resolution Garmin data but don’t need the app to run continuously in the background or trigger interventions based on sensor values, the Garmin Lite integration may be a better fit. It uses a lightweight sync item without requiring background sensing. Not sure which integration fits your study? check here for an overview of the different smartwatch integrations possible in m-Path

1. Setting Up Direct Garmin Integration

Create a Garmin sensing setup

To begin collecting data from Garmin devices, create an interaction and add a Sensing setup item from the m-Path dashboard. Then enable the Garmin sensors you want for your study.

The “Garmin High Heart Rate and High Stress Trigger” item is available as an example in the interaction library. For background information on sensing concepts and configuration, see the Mobile Sensing manual.

Garmin sensing setup screenshot

Configure sampling rates

Each Garmin sensor can be configured with a sampling interval (seconds) that determines how often entries are logged on the watch. For example, setting the interval to 1 for heart rate logs a value every second.

Sampling rate configuration in Garmin sensing setup

Valid sampling intervals

Not all measures support configurable sampling. The table below lists valid intervals and limitations.

MeasureDefaultMinimumMaximumNotes
BBI (Beat-to-Beat Interval)N/AN/AN/ANo processing interval required; all IBI values recorded by default.
Enhanced BBIN/AN/AN/ANo processing interval required; all IBI values recorded by default.
Zero Crossing30s30s3600sIntervals must be multiples of 30 seconds.
Steps60s60s60sLocked at 1 minute.
Stress10s1s3600sIntervals below 10 seconds may not update between recordings (device dependent).
Heart Rate30s1s3600s
SpO230s1s3600sIntervals below 10 seconds may not update between recordings (device dependent).
Respiration10s1s3600sIntervals below 10 seconds may not update between recordings (device dependent).
Skin Temperature1s3600s
Wrist StatusInterval field is ignored. Data is generated every 60 seconds and whenever the wrist status changes.
Actigraphy 130s1s3600sAny integer from 1–30s, or any multiple of 30s up to 3600s. Independently configurable from Actigraphy 2 and 3. See below for more details on configuration.
Actigraphy 230s1s3600sSame valid values as Actigraphy 1. Independently configurable.
Actigraphy 330s1s3600sSame valid values as Actigraphy 1. Independently configurable.
AccelerometerN/AN/AN/ARaw accelerometer at 25Hz. Not configurable. Very high data rate. Requires frequent sync and can significantly affect battery life.
GyroscopeN/AN/AN/ARaw gyroscope at 32Hz. Not configurable. Very high data rate. Requires frequent sync and can significantly affect battery life.

Extra configuration

Some measures support additional configuration options beyond the sampling interval. These are set in the sensing setup and affect how data is collected or processed.

Accelerometer

FieldDescription
allowSleepWhen enabled, accelerometer logging is suspended if the acceleration magnitude does not exceed 100 mG for 30 consecutive seconds. Logging resumes automatically when motion above this threshold is detected.

Actigraphy

The Direct Garmin integration supports three independent actigraphy streams: ACTIGRAPHY_1, ACTIGRAPHY_2, and ACTIGRAPHY_3. Each is configured separately in the sensing setup with its own thresholds. The instance field in the exported data identifies which configuration produced each record.

The following configuration fields are available per actigraphy instance:

FieldDescription
zcThresholdMilli-G threshold for zero crossing count. The acceleration magnitude must cross this value for a crossing to be counted in zeroCrossingCount.
tatThresholdMilli-G threshold for time-above-threshold. The magnitude must exceed this value to accumulate time in timeAboveThreshold.
energyThresholdMilli-G threshold for total energy accumulation. Samples below this value are excluded from totalEnergy.
filterBeforeMagnitudeWhen enabled: each axis (X, Y, Z) is filtered independently before the vector magnitude is computed. When disabled: magnitude is computed from raw axes first, then the scalar signal is filtered. Leave unconfigured to use the device default.

Zero Crossing

The deadband filter controls which zero crossings are counted by requiring the signal to deviate from the average by a minimum amount before a crossing is recorded.

FieldDescription
deadbandValueMilli-G threshold the signal must deviate from the average for a zero crossing to be counted. A positive integer in milli-G.
deadbandEnabledWhether the deadband filter is active. When disabled, the deadband output field will be 0.

Set up Garmin triggers

You can create triggers based on incoming Garmin data. To configure triggers:

  1. Add a Sensing trigger as an underlying item for the sensing setup. Your setup should look like this:
Sensing setup with underlying sensing trigger item
  1. Select a Garmin trigger type:
Choosing a Garmin trigger type
  1. Define the trigger conditions using computations (see Computation item (pseudo R)).

Available extract labels for Garmin data

When writing trigger computations, you can extract specific data using the extract(newSensorData, 'label') function. Below are all available extract labels organized by measurement type:

Heart Rate
  • heartRates – Vector of heart rate values (BPM)
  • heartRateTimestamps – Vector of timestamps for heart rate measurements
  • heartRateStatuses – Vector of status strings (e.g., “locked”, “unlocked”)
Stress
  • stressValues – Vector of stress scores (0-100)
  • stressTimestamps – Vector of timestamps for stress measurements
  • stressStatuses – Vector of status strings
Steps
  • stepValues – Vector of step counts per interval
  • totalStepsPerEntry – Vector of cumulative steps since midnight
  • stepsStartTimestamps – Vector of interval start timestamps
  • stepsEndTimestamps – Vector of interval end timestamps
BBI (Beat-to-Beat Interval)
  • bbiValues – Vector of BBI values in milliseconds
  • bbiTimestamps – Vector of timestamps for BBI measurements
Enhanced BBI
  • enhancedBbiValues – Vector of enhanced BBI values in milliseconds
  • enhancedBbiGapDurations – Vector of gap durations in milliseconds
  • enhancedBbiTimestamps – Vector of timestamps
  • enhancedBbiStatuses – Vector of status strings
Respiration
  • respirationRates – Vector of breaths per minute
  • respirationTimestamps – Vector of timestamps
  • respirationStatuses – Vector of status strings
SpO2 (Blood Oxygen)
  • spo2Values – Vector of SpO2 percentage readings
  • spo2Timestamps – Vector of timestamps
Accelerometer
  • accelerometerXValues – Vector of X-axis values in milli-g
  • accelerometerYValues – Vector of Y-axis values in milli-g
  • accelerometerZValues – Vector of Z-axis values in milli-g
  • accelerometerTimestamps – Vector of timestamps
Gyroscope
  • gyroscopeXValues – Vector of X-axis values in degrees/second
  • gyroscopeYValues – Vector of Y-axis values in degrees/second
  • gyroscopeZValues – Vector of Z-axis values in degrees/second
  • gyroscopeTimestamps – Vector of timestamps
Skin Temperature
  • skinTemperatureValues – Vector of temperature values in °C
  • skinTemperatureTimestamps – Vector of timestamps
  • skinTemperatureStatuses – Vector of status strings
Wrist Status
  • wristStatuses – Vector of wrist status strings (on-wrist/off-wrist)
  • wristStatusTimestamps – Vector of timestamps

Example: Simple heart rate trigger

Trigger when the average heart rate in the new Garmin data exceeds a threshold:

doTrigger = 0

# Extract heart rate data
heartRates = extract(newSensorData, 'heartRates')

# Handle missing data (e.g., watch off-wrist)
if(is.na(mean(heartRates))){
    heartRates = 0
}

# Calculate average and trigger
avgHR = nanmean(heartRates)

if(avgHR > 80){
    doTrigger = 1
}

Then configure the trigger in the builder:

Trigger configuration in builder

After saving your sensing setup + trigger, it’s ready to send to participants via an interaction (e.g., as part of an intake questionnaire).

Example: Combine multiple Garmin measures in one trigger

You can combine measures (e.g., heart rate + stress) to trigger when multiple conditions are met:

doTrigger = 0

# Extract heart rate
heartRates = extract(newSensorData, 'heartRates')

# Extract stress
stressValues = extract(newSensorData, 'stressValues')

# Handle missing data
if(is.na(mean(heartRates))){
    heartRates = 0
}
if(is.na(mean(stressValues))){
    stressValues = 0
}

# Check combined conditions
if(length(heartRates) > 0 && length(stressValues) > 0){
    avgHR = mean(heartRates)
    avgStress = mean(stressValues)

    # Trigger if BOTH are high
    if(avgHR > 50 && avgStress > 30){
        doTrigger = 1
    }
}

Example: Using entry counts for data quality checks

Check if enough data is available before triggering:

doTrigger = 0

# Get the count of heart rate measurements
hrCount = extract(newSensorData, 'heartRateCount')

# Only proceed if we have sufficient data
if(hrCount > 10){
    heartRates = extract(newSensorData, 'heartRates')
    avgHR = mean(heartRates)
    
    if(avgHR > 100){
        doTrigger = 1
    }
}

2. Participant Setup and Pairing

Send the sensing setup to participants

Once configured, send the sensing setup item to participants through an interaction (this can be part of an intake questionnaire). When participants encounter the sensing setup item, they are guided to pair their Garmin watch.

Bluetooth pairing process

The pairing process uses BLE to establish a direct connection between the participant’s phone and their Garmin watch.

Pairing screen in m-Path Sense

The m-Path Sense app scans for nearby Garmin devices:

Scanning for Garmin devices

Participants select their watch from the list of available devices and the app establishes a connection with the watch

Connected watch confirmation
Example: scanning state
Wearable device management screen
Example: paired state

After pairing, participants can continue the interaction.


Important: The app needs to be restarted to begin sensing with the correct setup. After the questionnaire finishes, participants will be prompted to restart.

Pre-pairing checklist

BLE pairing can fail for several reasons. Before attempting to pair, ensure that:

  • The Garmin watch is not connected to another phone or device.
  • Bluetooth is enabled on the participant’s phone.
  • The watch is in pairing mode.
  • If pairing fails, consult the pairing issues guide.

3. Data Collection and Monitoring

Background sensing

Once paired successfully, the m-Path Sense app continuously collects data from the Garmin watch in the background. Participants do not need to keep the app open for data collection to occur.

Like other sensors in m-Path Sense, direct Garmin sensing runs continuously until:

  • The app is killed by the operating system (iOS or Android).
  • The participant manually closes the app.
  • Bluetooth connection fails (disabled by the user, watch is dead/out of range)

Data sync and chunking behavior

The m-Path Sense app automatically syncs data from the Garmin watch at regular intervals. When syncing data after a large time gap (for example, when the app has been closed for several hours), the system automatically splits the data into 15-minute chunks to ensure reliable processing and upload.

This means that a single sync session may produce multiple measurement entries in your exported data, each covering a 15-minute window. This chunking behavior is automatic and requires no configuration.

Restart reminders

If the app stops gathering data (for example, if it is killed by the operating system), participants will receive a reminder notification to resume the app. This works the same as other m-Path Sense sensors.

You can configure reminder notifications in the sensing settings.

4. Exporting and Analyzing Data

Data export

Data collected through Direct Garmin integration is exported the same way as other Mobile Sensing data. Data is uploaded from the participant’s phone to a pCloud or OneDrive location configured in the researcher dashboard (see Adding a cloud storage location for client file uploads).

Data structure

Garmin sensing data is exported in JSON format, similar to other m-Path Sense data. Each measurement includes a sensorStartTime and a data object containing metadata (time window, entry counts) and the recorded samples.

{
  "sensorStartTime": 1765198435067150,
  "data": {
    "__type": "dk.cachet.carp.garminalllogsdata",
    "fromTime": "2025-12-08T13:51:50.101",
    "toTime": "2025-12-08T13:53:50.102091",
    "entryCounts": {
      "heartRate": 118,
      "stress": 2,
      "steps": 2,
      "bbi": 76,
      "enhancedBbi": 150,
      "respiration": 2,
      "spo2": 2,
      "accelerometer": 2150,
      "gyroscope": 0,
      "wristStatus": 0,
      "zeroCrossing": 2,
      "skinTemperature": 0,
      "actigraphy1": 2,
      "actigraphy2": 2,
      "actigraphy3": 2
    },
    "heartRate": [
      {
        "macAddress": "E6:82:85:38:8C:A9",
        "timestamp": 1765198310000,
        "beatsPerMinute": 73,
        "status": "locked"
      }
    ]
  }
}

Note: macAddress corresponds to the watch MAC address on Android devices. On iOS, this field contains a UUID instead (Apple does not expose MAC addresses for device identification). All measurement types include the macAddress field for device identification.

Garmin Measurement Types

AccelerometerData

Captures three-axis acceleration data from the device’s accelerometer.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp for the accelerometer sample
  • xValue (Double): X-axis in milli-g
  • yValue (Double): Y-axis in milli-g
  • zValue (Double): Z-axis in milli-g

ActigraphyData

Processed activity metrics derived from accelerometer data over a configured interval. There are three independent actigraphy streams (ACTIGRAPHY_1, ACTIGRAPHY_2, ACTIGRAPHY_3), each configured separately in the sensing setup. The instance field in each output record identifies which stream produced it.

FieldTypeDescription
macAddressStringDevice MAC address (Android) or UUID (iOS)
instanceStringIdentifies which actigraphy stream produced this record. One of "actigraphy1", "actigraphy2", or "actigraphy3".
startTimestampDateStart of the processing interval (seconds precision)
endTimestampDateEnd of the processing interval (seconds precision)
zeroCrossingCountIntNumber of times the acceleration magnitude crossed the configured zcThreshold during the interval
timeAboveThresholdDoubleSeconds the acceleration magnitude was above the configured tatThreshold during the interval
totalEnergyIntAccumulated acceleration magnitude over the interval. Samples below the configured energyThreshold are not accumulated. Units: milli-G

BBIData

Beat-to-beat interval (time between consecutive heartbeats).

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp
  • bbi (Int): Interval in milliseconds

EnhancedBBIData

Enhanced beat-to-beat interval data with status information and gap detection.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp
  • bbi (Int): Interval (ms) if valid; otherwise 0
  • gapDuration (Int): Gap duration (ms) when there is a gap in the heart rate signal; otherwise 0
  • status (String): Status of the entry (e.g., “valid”, “gap”)

GyroscopeData

Captures three-axis rotational data from the gyroscope.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp
  • xValue (Double): X-axis in degrees/second
  • yValue (Double): Y-axis in degrees/second
  • zValue (Double): Z-axis in degrees/second

HeartRateData

Heart rate measurements (beats per minute).

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp (seconds precision)
  • beatsPerMinute (Int): BPM value
  • status (String): Sensor status (e.g., “locked”, “unlocked”)

RespirationData

Breathing rate (breaths per minute).

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp (seconds precision)
  • breathsPerMinute (Double): BPM value (0.0 if unavailable, check status)
  • status (String): Measurement status

SPO2Data

Blood oxygen saturation (%).

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp (seconds precision)
  • spo2Reading (Int): SpO2 percentage

SkinTemperatureData

Skin temperature (°C).

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp (seconds precision)
  • temperature (Double): Temperature in °C (0–65°C, 0.0 if unavailable)
  • status (String): Measurement status

StepData

Step counts over time intervals.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • startTimestamp (Date): Start timestamp (seconds precision)
  • endTimestamp (Date): End timestamp (seconds precision)
  • stepCount (Int): Steps in the interval
  • totalSteps (Int): Steps since midnight up to endTimestamp

StressData

Stress scores derived from HRV and related metrics.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp (seconds precision)
  • stressScore (Int): 0–100 (≤25 indicates resting, 0 if unavailable)
  • status (String): Measurement status

WristStatusData

Indicates whether the watch is currently worn.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • timestamp (Date): Timestamp
  • status (String): On-wrist / off-wrist

Note: Wrist status is generated every minute and whenever the wrist status changes. The sampling interval field is ignored for this measure.

ZeroCrossingData

Activity metrics based on acceleration patterns and energy expenditure.

  • macAddress (String): Device MAC address (Android) or UUID (iOS)
  • startTimestamp (Date): Start timestamp (seconds precision)
  • endTimestamp (Date): End timestamp (seconds precision)
  • zeroCrossingCount (Int): Number of times the total acceleration magnitude transitions from above to below the average (or vice versa) during the interval. If deadband is active, the signal must also deviate from the average by at least the deadband value for the transition to count.
  • totalEnergy (Int): Sum of the RMS deviation of total acceleration from 1G, computed over rolling 8-second windows (updated every 2 seconds) across the configured interval.
  • deadband (Int?): The milli-G deviation threshold applied during this interval. Reflects the configured deadbandValue when deadband is enabled; 0 when deadband is disabled. See Extra configuration for setup details.

Troubleshooting pairing issues

Watch not visible during scanning

  • Confirm the watch is not already paired with another device.
  • Toggle Bluetooth off and on on the phone.
  • If the problem persists, perform a factory reset on the Garmin watch and try again.

Pairing process fails

If pairing fails or gets stuck:

  1. Restart the app and try connecting from the Wearable device management screen.
  2. If it still fails:
    • Close the m-Path Sense app completely.
    • Open the phone’s system Bluetooth settings. If the Garmin device appears as paired, Forget/Remove it.
    • Toggle Bluetooth off and on.
    • Reopen m-Path Sense and retry pairing from Wearable device management.

Connection lost after initial pairing

If a watch was successfully paired but fails to reconnect on a later app start, m-Path Sense will automatically prompt the participant to pair again and show the connection screen.

Updated on April 2, 2026
Was this article helpful?

Related Articles

Need Support?
Can't find the answer you're looking for?
Contact Support