XiaomiGateway3 icon indicating copy to clipboard operation
XiaomiGateway3 copied to clipboard

Support for Mi Body Composition Scale s400

Open razor-4eg opened this issue 1 year ago • 1 comments

Cant figure out how to create a converter for Xiaomi Scale s400 BLE

here the device info: extra: cloud_fw: 2.1.1_0057 cloud_name: Body Composition Scale did: blt.3.1i0oijp3sk400 mac: 84:46:93:20:07:0a market_brand: Xiaomi market_model: 12505, yunmai.scales.ms103 market_name: Body Scale s400 rssi_54ef4437c787: -62 seq: 24 type: ble last_seen: 54ef4437c787: 1m6s listeners: 5 model: 12505 params: {} ttl: 1h5m uid: 84469320070a

Here is debug logs with it (blt.3.1i0oijp3sk400) debug.log

razor-4eg avatar Jun 22 '24 13:06 razor-4eg

I have the s400 pro,but I don't know how to debug = =

tufeikafei avatar Sep 20 '24 08:09 tufeikafei

the s400 scale measures three metrics: impedance, heart rate and weight and combines these values into a single value value when reporting to gateway.

The formula is

(impedance * 10) << 18 + (heart_rate - 50) << 11 + (weight * 10)

To decode it properly, you need to add a custom converter:

from dataclasses import dataclass
from custom_components.xiaomi_gateway3.core.devices import *
from homeassistant.components.sensor import (
    SensorDeviceClass,
    SensorStateClass,
)


@dataclass
class S400RawDataConv(BaseConv):
    def decode(self, device: "XDevice", payload: dict, value: int):
        if value > 1:
            weight = value & (2**11 - 1)
            heart_rate = (value >> 11) & (2**7 - 1)
            impedance = value >> 18
            payload["raw_data"] = value
            if weight != 0:
                payload["weight"] = weight / 10
            if heart_rate > 0 and heart_rate < 127:
                payload["heart_rate"] = heart_rate + 50
            if impedance != 0:
                if weight != 0:
                    payload["impedance_high"] = impedance / 10
                else:
                    payload["impedance_low"] = impedance / 10


DEVICES = [
    {
        18639: [
            "Xiaomi",
            "Body Composition Scale S400",
            "12505",
            "yunmai.scales.ms103",
        ],
        "spec": [
            BaseConv(
                "weight",
                "sensor",
                entity={
                    "name": "Weight",
                    "icon": "mdi:human",
                    "class": SensorDeviceClass.WEIGHT,
                    "statistics": SensorStateClass.MEASUREMENT,
                    "units": "kg",
                },
            ),
            BaseConv(
                "heart_rate",
                "sensor",
                entity={
                    "name": "Heart Rate",
                    "icon": "mdi:heart-pulse",
                    "statistics": SensorStateClass.MEASUREMENT,
                    "units": "bpm",
                },
            ),
            BaseConv(
                "impedance_low",
                "sensor",
                entity={
                    "name": "Impedance (low)",
                    "icon": "mdi:omega",
                    "statistics": SensorStateClass.MEASUREMENT,
                    "units": "ohm",
                },
            ),
            BaseConv(
                "impedance_high",
                "sensor",
                entity={
                    "name": "Impedance (high)",
                    "icon": "mdi:omega",
                    "statistics": SensorStateClass.MEASUREMENT,
                    "units": "ohm",
                },
            ),
            # https://home.miot-spec.com/spec/yunmai.scales.ms107
            S400RawDataConv("raw_data", "sensor", mi="11.e.1022.p.2"),
        ],
    }
] + DEVICES

For other metrics like BMI, body fat, bones mass, you can leverage the bodymiscale custom component.

Final result:

image image

This setup is only works for single user. I only tested with yunmai.scales.ms107 but it should also works with yunmai.scales.ms103 and yunmai.scales.ms104.

PoiScript avatar Oct 29 '24 15:10 PoiScript

@PoiScript can you provide messages examples? So I can write tests on your converters.

AlexxIT avatar Oct 29 '24 16:10 AlexxIT

