oliexdev / openScale

Open-source weight and body metrics tracker, with support for Bluetooth scales
GNU General Public License v3.0
1.7k stars 296 forks source link

Reverse engineering Yunmai mini scale #71

Closed oliexdev closed 6 years ago

oliexdev commented 7 years ago

I am trying to reverse engineer the yunmai mini scale.

I already found out the weight values but I can't figure out the body fat percentage, muscle percentage and so on. Any help or idea is welcome.

So far what I got:

Here are my Bluetooth log files with the corresponding body measurements which we have to find (open it with wireshark):

23.9.2017 07:36 btsnoop_hci_979.log

23.9.2017 10:02 btsnoop_hci_988.log

22.9.2017 18:35 btsnoop_hci_1041.log

Compared last continous messages of all three values

 0d:1f:14:02:00:59:c5:f7:d6:23:d0:b6:32:26:3b:00:dd:08:f2:f9  // 97,9 kg; water 56,0 %
 0d:1f:14:02:00:59:c6:15:2f:23:d0:b6:32:26:95:00:a5:08:f2:37  // 98,8 kg; water 56,0 %
 0d:1f:14:02:00:59:c5:3b:d8:23:d0:b6:32:28:ae:00:c2:09:c4:88  // 104,1 kg; water 54,5 %
oliexdev commented 7 years ago

I discovered that the last byte of each row is a XOR checksum starting from byte 1.

oliexdev commented 7 years ago

ok byte 17-18 contains the body fat in percent multiplied by 100.

oliexdev commented 7 years ago

thanks to @pwnall and @conoro already analysed the protocol under, see here Also thanks to Dodo who found that information.

So in my example we have now the following information:

0d:1f:14:02:00:59:c5:f7:d6:23:d0:b6:32:26:3b:00:dd:08:f2:f9  

    Weight 97,9 kg
    Body fat 22,9 %
    Muscle 51,7 %
    Water 56,0 %
    Protein 16,2 %
    Bone mass 4,0 %

02: finished weighing
00: historical info
59:c5:f7:d6 = unix time in seconds = 1506146261 = Saturday, 23 September 2017 05:57:41
23:d0:b6:32 = user ID 
26:3b = 9787 = 97.9 kg
00:dd = resistance which is apparently used to calculate muscle mass, body water etc.
08:f2 = 2290 = 22,9 % bodyfat
f9: checksum

But sadly I have no idea how to calculate the muscle, water percentage, bone mass and protein out of the resistance. I found some formula but none are close to the above values. :/

oliexdev commented 7 years ago

implemented a first version of the Yunmai Mini (only supported weight and fat) with commit https://github.com/oliexdev/openScale/commit/c37f71939a613549c0532351a0605156b7b43ddf

Vanuan commented 6 years ago

I have Yunmai SE shown as "YUNMAI-ISSE-US" [device not supported] MAC: 60:64:05:xx:xx:xx (Vendor: Texas Instruments)

The protocol looks very similar. How can I force open scale to use Yunmai mini driver?

Vanuan commented 6 years ago
services and characteristics:
1800 (Generic Access)
  2a00 (Device Name)
    properties  read
    value       59554e4d41492d495353452d5553 | 'YUNMAI-ISSE-US'
  2a01 (Appearance)
    properties  read
    value       0000 | ''
  2a02 (Peripheral Privacy Flag)
    properties  read
    value       00 | ''
  2a03 (Reconnection Address)
    properties  write
  2a04 (Peripheral Preferred Connection Parameters)
    properties  read
    value       5000a0000000e803 | 'P h'
1801 (Generic Attribute)
  2a05 (Service Changed)
    properties  indicate
ffe0
  ffe4 (Key Press State)
    properties  notify
ffe5
  ffe9 (Key Press State)
    properties  write
oliexdev commented 6 years ago

If you want to try your scale with the Yunmai Mini protocol change the method checkDeviceName(...) in https://github.com/oliexdev/openScale/blob/master/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYunmaiMini.java to the following:

    @Override
    public boolean checkDeviceName(String btDeviceName) {
        if (btDeviceName.startsWith("YUNMAI-SIGNAL-M") || btDeviceName.startsWith("YUNMAI-ISSE")) {
            return true;
        }

        return false;
}

This will accepts your device name as a Yunmai Mini device.

Vanuan commented 6 years ago

It looks like it is identical. The only difference is that these 2 parameters are always 00 00 00 00:

    .uint16be('resistance')
    .uint16be('fatPercentage')
oliexdev commented 6 years ago

if I see it right on http://www.iyunmai.com/us/m/light-se/ the Yunmai SE scale can only measure your weight. @Vanuan did you received your weight with the yunmai mini protocol? If yes I can implement it in openScale.

Vanuan commented 6 years ago

