Skip to main content

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:

  1. 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, …).
  2. 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/BD FFB1 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/BD commands, A2/A3 layouts) is documented in docs/protocol.md. The encode/decode source in sacoma/encoder.py and sacoma/protocol.py is 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sacoma_lib-0.1.0.tar.gz (22.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sacoma_lib-0.1.0-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

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

Hashes for sacoma_lib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 686294c851dbe17a0c2ea95db4654e562c9bea1c1c308a7bf2b6229112fef241
MD5 97af43b2d111332a21d064f9ef21cc43
BLAKE2b-256 90efa30f10495a006ff47fd7a4204a3212a7f56fce42b3a7758a6cd49929c155

See more details on using hashes here.

Provenance

The following attestation bundles were made for sacoma_lib-0.1.0.tar.gz:

Publisher: publish.yml on ynsgnr/sacoma-lib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for sacoma_lib-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d15d0a8b9285831a2853827f2db9163adcd38e912d99f16f154084066c2066a0
MD5 40b110162d582e5a3e83bb9b597b2981
BLAKE2b-256 62efd23814e3b5b5051ad7b00f7df89ede69111a61f02184d39c0a273a353d1c

See more details on using hashes here.

Provenance

The following attestation bundles were made for sacoma_lib-0.1.0-py3-none-any.whl:

Publisher: publish.yml on ynsgnr/sacoma-lib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page