@AlexxIT sure! here're example data:

# case 1
input 260823     => weight = 72.7
# case 2
input 1338768096 => weight: 73.6, impedance_high: 510.6
input 1234960384 => impedance_low: 471.1
# case 3
input 1343068894 => weight 73.4, heart_rate: 101, impedance_high: 512.3
input 1240727552 => impedance_low: 473.3

Note that heart rate and impedance data can be missing (case 1) when wearing shoes, as the scale cannot measure them.

Heart rate measurement can be turned off in settings. (case 2)

The scale will report two impedance values (both case 2 and case 3) which is likely measured at different frequencies

image

PoiScript avatar Oct 29 '24 16:10 PoiScript

https://github.com/AlexxIT/XiaomiGateway3/releases/tag/v4.0.7

AlexxIT avatar Nov 26 '24 14:11 AlexxIT

Great, but you using a wrong id for it.

id for s400 is 12505, so I changed your code from:

18639: [
            "Xiaomi",
            "Body Composition Scale S400",
            "12505",
            "yunmai.scales.ms103",
        ],

to:

12505: ["Xiaomi", "Body Composition Scale s400", "12505", "yunmai.scales.ms103"]

and it start working.

Thank you!)

razor-4eg avatar Nov 26 '24 15:11 razor-4eg

Hi I have a s400 pro. ID: 19205 The model :xiaomi.scales.ms110 I don't know how to debug it= =. And the detail code is blow: https://home.miot-spec.com/spec/xiaomi.scales.ms110

tufeikafei avatar Nov 29 '24 06:11 tufeikafei

@tufeikafei what about features? Are they same for pro model?

AlexxIT avatar Nov 29 '24 07:11 AlexxIT

I add id with 19205,and found it works. image

tufeikafei avatar Nov 29 '24 15:11 tufeikafei

And with Impedance high and Impedance Low, how to config the BodyMiScale,the Body Mi Scale is need one impedance, I don't know use which impedance.

tufeikafei avatar Nov 29 '24 16:11 tufeikafei

My high impedance matches the impedance of my old Xiaomi scales.

AlexxIT avatar Nov 29 '24 16:11 AlexxIT

id for s400 is 12505, so I changed your code from: I add id with 19205,and found it works.

I guess three different BLE IDs correspond to three different models of s400 scale:

image

And with Impedance high and Impedance Low, how to config the BodyMiScale,the Body Mi Scale is need one impedance, I don't know use which impedance.

You can pick any one of them, or create a helper to calculate the average using https://www.home-assistant.io/integrations/min_max:

image

btw, I also tried to re-implantation the scale's body metrics algorithm in Home Assistant, but turns out these metrics are actually calculate on the cloud.

So unless you mock the http request, you won't be able to replicate the exact same body metrics as the Mi Home app

image

PoiScript avatar Nov 29 '24 19:11 PoiScript

Just bought scale yunmai.scales.ms104, "Xiaomi Body Composition Scale S400 (BHR7793GL)".

popstas avatar Dec 26 '24 20:12 popstas

Hi,

Does the scale connect similarly to Mi Body Composition Scale 2 (tested on XMTZC05HM)? and data (weight, impedance) can be pulled in the same way (plus optional data)

I am this integration author: https://github.com/RobertWojtowicz/export2garmin Is anyone able to help me customize the code (I don't have the scale to test yet), here is the module current to read: https://github.com/RobertWojtowicz/export2garmin/blob/master/miscale/miscale_ble.py

BR, Robert

RobertWojtowicz avatar Dec 31 '24 11:12 RobertWojtowicz

@RobertWojtowicz Interesting integration. I was planning on doing something similar for my scales. Only take data from Fitbit, Zepp and Xiaomi clouds. And transmit the result to the Garmin cloud. I hope to have time for that someday.

Data from the new scales can be obtained, but the format is different. It is likely that encryption of the data being transmitted is used, as with any new devices.

For this integration, packet decryption is handled by the gateway. So I haven't looked into how to decrypt packets without a gateway. I think you need to wait for the support to appear in this integration: https://github.com/custom-components/ble_monitor