Yes.

oliexdev commented 6 years ago

I implemented a version of Yunmai SE. Please install and try the beta version of the openScale under https://github.com/oliexdev/openScale/releases and give feedback if it works or not.

Can you send maybe a picture of your Yunmai SE scale (same angle as in the openScale wiki)? I don't want to use a official photo due copyright issues.

Vanuan commented 6 years ago

Sure. Does this look good? img_20171031_235813

Vanuan commented 6 years ago

It works. I see "[weight] to [user] added". Can this app send some command so that units are changed from lb to kg?

oliexdev commented 6 years ago

sure openScale can send commands but I need to know what I have to send to change the unit :wink: You have to analyse the Bluetooth protocol with wireshark see openScale wiki for more information how to do that.

Thanks for your image. Is it possible to take another one while the scale is turned off?

Vanuan commented 6 years ago

img_20171031_235754

cantruchd commented 6 years ago

Maybe we can use the body fat % to calculate the other factor?

MarvinT commented 6 years ago

@oliexdev

If we get a bunch of data points i.e. different peoples weights and resistances... or even weights and resistances for different times throughout the day we can figure out the equations. Probably doable with 6, fairly easy with 10, and very easy with 20 data points

I'm trying to decide which scale to buy now and probably going to use your app as the determining factor.

oliexdev commented 6 years ago

@MarvinT

Yeah the idea is not new. You can try it but be aware that the formula will probably change if you are male or female and it will be probably also depends on your body height, age and the impedance value.

So you have to consider a few variables.

Maybe the issue #154 helps you for your decision.

Vaevictus commented 6 years ago

Hi there,

I installed the dev version yesterday and connected it up to my yunmai mini (reported as YUNMAI-SIGNAL-M1US device.)

It didnt pull the body fat %, just the weight.

dylanlt commented 6 years ago

Total Body Water (TBW) = (0.372 HeightCM HeightCM / Resistance) + (0.142 massKg) - (0.069 ageYears) + (3.05 * ifMale)

Fat Free Mass = TBW ÷ 0.73

Can you test with your height and age and see how well it compares to the app value?

Reference: LUKASKI and BOLONCHUK (1988) Formula for total body water. Aviation Space and Environmental Medicine, 59, p. 1163-1169

See also https://www.quora.com/How-do-bathroom-scales-that-calculate-body-fat-water-muscle-bone-kcal-actually-work-And-are-they-accurate

More detailed explanation from fundamental principles: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4118362/

oliexdev commented 6 years ago

@dylanlt I already tried that formula but it didn't work out. Try for yourself for the example measurements:

used user data on all measurements: Height 5'9“ ft (175cm) Age 25 male

example measurements 1:

0d:1f:14:02:00:59:c4:ff:cf:23:d0:b6:32:26:aa:00:9f:08:de:16  // 99,0 kg
22.9.2017 14:19  99,0 kg
Body fat 22,7
Muscle 51,8
Water 56,1
Protein 16,2
Bone mass 3,9
Resistance 0x9f (maybe!?)

example measurements 2:

0d:1f:14:02:00:59:c5:3b:d8:23:d0:b6:32:28:ae:00:c2:09:c4:88  // 104,1 kg
22.9.2017 18:35 104,1 kg 
Body fat 25,0
Muscle 50,3% 
Water 54,5% 
Protein 16,1
bone mass 3,8
Resistance 0xc2 (maybe!?)

example measurements 3:

0d:1f:14:02:00:59:c5:f7:d6:23:d0:b6:32:26:3b:00:dd:08:f2:f9  // 97,9 kg
23.9.2017 07:36 97,9 kg 
Body fat 22,9
Muscle 51,7% 
Water 56,0% 
Protein 16,2
bone mass 4,0
Resistance 0xdd (maybe!?)

example measurements 4:

0d:1f:14:02:00:59:c6:15:2f:23:d0:b6:32:26:95:00:a5:08:f2:37  // 98,8 kg
23.9.2017 10:02 98,8 kg 
Body fat 22,9
Muscle 51,7% 
Water 56,0% 
Protein 16,2
bone mass 3,9
Resistance 0xa5 (maybe!?)
dylanlt commented 6 years ago

Typical population average resistance index (height squared divided by resistance) is roughly 60 a seen here: https://pdfs.semanticscholar.org/98a3/16bcdb1ce64790ca796278ed7731b204764c.pdf

Their formula has slightly different weightings, too.

Working backwards though (I used measurement 3) Fat of 22.9% means that fat = 22.4kg, so FFM = 97.9 - 22.4kg = 75.5kg

Hydration constant is 73% so TBW = 75.5 x 73% = 55.1kg ; 55.1 / 97.9 = 56% That matches the scale result.

