wedopy
Python library for the LEGO WeDo 2.0 Smart Hub over Bluetooth Low Energy. Public API in Python, execution core in Cython. Implements design spec 1.2.0.
from wedopy import Hub, task
with Hub() as hub:
motor = hub.motor("A")
motor.run(100)
Install (development)
python -m venv .venv && source .venv/bin/activate
python -m pip install -e ".[dev]" # builds the Cython extension, installs bleak
python -m pytest
Or with uv:
uv sync
uv run pytest
Linux/BlueZ is the first supported platform (BLE through bleak).
Layout
| Path | Contents |
|---|---|
src/wedopy/ |
Public API: Hub, Motor, MotorGroup, sensors, LED, Button, task, tasks, exceptions |
wedopy_core/_wedopy.pyx |
Cython core: protocol codecs, state machine, single-writer coordinator, heartbeat, watchdog |
wedopy_core/transport/ |
Transport interface, BleakTransport (BLE), SimulatedHub (tests) |
wedopy_core/protocol/ |
UUIDs and constants |
wedopy_core/runtime/ |
Timing parameters, process supervisor |
tests/, examples/ |
pytest suite (simulated hub), runnable examples |
Deviations from the spec's tree: src/wedo/ is src/wedopy/ (the import name is wedopy); the
compiled module is wedopy_core._wedopy; protocol codecs live in the Cython core instead of
separate .py files; exceptions are defined in wedopy_core/exceptions.py and re-exported by
wedopy.exceptions, so the core never imports the public package.
Behaviour worth knowing
- Every BLE operation goes through one coordinator thread (single writer). Writes and the heartbeat are always with response; there is no silent fallback to write-without-response.
- While any motor has a non-zero speed, a heartbeat (Battery Level read) runs every 0.5 s. With
no valid ACK for 2 s the watchdog stops the motors with emergency priority (2 attempts), logs
the result on
wedopy.watchdog, and moves the hub toerror. The watchdog and heartbeat run on their own thread, so a blocked task scheduler cannot disable them. - Normal operations time out after 1 s, which bounds how long an emergency request can wait behind an in-flight operation (an in-flight BLE call cannot be aborted).
- Stop profile is
nobarrier.strongis not offered. hub.tasks.cancel()never stops motors; protect motors withtry/finally, or callhub.stop_all(). Leavingwith Hub()cancels tasks first, then stops motors.- Logging goes through the standard
loggingmodule (wedopy,wedopy.watchdog,wedopy.tasks). - Sensors only notify on change.
read_angle(),read_direction()and the distance sensor return the last value; if the physical value has not changed since the last notification, the call blocks until the sensor sends a new sample or the timeout fires. Move/incline the sensor (or expose it to a new distance) after configuring it. - The tilt sensor is a 4-position switch, not an accelerometer. Its direction mode (1) uses
UNIT_SI(4-bytefloat32); its angle mode (0) requiresUNIT_RAW(2-byteint8pair) — withUNIT_SIthe hub silently ignores the configuration. Bump mode (2) is accepted by the hub but never emits; the firmware does not implement it.
Status
Verified with the simulated hub and on real WeDo 2.0 hardware (Nov 2026):
- Compiled Cython build (
wedopy_core._wedopy). BleakTransporton Linux/BlueZ: connect, port discovery, notifications.- Tilt sensor: direction mode (1,
UNIT_SI) and angle mode (0,UNIT_RAW). - Battery, button, LED, motor, distance sensor.
Not yet verified on hardware: watchdog timings under a real BLE stall,
refresh_ports() replay, behaviour when the process is killed with the link
open, and the strong stop profile (not implemented).
wedopy_core/_wedopy.pyx is written in the subset of Cython that is also valid Python, so
tests/conftest.py can run it uncompiled when the extension is not built (it warns). Typed
cdef optimisations can be added later once profiling shows they matter.
Metadata
Release files for wedopy 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| wedopy-0.1.0.tar.gz | 283.4 kB | With provenance | Details for wedopy-0.1.0.tar.gz |
Release files / wedopy-0.1.0.tar.gz
| Download URL | wedopy-0.1.0.tar.gz |
|---|---|
| Size | 283.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f32fd9d55c42d2939f95bc1f6fe9fef12771068c24c86ce25229c1c4be311fef
|
|
BLAKE2b-256 checksum How to use checksums |
ae7ed4779ad48b923a6b2b5b991993d39b99f775589f17678af11646e4ed4d23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 8, 2026.
Transparency logSecurity for wedopy 0.1.0
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.
Full provenance
1 file in this release has been uploaded with provenance metadata.
Attestation for wedopy-0.1.0.tar.gz
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 Nov 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.