After some time there is support for all BLE devices from this integration.

AlexxIT avatar Dec 31 '24 13:12 AlexxIT

@AlexxIT

@RobertWojtowicz Interesting integration. I was planning on doing something similar for my scales.

I invite you to cooperate, I will be happy to add you as a co-author :)

He wants to simplify the integration to a minimum and as less costly as possible (using internal ble like cheap dongles)

BR Robert

RobertWojtowicz avatar Dec 31 '24 13:12 RobertWojtowicz

No, I have other plans. I have a long history with two old scales. Fitbit and Zepp in the clouds. I want to transfer that data to Garmin. And then keep the new scales in the Xiaomi and Garmin clouds. That way the Garmin will have a single history from all my scales.

AlexxIT avatar Dec 31 '24 13:12 AlexxIT

You can enable debug log and check all incoming data.

AlexxIT avatar Mar 26 '25 03:03 AlexxIT

Same here but for heartrate, always shows 124bpm, not sure how to use custom converter. may be doing something wrong.

Psytoshgen avatar Mar 26 '25 22:03 Psytoshgen

Hi all, and please scold me if I should not be posting this question here (though if you do so, and are aware of a better place for the question, I'd appreciate that info).

I'm trying to decipher the BLE traffic between the Xiaomi S400 and my iPhone's app. I am passively monitoring the traffic. I'm having a very hard time figuring out what's going on--there are definite patterns but when I zero in on the actual substance of the data being exchanged, it seems completely random.

I don't have a gateway, so I don't think the information above is helpful. If anyone has any pointers for me, I'd appreciate it. I'd really like to be able to extract basic measurements from this device using my own code, without relying on Xiaomi's app.

dbsdbs93 avatar Apr 25 '25 21:04 dbsdbs93

@RobertWojtowicz I finally released my weight synchronization project: https://github.com/AlexxIT/SmartScaleConnect

AlexxIT avatar Aug 09 '25 08:08 AlexxIT

@AlexxIT

Good job, I also did BLE communication with s400 (export2garmin project), passed the info to mi-scale-exporter project and also it is already in the mobile app thanks @lswiderski :)

I will add a link to your project in my project, great initiative, I like it :)

BR Robert

RobertWojtowicz avatar Aug 09 '25 08:08 RobertWojtowicz

@PoiScript I don't know where you get your code. Maybe you can get formulas for S800 model?

20962: ["Xiaomi", "8-electrode Body Fat Scale S800", "MJTZC04YM", "xiaomi.scales.ms116"],

logs:

2025-09-24 21:44:22.475 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":88142293,  "method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":89,"arguments":[{"piid":1,"value":144},{"piid":2,"value":201654272},{"piid":3,"value":293955796}]},"type":6}'}
2025-09-24 21:44:23.498 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":1131698294,"method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":90,"arguments":[{"piid":1,"value":144},{"piid":2,"value":202718212},{"piid":3,"value":0}]},"type":6}'}
2025-09-24 21:44:24.515 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":1174714295,"method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":91,"arguments":[{"piid":1,"value":144},{"piid":2,"value":203751424},{"piid":3,"value":0}]},"type":6}'}
2025-09-24 21:44:25.536 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":198538296, "method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":92,"arguments":[{"piid":1,"value":144},{"piid":2,"value":204800000},{"piid":3,"value":0}]},"type":6}'}
2025-09-24 21:44:27.065 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":120318297, "method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":93,"arguments":[{"piid":1,"value":144},{"piid":2,"value":205848576},{"piid":3,"value":0}]},"type":6}'}
2025-09-24 21:44:28.087 DEBUG (MainThread) [custom_components.xiaomi_gateway3.mqtt.xxx] {'topic': 'miio/report', 'data': b'{"id":937360298, "method":"event_occured","params":{"did":"blt.6.xxx","siid":3,"eiid":1022,"tid":94,"arguments":[{"piid":1,"value":144},{"piid":2,"value":206897152},{"piid":3,"value":0}]},"type":6}'}

AlexxIT avatar Sep 27 '25 11:09 AlexxIT