Skip to content

Add Relaxmedic scale support (icomon protocol 107) - #1441

Open
Caiofiga wants to merge 1 commit into
oliexdev:masterfrom
Caiofiga:relaxmedic-support
Open

Add Relaxmedic scale support (icomon protocol 107)#1441
Caiofiga wants to merge 1 commit into
oliexdev:masterfrom
Caiofiga:relaxmedic-support

Conversation

@Caiofiga

@Caiofiga Caiofiga commented Aug 4, 2026

Copy link
Copy Markdown

Adds a Handler for the Relaxmedic FG2015B-A scale, reverse-engineered by decompiling the vendor app, plus testing on the physical device.
Working: Weight; Body fat; Water; Muscle; Bone; Visceral fat; Protein; BMR; LBM.
Not Implemented: Offline history (Not supported);Segmented values.

It shares service 0xFFB0 and the 20-byte frame family with RobiS9Handler and RunstarR6Handler, but has fragmented frames, where byte 2 works as an index, with the result spanning 2 frames.

Attached is the btsnoop capture, filtered to this scale's traffic only.

Shares service 0xFFB0 and the 20-byte frame family with RobiS9Handler and
RunstarR6Handler, but differs in two ways.

Frames fragment: byte 2 is a fragment index, not a constant zero, and the
0xA3 result spans two frames. Every fragment contributes bytes[3..18], so
the byte after the fragment index is payload rather than a header byte to
skip. Both existing handlers in this family reject such frames outright.

The 0xBA profile is generated rather than replayed. RobiS9Handler replays
a captured handshake because its timestamp and token could not be
regenerated; this one is understood field by field, so it is built from
the openScale user. flags1 carries sex and age and is the only place they
are sent -- getting it wrong is silent, the scale simply computes for the
wrong person. The generated frame is byte-identical to a capture the scale
accepts.

Body composition comes from Wla25BodyComposition, ported from
ICBodyFatAlgorithmWLA25::calc in the vendor library: fat mass is a 13-term
linear regression over height, weight, the rounded BMI and all ten
impedances, and the rest follows from fat-free mass. Verified against the
vendor library over 240 randomised inputs spanning both clamp boundaries,
both impedance branches and both sexes -- exact on all ten fields.

Three roundings are load-bearing and each is worth a tenth of a unit: the
weight is rounded before anything else, the BMI fed into the regression is
rounded, and fat mass is rounded before fat-free mass is derived from it.
The rounding is half-up and computed in float32; everything else runs in
double, matching the library. Doing it all in Float shifts BMR by 1 kcal
in roughly one case in eighty.

compute() takes no sex parameter: this algorithm's body composition does
not depend on it, only metabolic age does.

Known limitation: bone mass can read 0.1 kg below the scale's own display.
The vendor app agrees with this code, and no algorithm the vendor library
ships reproduces the scale's combination of values, so the scale's
firmware appears to compute bone differently.

Metabolic age is implemented but not published -- ScaleMeasurement has no
field for it. EtekcityLib and HesleyHandler hit the same wall, one
computing it and the other reading it off the wire, both discarding it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant