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

Sawpy CF398BLE Support #580

Open teeks99 opened 4 years ago

teeks99 commented 4 years ago

Sawpy CF398BLE

I can find no information online about this scale other than the Amazon page I got it from

Step 1: Read the general reverse engineer process

Step 2: Acquiring some Bluetooth traffic (sorry, I started using lbs instead of kgs so files are names as such, all conversions are done below)

  1. Bluetooth HCI Snoop log file

    user settings in the vendors app:

    sex: male, birth: 3-21-1981, height: 185cm, target: 79.4kg

    measured true values in the vendors app for the 1. HCI Snoop log file:

    2020-05-28 06:36
    187.6lb - 85.1kg
    51.6% water
    24.7% fat
    7.0lb bone - 3.2kg
    24.9 BMI
    12.0 visceral fat
    134.2lb muscle mass - 60.9
    1653.0kcal BMR
  2. Bluetooth HCI Snoop log file

    user settings in the vendors app:

    sex: male, birth: 3-21-1981, height: 185cm, target: 79.4kg

    measured true values in the vendors app for the 2. HCI Snoop log file:

    2020-05-28 06:51
    195.4lb - 88.6kg
    50.5 water
    26.4 fat
    7.0lb bone - 3.2kg
    25.9 BMI
    12.0 visceral fat - 
    136.4lb muscle mass - 61.9kg
    1706.0kcal BMR
  3. Bluetooth HCI Snoop log file

    user settings in the vendors app:

    sex: male, birth: 3-21-1981, height: 185cm, target: 79.4kg

    measured true values in the vendors app for the 3. HCI Snoop log file:

    2020-05-28 07:01
    189.6lb - 86.0kg
    51.3% water
    25.2% fat
    7.0lb bone - 3.2kg
    25.1 BMI
    12.0 visceral fat
    135.0lb muscle mass - 61.2kg
    1667.0kcal BMR
  4. Bluetooth HCI Snoop log file

    user settings in the vendors app:

    sex: male, birth: 3-21-1981, height: 185cm, target: 79.4kg

    measured true values in the vendors app for the 4. HCI Snoop log file:

    2020-05-28 07:06
    193.0lb - 87.5kg
    50.8% water
    25.9% fat
    7.0lb bone - 3.2kg
    25.6 BMI
    12.0 visceral fat
    135.8lb muscle mass - 61.6kg
    1689.0kcal BMR
  5. Bonus - changing weight during measurement...

    I kept the weight changing during the measurement to see differences come in across the packets. I started with drastic changes, stepping partially off the scale. Towards the end just shifting my weight around kept it from completing the measurement and sending data.

    I had socks on so no other measurements were taken.

  6. Bonus - changing units on scale...

    .... didn't have any impact on the weight measurement in the data stream.

  7. Light Weight Child

  8. Medium Weight Woman

  9. Next Day

Step 3: Discover Bluetooth services and characteristic

openScale_2020-05-28_15-07.txt

Scale Images

Front Image Info Label Image

Weight Determination

For the second example, with of measurement of 88.6kg, I got the data

37:76:71:51:cf:c4:13:9c:22:1f:14:71:01:00:dd

The (swapped) 22:9c is 8860, matching 88.6. These 8&9 bytes of the payload were always the weight for any valid data packets received.

Other Data

The app also reports "Bone Mass", "Body Fat %", "Muscle Mass", "Body Water %", "Visceral Fat", "BMI", and "BMR". Some must certainly be calculated by the app, but not sure which.

It appears there is no time/date stamp in here, unless that last byte is some kind of sub-second time. It seems to change with every unique measurement.

Hopefully someone else can make more sense of these than I could.

1 - 2020-05-28 06:36 85.1kg 51.6% 24.7% 3.2kg 12.0 60.9kg 1653.0kcal
37:76:71:51:cf:ba:13:3e:21:aa:a6:a4:01:00:d0

2 - 2020-05-28 06:51 88.6kg 50.5% 26.4% 3.2kg 12.0 61.9kg 1706.0kcal
37:76:71:51:cf:c4:13:9c:22:1f:14:71:01:00:dd

3 - 2020-05-28 07:01 86.0kg 51.3% 25.2% 3.2kg 12.0 61.2kg 166.0kcal
37:76:71:51:cf:b0:13:98:21:ad:a6:ae:01:00:71

4 - 2020-05-28 07:06 87.5kg 50.8% 25.9%  3.2kg 12.0 61.6kg 1689.0kcal
37:76:71:51:cf:b0:13:2e:22:5a:55:5d:01:00:33 x22

7 - 2020-05-28 19:37 20.0kg 65.2% 5% 2.1kg 1.9 17.7kg 682kcal
37:76:71:51:cf:88:18:d0:07:da:d8:5d:01:00:d6

8 - 2020-05-28 20:45 67.3kg 59.4% 13.5% 2.9kg 7.0 55.4kg 1388.0kcal
37:76:71:51:cf:64:14:4a:1a:e5:e7:b6:01:00:5a

9 - 2020-05-29 06:52 85.9kg 51.5% 24.9% 3.2kg 12.0 61.3kg 1665.0kcal
37:76:71:51:cf:a2:12:8e:21:ac:a6:74:01:00:af
lbdroid commented 3 years ago

The plastic casing is identical to a 1byone CF398BLE, which is supported and works. I doubt its a coincidence that they have the same model number.

Try it, but make sure to have bare feet and step on the metal pads or it won't work.

teeks99 commented 3 years ago

Is there a quick way to add my LFScale [ED:67:37:76:71:51] so that it can be interpreted as a 1byone CF398BLE?

lbdroid commented 3 years ago

Yes, just copy the onebyone if block from here; https://github.com/oliexdev/openScale/blob/master/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothFactory.java#L90

Add a new block (or an OR) with a name of "LFScale" should to the job.

lbdroid commented 3 years ago

Yeah, looking at the data dumps you've provided, it matches onebyone.

The actual block you are looking for starts at the 5th byte (always 0xCF). The last byte is the checksum of the 5th byte onward. The first 2 bytes AFTER the CF is the impedance (you will want to look at the open pull requests, because there were some errors in the onebyone calculations). Next 2 bytes are the weight. Next 3 bytes are unknown, but you can see how wildly they swing, so they're not impedance even though they've been used as so. I don't know what the next byte (always 0x01 in your samples) means. The final data byte goes to 0x01 if the impedance is invalid.