No description
Find a file
Tiago Águeda 6cf4b54566
docs: make the Forgejo repository canonical, GitHub a mirror
GitHub now exists solely so HACS can ingest the integration — it resolves
updates from GitHub releases and cannot read the forge. Everything else lives
on source.tiagoagueda.com.

The manifest's documentation and issue_tracker links move to the canonical
repository, and the README says plainly that changes pushed only to the mirror
will be overwritten, so nobody wastes a pull request there.

`origin` points at Forgejo and carries a second push URL for GitHub, so one
`git push origin main --tags` updates both and the two cannot silently drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 17:59:34 +02:00
custom_components/pcpw3008 docs: make the Forgejo repository canonical, GitHub a mirror 2026-08-16 17:59:34 +02:00
scripts feat: add entity icons and a placeholder brand icon 2026-08-16 16:04:12 +02:00
tests feat: multi-user support, one person per on-scale profile slot 2026-08-16 16:12:40 +02:00
.gitignore feat: ProfiCare PC-PW 3008 BT scale integration 2026-08-16 14:33:47 +02:00
hacs.json feat: ProfiCare PC-PW 3008 BT scale integration 2026-08-16 14:33:47 +02:00
LICENSE feat: ProfiCare PC-PW 3008 BT scale integration 2026-08-16 14:33:47 +02:00
README.md docs: make the Forgejo repository canonical, GitHub a mirror 2026-08-16 17:59:34 +02:00

ProfiCare PC-PW 3008 BT — Home Assistant integration

Canonical source: https://source.tiagoagueda.com/tiagoagueda/hass-pcpw3008

The GitHub repository is a mirror. It exists only so HACS can ingest the integration — HACS installs from GitHub releases and cannot read this forge. Open issues and pull requests on the canonical repository; changes pushed only to the mirror will be overwritten.

Reads weight and body composition from a ProfiCare PC-PW 3008 BT bathroom scale over Bluetooth LE, with no vendor cloud and no phone app involved.

The same firmware ships under other brands (it is the Chipsea "WeChat scale" platform, also sold as the Hoffen BBS-8107), so other rebrands may work by changing LOCAL_NAME in const.py.

Sensors

Sensor Notes
Weight kg, the only value measured directly
Body fat, Water, Muscle % — computed on the scale, see below
Bone mass kg
Basal metabolic rate kcal
BMI, Visceral fat, Body age computed on the scale

The profile matters

The scale has no impedance output. It computes body composition itself, from a gender/age/height profile pushed to it at the start of every session, and returns only the finished numbers. So:

  • Weight is always correct, whatever the profile says.
  • Everything else is only as correct as the profile you configure.

You can edit the profile any time via the integration's Configure button; the entry reloads so the next weigh-in uses it.

The profile also carries a slot (P0, P1, …) — the same user selector the scale's own display and the vendor app use. Set it to the slot you normally weigh under so Home Assistant and the scale agree about whose history a reading belongs to.

Multi-person households are handled with one person per config subentry (Settings → the integration → Add person), each bound to a Home Assistant user and to an on-scale profile slot (P0, P1, …). Home Assistant already restricts config and subentry flows to admins, so only an admin can create or change those associations.

Identification is by weight. At the start of a session the integration pushes the profile of whoever weighed last — households repeat, so this is usually right — then attributes the settled reading to whoever's known weight is nearest, learning that weight for next time.

When the guess was right, the scale's composition figures are correct and kept. When it was wrong, they were computed for somebody else's body, so they are dropped rather than shown under the wrong name: weight survives, and BMI is recomputed for the right height. The weight sensor carries body_composition_valid and match_margin_kg attributes so an uncertain attribution is visible instead of looking confident.

Use the pcpw3008.reassign_measurement service to move a weigh-in to the right person. Same rule applies — weight and BMI move, composition does not.

How it works

The scale is powered down and invisible almost all the time. Rather than poll, the integration asks Home Assistant's Bluetooth stack to notify it when the scale starts advertising — which happens when you step on it — and then runs one short session:

connect                        ~2.7s once awake
subscribe 0xFFB2
write user profile     -> ACK
write unit             -> ACK, sometimes nothing at all
... live frames while you settle ...
final frame                    ~15s after connect
write measurement-done         -> scale powers off

Two behaviours worth knowing, both observed on real hardware:

  • The unit ACK is optional — on some sessions the scale skips it and streams immediately, so the handshake is fire-and-forget rather than a state machine that waits.
  • The final frame repeats several times, so measurements are de-duplicated.

Sensors deliberately stay available between weigh-ins. Tying availability to the radio would make every entity unavailable most of the day and shred history.

Requirements

  • A connectable Bluetooth adapter or proxy within range of the scale. A passive-only ESPHome bluetooth_proxy can see the scale but never connect to it; it needs active: true.
  • Nothing else — no account, no internet.

Installation

HACS → ⋮ → Custom repositories → add this repo as an Integration → install → restart Home Assistant.

Manual — copy custom_components/pcpw3008/ into your config/custom_components/ and restart.

Then step on the scale: it should be discovered automatically. If not, add it via Settings → Devices & Services → Add Integration while the scale is awake — it cannot be found while asleep.

Protocol

Documented in custom_components/pcpw3008/protocol.py, which is pure functions and covered by tests/test_protocol.py against frames captured from real hardware. Cross-checked against the vendor's "Dr.Curve+" app and openScale's HoffenBbs8107Handler.

Releasing

origin is the canonical Forgejo repository and fans out to the GitHub mirror on every push, so the two cannot silently drift:

git push origin main --tags     # -> Forgejo AND GitHub

HACS resolves updates from GitHub releases, so a release has to be tagged there as well as pushed. github is a separate remote for that.

Credits

Protocol work grew out of adding this scale to openScale (PR #1476).