magnific0 / nokia-weight-sync

Get weight from Nokia Health and update in Garmin Connect or Smashrun
GNU General Public License v3.0
71 stars 30 forks source link

Calculate BMI #13

Closed vholer closed 5 years ago

vholer commented 5 years ago

Garmin Connect web doesn't show additional metrics, only weight and Garmin calculated BMI. This is caused by very poor weight scale type detection just by available metrics. There are 3 types of view: base, Atlas scale, Tanita scale. Unfortunately, the Atlas scale view (showing the additional metrics) is detected only by presence of calculated BMI, the Tanita scale by presence of visceral fat. If any of these metrics are missing, it fallbacks to base view (just weight + Garmin calculated BMI).

To show additional metrics from Withings, it's necessary to fake Atlas scale by computing the BMI on import. This PR reads user's height from Withings, calculates the BMI and puts it into the FIT. I have to admit that I haven't found the BMI attribute in the offical FIT specification, so it was discovered by experiment.

It happens only on Garmin Connect Web:

image

The Garmin Connect mobile doesn't suffer of this problem:

image

Here is the Garmin Connect JavaScript code, which detects weight type by available metrics:

https://connect.garmin.com/modern/main/js/pages/weight/WeightPageView.js?bust=4.15.1.0

        getSelectWeightType: function() {
            return this.checkTanitaDataExist() ? C.TANITA : this.checkAtlasDataExist() ? C.ATLAS : C.OTHER
        },
        checkTanitaDataExist: function() {
            return t.find(this.weights.weightDataList, function(e) {
                return e.visceralFat
            })
        },
        checkAtlasDataExist: function() {
            return t.find(this.weights.weightDataList, function(e) {
                return e.bmi
            })
        },

and, here we can see most metrics is hidden for non-Tanita or non-Atlas scales:

           r && this.$("#directBMIClickedTableRow").html(r);
            if (e === C.TANITA || e === C.ATLAS) {
                var s = this.weightChartView.getSelectBodyFat();
                s != "--" && (s = i.personalizeWeightWithoutConvert(s));
                var o = this.weightChartView.getSelectBodyWater();
                o != "--" && (o = i.personalizeWeightWithoutConvert(o));
                var u = this.weightChartView.getSelectBoneMass();
                u != "--" && (u = this.convertToWeightString(u));
...
            } else
                this.$(".js-body-fat-unit").hide(),
                this.$(".js-body-water-unit").hide(),
                this.$(".js-bone-mass-unit").hide(),

With provided patch and calculated BMI, the view is switched to show additional (Atlas scale) metrics:

image

nurps commented 5 years ago

Nice, I'm going to test that. :)

nurps commented 5 years ago

Btw on the topic of calculating stuff: Is it possible to calculate the other missing values for people with scales that only do body-fat and weight?

vholer commented 5 years ago

Some of the metrics could be probably calculated, but not much of them. That's why you buy a more expensive scale doing a body (bioelectrical impedance) analysis.

E.g., body fat https://en.wikipedia.org/wiki/Body_fat_percentage calculated from BMI:

I think it makes sense to compute additional metrics which can be reliably calculated base on provided data, but from just weight, heigh and age you can only guess...

Anyway, this PR is more a workaround for crappy Garmin Connect web. I would handle the additional metrics separately ;) Thanks.

nurps commented 5 years ago

Well the Withings WS-50 only measures body-fat. Replacing it with the newer Withings scales doesn't really make sense for me, was just an idea.

nurps commented 5 years ago

428a2cc4-b9cd-41a4-b79b-7dc7bcb75a4f png

Nice it worked (just missing the water, bone and muscle my scale does not record), I can even see my full bodyfat graph dating back when I started measuring.

Only the BMI graph just starts with todays sync, is there a way to sync that for the older entries?

vholer commented 5 years ago

From config.ini delete the line with last_sync=. If you start the script now, it should synchronize all data from Withings again. Obviously, now with calculated BMI.

magnific0 commented 5 years ago

@vholer This is really great stuff. Thanks for the code and very detailed PR! Unfortunately, I didn't have time yet to properly test this feature. However, @nurps comments indicate the code works as expected. So I'm going to go ahead with the merge.

Thanks again for all your efforts!