Quickstart
Build an app that finds a Movesense sensor, connects to it and prints its heart rate.
The finished app connects to the first Movesense sensor it finds and prints the sensor's average heart rate after each heartbeat.
Prerequisites
- The setup in Installation. The example reuses the function from Request permissions at runtime.
- A Movesense MD, Movesense Active HR+ or Movesense HR2 sensor on its strap or electrodes. See Movesense Plus for the supported sensors.
- An Android phone or iPhone with Bluetooth turned on. Emulators and simulators do not work. See Installation.
Complete example
Add the plugins that the example uses to request the Android permissions:
permission_handler requires compileSdk 37 or later. See Request permissions at runtime.
Replace the contents of lib/main.dart with:
How it works
| Stage | What it does |
|---|---|
| 1. Permissions | Asks for access to nearby devices on Android 12 or later, and for location on Android 11 and lower. On iOS, the function returns true, because iOS asks for Bluetooth access by itself when the app starts. |
| 2. Scan | startScan() on a Movesense client scans for sensors that advertise the Movesense services. scanResults emits a MovesenseDevice for each advertisement, and drops the ones that arrive while nothing listens. The example listens before it starts the scan, stops the scan at the first sensor and prints scan errors with handleError(). |
| 3. Connect | connect() returns as soon as the platform accepts the command. When the sensor is connected, the plugin reads its device information and battery level, and statusEvents emits connected. The example listens to statusEvents before it calls connect(), so that it cannot miss the event. |
| 4. Stream | hr subscribes to the /Meas/HR resource through the Movesense mobile library (MDS). It emits a MovesenseHR after each heartbeat. Its average is the average heart rate in beats per minute, or 0.0 when the sensor has no valid heart rate. |
On iOS, a scan that starts before Bluetooth is ready reports an error, for example at the first launch, before the user allows Bluetooth access. The plugin then starts the scan by itself once Bluetooth is ready, so the example prints the error and keeps waiting.
The example waits forever when it finds no sensor or the sensor never connects. On Android, a failed connection sets the status to MovesenseDeviceStatus.error, which the example ignores. On iOS, a failed attempt reports no error, and the status stays connecting.
To give up after 30 seconds, replace stages 2 and 3, and import dart:async for TimeoutException:
The status leaves connecting when the sensor is ready, when the plugin reports an error, or when the connection drops. After an error or a timeout, disconnect() ends the attempt. For connection timeouts, see Connect to a sensor.
Run the app
Put on the sensor
Wear the sensor on its strap or electrodes, so that it can measure heart rate.
Start the app on your phone
On Android 12 or later, the app asks for access to nearby devices; on Android 11 and lower, it asks for location. On iOS, it asks for Bluetooth access. Allow them.
Check the console
When the sensor is connected, the console prints
Heart rate: <average> bpmafter each heartbeat. On iOS, the first launch may also print a scan error, because the scan starts before you allow Bluetooth access:The plugin starts the scan by itself once you allow access.
The plugin's example app has tabs that scan for sensors, connect to one, send MDS requests, subscribe to resources and show a log.
Troubleshooting
Keep the sensor close to the phone, check that Bluetooth is on, and run the app again. The example waits without a message until it finds a sensor and the sensor connects. Other causes:
- On Android 11 and lower, location is turned off in the phone's settings. See Installation.
- The connection failed or never completed. Add the timeouts from How it works.
- You used hot restart. It restarts the Dart code but not the plugin's native code, which keeps any connection to the sensor. Stop the app and run it again.
Turn on Bluetooth, and allow Bluetooth access for the app. On Android, run the app again; on iOS, the plugin then starts the scan by itself.
For each scan error and its cause, see Scan for sensors.
Read device.hr after the status is connected. The plugin checks the connection when you read a stream, not when you listen to it, so a stream read too early emits:
Move the sensor closer to the phone, and run the app again. To see why a connection failed on Android, print the connection events. See Follow all connections.
On iOS, a failed attempt reports no error, so only a timeout ends it.
Next steps
Connecting a device
Scan for sensors, connect to one and follow its status.
Sensor data
Stream heart rate, ECG, IMU and temperature data.
Device status
Read device information, battery level and system states.
MDS requests
Send requests and subscriptions to any Movesense resource.