Decode/encode BLE packets for the SACOMA Ultra (ICOMON/Fitdays) 8-electrode body-composition scale, and compute body composition (WLA25).
Project description
sacoma
A small, focused Python library for the SACOMA Ultra 8-electrode body-composition scale (ICOMON / Chipsea hardware, Fitdays app). Its single responsibility is BLE bytes ⇄ values:
- bytes → values — decode the scale's notification frames into weight + impedances, and compute the full body composition (BMI, body-fat %, segmental fat/muscle, water, BMR, …).
- values → bytes — build the command frames to send back to the scale.
The library performs no I/O — it never touches Bluetooth, files, or the network. Bring your own BLE stack; feed it bytes and it returns values.
Status
- ✅ Frame reassembly + decoding — A2 weight stream and A3 result (weight + 10 segmental impedances).
- ✅ Body-composition algorithm (
WLA25) — bit-exact pure-Python port (sacoma/wla25.py). - ✅ Command encoding (values → bytes) —
BA/BB/B0/BDFFB1 frames (sacoma/encoder.py).
Install
The distribution is sacoma-lib; the import package is sacoma.
pip install sacoma-lib # from PyPI
pip install -e . # from a checkout (pulls ezpacket from PyPI)
pip install -e ".[dev]" # + pytest/ruff/build/twine for development
pip install -e ".[ble]" # + bleak, only for the example runner
Usage
Decode (scale → app):
from sacoma import FrameAssembler, decode_frame
assembler = FrameAssembler()
for frame in notifications: # raw 20-byte FFB2/FFB3 frames from your BLE stack
measurement = decode_frame(frame, assembler)
if measurement is not None: # a complete result message arrived
print(measurement.weight_kg, measurement.impedances_ohm)
Compute body composition from a result:
from sacoma import calculations, UserProfile, Sex, PeopleType
profile = UserProfile(height_cm=165, age=30, sex=Sex.MALE, people_type=PeopleType.NORMAL)
body = calculations.compute(measurement, profile) # BodyComposition: bmi, body_fat, segments, ...
Encode (app → scale): build the FFB1 command frames the scale expects.
from sacoma import encoder
frames = encoder.encode_sync(sequence=0, weight_kg=64.9) # list[bytes], ready to write to FFB1
for f in frames:
ble_write("0000ffb1-...", f)
Talking to a real scale (Windows)
scripts/ble_test.py is a tiny bleak runner that uses only this
library for encode/decode:
py -3 scripts\ble_test.py --scan # find the scale's BLE address
py -3 scripts\ble_test.py --address AA:BB:CC:.. # stream decoded weight + result
py -3 scripts\ble_test.py --address AA:BB:CC:.. --drive # also push the handshake (experimental)
Documentation
- The wire protocol (frame format, 5-bit checksum, the
BA/BB/B0/BDcommands, A2/A3 layouts) is documented indocs/protocol.md. The encode/decode source insacoma/encoder.pyandsacoma/protocol.pyis the authoritative spec. - The algorithm (how impedances + profile become the reported values, with the formulas
and clamps) is documented in
docs/algorithm.md.
Note — the scale displays its own numbers. Verified byte-for-byte across many captures: the phone never transmits computed body-composition to the scale. The scale computes the 6 values on its own screen (fat %, BMI, muscle, water %, body age, bone) from the impedance it measures plus the profile/weight the phone syncs over
BA/BB. So this library drives the scale (by syncing profile/weight); it cannot override what the scale chooses to display.
Scope
Intentionally tiny: BLE bytes ⇄ values, nothing else. Device discovery, connection management, retries, and Home Assistant wiring live outside the library.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sacoma_lib-0.1.0.tar.gz.
File metadata
- Download URL: sacoma_lib-0.1.0.tar.gz
- Upload date:
- Size: 22.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
686294c851dbe17a0c2ea95db4654e562c9bea1c1c308a7bf2b6229112fef241
|
|
| MD5 |
97af43b2d111332a21d064f9ef21cc43
|
|
| BLAKE2b-256 |
90efa30f10495a006ff47fd7a4204a3212a7f56fce42b3a7758a6cd49929c155
|
Provenance
The following attestation bundles were made for sacoma_lib-0.1.0.tar.gz:
Publisher:
publish.yml on ynsgnr/sacoma-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sacoma_lib-0.1.0.tar.gz -
Subject digest:
686294c851dbe17a0c2ea95db4654e562c9bea1c1c308a7bf2b6229112fef241 - Sigstore transparency entry: 1818949006
- Sigstore integration time:
-
Permalink:
ynsgnr/sacoma-lib@76a461f25653f24274f4d2562bda31e43d2835b5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ynsgnr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76a461f25653f24274f4d2562bda31e43d2835b5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file sacoma_lib-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sacoma_lib-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d15d0a8b9285831a2853827f2db9163adcd38e912d99f16f154084066c2066a0
|
|
| MD5 |
40b110162d582e5a3e83bb9b597b2981
|
|
| BLAKE2b-256 |
62efd23814e3b5b5051ad7b00f7df89ede69111a61f02184d39c0a273a353d1c
|
Provenance
The following attestation bundles were made for sacoma_lib-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ynsgnr/sacoma-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sacoma_lib-0.1.0-py3-none-any.whl -
Subject digest:
d15d0a8b9285831a2853827f2db9163adcd38e912d99f16f154084066c2066a0 - Sigstore transparency entry: 1818949058
- Sigstore integration time:
-
Permalink:
ynsgnr/sacoma-lib@76a461f25653f24274f4d2562bda31e43d2835b5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ynsgnr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76a461f25653f24274f4d2562bda31e43d2835b5 -
Trigger Event:
release
-
Statement type: