Python library for interacting with the Acaia Lunar coffee scale over Bluetooth Low Energy (BLE)
Project description
acaia-lunar-ble
Python library for interacting with the Acaia Lunar coffee scale over Bluetooth Low Energy (BLE).
Built for specialty coffee enthusiasts who want to programmatically read weight data from their Acaia Lunar scale. Uses the bleak library for cross-platform BLE support (macOS, Linux, Windows).
Note: This library is specifically built for the Acaia Lunar model only — it does not support other Acaia scales (Acaia Pearl, Pyxis, etc.). It has been tested with the Lunar 2021 (Model AL008). Models AL009 and AL010 should work as well since they share the same BLE protocol, but have not been tested.
Features
- Real-time weight streaming (stable and unstable readings)
- Timer readback and control (start, stop, reset)
- Tare command
- Battery level and scale settings (units, auto-off, beep)
- Button event notifications (tare, start, stop, reset pressed on scale)
- Scan and discover nearby Acaia scales
- Automatic heartbeat to maintain connection
- Async/await API built on bleak
- Context manager support for clean connect/disconnect
Installation
pip install acaia-lunar-ble
Quick Start
import asyncio
from acaia_lunar_ble import ScaleConnection
def on_weight(weight: float):
print(f"Weight: {weight:.2f} g")
async def main():
scale = ScaleConnection("YOUR-SCALE-ADDRESS", weight_callback=on_weight)
if not await scale.connect():
print("Failed to connect")
return
await asyncio.sleep(30) # read weights for 30 seconds
await scale.disconnect()
asyncio.run(main())
Finding Your Scale's Address
If you don't know your scale's BLE address, use the built-in discovery:
import asyncio
from acaia_lunar_ble import ScaleConnection
async def main():
acaia_devices, all_devices = await ScaleConnection.discover()
for d in acaia_devices:
print(f"{d.name}: {d.address}")
if not acaia_devices:
print("No Acaia scales found. All nearby BLE devices:")
for d in all_devices:
print(f" {d.name or '(unknown)'}: {d.address}")
asyncio.run(main())
Example Script
An interactive example script is included in examples/demo.py:
python examples/demo.py <SCALE-ADDRESS>
Interactive commands during the session:
| Key | Action |
|---|---|
c |
Connect to the scale |
d |
Disconnect from the scale |
s |
Show connection status |
t |
Tare (zero the scale) |
1 |
Start timer |
2 |
Stop timer |
3 |
Reset timer |
g |
Get settings (battery, units, auto-off, beep) |
r |
Toggle raw BLE data stream logging |
h |
Show commands |
q |
Quit |
Weight and timer readings update in real-time. Type a command letter and press Enter. Press q + Enter to quit, or Ctrl+C.
Context Manager
For automatic cleanup, use async with:
async with ScaleConnection(address, weight_callback=on_weight) as scale:
await asyncio.sleep(60) # stream weights for 60 seconds
# automatically disconnects when exiting the block
API Reference
ScaleConnection(address, *, ...)
Main class for interacting with the scale.
Constructor parameters:
address— BLE address (MAC or UUID) of the scaleweight_callback— called with each weight reading in grams (float)timer_callback— called with timer value in seconds (float)battery_callback— called with battery percentage (int, 0-100)settings_callback— called with aScaleSettingsobject (battery, units, auto-off, beep)button_callback— called with button name (str):"tare","start","stop", or"reset"notification_callback— called with every raw BLE notification payload (bytearray)
Methods
| Method | Description |
|---|---|
await connect() |
Connect and start data streaming. Returns True on success. |
await disconnect() |
Stop streaming and disconnect. |
await scan_until_found() |
Block until the scale is found via BLE scan. |
await ScaleConnection.discover(timeout=5.0) |
Scan for nearby Acaia scales. Returns (acaia_devices, all_devices). |
await tare() |
Zero the scale. |
await start_timer() |
Start the scale's built-in timer. |
await stop_timer() |
Stop/pause the timer. |
await reset_timer() |
Reset the timer to zero. |
await get_settings() |
Request settings (response arrives via settings_callback). |
Properties
| Property | Type | Description |
|---|---|---|
weight |
float | None |
Latest weight reading in grams. |
timer |
float | None |
Latest timer value in seconds. |
settings |
ScaleSettings | None |
Latest settings from the scale. |
is_connected |
bool |
Whether the scale is currently connected. |
ScaleSettings
Dataclass with fields: battery (int), units (str), auto_off_minutes (int), beep (bool).
decode_weight(data)
Standalone function to decode a BLE notification payload into a weight value in grams. Returns None if the data doesn't match the expected format.
Protocol Details
The Acaia Lunar uses a proprietary BLE protocol. Communication happens over two GATT characteristics:
- Write characteristic (
49535343-8841-43f4-a8d4-ecbe34729bb3) — used for sending commands (identify, notification request, heartbeat) - Notify characteristic (
49535343-1e4d-4bd9-ba61-23c647249616) — streams weight and other data from the scale
The initialization sequence must follow this exact order:
- Subscribe to notifications
- Send IDENTIFY handshake
- Send NOTIFICATION_REQUEST to enable data streaming
- Start heartbeat loop (~3 second interval)
Requirements
- Python 3.10+
- Bluetooth Low Energy hardware
- bleak (installed automatically)
License
MIT
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 acaia_lunar_ble-1.0.0.tar.gz.
File metadata
- Download URL: acaia_lunar_ble-1.0.0.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9f2601ddcdb39bad6a51c0632b3054d7c3a89853f0d3766a06d660a6239d31d
|
|
| MD5 |
d9ddfe5e1de7cb2deb88329c882ce0c0
|
|
| BLAKE2b-256 |
666fcc46d8ce5a9ded70ba0c71dc2d00f1535399df447dd0d40c179250e5a889
|
Provenance
The following attestation bundles were made for acaia_lunar_ble-1.0.0.tar.gz:
Publisher:
publish.yml on beat843796/acaia-lunar-ble
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
acaia_lunar_ble-1.0.0.tar.gz -
Subject digest:
d9f2601ddcdb39bad6a51c0632b3054d7c3a89853f0d3766a06d660a6239d31d - Sigstore transparency entry: 1236048864
- Sigstore integration time:
-
Permalink:
beat843796/acaia-lunar-ble@12e4378d8d56cd4ac927807a50c0f43f05164ae5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/beat843796
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12e4378d8d56cd4ac927807a50c0f43f05164ae5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file acaia_lunar_ble-1.0.0-py3-none-any.whl.
File metadata
- Download URL: acaia_lunar_ble-1.0.0-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1ea9f1004d1d46ac7f3824a0bd6863d9e9b59858073fea825e789fe291fef28
|
|
| MD5 |
c807a3c3b434110322a93471eeb73377
|
|
| BLAKE2b-256 |
cf49217d07d85380498025c0c57f498a6e437e4aca136daeb1b30ce9fda1624b
|
Provenance
The following attestation bundles were made for acaia_lunar_ble-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on beat843796/acaia-lunar-ble
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
acaia_lunar_ble-1.0.0-py3-none-any.whl -
Subject digest:
b1ea9f1004d1d46ac7f3824a0bd6863d9e9b59858073fea825e789fe291fef28 - Sigstore transparency entry: 1236048879
- Sigstore integration time:
-
Permalink:
beat843796/acaia-lunar-ble@12e4378d8d56cd4ac927807a50c0f43f05164ae5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/beat843796
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12e4378d8d56cd4ac927807a50c0f43f05164ae5 -
Trigger Event:
push
-
Statement type: