Metadata-Version: 2.4
Name: pyrustuyabridge
Version: 0.4.0.dev1
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Home Automation
Classifier: Topic :: System :: Networking
Requires-Dist: pytest ; extra == 'test'
Requires-Dist: paho-mqtt>=2 ; extra == 'test'
Requires-Dist: tuyamock ; extra == 'test'
Provides-Extra: test
Summary: Python bindings for rustuyabridge — an MQTT bridge for Tuya devices
Keywords: tuya,mqtt,iot,bridge,smart-home,automation
Author: 3735943886
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Project-URL: Homepage, https://github.com/3735943886/rustuya-bridge
Project-URL: Issues, https://github.com/3735943886/rustuya-bridge/issues
Project-URL: Repository, https://github.com/3735943886/rustuya-bridge

# pyrustuyabridge

Python bindings for [rustuya-bridge](https://github.com/3735943886/rustuya-bridge),
an MQTT bridge for managing Tuya devices via the Tuya Local API.

This package exposes the bridge server as an embeddable component, so Python
code can run it alongside and interpret MQTT topics/payloads identically to
the native bridge.

## Install

```bash
pip install pyrustuyabridge
```

Pre-built wheels are provided for Linux (manylinux2014 / musllinux_1_2 on
x86_64 and aarch64), Windows x64, and macOS (x86_64 / arm64). Wheels are
built with PyO3 `abi3-py39`, so a single wheel per platform supports
CPython 3.9 and newer.

## Quick start

```python
import asyncio
from pyrustuyabridge import PyBridgeServer

async def main():
    server = PyBridgeServer(
        mqtt_broker="mqtt://localhost:1883",
        mqtt_root_topic="rustuya",
    )
    await server.start_async()

asyncio.run(main())
```

## Applying config changes at runtime

The bridge is meant to be driven entirely over MQTT — including config changes.
To apply a change to the topic/payload templates or `mqtt_retain`, edit the
`config_path` file and publish a `reconfigure` action to the command topic. The
bridge clears the retained messages published under the old scheme and then
**restarts itself in place** — `start()`/`start_async()` keep running; they do
not return, and live device connections carry over to the new cycle, so
applying a change to a large fleet costs zero reconnects.

```python
import asyncio
from pyrustuyabridge import PyBridgeServer

async def main():
    server = PyBridgeServer(config_path="/etc/rustuya/config.json")
    await server.start_async()  # only returns on stop()/close() or a signal

asyncio.run(main())
```

`start()`/`start_async()` return only when the bridge actually shuts down —
`stop()`/`close()` from another thread/task, or (unless `no_signals=True`)
SIGINT/SIGTERM. A supervisor is still worth running for boot and crash
recovery, just not to change a topic.

**Config precedence is kwargs > `config_path` file > defaults** (the file only
fills fields left unset). So put any field you want to change via
`reconfigure` in the **file**, not in kwargs — a field passed as a kwarg wins
and the file edit is ignored (same rule as CLI flags vs. config file in the
native binary).

## Helpers

The module also exposes topic/payload utilities for code that needs to
match the bridge's wire format:

- `tpl_to_wildcard(template, root_topic)` — template → MQTT wildcard.
- `match_topic(topic, template)` — returns extracted variables or `None`.
- `render_template(template, vars)` — substitutes `{key}` placeholders.
- `parse_payload(payload, vars)` — parses an MQTT payload into a structured value.
- `parse_payload_with_template(payload, template)` — reverse of `render_template`:
  recovers placeholder values from a rendered payload, or `None` if not reversible.
- `parse_seed_dps(payload, dp=None, template=None)` — extracts the DPS map from an
  event payload exactly as the bridge's seed phase does; pass `dp` for single-DP
  (`{dp}`) topics, `None` for multi-DP topics whose payload is the full DPS object.
- `validate_payload_template(template)` — `(ok, message)`; checks whether a payload
  template can be reverse-parsed.

See the [project repository](https://github.com/3735943886/rustuya-bridge)
for full documentation.

