TinyTuya: Tuya Smart Device Interface
TinyTuya is a Python library that enables local and cloud-based control and monitoring of Tuya WiFi smart devices such as plugs, switches, and lights. It provides an API for direct communication over a local area network (LAN), supporting Tuya protocols from 3.1 to 3.5, and can also integrate with the Tuya Cloud API. Currently at version 1.17.6, the project is actively maintained with frequent updates and a focus on community contributions. [1, 3, 6, 9]
Warnings
- breaking Starting with v1.14.0, running the `tinytuya` command-line interface without arguments no longer initiates a scan; it now displays a 'Usage' page. Users must explicitly specify `tinytuya scan` or `python -m tinytuya scan` to discover devices.
- gotcha The local key for Tuya devices is crucial for local control but will change if the device is re-paired with the Smart Life/Tuya Smart app or removed and re-added. If you encounter decrypt errors or loss of control, you likely need to re-obtain the local key. [1, 3, 10, 11]
- gotcha Tuya devices typically allow only one TCP connection at a time for local control. Ensure that official Tuya/Smart Life apps or other smart home integrations (like Home Assistant's native Tuya integration) are completely closed or disconnected from the device before attempting to control it with TinyTuya to avoid connection issues. [1, 10, 11]
- gotcha Setting up the Tuya IoT Platform project to retrieve local keys often requires subscribing to specific API services (e.g., IoT Core, Authorization, Smart Home Scene Linkage). These services may have trial periods that expire, potentially interrupting your ability to fetch keys or use cloud-dependent features. [1, 5, 8]
- gotcha The `BulbDevice` class underwent significant rewrites and fixes across multiple minor versions (v1.17.0, v1.17.1, v1.17.2). If you are using `BulbDevice` or encounter unexpected behavior with lighting controls, review the changes in these versions, as the expected interaction or internal handling might have evolved.
- gotcha Local device discovery and control require specific network ports to be open. UDP ports 6666, 6667, and 7000 are used for discovery, and TCP port 6668 is used for device communication. Firewall rules or network configurations blocking these ports will prevent TinyTuya from functioning correctly. [1, 3, 6, 11, 13]
Install
-
pip install tinytuya -
pipx install tinytuya
Imports
- tinytuya
import tinytuya
- Device
from tinytuya import Device
- OutletDevice, BulbDevice, Cloud
from tinytuya import OutletDevice, BulbDevice, Cloud
Quickstart
import os
import tinytuya
# --- Configuration (replace with your device details or environment variables) ---
DEVICE_ID = os.environ.get('TUYA_DEVICE_ID', 'YOUR_DEVICE_ID')
DEVICE_IP = os.environ.get('TUYA_DEVICE_IP', 'YOUR_DEVICE_IP') # Can be 'Auto' if devices.json is present
LOCAL_KEY = os.environ.get('TUYA_LOCAL_KEY', 'YOUR_LOCAL_KEY')
DEVICE_VERSION = float(os.environ.get('TUYA_DEVICE_VERSION', '3.3')) # e.g., 3.1, 3.3, 3.5
# --- Local Control Example (OutletDevice) ---
print(f"Connecting to device {DEVICE_ID} at {DEVICE_IP} (version {DEVICE_VERSION})...")
try:
# Initialize the device object
d = tinytuya.OutletDevice(DEVICE_ID, DEVICE_IP, LOCAL_KEY, version=DEVICE_VERSION)
d.set_version(DEVICE_VERSION) # Ensure the correct protocol version is set
# Get current status
data = d.status()
if data and 'dps' in data:
print(f"Device status: {data['dps']}")
# Assuming DP '1' controls the main switch (common for outlets)
current_state = data['dps'].get('1')
print(f"Current switch state (DP 1): {'ON' if current_state else 'OFF'}")
# Toggle the power state
new_state = not current_state
print(f"Setting switch state (DP 1) to: {'ON' if new_state else 'OFF'}")
d.set_status(new_state)
print("Command sent. Waiting for update...")
# Re-check status after a short delay (optional, for verification)
import time
time.sleep(2)
updated_data = d.status()
if updated_data and 'dps' in updated_data:
print(f"Updated switch state (DP 1): {'ON' if updated_data['dps'].get('1') else 'OFF'}")
else:
print("Failed to get device status or 'dps' key not found.")
except Exception as e:
print(f"An error occurred: {e}")
print("Troubleshooting tips:")
print("- Ensure your device ID, IP, and local key are correct.")
print("- Confirm the device is on the same local network as the script.")
print("- Close any official Tuya/Smart Life apps to free the device's TCP connection. [11]")
print("- Check your firewall for UDP (6666, 6667, 7000) and TCP (6668) port access. [3]")