Skip to main content

Modern Async driver for Mobvoi/Horizon treadmills (Python 3.13+)

Project description

pymvtreadmill 🏃💨

A modern Python 3.13+ library to control and read data from Mobvoi Home Treadmills and Horizon fitness devices.

Features

  • Real-time Reading: Parses Speed directly from BLE notifications.
  • Modern Async: Built on asyncio and bleak.
  • Control: Set target speed (km/h) via Python commands.
  • Auto-Reconnect: Robust connection handling for continuous use.
  • Type Safe: Fully typed with modern Python 3.13+ syntax.
  • MQTT Bridge: Built-in CLI to bridge treadmill data to MQTT.

Data Protocol

The treadmill sends data as BLE notifications. Currently, only Speed is parsed.

Feature Resolution Protocol
Speed (Mobvoi) 0.01 km/h Bytes 3-4 (Big Endian)
Speed (Horizon) 0.1 km/h Bytes 3-4 (Big Endian)

Note: The current implementation defaults to Mobvoi resolution (0.01 km/h).

Installation

Using uv (Recommended)

uv pip install pymvtreadmill

Using pip

pip install pymvtreadmill

MQTT Bridge (CLI)

This package includes a command-line interface (CLI) to bridge treadmill data to an MQTT broker (e.g., for Home Assistant).

Usage

pymvtreadmill --help

Arguments

Argument Description Default
--treadmill-name Name filter for the treadmill Mobvoi
--mqtt-host MQTT broker hostname (Required for MQTT) -
--mqtt-port MQTT broker port 1883
--mqtt-username MQTT username -
--mqtt-password MQTT password -
--mqtt-topic MQTT topic for speed homeassistant/sensor/treadmill/speed/state

Running with Docker

You can run the project using Docker. This is useful if you want to run the treadmill controller in an isolated environment.

Prerequisites

  • Docker installed on your machine.
  • A Bluetooth adapter compatible with Linux (BlueZ).

Building the Image

docker build -t pymvtreadmill .

Running the CLI

To access the Bluetooth adapter from within the container, you need to share the DBus socket and run in privileged mode (or with NET_ADMIN capabilities).

By default, the container runs the pymvtreadmill CLI. You can pass arguments directly to it.

# Show help
docker run --rm -it pymvtreadmill --help

# Run as MQTT Bridge
docker run --rm -it \
  --net=host \
  --privileged \
  -v /var/run/dbus:/var/run/dbus \
  pymvtreadmill --mqtt-host 192.168.1.100 --mqtt-username myuser --mqtt-password mypass

Running Custom Scripts

If you want to run a custom python script (like the examples), you need to override the entrypoint:

docker run --rm -it \
  --entrypoint python \
  --net=host \
  --privileged \
  -v /var/run/dbus:/var/run/dbus \
  -v $(pwd)/my_script.py:/app/my_script.py \
  pymvtreadmill my_script.py

Docker Compose

For a more permanent setup, you can use the provided docker-compose.yml file.

  1. Edit docker-compose.yml to set your MQTT broker details in the command section.
  2. Run:
    docker-compose up -d
    

Usage (Library)

import asyncio
from pymvtreadmill import TreadmillClient

async def main():
    # You can connect by:
    # 1. Scanning (default): TreadmillClient()
    # 2. Address: TreadmillClient().connect("AA:BB:CC:DD:EE:FF")
    # 3. BLEDevice: TreadmillClient().connect(ble_device)

    async with TreadmillClient() as client:
        print(f"Connected to {client.client.address}")

        # Read properties
        print(f"Speed: {client.speed} km/h")
        print(f"Inclination: {client.inclination}%")
        print(f"Distance: {client.distance} m")

        # Set speed to 2.5 km/h
        await client.set_speed(2.5)

        # Keep running for a bit
        await asyncio.sleep(10)

if __name__ == "__main__":
    asyncio.run(main())

API Reference

TreadmillClient

Properties (Read-Only):

  • speed (float): Current speed in km/h.
  • inclination (float | None): Current inclination percentage (0.0 - 15.0+).
  • distance (int | None): Current session distance in meters.
  • total_distance (int): Total accumulated distance in meters across sessions.
  • last_run_distance (int | None): Distance of the last completed run session.
  • is_running (bool): Whether the treadmill is currently active.

Methods:

  • connect(device: BLEDevice | str | None = None): Connects to the treadmill. Accepts a bleak.backends.device.BLEDevice, a MAC address string, or None (triggers a scan).
  • disconnect(): Disconnects from the device.
  • set_speed(speed_kmh: float): Sets the target speed in km/h.

Development

This project strictly requires Python 3.13 or newer. We use uv for dependency management.

Setup

./scripts/setup_env.sh

Verification

uv run ruff check .
uv run black --check .
uv run mypy .
uv run pytest

Please read AGENTS.md before contributing to understand the architectural guidelines and protocol details.

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

pymvtreadmill-0.1.0.tar.gz (44.2 kB view details)

Uploaded Source

Built Distribution

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

pymvtreadmill-0.1.0-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file pymvtreadmill-0.1.0.tar.gz.

File metadata

  • Download URL: pymvtreadmill-0.1.0.tar.gz
  • Upload date:
  • Size: 44.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymvtreadmill-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9d7849ff96c37daa2e564550aa5a11af8ea4fab7560ffd8e1155acbbf0e1c558
MD5 59a638399fc4403f49f1a76a97dc5d1c
BLAKE2b-256 1da3210faf98ab950955c94cb83bc396cd35251623df9f0024fdbfd20ae366e7

See more details on using hashes here.

Provenance

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

Publisher: release.yml on JohNan/pymvtreadmill

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

File details

Details for the file pymvtreadmill-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pymvtreadmill-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymvtreadmill-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ccc27300a1e22dc7d1bc2897857e48bcb5e3287d5b10775c14d24df9c6b8f9ec
MD5 57953c8d379bd97a0d0db68b4bcd3640
BLAKE2b-256 5b303037675f779ebcf75328c3022ba2814279c3b70affb34a175b06ce142c36

See more details on using hashes here.

Provenance

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

Publisher: release.yml on JohNan/pymvtreadmill

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