Setup

Get it running, end to end.

Most cheap Wi-Fi RGB bulbs — Bytech, Merkury, Teckin, Feit, many Govee — run Tuya firmware even under a different brand's app. This walks through confirming that, getting the one hard-to-get credential, and running the dashboard.

1. Find the bulb and its protocol version

Install tinytuya and scan the LAN:

pip install tinytuya
python -m tinytuya scan

A Tuya device shows up with a Device ID and a protocol Version (3.1–3.5). Note both. Nothing shown usually means the bulb is on 5GHz — Tuya bulbs are almost always 2.4GHz-only, so the scanning machine needs to share that band.

2. Get the local key

This is the one genuinely hard step — a per-device secret Tuya's servers generate at pairing time, required for any local command.

Recommended: cloud-assisted login

The same official QR-login flow Home Assistant's built-in Tuya integration uses. No Tuya IoT Platform project needed — just the app's own User Code (Me → Settings → Account and Security) and its in-app scanner.

pip install tuya-device-sharing-sdk qrcode[pil]

Full working script and the two fallback options (Tuya IoT Platform, and a rooted-emulator approach) are in the repo's SETUP.md — this page keeps the short version; that one has every line of code.

Known bug to route around: the Tuya IoT Platform's QR-link step sometimes scans successfully but never shows a confirmation popup. That's almost always a data-center mismatch between the Cloud Project's region and the app account's region — the cloud-assisted path above sidesteps this entirely.

3. Install the backend

cd backend
python -m venv venv
./venv/Scripts/activate      # or: source venv/bin/activate
pip install -r requirements.txt

4. Configure your device

cp config.example.json config.json

Edit config.json with the device_id, local_key, and ip from steps 1–2. version must match what tinytuya scan reported — try 3.3 first if unsure. Never commit your real config.json — it's git-ignored, and holds your bulb's plaintext local key.

5. Run it

python -m uvicorn main:app --host 0.0.0.0 --port 8500

Open http://localhost:8500. Go to Diagnostics → Run Connection Test first — it should report tcp_6668_reachable: true and status_ok: true.

Optional next steps

Troubleshooting

Full troubleshooting table, all three local-key options in full code, and the Docker deployment notes: the complete SETUP.md.