Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

joule-ble

Asynchronous Python library for interfacing with ChefSteps and Breville Joule sous vide devices over Bluetooth Low Energy (BLE).

Designed following Home Assistant standards for Bluetooth integration libraries, supporting both passive advertisement discovery and active appliance control.


Features

  • Hardware Generation Support:
    • Original ChefSteps Joule (CS10001 / CS20001): ChefSteps Stream GATT Service (700b4321-9836-4383-a2b2-31a9098d1473).
    • Breville Joule Turbo (CS30001): Breville FreeRTOS GATT Service (c6f2d9e3-49e7-4125-9014-bfc6d669ff00).
  • Complete Sous Vide Operations:
    • Start cook program (setpoint temperature in °C, optional cook time, delayed start, holding temperature).
    • Adjust target temperature setpoint dynamically during cooking.
    • Stop heating and circulation.
    • Clear errors and faults.
    • Identify device (flashes indicator LED).
    • Authenticated session pairing and key exchange support.
  • Rich Live Telemetry:
    • Bath water temperature (°C).
    • Heater temperature (°C).
    • Upper and lower control board temperatures (°C).
    • Motor RPM and motor current / PWM.
    • Program step (Idle, Preheating, Waiting for food, Cooking, Complete, Error).
    • Low water level and safety fault detection.
  • Home Assistant Standards:
    • Modern bleak and bleak-retry-connector connection management with auto-reconnect handling.
    • Built-in JouleBluetoothDeviceData for BLE advertisement decoding and device discovery in config flows.
    • Fully typed dataclasses with native Celsius float representation.

Installation

pip install joule-ble

Quickstart

1. Advertisement Discovery (Config Flow)

from bleak.backends.scanner import AdvertisementData
from bleak.backends.device import BLEDevice
from joule_ble import JouleBluetoothDeviceData

scanner_parser = JouleBluetoothDeviceData()

# Called from Home Assistant bluetooth scanner callback:
device_info = scanner_parser.update(ble_device, advertisement_data)
if device_info:
    print(f"Discovered {device_info.name} ({device_info.model}) at {device_info.mac_address}")

2. Controlling the Joule & Live Telemetry

import asyncio
from bleak import BleakScanner
from joule_ble import JouleClient, JouleState, MIN_TEMP_C, MAX_TEMP_C

async def main():
    # Discover device
    device = await BleakScanner.find_device_by_filter(
        lambda d, adv: "joule" in (adv.local_name or "").lower()
    )
    if not device:
        print("No Joule found!")
        return

    client = JouleClient(device)

    # Listen for live status updates
    def state_updated(state: JouleState):
        print(
            f"Bath: {state.bath_temp_c}°C | Target: {state.target_temp_c}°C | "
            f"Step: {state.program_step} | RPM: {state.motor_rpm} | Low Water: {state.low_water}"
        )

    client.register_callback(state_updated)

    await client.connect()
    print("Connected! Device:", client.device_info)

    # Start heating to 54.0°C with a 1 hour timer (3600s)
    await client.start_cook(target_temp_c=54.0, cook_time_seconds=3600)
    await asyncio.sleep(10)

    # Change temperature setpoint to 55.0°C
    await client.set_temperature(55.0)
    await asyncio.sleep(10)

    # Stop cooking
    await client.stop_cook()
    await client.disconnect()

asyncio.run(main())

Architecture & Protocols

The Joule uses Google Protocol Buffers (StreamMessage) transmitted across BLE GATT characteristics:

  • ChefSteps Stream Service: 700b4321-9836-4383-a2b2-31a9098d1473
    • Write: 700b4322-9836-4383-a2b2-31a9098d1473
    • Subscribe: 700b4325-9836-4383-a2b2-31a9098d1473
  • Breville Service: c6f2d9e3-49e7-4125-9014-bfc6d669ff00
    • App Message (Write): c6f2d9e3-49e7-4125-9014-bfc6d669ff09
    • Appliance Message (Notify): c6f2d9e3-49e7-4125-9014-bfc6d669ff08

Messages exceeding the negotiated ATT MTU are automatically fragmented into chunks on transmission and reassembled upon reception.


License

Apache 2.0

Metadata

Release files for joule-ble 0.1.0a19

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for joule-ble 0.1.0a19
File Size Uploaded
joule_ble-0.1.0a19.tar.gz 58.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for joule-ble 0.1.0a19
File Interpreter ABI Platform
joule_ble-0.1.0a19-py3-none-any.whl Python 3 none any Details

Total release size: 109.0 kB

Release files / joule_ble-0.1.0a19.tar.gz

Download URL joule_ble-0.1.0a19.tar.gz
Size 58.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e3dfb1488acc354ba0390934c50f87079e9e422d9f4c5cbb36ef4f4dab195bef
BLAKE2b-256 checksum
How to use checksums
d19350b9b506bf76209cd9028fd4f55ebc2db13bc874a9f134709f0d3b6823f3
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 17, 2026.

Transparency log

Release files / joule_ble-0.1.0a19-py3-none-any.whl

Download URL joule_ble-0.1.0a19-py3-none-any.whl
Size 50.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
62c23d630620e7a79d4e9ce69f47e2f0f8cbb43b0ffbae574bd20eb5760d9073
BLAKE2b-256 checksum
How to use checksums
ffba33d0e533afb6ee07a2380a89b6dde770398f0d2aacafa8b7cc4b25f16e61
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 17, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page