I have had a Withings Body+ for years. We step on it, it figures out who is who, and the measurements appear in the Withings app. Nothing was wrong with that. I just wanted the same data in Home Assistant.

Home Assistant already has a Withings integration. It would have taken me a few minutes to set up, but it gets the measurements from your Withings account. The data still has to make this trip:

Body+ -> Withings cloud -> Home Assistant

I wanted to remove the middle step. After some digging with ChatGPT, it looked like an original ESP32 could talk to the scale over Bluetooth and send the result to Home Assistant using ESPHome. I already had one in a drawer, which was enough of an excuse to try it.

The hardware#

I didn't modify or open the scale. The ESP32 sits nearby and only needs a USB cable for power.

After a weigh-in, the Body+ sends the measurement to the ESP32 over Bluetooth. ESPHome passes it to Home Assistant over Wi-Fi.

Body+ -> ESP32 -> Home Assistant

I also removed the saved Wi-Fi network from the Body+, so the scale itself can no longer upload anything to Withings.

The exact ESP32 matters here. The Body+ syncs using Bluetooth Classic, while ESP32-C3 and ESP32-S3 boards only support Bluetooth LE. I happened to have an original ESP32 development board, and that was the right one. Any original ESP32 with Bluetooth Classic should work; a C3 or S3 won't.

Reverse-engineering the scale#

The ESP32 was the easy part. The problem was that the Body+ protocol isn't documented for anyone trying to replace the Withings app.

I gave the problem to OpenCode running Codex. It went through an old version of the Withings Android app, compared it with existing work on the protocol, and started building an ESPHome component.

That turned me into the world's least efficient test setup:

  1. Flash the ESP32.
  2. Walk to the bathroom.
  3. Put the scale into setup mode.
  4. Step on it.
  5. Walk back with the logs.
  6. Give the logs to Codex.
  7. Repeat.

The first builds did nothing. Later ones connected over Bluetooth but left the scale stuck on the setup screen. Every change meant another firmware build and another walk to the bathroom.

Then one of the logs finally showed Body+ association complete. I stepped on the scale again and my weight appeared in Home Assistant.

Codex did the part I realistically wasn't going to do myself: reading decompiled Android code, comparing Bluetooth packets, and turning that into C++ for the ESP32. I supplied the scale, the logs, and a ridiculous number of nearly identical weigh-ins.

It wasn't one magic prompt. It was mostly “that still doesn't work,” followed by another firmware build.

Two profiles, two sets of sensors#

I thought I might have to guess who was on the scale based on our weights. Luckily, the Body+ already identifies us and includes a user ID with every measurement.

I put both IDs in the ESPHome configuration. The component uses them to update either my sensors or my wife's and ignores IDs it doesn't know.

We each get our own history for:

  • Weight
  • Body fat
  • Fat mass
  • Muscle mass
  • Body water
  • Bone mass
  • Fat-free mass

The scale decides whose measurement it is. The ESP32 only sends it to the right place.

Keeping the last measurement in Home Assistant#

ESPHome exposes everything as normal sensors, so Home Assistant discovered the device without any extra work.

The raw sensors do become unavailable when I unplug the ESP32. That's correct, but not very helpful on a weight dashboard. My last weight shouldn't disappear because I borrowed the USB cable.

I added Home Assistant template sensors that keep the latest measurement. The ESP32 stores the same values, so they come back immediately after a restart. Our dashboards use step charts as well: a measurement stays flat until the next weigh-in instead of creating fake values between the two.

The result#

We still use the scale exactly as we did before. A few seconds after either of us steps on it, the correct sensors update in Home Assistant. The Body+ doesn't need Wi-Fi, we don't need to open the Withings app, and the data stays at home.

I've only tested this with our Body+, two profiles, and this particular ESP32. It isn't a universal integration for every Withings scale, so I wouldn't buy any hardware assuming it will work with a different model.

It was a lot of spend tokens when the official integration already exists, but now it works exactly how I wanted. And the ESP32 from my drawer finally has a permanent job.

Where is this code?#

Still haven't uploaded the code to GitHub but soon enought i will add the link here.