Skip to main content

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 scale
  • weight_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 a ScaleSettings object (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:

  1. Subscribe to notifications
  2. Send IDENTIFY handshake
  3. Send NOTIFICATION_REQUEST to enable data streaming
  4. Start heartbeat loop (~3 second interval)

Requirements

  • Python 3.10+
  • Bluetooth Low Energy hardware
  • bleak (installed automatically)

License

MIT

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

acaia_lunar_ble-1.0.0.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

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

acaia_lunar_ble-1.0.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

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

Hashes for acaia_lunar_ble-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d9f2601ddcdb39bad6a51c0632b3054d7c3a89853f0d3766a06d660a6239d31d
MD5 d9ddfe5e1de7cb2deb88329c882ce0c0
BLAKE2b-256 666fcc46d8ce5a9ded70ba0c71dc2d00f1535399df447dd0d40c179250e5a889

See more details on using hashes here.

Provenance

The following attestation bundles were made for acaia_lunar_ble-1.0.0.tar.gz:

Publisher: publish.yml on beat843796/acaia-lunar-ble

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

File details

Details for the file acaia_lunar_ble-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for acaia_lunar_ble-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b1ea9f1004d1d46ac7f3824a0bd6863d9e9b59858073fea825e789fe291fef28
MD5 c807a3c3b434110322a93471eeb73377
BLAKE2b-256 cf49217d07d85380498025c0c57f498a6e437e4aca136daeb1b30ce9fda1624b

See more details on using hashes here.

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

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