Skip to main content

rustuya-local

hacs_badge

Local control of Tuya devices through rustuya-bridge, as IL (ildevice) devices, and in Home Assistant. It replaces rustuya-homeassistant.

rustuya-bridge ──MQTT──► rustuya-local ──MQTT (il/…)──► il-ha (Home Assistant integration), or any IL consumer
 raw LAN dps             Service:
                         BridgeClient + tuya2ildevice.Hub
  • tuya2ildevice is the only place that interprets Tuya: Home Assistant core's tuya behaviour, the user overrides for non-standard devices, and the host parts (runner, transports, file watchers).
  • rustuya-local is one Service (src/rustuya_local/service.py) and three thin shells that run it: the rustuya-local run daemon, the custom_components/rustuya Home Assistant integration, and a rustuya-manager plugin. It only produces IL and knows nothing of Home Assistant entities.
  • il-ha turns IL descriptors into Home Assistant entities.

Daemon

uv venv && uv pip install -e .        # sibling checkouts: see pyproject.toml's [tool.uv.sources]
rustuya-local run --config config.json

config.json (see src/rustuya_local/config.py): the bridge and IL brokers, the IL prefix, the device list, a custom_converters directory, and options for the Hub (allow_hazardous, expose_unused, overrides). The device list is the tuyadevices.json that rustuya-manager keeps (its QR-login wizard writes it, with each device's cloud category/function/status_range/local_strategy); rustuya-local follows it as it changes and never writes it. IL carries only the devices that are also registered on the bridge. The bridge's own topic templates are read from its retained {root}/bridge/config.

Home Assistant

Coming from rustuya-homeassistant: docs/MIGRATING.md.

Install il-ha, and run one IL producer per bridge: the daemon, the integration below, or the manager plugin. A second one with the same IL prefix and source refuses to start while the first runs (every device would show twice): the daemon exits, the integration is retried by Home Assistant, the plugin's tab shows it and retries. To move from one to another, stop the old one first.

The rustuya integration (HACS: add this repository as a custom repository of type Integration, install Rustuya, restart, then Add Integration → Rustuya) is the service tied to a config entry, with the QR login wizard, bridge registration and an optional embedded bridge. It creates no entities itself.

Overrides for non-standard devices

Tuya's cloud schemas are fragmented; fixes go in a custom_converters/ directory (daemon: custom_converters in the config; integration: <config>/rustuya_converters; manager plugin: its data dir), followed live:

  • *.json: tuya2ildevice override blocks by product or device id: rename a dp, define one the schema lacks, map the device's words to the standard ones (remap.alias), invert a direction (remap.invert), fix labels and classes, turn on a code converter. rustuya-homeassistant's custom_converters JSON files load as they are.
  • *.py: code converters (CONVERTERS = {"name": factory}).

See tuya2ildevice's README ("User overrides") for the format. A curated set ships in tuya2ildevice, and fixes published between its releases (its override pack) are copied into the directory at start and daily, as 00_pack_* files that your own files refine. Turn that off with "pack": false (daemon), the integration's Tuning options, or the plugin tab. The pack only replaces or removes the files it put there, and leaves a file alone once you edit it.

In Home Assistant the files can be edited from a sidebar panel: turn on Show the Rustuya panel in the integration's Tuning options. The panel is for administrators. It shows the bridge's devices against the cloud list as rustuya-manager does (missing, orphan, mismatch, synced, each a filter you can turn off; sub-devices under their gateway; each device's bridge connection, live while the panel is open) with add / update / remove, lists the converter files with the pack's marked, edits and deletes them, and runs the pack sync on demand.

rustuya-manager plugin

Installed next to rustuya-manager, as a pip package (pip install rustuya-local in the manager's environment) or as the drop-in zip each release carries (rustuya_local-<version>-dropin.zip, tuya2ildevice vendored inside, built by scripts/build_dropin.py; unpack it into the manager's plugin directory, or install it from the manager's plugin catalog once listed there), it appears as a Tuya (IL) tab and runs the service under the manager: the manager's broker and bridge root, the manager's device list (followed). Its data dir (rustuya-local/ next to the manager's plugins) holds settings.json (il, options) and custom_converters/, and the tab edits both: saved settings restart the service in place, saved converter files are picked up while it runs. A settings file it cannot use is shown on the tab until it is fixed.

The drop-in zip freezes the tuya2ildevice it was built with: a tuya2ildevice fix reaches manager users with the next rustuya-local release (bump the patch version and tag; the manager's catalog follows the release). Installed both ways (pip and the plugin directory), the plugin runs once.

Tests

.venv/bin/python -m pytest

Everything here needs the sibling repos and, for the last two groups, mosquitto, pyrustuya-bridge and tuyamock (pip install -e ".[test,fullstack]"); those are skipped when missing. Parity with Home Assistant core's fixtures lives in tuya2ildevice/tests/chain, the wire and topic vectors in ildevice/vectors.

  • tests/unit/: the configuration.
  • tests/e2e/test_service.py: the service on in-memory brokers (overrides directory, a failed start).
  • tests/e2e/test_chain_*.py, test_daemon.py: the runner with il-ha's consumer model on the other side, in one process and over a real broker; the daemon as a subprocess.
  • tests/e2e/test_manager_plugin.py: the plugin under rustuya-manager's real plugin host (skipped without it).
  • tests/ha/: the integration (config flow, setup).
  • tests/e2e/test_full_stack*.py: the real rustuya-bridge (pyrustuyabridge, in process) and Tuya device emulators (tuyamock) around the daemon: state, commands, rejections, a device dropping off and returning, a daemon restart, and a differential check that 38 real device shapes come out of the whole chain exactly as tuya2ildevice computes them.

Status

Planning, progress and open decisions: docs/REDESIGN.md.

Licence: LICENSE (MIT).

Metadata

Release files for rustuya-local 0.0.25

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

Source distribution (sdist)

Source distribution for rustuya-local 0.0.25
File Size Uploaded
rustuya_local-0.0.25.tar.gz 190.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rustuya-local 0.0.25
File Interpreter ABI Platform
rustuya_local-0.0.25-py3-none-any.whl Python 3 none any Details

Total release size: 218.2 kB

Release files / rustuya_local-0.0.25.tar.gz

Download URL rustuya_local-0.0.25.tar.gz
Size 190.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5045ce25ab113d349d8828ab3163e6628af60e5b70121f8621ed3bd6f36d3cea
BLAKE2b-256 checksum
How to use checksums
5b38fd56d57d51baf690f05a5cddf5d502e2d1e3c62be7c7468bc31967e02753
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 Sep 28, 2026.

Transparency log

Release files / rustuya_local-0.0.25-py3-none-any.whl

Download URL rustuya_local-0.0.25-py3-none-any.whl
Size 27.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36f6675f035e9241a6694fe13738eb0f92dcbdae99627037a750d21d30dc9f84
BLAKE2b-256 checksum
How to use checksums
ee27fbbb443668ac2b4cb6ad4bcae527a8b9934c59ec1bd548530b2fe34c37a4
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 Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.0.53

2 release files

0.0.48

2 release files

0.0.47

2 release files

0.0.46

2 release files

0.0.45

2 release files

0.0.44

2 release files

0.0.43

2 release files

0.0.42

2 release files

0.0.40

2 release files

0.0.39

2 release files

0.0.38

2 release files

0.0.37

2 release files

0.0.36

2 release files

0.0.34

2 release files

0.0.33

2 release files

0.0.32

2 release files

0.0.31

2 release files

0.0.30

2 release files

0.0.29

2 release files

0.0.28

2 release files

0.0.27

2 release files

0.0.26

2 release files

This release

0.0.25 This release

2 release files

0.0.24

2 release files

0.0.23

2 release files

0.0.22

2 release files

0.0.21

2 release files

0.0.20

2 release files

0.0.19

2 release files

0.0.18

2 release files

0.0.17

2 release files

0.0.16

2 release files

0.0.15

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

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