- This project works only on Linux, Windows is not supported;
- It is possible to run Linux as a virtual machine on Windows;
- This project is based on following projects:
- It allows Mi Body Composition Scale 2 (model: XMTZC05HM) to be fully automatically synchronized to Garmin Connect, following parameters:
- Time;
- Weight (NOTE: kg units only);
- BMI;
- Body Fat;
- Skeletal Muscle Mass;
- Bone Mass;
- Body Water;
- Physique Rating;
- Visceral Fat;
- Metabolic Age;
- Synchronization diagram from Mi Body Composition Scale 2 to Garmin Connect:
- Install Zepp Life App on your mobile device, user manual: https://files.xiaomi-mi.com/files/smart_scales/smart_scales-EN.pdf;
- Configure your scale with Zepp Life App on your mobile device (tested on Android 10-13);
- Retrieve scale's MAC Address from Zepp Life App (Profile > My devices > Mi Body Composition Scale 2);
- Turn off weigh small object in Zepp Life App (Profile > My devices > Mi Body Composition Scale 2) for better measurement quality:
- Launch Zepp Life App, go to scale (Profile > My devices > Mi Body Composition Scale 2);
- Start scale and select Clear data in App;
- Take a new weight measurement with App, App should synchronize date and time;
- 2 times a year it is necessary to perform synchronization due to change from winter to summer time and then vice versa;
- If time is still not synchronized correctly, check NTP synchronization on server or change time offset in import_data.sh file (offset parameter);
- You should also synchronize scale after replacing batteries;
- Script import_data.sh detects same weighing done in less than 30 seconds (protection against duplicates);
- Script import_data.sh have time difference detection of more than 20 minutes (between scale data and os).
- After weighing, Mi Body Composition Scale 2 is active for 15 minutes on bluetooth transmission;
- USB bluetooth adapter or internal module (tested with bluetooth versions 4.0/4.1 and 5.0/5.1) scans for BLE device every 1 minute for 10 seconds and queries scale for data;
- Body weight and impedance data on server are appropriately processed by scripts;
- Processed data are sent by program bodycomposition to Garmin Connect;
- Raw and calculated data from scale is backed up on server in backup.csv file;
- backup.csv file can be imported e.g. for analysis into Excel.
- How to run USB bluetooth adapter? read section 5. How to increase BLE range?
- Minimum hardware and software requirements are: 1CPU, 512MB RAM, 2GB disk space, network connection, Raspberry Pi OS or Debian operating system;
- Update your system and then install following modules:
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install wget python3 bc bluetooth python3-pip libglib2.0-dev -y
sudo pip install bluepy
- Modify file
sudo nano /etc/systemd/system/bluetooth.target.wants/bluetooth.service
:
ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap
- Download and extract to your home directory (e.g. "/home/robert/"), make a files executable, choose correct version of boodycomposition depending on your operating system:
- Raspberry Pi OS (ARM, 32-bit) use _Linux_armv6.tar.gz
- Raspberry Pi OS (ARM, 64-bit) use _Linux_arm64.tar.gz
- Debian (x86, 32-bit) use _Linux_i386.tar.gz
- Debian (x86, 64-bit) use _Linux_x86_64.tar.gz
wget https://github.com/RobertWojtowicz/miscale2garmin/archive/refs/tags/5.tar.gz -O - | tar -xz
cd miscale2garmin-5
wget https://github.com/davidkroell/bodycomposition/releases/download/v1.7.0/bodycomposition_1.7.0_Linux_x86_64.tar.gz -O - | tar -xz bodycomposition
sudo chmod +x bodycomposition import_data.sh scanner_ble.py export_garmin.py
sudo setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python3.9/dist-packages/bluepy/bluepy-helper
- First script is "scanner_ble.py", you need to complete data: "scale_mac_addr", which is related to MAC address of scale;
- If you have multiple BLE devices, check which device should scan scale with command
sudo hcitool dev
and set hci_num parameter in "scanner_ble.py" script; - Script "scanner_ble.py" has implemented debug mode, you can verify if everything is working properly, just execute it from console:
$ python3 /home/robert/miscale2garmin-5/scanner_ble.py
Mi Body Composition Scale 2 Garmin Connect v5.3 (scanner_ble.py)
* Starting BLE scan:
BLE device found with address: 3f:f1:3e:a6:4d:00, non-target device
BLE device found with address: 42:db:e4:c4:5c:d4, non-target device
BLE device found with address: 24:fc:e5:8f:ce:bf, non-target device
BLE device found with address: 00:00:00:00:00:00 <= target device
* Reading BLE data complete, finished BLE scan
1672412076;58.4;521
- Second script is "export_garmin.py", you must complete data in "users" section: sex, height in cm, birthdate in dd-mm-yyyy, email and password to Garmin Connect, max_weight in kg, min_weight in kg;
- Script "export_garmin.py" supports multiple users with individual weights ranges, we can link multiple accounts with Garmin Connect;
- Script "import_data.sh" has implemented debug mode, you can verify if everything is working properly, just execute it from console:
$ /home/robert/miscale2garmin-5/import_data.sh
Mi Body Composition Scale 2 Garmin Connect v5.3 (import_data.sh)
* backup.csv file exists, check if temp.log exists
* temp.log file exists, checking for new data
* Importing data from a BLE scanner
* Saving import 1672412076 to backup.csv file
* Calculating data from import 1672412076, upload to Garmin Connect
* Data upload to Garmin Connect is complete
* Saving calculated data from import 1672412076 to backup.csv file
- If there is an error upload to Garmin Connect, data will be sent again on next execution, upload errors and other operations are saved in temp.log file:
$ cat /home/robert/miscale2garmin-5/temp.log
... uploading weight
Mi Body Composition Scale 2 Garmin Connect v5.3 (export_garmin.py)
* Import data: 1672412076;58.1;526
* Calculated data: 07.01.2023;19:09;58.1;19.6;13.8;47.5;2.6;59.2;7;6;22;526;email@email.com;07.01.2023;19:21
- Finally, if everything works correctly add script import_ble.sh to CRON to run it every 1 minute
sudo crontab -e
:
*/1 * * * * /home/robert/miscale2garmin-5/import_data.sh
- This section is an expansion of section 4. BLE VERSION;
- Purchase a cheap USB bluetooth 5.0/5.1 adapter with external antenna (tested on RTL8761B chipset);
- Bluetooth adapter should have a removable RP-SMA antenna;
- You will have option to change if standard RP-SMA antenna included with bluetooth adapter gives too little range;
- Sometimes if you increase antenna range, scan time is too short to find your scale (too many devices around), you should increase scan_time parameter in scanner_ble.py script;
- Download driver from Realtek repository https://github.com/Realtek-OpenSource:
wget https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT/rtl8761b_fw
wget https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT/rtl8761b_config
- Add USB chipset using passthrough mechanism (for performance and stability), connect USB bluetooth adapter;
- Assign USB chipset to virtual machine from hypevisor (tested on VMware ESXi 7/8);
- Create a folder and move driver to destination folder, restart virtual machine:
sudo mkdir /lib/firmware/rtl_bt
sudo mv rtl8761b_config /lib/firmware/rtl_bt/rtl8761b_config.bin
sudo mv rtl8761b_fw /lib/firmware/rtl_bt/rtl8761b_fw.bin
sudo reboot
- Purchase an OTG cable (micro USB male to USB Type-A female), connect bluetooth to Raspberry Pi Zero W;
- Disable BLE internal module by adding a line in file
sudo nano /boot/config.txt
:
dtoverlay=disable-bt
- Move to destination folder (add an extra letter "u" in driver name), restart Raspberry Pi Zero W:
sudo mv rtl8761b_config /lib/firmware/rtl_bt/rtl8761bu_config.bin
sudo mv rtl8761b_fw /lib/firmware/rtl_bt/rtl8761bu_fw.bin
sudo reboot
- Sample photo with test configuration, on left Raspberry Pi Zero W, on right server with virtual machine (stronger antenna added):
- After weighing, Mi Body Composition Scale 2 is active for 15 minutes on bluetooth transmission;
- ESP32 module operates in a deep sleep and wakes up every 7 minutes, scans for BLE device for 10 seconds and queries scale for data, process can be started immediately via reset button;
- ESP32 module sends acquired data via MQTT protocol to MQTT broker installed on server;
- Body weight and impedance data on server are appropriately processed by scripts;
- Processed data are sent by program bodycomposition to Garmin Connect;
- Raw and calculated data from scale is backed up on server in backup.csv file;
- backup.csv file can be imported e.g. for analysis into Excel.
- Use Arduino IDE to compile and upload software to ESP32, following board and libraries required:
- Arduino ESP32: https://github.com/espressif/arduino-esp32;
- Battery 18650 Stats: https://github.com/danilopinotti/Battery18650Stats;
- PubSubClient: https://github.com/knolleary/pubsubclient;
- Timestamps: https://github.com/alve89/Timestamps;
- How to install board and library in Arduino IDE?:
- board (NOTE: use version 1.0.4, newer is unstable): https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html;
- libraries: https://www.arduino.cc/en/Guide/Libraries;
- Preparing Arduino IDE to upload project to ESP32, go to Tools and select:
- Board: > ESP32 Arduino > "WEMOS LOLIN32";
- Upload Speed: "921600";
- CPU Frequency: > "80MHz (WiFi / BT)" for better energy saving;
- Flash Frequency: "80Mhz";
- Partition Scheme: > "No OTA (Large APP)";
- Port: > "COM" on which ESP32 board is detected;
- Following information must be entered before compiling code (esp32.ino) in Arduino IDE:
- mac address of scale read from Zepp Life App ("scale_mac_addr");
- parameters of your WiFi network ("ssid", "password");
- other settings ("led_pin", "Battery18650Stats");
- connection parameters MQTT ("mqtt_server", "mqtt_port", "mqtt_userName", "mqtt_userPass");
- Debug and or comments:
- Project is prepared to work with ESP32 board with charging module (red LED indicates charging). I based my version on Li-ion 18650 battery;
- Program for ESP32 has implemented UART debug mode (baud rate must be set to 115200), you can verify if everything is working properly:
Mi Body Composition Scale 2 Garmin Connect v5.3 (esp32.ino) * Starting BLE scan: BLE device found with address: 3f:f1:3e:a6:4d:00, non-target device BLE device found with address: 42:db:e4:c4:5c:d4, non-target device BLE device found with address: 24:fc:e5:8f:ce:bf, non-target device BLE device found with address: 00:00:00:00:00:00 <= target device * Reading BLE data complete, finished BLE scan * Connecting to WiFi: connected IP address: 192.168.4.18 * Connecting to MQTT: connected * Publishing MQTT data: 1672412076;58.4;521;3.5;5 * Waiting for next scan, going to sleep
- After switching device on, blue LED will light up for a moment to indicate that module has started successfully;
- If data are acquired correctly in next step, blue LED will flash for a moment 2 times;
- If there is an error, e.g. data is incomplete, no connection to WiFi network or MQTT broker, blue LED will light up for 5 seconds;
- Program implements voltage measurement and battery level, which are sent toger with scale data in topic MQTT;
- Device has 2 buttons, first green is reset button (monostable), red is battery power switch (bistable);
- Sample photo of finished module with ESP32 (Wemos LOLIN D32 Pro) and Li-ion 18650 battery (LG 3600mAh, LGDBM361865):
- Minimum hardware and software requirements are: 1CPU, 512MB RAM, 2GB disk space, network connection, Raspberry Pi OS or Debian operating system;
- Update your system and then install following modules:
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install wget python3 bc mosquitto mosquitto-clients -y
- You need to set up a password for MQTT (password must be same as in ESP32):
sudo mosquitto_passwd -c /etc/mosquitto/passwd admin
; - Create a configuration file for Mosquitto:
sudo nano /etc/mosquitto/mosquitto.conf
and enter following parameters:
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
- Download and extract to your home directory (e.g. "/home/robert/"), make a files executable, choose correct version of boodycomposition depending on your operating system:
- Raspberry Pi OS (ARM, 32-bit) use _Linux_armv6.tar.gz
- Raspberry Pi OS (ARM, 64-bit) use _Linux_arm64.tar.gz
- Debian (x86, 32-bit) use _Linux_i386.tar.gz
- Debian (x86, 64-bit) use _Linux_x86_64.tar.gz
wget https://github.com/RobertWojtowicz/miscale2garmin/archive/refs/tags/5.tar.gz -O - | tar -xz
cd miscale2garmin-5
wget https://github.com/davidkroell/bodycomposition/releases/download/v1.7.0/bodycomposition_1.7.0_Linux_x86_64.tar.gz -O - | tar -xz bodycomposition
sudo chmod +x bodycomposition import_data.sh export_garmin.py
- First script is "import_data.sh", you need to complete data: "user", "password" which are related to MQTT broker, "mqtt" set to "on";
- Second script is "export_garmin.py", you must complete data in "users" section: "sex", "height" in cm, "birthdate" in dd-mm-yyyy, "email" and "password" to Garmin Connect, "max_weight" in kg, "min_weight" in kg;
- Script "export_garmin.py" supports multiple users with individual weights ranges, we can link multiple accounts with Garmin Connect;
- Script "import_data.sh" has implemented debug mode, you can verify if everything is working properly, just execute it from console:
$ /home/robert/miscale2garmin-5/import_data.sh
Mi Body Composition Scale 2 Garmin Connect v5.3 (import_data.sh)
* backup.csv file exists, check if temp.log exists
* temp.log file exists, checking for new data
* Importing data from an MQTT broker
* Saving import 1672412076 to backup.csv file
* Calculating data from import 1672412076, upload to Garmin Connect
* Data upload to Garmin Connect is complete
* Saving calculated data from import 1672412076 to backup.csv file
- If there is an error upload to Garmin Connect, data will be sent again on next execution, upload errors and other operations are saved in temp.log file:
$ cat /home/robert/miscale2garmin-5/temp.log
... uploading weight
Mi Body Composition Scale 2 Garmin Connect v5.3 (export_garmin.py)
* Import data: 1672412076;58.1;526
* Calculated data: 07.01.2023;19:09;58.1;19.6;13.8;47.5;2.6;59.2;7;6;22;526;email@email.com;07.01.2023;19:21
- Finally, if everything works correctly add script import_mqtt.sh to CRON to run it every 1 minute
sudo crontab -e
:
*/1 * * * * /home/robert/miscale2garmin-5/import_data.sh
- I don't plan to create a mobile app, but I encourage you to take advantage of another project: https://github.com/lswiderski/mi-scale-exporter
- If you like my work, you can buy me a coffee: