openble-lifesense
The Lifesense A2/A3 Bluetooth weight-scale protocol, as spoken by the Philips DL8780 and other scales built on the Lifesense SDK.
openble.lifesense.packets: parsers for the weight (8A21, 8A24) and body-composition (8A22) packets.openble.lifesense.link: the 8A81 command frames, and the pair and sync handshake that makes the scale send a weigh.openble.lifesense.identify: matches advertisements and GATT tables to a scale.openble.lifesense.uuids: service and characteristic ids.
Pure Python 3.11+ with no dependencies and no Bluetooth stack. The handshake takes a write coroutine and a queue of indications, so it runs over bleak, a test double, or anything else.
pip install openble-lifesense
Parse a weigh
from openble.lifesense.packets import parse_a3_append, parse_a3_weight
weight = parse_a3_weight(
bytes.fromhex("1f 16 26 00 fe 89 50 91 1f 00 00 00 00 17 13 00 ff 01 19 00")
)
weight["weight_kg"], weight["impedance"], weight["date"]
# ('97.5', '488.7', '2026-10-13 19:50:33')
append = parse_a3_append(
bytes.fromhex("6d 89 50 91 1f 01 fc f0 32 f2 79 f1 26 f0 00 00 00 00 00 00")
)
append["body_fat_ratio"]
# '25.2'
parse_scale_notification(short, data, family=..., previous=...) picks the parser the Lifesense dispatcher would use for a characteristic. identify.protocol_digit(service_uuids) gives the family.
Pair and sync with bleak
The scale sends a 0xA0 password when it is in pairing mode (hold the unit button for 3 s) and a 0xA1 random when it is already paired. run_scale_handshake answers either one. It stores the password and broadcast id in a ScaleStore JSON file, and it needs that same file for every later sync.
import asyncio
from pathlib import Path
from bleak import BleakClient
from openble.lifesense.link import ScaleStore, run_scale_handshake
from openble.lifesense.packets import parse_a3_weight
from openble.lifesense.uuids import sig
async def weigh(address: str) -> None:
commands: asyncio.Queue[bytes] = asyncio.Queue()
async with BleakClient(address) as client:
await client.start_notify(
sig("8a24"), lambda _, data: print(parse_a3_weight(bytes(data)))
)
await client.start_notify(
sig("8a82"), lambda _, data: commands.put_nowait(bytes(data))
)
async def write(payload: bytes) -> None:
await client.write_gatt_char(sig("8a81"), payload, response=True)
await run_scale_handshake(
write=write,
queue=commands,
store=ScaleStore(Path("scale.json")),
device_key=address,
user_number=1,
user_name="User",
password_override=None,
listen_seconds=60,
log=lambda kind, **payload: print(payload.get("message", "")),
)
apps/ble-probe and apps/bathroom-hub in the repository are complete clients built this way.
Protocol notes
- docs/lifesense-scale-protocol.md: the static manual, read from the Philips Health app's bytecode.
- docs/dl8780-connection-handoff.md: what worked against a live DL8780, including the HCI capture the sync sequence follows.
Not affiliated with Philips or Lifesense. The names identify the devices this interoperates with.
License
MIT License, copyright 2026 Kadima Tech.
Metadata
Release files for openble-lifesense 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| openble_lifesense-0.1.0.tar.gz | 38.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openble_lifesense-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.7 kB
Release files / openble_lifesense-0.1.0.tar.gz
| Download URL | openble_lifesense-0.1.0.tar.gz |
|---|---|
| Size | 38.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c2771cf1664ed20a6e996c961842d958995e327724fd4c02bbad28751a7f73b
|
|
BLAKE2b-256 checksum How to use checksums |
cb0de836a9fe56a5ec40619a71f8d0c90e2428da83aac8eab44643ffc92ebf1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / openble_lifesense-0.1.0-py3-none-any.whl
| Download URL | openble_lifesense-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d8750fb4fba1bbeeb1a591eb1cecd0fe6a1d8775e6b351d874e1b9209afb588c
|
|
BLAKE2b-256 checksum How to use checksums |
a99329428a20fbb7873c1c3fe432fd7b9940a3dabb2235cb665e5439f5b8a1bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for openble-lifesense 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for openble_lifesense-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.