---
title: "Getting Rowing Machine Data Into an App (2026)"
canonical: "https://aifitnessapi.com/devices/rowing-machine-data"
cluster: "Connected Devices"
primary_query: "get rowing machine data into app"
last_reviewed: "2026-08-14"
description: "Rower Data 0x2AD1 under FTMS 0x1826 is the standard path for ergometer metrics, but some vendors document their own interfaces and those docs win."
publisher: "AIFitnessAPI — independent, not sponsored"
cite_as: "\"Getting Rowing Machine Data Into an App (2026)\", AIFitnessAPI, https://aifitnessapi.com/devices/rowing-machine-data"
---

# Getting Rowing Machine Data Into an App (2026)

> The standard path for ergometer metrics is Rower Data, characteristic 0x2AD1, under the Bluetooth Fitness Machine Service 0x1826. A conforming rower advertises that service and streams its metrics through that characteristic, so one integration covers conforming machines from any vendor rather than one per brand. The exact contents and layout of the value are defined in the FTMS specification published by the Bluetooth SIG, which is the only thing worth parsing against. Some manufacturers also document their own proprietary interfaces alongside or instead of FTMS, and where that is the case the vendor's own documentation is the source of truth. Build the transport and session layers so a second data source can be added without rewriting them.

- Canonical: https://aifitnessapi.com/devices/rowing-machine-data
- Last reviewed: 2026-08-14
- Publisher: AIFitnessAPI (https://aifitnessapi.com) — independent, not sponsored
- Cite as: "Getting Rowing Machine Data Into an App (2026)", AIFitnessAPI, https://aifitnessapi.com/devices/rowing-machine-data

---

Rowing is the machine category where standardization and vendor-specific interfaces coexist most visibly, so it is worth being clear about which path you are on before you write any parsing code.

## Rower Data is the standard path

The Bluetooth SIG's public assigned-numbers registry lists the Fitness Machine Service as **0x1826** and the **Rower Data** characteristic as **0x2AD1**. A conforming ergometer advertises the service and streams through that characteristic, which is the whole point of [FTMS](/devices/ftms-fitness-machine-service): one integration against a profile instead of one per manufacturer.

The mechanics are identical to every other machine in the family. Scan filtered on the service UUID, connect, discover services and characteristics by UUID rather than by handle, enable notifications on the data characteristic, and treat disconnects as an ordinary event rather than an exception. If you have already built [treadmill](/devices/treadmill-app-integration) or [indoor bike](/devices/indoor-bike-trainer-integration) support, the only genuinely new code is parsing and the domain model.

## What a rowing app needs, without inventing a field list

Rowing apps are built around the stroke. Whatever your product does — pacing, splits, intervals, a session summary, a leaderboard — the metrics it presents are stroke-derived, and the session is a sequence of strokes rather than a continuous distance readout that happens to have a cadence attached.

We are not publishing a field list here. What Rower Data contains and how it is laid out is defined in the FTMS specification published by the Bluetooth SIG, and inventing that detail from memory is exactly how a plausible-looking parser ends up misreading one manufacturer's machine. Read the spec, then confirm empirically per model which of the optional content a given ergometer actually populates, and render what arrived rather than what you assumed would. A metric tile that shows a stale zero because the machine never sent that field is a bug your users will find before you do.

Capability discovery helps here too. **Fitness Machine Feature, 0x2ACC**, carries the machine's feature declaration, and the Supported Range characteristics — including **Supported Power Range, 0x2AD8**, and **Supported Heart Rate Range, 0x2AD7** — describe bounds. Read them at connection time and cache them per device. The cluster-wide rule applies: nothing in the interface that the connected machine has not confirmed.

## Vendor interfaces are real, and vendor docs win

Some manufacturers document their own interfaces alongside or instead of FTMS. We are making no claims about which ones, because that is exactly the kind of detail that changes with a firmware release and that we could not verify for this page. What we will say is structural.

If the ergometer you need to support documents a proprietary interface, that documentation is the source of truth for it — not a forum thread, not a reverse-engineering write-up, and not an analogy from FTMS. Read what the manufacturer publishes, note the date you read it, and re-check it when you next touch the integration.

And design for the possibility from the start. Keep the transport, the session model and the reconciliation layer independent of any one interface, so that adding a second source is a new adapter rather than a rewrite. In practice that means: a domain type of your own that neither FTMS nor any vendor type leaks into, a single place where raw notifications become domain events, and a session assembler that does not care which adapter produced them. This is judgement, but it is cheap judgement — the seam costs a morning up front and saves the rewrite that a second supported machine would otherwise force.

## Heart rate is a separate connection

Rowing apps almost always want heart rate alongside stroke data, and it does not come from the ergometer's service. Heart rate has its own standardized service, 0x180D, with its own connection, its own lifecycle and its own ways of failing — see [Bluetooth heart rate monitors](/devices/bluetooth-heart-rate-monitor) and [heart rate APIs](/data/heart-rate-api).

The consequence for your session model is that a rowing session is two independent streams that can drop independently. Decide now what a session looks like when the strap dies at minute twelve and the erg keeps streaming. Our answer would be: keep the session, mark the heart rate range unknown rather than zero, and never let a missing secondary stream discard a primary one.

## Sessions, storage and reconciliation

FTMS streams live; it does not hand you history. Your app builds the session record from the stream, which means you own the timestamping, the pause semantics, and the decision about whose midnight ends the day. See [time zones and day boundaries](/architecture/timezones-and-day-boundaries) for that decision, and [data quality monitoring](/architecture/data-quality-monitoring) for catching the sessions that come out implausible.

If your users also wear a watch, you now have two claims about the same twenty minutes. Pick one source of truth per metric per session and record it on the session — the design is in [deduplicating health data](/architecture/deduplicate-health-data). Rowing is a case where the machine is usually the better authority for work done and the wearable is the better authority for physiological response, but that is a judgement about your product, not a rule.

## Testing

A physical device is the only reliable test target for BLE, and ergometers are not standard desk furniture. So put a seam in front of the transport, capture real notification streams from whatever hardware you can get access to, and let those recordings drive parsing, session assembly, gap handling and reconnect logic in CI. Then use scarce hardware time for the things fixtures cannot answer: which fields a given model populates, how it behaves when a user stops mid-piece, and whether it survives a reconnect cleanly. [Testing BLE fitness devices](/devices/testing-ble-fitness-devices), [mocking wearable data](/test/mock-wearable-data) and [device lab and CI](/test/device-lab-and-ci) cover the pattern.

One more limit worth naming honestly: the first ergometer you support will teach you things about the profile that no specification reading would have. Budget for the second machine to be cheaper than the first only if you built the adapter seam. If you did not, it will cost the same again.

## FAQ

### Which Bluetooth characteristic carries rowing machine data under FTMS?

Rower Data, characteristic 0x2AD1, under the Fitness Machine Service 0x1826, per the Bluetooth SIG's assigned-numbers registry. A conforming ergometer advertises the service and streams its metrics through that characteristic, so the integration is against the profile rather than a manufacturer. The exact contents and layout of the value are defined in the FTMS specification published by the Bluetooth SIG, and that document is what your parser should be written against. Pair it with Fitness Machine Feature 0x2ACC and the Supported Range characteristics, read at connection time, so your interface only shows what this machine has confirmed.

[Permalink](https://aifitnessapi.com/devices/rowing-machine-data#faq-1)

### Why does my rowing machine expose a proprietary interface instead of FTMS Rower Data?

Some manufacturers document their own interfaces alongside or instead of the standard service, and we make no claims about which ones, because that changes with firmware and we could not verify it for this page. The rule that holds is about authority: where a vendor documents its own interface, that documentation is the source of truth for it, not a forum thread or a reverse-engineering write-up. Note the date you read it and re-check when you next touch the integration. Design for it from the start by keeping your transport, domain model and session assembly independent of any one interface, so a second source is a new adapter rather than a rewrite.

[Permalink](https://aifitnessapi.com/devices/rowing-machine-data#faq-2)

### How should a rowing app record a session when the ergometer only streams live data?

Build the session record yourself, because FTMS streams live and hands you no history. That means you own the timestamping, the pause semantics and the day-boundary decision about whose midnight ends the day. Model the session as a sequence of stroke-derived events from the data characteristic, and treat heart rate as an independent stream on service 0x180D that can drop without ending the session. When a secondary stream disappears, mark that range unknown rather than writing zeros, and if the user also wore a watch, pick one source of truth per metric and record which source the session used.

[Permalink](https://aifitnessapi.com/devices/rowing-machine-data#faq-3)
