Added impedance support for Huawei AH/CH 100 - #1497
Conversation
Enabled the impedance reading in the handler and added all the fields that derive from the impedance. Tested the changes in my phone with HUAWEI AH100 and they work. Please let me know if these changes make it into the play store app by emailing me in: voikiaetsi@gmail.com
There was a problem hiding this comment.
🟡 Changes recommended
The new impedance-derived calculations need additional input validation/guarding (e.g., unset/invalid user height/age and sane impedance range) to avoid publishing nonsensical derived values.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR enables impedance handling for Huawei AH/CH 100 measurements and derives additional body-composition fields from impedance using the shared StandardImpedanceLib, integrating those computed values into published ScaleMeasurements.
Changes:
- Passes
ScaleUserthrough the decode/publish pipeline so impedance-derived metrics can be calculated with user profile data. - When impedance is present, computes and populates
water,muscle,bone,bmr, andlbmviaStandardImpedanceLib.
File summaries
| File | Description |
|---|---|
| android_app/app/src/main/java/com/health/openscale/core/bluetooth/scales/HuaweiAhCh100Handler.kt | Wires impedance into measurement publishing and derives additional metrics from impedance using StandardImpedanceLib. |
Review details
Suppressed comments (1)
android_app/app/src/main/java/com/health/openscale/core/bluetooth/scales/HuaweiAhCh100Handler.kt:346
- This change introduces new impedance-derived fields (water/muscle/bone/bmr/lbm) in the Huawei handler, but the existing HuaweiAhCh100HandlerTest suite only exercises the wire-protocol primitives and doesn't cover the derived body-composition mapping. Adding a small unit test for the new mapping/guards would help prevent regressions (e.g., invalid height/age or out-of-range impedance producing implausible values).
val lib = StandardImpedanceLib(
gender = user.gender,
age = user.age,
weightKg = m.weightKg.toDouble(),
heightM = user.bodyHeight / 100.0,
impedance = m.impedanceOhm.toDouble(),
)
this.water = lib.totalBodyWaterPercentage.toFloat()
this.muscle = lib.skeletalMusclePercentage.toFloat()
this.bone = lib.boneMassKg.toFloat()
this.bmr = lib.basalMetabolicRate.toFloat()
this.lbm = lib.fatFreeMassKg.toFloat()
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
The new impedance-derived calculation path should guard against zero/invalid weight to avoid producing Infinity/NaN values (and there’s also a small lint-risk whitespace-only line).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 2
- Review effort level: Lite
| this.fat = m.fatPct | ||
| // The scale reports impedance but the v2.5.4 reference doesn't | ||
| // derive water/muscle/bone from it; openScale's existing | ||
| // StandardImpedanceLib can be wired in later for that. | ||
|
|
||
| if (m.impedanceOhm in 1..3999) { |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
A published measurement’s userId is still set from the scale’s on-wire slot ID instead of the app user ID, which can misattribute data to the wrong user.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 2
- Review effort level: Lite
| this.water = lib.totalBodyWaterPercentage.toFloat() | ||
| this.muscle = lib.skeletalMusclePercentage.toFloat() | ||
| this.bone = lib.boneMassKg.toFloat() | ||
| this.bmr = lib.basalMetabolicRate.toFloat() | ||
| this.lbm = lib.fatFreeMassKg.toFloat() |
|
|
||
| val sm = ScaleMeasurement().apply { | ||
| this.userId = m.userId | ||
| this.dateTime = m.dateTime ?: Date() |
|
Thanks for wiring Before we look at the code: do the derived values match reality on your device?
From two or three weigh-ins, could you post:
If it's close, this is good to go. If it's far off, better to store nothing than wrong values — people track these over months. Two things for a later round:
On your question from the first commit message: releases go to both F-Droid and Play Store, so this lands there once merged — GitHub will notify you, no email needed. |
Enabled the impedance reading in the handler and added all the fields that derive from the impedance. Tested the changes in my phone with HUAWEI AH100 and they work. Please let me know if these changes make it into the play store app by emailing me in: voikiaetsi@gmail.com