FFM = bone + water + muscle Checking that: 51.7% (muscle from scale) of 75.5kg

If we can resolve either bone mass or muscle mass then we are done.

There seem to be a lot of variation on these formulas, though, and most have 2 components to the resistance. The 0xdd value in measurement 3 doesn't seem typical of either value, though. The resistance values also vary wildly between the 4 measurements.

oliexdev commented 6 years ago

Working backwards though (I used measurement 3) Fat of 22.9% means that fat = 22.4kg, so FFM = 97.9 - 22.4kg = 75.5kg

Hydration constant is 73% so TBW = 75.5 x 73% = 55.1kg ; 55.1 / 97.9 = 56% That matches the scale result.

if the position after decimal point is not so important it will mostly match but the results differs slightly between the calculation and the scale.

FFM = bone + water + muscle Checking that: 51.7% (muscle from scale) of 75.5kg

  • 3.9kg (bone from scale)
  • 55.1kg (calculation above) = 97.9kg

If we can resolve either bone mass or muscle mass then we are done.

true but I have never seen any formula which were the bone mass was calculated or the muscle percentage. :(

There seem to be a lot of variation on these formulas, though, and most have 2 components to the resistance. The 0xdd value in measurement 3 doesn't seem typical of either value, though. The resistance values also vary wildly between the 4 measurements.

yes maybe it is not the right values or they use some kind of offset.

dylanlt commented 6 years ago

There's an ad-support app (yourscales.com) which does the calculation as well. It seems like he is using the Yunmai code library.

erijo commented 6 years ago

What do you mean with "the Yunmai code library" @dylanlt?

dylanlt commented 6 years ago

The namespace used in the other app is com.yunmai.scale. Have you tried contacting Yunmai?

oliexdev commented 6 years ago

@dylanlt no, I haven't contacted Yunmai. I doubt that they will response. Even if they have a library available it has to be compatible with the GPLv3.

erijo commented 6 years ago

Similar to #159 there seems to be a native library (libconfig.so) at the bottom doing the conversion from resistance etc. to fat etc. If there is someone fluent in arm assembler or have an IDA license it might be possible to figure it out...

Erol444 commented 6 years ago

Hello! I was really excited when I saw this, since my yunmai app said that it doesn't support my Yunmai mini scale anymore and that I have to download chinese version. If I get that working I might help you guys with reverse engeenering the body metrics info. But how do you connect the yunmai mini scale to the openScale app? I can only manually add weight, and scale doesn't want to autoconnect to openScale app either.

erijo commented 6 years ago

You connect to the scale under settings/Bluetooth.

You can try the dev version if that works better.

Erol444 commented 6 years ago

Nevermind, at first the bluetooth icon on main screen didn't show up(a bug..?), now I just know where to click to turn it on. Just re-installed my yunmai app and tried to get it running so I could help you reverse engineer the rest of the info but like previously, I would have to download chinese version(no tnx)

31944705_2257362184275703_257210893979353088_n

Does the data from scale get sent to openScale so I could help(Bluetooth HCI Snoop Log) or would I need original yunmai app for that?

erijo commented 6 years ago

I think all data is sent from the scale to openScale, but the problem is that bone, water, muscle etc. isn't sent by the scale directly, but instead calculated by the app using the resistance value from the scale. It is this formula that's hard to figure out.

What is the name of chinese version app you need to use to get the mini support?

Erol444 commented 6 years ago

Ohh that's the problem. Saw few formulas up on this issue. So you are trying to figure out what formulas are used by the yunmai app so you can implement it in openScale? Wouldn't it be easier to just decompile the app itself and look into the source for that? And this is the link that opens up if I click "confirm": http://app.qq.com/#id=detail&appid=1102855655

erijo commented 6 years ago

The problem is that the calculations aren't done in java, but in an included native library. I'm not as fluent in asm as I would need to be to figure that out :(

erijo commented 6 years ago

Has anyone here with a Yunmai mini scale seen the issue in #261?

ivangill commented 6 years ago

I tried the App "Your Scale" on the Yunmai. Much better than yanmai app at finding scale Most ibteresting, it calculates a noticeabley different figure for body fat %, and this new figure displays on the scales too. So the scales have a default calculation unless overrideen by the app...

oliexdev commented 6 years ago

added water, muscle and bone mass for Yunmai mini with commit https://github.com/oliexdev/openScale/commit/2e8a2cdfedd36bb0809ac31916c0b01c96ec9c2c

vitoresende commented 4 years ago

Hi people, hi @oliexdev . Thanks for your help here. Did anyone pair / bond the app with yunmai? Is it possible?

Erol444 commented 4 years ago

Hi people, hi @oliexdev . Thanks for your help here. Did anyone pair / bond the app with yunmai? Is it possible?

If you have a pro version than yes, it's straight forward.