Python module to interface with Tuya WiFi smart devices

Overview

TinyTuya

Build Status PyPI version CI

Python module to interface with Tuya WiFi smart devices

Description

This python module controls and monitors Tuya compatible WiFi Smart Devices (Plugs, Switches, Lights, Window Covers, etc.) using the local area network (LAN). This is a compatible replacement for the pytuya PyPi module.

Tuya devices are designed to communicate with the TuyaCloud but most also expose a local area network API, allowing us to directly control the devices without using the cloud. This python module provides a socket based way to poll status and issue commands to these devices.

TinyTuya Diagram

NOTE: This module requires the devices to have already been activated by Smart Life App (or similar).

TinyTuya Setup

Install pip and python modules if you haven't already.

# Install PIP
 sudo apt-get install python-crypto python-pip  # for RPi, Linux

 # Install TinyTuya
 python -m pip install tinytuya

The PyPI module will attempt to install pycryptodome if you don't have it. The modules pycrypto, Crypto or pyaes could be used instead.

Tuya Device Preparation

Controlling and monitoring Tuya devices on your network requires the following:

  • Address - The network address (IPv4) of the device e.g. 10.0.1.100
  • Device ID - The unique identifier for the Tuya device
  • Version - The Tuya protocol version used (3.1 or 3.3)
  • Local_Key - The security key created to encrypt and decrypt communication. Devices running the latest protocol version 3.3 (e.g. Firmware 1.0.5 or above) will require a device Local_Key to read the status. Both 3.1 and 3.3 devices will require a device Local_Key to control the device.

Network Scanner

TinyTuya has a built in network scanner that can be used to find Tuya Devices on your local network. It will show Address, Device ID and Version for each device.

python -m tinytuya scan

Setup Wizard

TinyTuya has a built in setup Wizard that uses the Tuya IoT Cloud Platform to generate a JSON list (devices.json) of all your registered devices. This includes the secret Local_Key as well as the Name of each device.

Follow the instructions below to get the Local_Key:

  1. Download the Smart Life App, available for iPhone or Android. Pair all of your Tuya devices (this is important as you cannot access a device that has not been paired).

  2. Run the TinyTuya scan to get a list of Tuya devices on your network along with their device Address, Device ID and Version number (3.1 or 3.3):

    python -m tinytuya scan

    NOTE: You will need to use one of the displayed Device IDs for step 4.

  3. Set up a Tuya Account:

    • Create a Tuya Developer account on iot.tuya.com and log in. NOTE: Tuya makes changes to their portal and this process frequently so details may vary. Please create an issue or pull request with screenshots if we need to update these instructions.
    • Click on "Cloud" icon -> "Create Cloud Project"
      1. Remember the "Data Center" you select. This will be used by TinyTuya Wizard (screenshot)
      2. Skip the configuration wizard but remember the Authorization Key: API ID and Secret for below (screenshot).
    • Click on "Cloud" icon -> Select your project -> Devices -> Link Tuya App Account) (see screenshot)
    • Click Add App Account (screenshot) and it will display a QR code. Scan the QR code with the Smart Life app on your Phone (see step 1 above) by going to the "Me" tab in the Smart Life app and clicking on the QR code button [..] in the upper right hand corner of the app. When you scan the QR code, it will link all of the devices registered in your Smart Life app into your Tuya IoT project.
    • IMPORTANT Under "Service API" ensure this API is listed: IoT Core - Make sure you authorize your Project to use that API:
      • Click "Service API" tab
      • Click "Go to Authorize" button
      • Select the API Groups from the dropdown and click Subscribe (screenshot)
  4. Run Setup Wizard:

    • Tuya has changed datacenter regions. Make sure you are using the latest version of TinyTuya (v1.2.10 or newer).
    • From your Linux/Mac/Win PC run the TinyTuya Setup Wizard to fetch the Local_Keys for all of your registered devices:
      python -m tinytuya wizard   # use -nocolor for non-ANSI-color terminals
    • The Wizard will prompt you for the API ID key, API Secret, API Region (cn, us, us-e, eu, eu-w, or in) from your Tuya IoT project as set in Step 3 above.
      • To find those again, go to iot.tuya.com, choose your project and click Overview
        • API Key: Access ID/Client ID
        • API Secret: Access Secret/Client Secret
    • It will also ask for a sample Device ID. Use one from step 2 above or found in the Device List on your Tuya IoT project.
    • The Wizard will poll the Tuya IoT Cloud Platform and print a JSON list of all your registered devices with the "name", "id" and "key" of your registered device(s). The "key"s in this list are the Devices' Local_Key you will use to access your device.
    • In addition to displaying the list of devices, Wizard will create a local file devices.json that TinyTuya will use this file to provide additional details to scan results from tinytuya.deviceScan() or when running python -m tinytuya scan to scan your local network. The wizard also creates a local file tuya-raw.json that contains the entire payload from Tuya Cloud.
    • The Wizard will ask if you want to poll all the devices. If you do, it will display the status of all devices on record and create a snapshot.json file with the results.

Notes:

  • If you ever reset or re-pair your smart devices, the Local_Key will be reset and you will need to repeat the steps above.
  • The TinyTuya Wizard was inspired by the TuyAPI CLI which is an alternative way to fetch the Local_Keys: npm i @tuyapi/cli -g and run tuya-cli wizard

Programming with TinyTuya

After importing tinytuya, you create a device handle for the device you want to read or control. Here is an example for a Tuya smart switch or plug:

    import tinytuya

    d = tinytuya.OutletDevice('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE')
    d.set_version(3.3)
    data = d.status() 
    print('set_status() result %r' % data)

TinyTuya Module Classes and Functions

Global Functions
    devices = deviceScan()             # Returns dictionary of devices found on local network
    scan()                             # Interactive scan of local network
    wizard()                           # Interactive setup wizard
    set_debug(toggle, color)           # Activate verbose debugging output

Classes
    OutletDevice(dev_id, address, local_key=None, dev_type='default')
    CoverDevice(dev_id, address, local_key=None, dev_type='default')
    BulbDevice(dev_id, address, local_key=None, dev_type='default')

        dev_id (str): Device ID e.g. 01234567891234567890
        address (str): Device Network IP Address e.g. 10.0.1.99 or 0.0.0.0 to auto-find
        local_key (str, optional): The encryption key. Defaults to None.
        dev_type (str): Device type for payload options (see below)

Functions:

  Configuration Settings: 

    set_version(version)               # Set device version 3.1 [default] or 3.3 (all new devices)
    set_socketPersistent(False/True)   # Keep connect open with device: False [default] or True
    set_socketNODELAY(False/True)      # Add cooldown period for slow Tuya devices: False or True [default]
    set_socketRetryLimit(integer)      # Set retry count limit [default 5]
    set_socketTimeout(s)               # Set connection timeout in seconds [default 5]
    set_dpsUsed(dpsUsed)               # Set data points (DPs) to expect (rarely needed)
    set_retry(retry=True)              # Force retry if response payload is truncated
    set_sendWait(num_secs)             # Seconds to wait after sending for a response
    set_bulb_type(type):               # For BulbDevice, set type to A, B or C

  Device Commands:

    status()                           # Fetch status of device (json payload)
    detect_available_dps()             # Return list of DPS available from device
    set_status(on, switch=1)           # Control status of the device to 'on' or 'off' (bool)
    set_value(index, value)            # Send and set value of any DPS/index on device.
    heartbeat()                        # Send heartbeat to device
    updatedps(index=[1])               # Send updatedps command to device to refresh DPS values
    turn_on(switch=1)                  # Turn on device / switch #
    turn_off(switch=1)                 # Turn off device
    set_timer(num_secs)                # Set timer for num_secs on devices (if supported)
    generate_payload(command, data)    # Generate TuyaMessage payload for command with data
    send(payload)                      # Send payload to device (do not wait for response)
    receive()                          # Receive payload from device

    OutletDevice:
        set_dimmer(percentage):
        
    CoverDevice:
        open_cover(switch=1):  
        close_cover(switch=1):
        stop_cover(switch=1):

    BulbDevice
        set_colour(r, g, b):
        set_hsv(h, s, v):
        set_white(brightness, colourtemp):
        set_white_percentage(brightness=100, colourtemp=0):
        set_brightness(brightness):
        set_brightness_percentage(brightness=100):
        set_colourtemp(colourtemp):
        set_colourtemp_percentage(colourtemp=100):
        set_scene(scene):             # 1=nature, 3=rave, 4=rainbow
        set_mode(mode='white'):       # white, colour, scene, music
        result = brightness():
        result = colourtemp():
        (r, g, b) = colour_rgb():
        (h,s,v) = colour_hsv():
        result = state():

TinyTuya Error Codes

Starting with v1.2.0 TinyTuya functions will return error details in the JSON data responses instead of raising exceptions. The format for this response:

{ "Error":"Invalid JSON Payload", "Err":"900", "Payload":"{Tuya Message}" }

The "Err" number will be one of these:

  • 900 (ERR_JSON) - Invalid JSON Response from Device
  • 901 (ERR_CONNECT) - Network Error: Unable to Connect
  • 902 (ERR_TIMEOUT) - Timeout Waiting for Device
  • 903 (ERR_RANGE) - Specified Value Out of Range
  • 904 (ERR_PAYLOAD) - Unexpected Payload from Device
  • 905 (ERR_OFFLINE) - Network Error: Device Unreachable
  • 906 (ERR_STATE) - Device in Unknown State
  • 907 (ERR_FUNCTION) - Function Not Supported by Device

Example Usage

See the sample python script test.py for an OutletDevice example or look in the examples directory for other scripts.

    import tinytuya

    """
    OUTLET Device
    """
    d = tinytuya.OutletDevice('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE')
    d.set_version(3.3)
    data = d.status()  

    # Show status and state of first controlled switch on device
    print('Dictionary %r' % data)
    print('State (bool, true is ON) %r' % data['dps']['1'])  

    # Toggle switch state
    switch_state = data['dps']['1']
    data = d.set_status(not switch_state)  # This requires a valid key
    if data:
        print('set_status() result %r' % data)

    # On a switch that has 4 controllable ports, turn the fourth OFF (1 is the first)
    data = d.set_status(False, 4)
    if data:
        print('set_status() result %r' % data)
        print('set_status() extra %r' % data[20:-8])

    """
    RGB Bulb Device
    """
    d = tinytuya.BulbDevice('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE')
    d.set_version(3.3)  # IMPORTANT to set this regardless of version
    data = d.status()

    # Show status of first controlled switch on device
    print('Dictionary %r' % data)

    # Set to RED Color - set_colour(r, g, b):
    d.set_colour(255,0,0)  

    # Brightness: Type A devices range = 25-255 and Type B = 10-1000
    d.set_brightness(1000)

    # Set to White - set_white(brightness, colourtemp):
    #    colourtemp: Type A devices range = 0-255 and Type B = 0-1000
    d.set_white(1000,10)

    # Set Bulb to Scene Mode
    d.set_mode('scene')

    # Scene Example: Set Color Rotation Scene
    d.set_value(25, '07464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000')

Example Device Monitor

You can set up a persistent connection to a device and then monitor the state changes with a continual loop. This is helpful for troubleshooting and discovering DPS values.

Send Request for Status < ") payload = d.generate_payload(tinytuya.DP_QUERY) d.send(payload) print(" > Begin Monitor Loop <") while(True): # See if any data is available data = d.receive() print('Received Payload: %r' % data) # Send keyalive heartbeat print(" > Send Heartbeat Ping < ") payload = d.generate_payload(tinytuya.HEART_BEAT) d.send(payload) # NOTE If you are not seeing updates, you can force them - uncomment: # print(" > Send Request for Status < ") # payload = d.generate_payload(tinytuya.DP_QUERY) # d.send(payload) # NOTE Some smart plugs require an UPDATEDPS command to update power data # print(" > Send DPS Update Request < ") # payload = d.generate_payload(tinytuya.UPDATEDPS) # d.send(payload) ">
import tinytuya

d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
d.set_version(3.3)
d.set_socketPersistent(True)

print(" > Send Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)

print(" > Begin Monitor Loop <")
while(True):
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)

    # Send keyalive heartbeat
    print(" > Send Heartbeat Ping < ")
    payload = d.generate_payload(tinytuya.HEART_BEAT)
    d.send(payload)

    # NOTE If you are not seeing updates, you can force them - uncomment:
    # print(" > Send Request for Status < ")
    # payload = d.generate_payload(tinytuya.DP_QUERY)
    # d.send(payload)

    # NOTE Some smart plugs require an UPDATEDPS command to update power data
    # print(" > Send DPS Update Request < ")
    # payload = d.generate_payload(tinytuya.UPDATEDPS)
    # d.send(payload)    

Encryption notes

These devices uses AES encryption which is not available in the Python standard library. There are three options:

  1. PyCryptodome (recommended)
  2. PyCrypto
  3. pyaes (note Python 2.x support requires https://github.com/ricmoo/pyaes/pull/13)

Command Line

    python -m tinytuya [command] [
   
    ] [-nocolor] [-h]

      command = scan        Scan local network for Tuya devices.
      command = wizard      Launch Setup Wizard to get Tuya Local KEYs.
      max_retry             Maximum number of retries to find Tuya devices [Default=15]
      -nocolor              Disable color text output.
      -h                    Show usage.

   

Scan Tool

The function tinytuya.scan() will listen to your local network (UDP 6666 and 6667) and identify Tuya devices broadcasting their Address, Device ID, Product ID and Version and will print that and their stats to stdout. This can help you get a list of compatible devices on your network. The tinytuya.deviceScan() function returns all found devices and their stats (via dictionary result).

You can run the scanner from the command line using this:

python -m tinytuya

By default, the scan functions will retry 15 times to find new devices. If you are not seeing all your devices, you can increase max_retries by passing an optional arguments (eg. 50 retries):

# command line
python -m tinytuya 50
# invoke verbose interactive scan
tinytuya.scan(50)

# return payload of devices
devices = tinytuya.deviceScan(false, 50)

Troubleshooting

  • Tuya devices only allow one TCP connection at a time. Make sure you close the TuyaSmart or SmartLife app before using TinyTuya to connect.
  • Some devices ship with older firmware that may not work with TinyTuya. If you're experiencing issues, please try updating the device's firmware in the official app.
  • The LOCAL KEY for Tuya devices will change every time a device is removed and re-added to the TuyaSmart app. If you're getting decrypt errors, try getting the key again as it might have changed.
  • Some devices with 22 character IDs will require additional setting to poll correctly - here is an example:
      a = tinytuya.OutletDevice('here_is_my_key', '192.168.x.x', 'secret_key_here', 'device22')
      a.set_version(3.3)
      a.set_dpsUsed({"1": None})  # This needs to be a datapoint available on the device
      data =  a.status()
      print(data)
  • Windows 10 Users - TinyTuya wizard and scan interactive tools use ANSI color. This will work correctly in PowerShell but will show cryptic escape codes when run in Windows CMD. You can fix this by using the -nocolor option on tinytuya, or by changing the Windows CMD console registry to process ANSI escape codes by doing something like this:
    reg add HKEY_CURRENT_USER\Console /v VirtualTerminalLevel /t REG_DWORD /d 0x00000001 /f
    

Tuya Data Points - DPS Table

The Tuya devices send back data points (DPS) also called device function points, in a json string. The DPS attributes define the state of the device. Each key in the DPS dictionary refers to key value pair, the key is the DP ID and its value is the dpValue. You can refer to the Tuya developer platform for definition of function points for the products.

The following table represents several of the standard Tuya DPS values and their properties. It represents data compiled from Tuya documentation and self-discovery. Devices may vary. Feedback or additional data would would be appreciated. Please submit a Issue or Pull Request if you have additional data that would be helpful for others.

DPS Read and Set Example:

# Read Value of DPS 25
data = d.status()  
print("Value of DPS 25 is ", data['dps']['25'])

# Set Value of DPS 25
d.set_value(25, '010e0d0000000000000003e803e8')

Version 3.1 Devices

Version 3.1 - Plug or Switch Type

DP ID Function Point Type Range Units
1 Switch bool True/False
2 Countdown? integer 0-86400 s
4 Current integer 0-30000 mA
5 Power integer 0-50000 W
6 Voltage integer 0-5000 V

Version 3.1 - Light Type (RGB)

DP ID Function Point Type Range Units
1 Switch bool True/False
2 Mode enum white,colour,scene,music
3 Bright integer 10-1000*
4 Color Temp integer 0-1000*
5 Color hexstring r:0-255,g:0-255,b:0-255,h:0-360,s:0-255,v:0-255 rgb+hsv

Version 3.3 Devices

Version 3.3 - Plug, Switch, Power Strip Type

DP ID Function Point Type Range Units
1 Switch 1 bool True/False
2 Switch 2 bool True/False
3 Switch 3 bool True/False
4 Switch 4 bool True/False
5 Switch 5 bool True/False
6 Switch 6 bool True/False
7 Switch 7/usb bool True/False
9 Countdown 1 integer 0-86400 s
10 Countdown 2 integer 0-86400 s
11 Countdown 3 integer 0-86400 s
12 Countdown 4 integer 0-86400 s
13 Countdown 5 integer 0-86400 s
14 Countdown 6 integer 0-86400 s
15 Countdown 7 integer 0-86400 s
17 Add Electricity integer 0-50000 kwh
18 Current integer 0-30000 mA
19 Power integer 0-50000 W
20 Voltage integer 0-5000 V
21 Test Bit integer 0-5 n/a
22 Voltage coe integer 0-1000000
23 Current coe integer 0-1000000
24 Power coe integer 0-1000000
25 Electricity coe integer 0-1000000
26 Fault fault ov_cr

Version 3.3 - Dimmer Switch

DP ID Function Point Type Range Units
1 Switch bool True/False
2 Brightness integer 10-1000*
3 Minimum of Brightness integer 10-1000*
4 Type of light source1 enum LED,incandescent,halogen
5 Mode enum white

Version 3.3 - Light Type (RGB)

DP ID Function Point Type Range Units
20 Switch bool True/False
21 Mode enum white,colour,scene,music
22 Bright integer 10-1000*
23 Color Temp integer 0-1000
24 Color hexstring h:0-360,s:0-1000,v:0-1000 hsv
25 Scene string n/a
26 Left time integer 0-86400 s
27 Music string n/a
28 Debugger string n/a
29 Debug string n/a

Version 3.3 - Automated Curtain Type

DP ID Function Point Type Range Units
1 Curtain Switch 1 enum open, stop, close, continue
2 Percent control 1 integer 0-100 %
3 Accurate Calibration 1 enum start, end
4 Curtain Switch 2 enum open, stop, close, continue
5 Percent control 2 integer 0-100
6 Accurate Calibration 2 enum start, end
8 Motor Steer 1 enum forward, back
9 Motor steer 2 enum forward, back
10 Quick Calibration 1 integer 1-180 s
11 Quick Calibration 2 integer 1-180 s
12 Motor Mode 1 enum strong_power, dry_contact
13 Motor Mode 2 enum strong_power, dry_contact
14 Light mode enum relay, pos, none

Version 3.3 - Fan Switch Type

DP ID Function Point Type Range Units
1 Fan switch bool True/False n/a
2 Fan countdown integer 0-86400 s
3 Fan speed enum level_1, level_2, level_3, level_4, level_5
4 Fan speed integer 1-100 %
5 Fan light switch bool True/False
6 Brightness integer integer 10-1000
7 Fan light countdown integer 0-86400
8 Minimum brightness integer 10-1000
9 Maximum brightness integer 10-1000
10 Mode enum white
11 Power-on state setting enum off, on, memory
12 Indicator status setting enum none, relay, pos
13 Backlight switch bool True/False

Version 3.3 - Universal IR Controller with Temp/Humidity

DP ID Function Point Type Range Units
101 Current Temperature integer 0-600 10x Celsius
102 Current Humidity integer 0-100 %

Version 3.3 - Sensor Type

Important Note: Battery-powered Tuya sensors are usually designed to stay in sleep mode until a state change (eg.open or close alert). This means you will not be able to poll these devices except in the brief moment they awake, connect to the WiFi and send their state update payload the the Tuya Cloud. Keep in mind that if you manage to poll the device enough to keep it awake, you will likely quickly drain the battery.

DP ID Function Point Type Range Units
1 Door Sensor bool True/False
2 Battery level state enum low, middle, high
3 Battery level integer 0-100 %
4 Temper alarm bool True/False
5 Flooding Detection State enum alarm, normal
6 Luminance detection state enum low, middle, high, strong
7 Current Luminance integer 0-100 %
8 Current Temperature integer 400-2000
9 Current Humidity integer 0-100 %
10 Shake State enum normal, vibration, drop, tilt
11 Pressure State enum alarm, normal
12 PIR state enum pir, none
13 Smoke Detection State enum alarm, normal
14 Smoke value integer 0-1000
15 Alarm Volume enum low, middle, high, mute
16 Alarm Ringtone enum 1, 2, 3, 4, 5
17 Alarm Time integer 0-60 s
18 Auto-Detect bool True/False
19 Auto-Detect Result enum checking, check_success, check_failure, others
20 Preheat bool True/False
21 Fault Alarm fault fault, serious_fault, sensor_fault, probe_fault, power_fault Barrier
22 Lifecycle bool True/False
23 Alarm Switch bool True/False
24 Silence bool True/False
25 Gas Detection State enum alarm, normal
26 Detected Gas integer 0-1000
27 CH4 Detection State enum alarm, normal
28 CH4 value integer 0-1000
29 Alarm state enum alarm_sound, alarm_light, alarm_sound_light, normal
30 VOC Detection State enum alarm, normal
31 VOC value integer 0-999
32 PM2.5 state enum alarm, normal
33 PM2.5 value integer 0-999
34 CO state enum alarm, normal
35 CO value integer 0-1000
36 CO2 Detection State enum alarm, normal
37 CO2 value integer 0-1000
38 Formaldehyde Detection State enum alarm, normal
39 CH2O value integer 0-1000
40 Master mode enum disarmed, arm, home, sos
41 Air quality index enum level_1, level_2, level_3, level_4, level_5, level_6

NOTE (*) - The range can vary depending on the device. As an example, for dimmers, it may be 10-1000 or 25-255.

Tuya References

Credits

Related Projects

Comments
  • IR REMOTE CONTROL

    IR REMOTE CONTROL

    HI, first of all apologize my poor english. Im facing a major issue trying to code the IR remote control. Is there anyway to find out how to control it with tinytuya?

    Im using yout code:

    import tinytuya
    
    d = tinytuya.OutletDevice('XXX, "YYY", "ZZZ")
    d.set_version(3.3)
    d.set_socketPersistent(True)
    payload = d.generate_payload
    print(" > Send Request for Status < ")
    payload = d.generate_payload(tinytuya.DP_QUERY)
    
    print(" > Begin Monitor Loop <")
    while(True):
        # See if any data is available
        data = d.receive()
        print('Received Payload: %r' % data)
    
        # Send keyalive heartbeat
        print(" > Send Heartbeat Ping < ")
        payload = d.generate_payload(tinytuya.HEART_BEAT)
        d.send(payload)
    
        print(" > Send Request for Status < ")
        payload = d.generate_payload(tinytuya.DP_QUERY)
        d.send(payload)
        
        
        # NOTE Some smart plugs require an UPDATEDPS command to update power data
        print(" > Send DPS Update Request < ")
        payload = d.generate_payload(tinytuya.UPDATEDPS)
        d.send(payload) 
    

    AS result i get the follow message:

    Received Payload: {'dps': {'201': '{"control":"study_exit"}'}}

    Is there a way that i can have a list of commands? what shoud be this "study_exit"?

    Thank you so much! Best regards

    tuya_device 
    opened by adlerlinhares 71
  • Add fetching device logs to Cloud, and generic URLs

    Add fetching device logs to Cloud, and generic URLs

    In addition, I reworked the error handling a bit. I usually use tinytuya.json to pass the cloud login info, but I forgot to copy it in after creating a new branch and Cloud.__init__() immediately blew up with TypeError: __init__() should return None, not 'dict' because a dict cannot be returned by __init__. I wasn't sure if just setting the new .error variable would be sufficient, so I currently have it throwing a more descriptive error. This also mimics existing behavior better.

    ._gettoken() now sets .error (and returns it) on error (such as bad auth or wrong region) instead of setting .token to an error_json object. I considered but ultimately decided not to set .error in the various get...() functions as a bad device_id or parameter isn't necessarily fatal, unlike a ._gettoken() error.

    Included in the PR are 2 new functions, getdevicelog() and cloudrequest(). cloudrequest() just offers an easy way of fetching one of the many URLs listed in https://developer.tuya.com/en/docs/cloud/device-connection-service?id=Kb0b8geg6o761

    Assuming your credentials are in tinytuya.json, you can pull the last 24 hours of logs for a device by simply:

    import tinytuya
    import json
    
    c = tinytuya.Cloud()
    r = c.getdevicelog( '00112233445566778899' )
    print( json.dumps(r, indent=2) )
    

    Tuya's servers hold one week worth of logs IIRC.

    Inspired by #214

    opened by uzlonewolf 37
  • [WinError 10054]

    [WinError 10054]

    Sometimes this error appears, probably because a connection hasnt been closed before connecting to it again. How would I make sure that a connection to a device is closed?

    opened by burakmartin 25
  • Error from Tuya server: sign invalid

    Error from Tuya server: sign invalid

    Unable to connect to Tuya iot anymore.

    Perhaps related to this change.

    To better secure your cloud development, Tuya will upgrade the signature algorithm. Projects created after June 30, 2021 are subject to signature verification with the new algorithm. View details. https://developer.tuya.com/en/docs/iot/singnature?id=Ka43a5mtx1gsc

    opened by leopoldwang 21
  • Unable to control RGB led strip, scanner yielding strange results

    Unable to control RGB led strip, scanner yielding strange results

    Hello! I recently purchased an RGB led strip with wifi connection for use with the Tuya Smart Home system. (This is the one: https://www.amazon.nl/gp/product/B08FXBD8J9/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1, I'm sure it's a fairly generic wifi led strip). I am having some issues controlling it with TinyTuya. Here's a rundown of the issues I've encountered:

    It starts off with the TinyTuya scanner (the python -m tinytuya scan command). My smart sockets register just fine, but my led strip is giving some strange results:

    Unknown v Device   Product ID =   [Unknown payload]:
        Address = 192.168.178.87,  Device ID = , Local Key = ,  Version = 
        No Stats for 192.168.178.87: DEVICE KEY required to poll for status
    

    After this it prints out an unexpected payload, I am however unsure what data this contains and thus cautious about sharing it. It looks like this:

    b"/jd8/x87f3oi/bex/10r/dj5/jf7/fxj/kjsd*.y/n58+eL/x92'd/.... (continues like this for a total of 400 characters)
    

    Knowing the IP address of the light, I shrugged it off and continued with trying to control it. Trying to control the device gave me a new error:

    {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': ''}
    

    I didn't really know what this error meant, so I went here on GitHub to look at some issues other users were facing. There, I found this code that monitors the device: https://github.com/jasonacox/tinytuya/issues/61#issuecomment-898936843

    Some interesting behavior happens when I run that code while controlling the lights via the Smart Life app. Every time I make a change, like turning off or on the led strip, I do actually receive something:

    Received Payload: {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
     > Send Heartbeat Ping < 
    Received Payload: {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
     > Send Heartbeat Ping < 
    Received Payload: {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
     > Send Heartbeat Ping < 
    Received Payload: {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
     > Send Heartbeat Ping < 
    

    More 904 error codes. This was after turning my led strip off and on twice, so it did register every change, which makes the problem even stranger to me.

    Clearly there is an established connection thru TinyTuya, but for some reason this led strip doesn't want to play nice. I've tried using TinyTuya for my smart sockets, and I am able to control them without any problems.

    Any help with this would be greatly appreciated, as I really have no idea what is causing this issue.

    Thanks!

    opened by mervinvb 18
  • tinytuya requests time out

    tinytuya requests time out

    When running tinytuya the smartbulb is found and its status is displayed. But when running the wizard or trying to change the status of the light, there is no response. The light works fine with the tuya app and with Alexa.

    Help would be much appreciated as I am running out of ideas myself :)

    opened by 41pha1 15
  • Unable to control Universal IR Device

    Unable to control Universal IR Device

    Hi. just bought a Smart IR Remote Control Hub unable to control it with tinytuya

    I can control the device with Tuya App. the led on the device blinks when sending any button with the app. But there is no response from the device nor the led blinks when trying to control it with tinytuya

    python -m tinytuya scan

    TinyTuya (Tuya device scanner) [1.8.0]
    
    [Loaded devices.json - 3 devices]
    
    Scanning on UDP ports 6666 and 6667 for devices (18 retries)...
    
    Smart IR   Product ID = keyf9fsmuufeywsr  [Valid payload]:
        Address = 192.168.0.184,  Device ID = 35217541c45bbef5a1f1, Local Key = e363f4ddda******,  Version = 3.3, MAC = c4:5b:**:**:**:**
        Status: {'1': 'send_ir'}
    
    Scan Complete!  Found 1 devices.
    
    >> Saving device snapshot data to snapshot.json
    

    My Code:

    import tinytuya
    from tinytuya import Contrib
    
    tinytuya.set_debug(toggle=True, color=False)
    
    ir = Contrib.IRRemoteControlDevice("35217541c45bbef5a1f1")
    
    ir.send_button("IyOvEToCZQI5AkoCOgJNAjYCTwI4AlACNQJMAjkCTQI2ApsGSwKZBkkClwZMAp8GLALLBhgC0wYRAtMGEwLRBhMCbgIdAmkCGwLKBhsCagIaAsoGGgJzAhACbwIWAnICFAJvAh0CxgYdAmoCFwLMBhoCcAIUAtAGFALRBhQC0QYUAtAGFQKXnBgjCAkXAiDL")
    # Nothing happenes, no light on IR device.
    """
    DEBUG:TinyTuya [1.8.0]
    
    DEBUG:loaded=devices.json [3 devices]
    DEBUG:Device '35217541c45bbef5a1f1' found in devices.json
    DEBUG:Listening for device 35217541c45bbef5a1f1 on the network
    DEBUG:find() received broadcast from '192.168.0.184': {'ip': '192.168.0.184', 'gwId': '35217541c45bbef5a1f1', 'active': 2, 'ability': 0, 'mode': 0, 'encrypt': True, 'productKey': 'keyf9fsmuufeywsr', 'version': '3.3'}
    DEBUG:find() is returning: {'ip': '192.168.0.184', 'version': '3.3', 'id': '35217541c45bbef5a1f1', 'product_id': 'keyf9fsmuufeywsr', 'data': {'ip': '192.168.0.184', 'gwId': '35217541c45bbef5a1f1', 'active': 2, 'ability': 0, 'mode': 0, 'encrypt': True, 'productKey': 'keyf9fsmuufeywsr', 'version': '3.3'}}
    DEBUG:Sending IR Button: 1IyOvEToCZQI5AkoCOgJNAjYCTwI4AlACNQJMAjkCTQI2ApsGSwKZBkkClwZMAp8GLALLBhgC0wYRAtMGEwLRBhMCbgIdAmkCGwLKBhsCagIaAsoGGgJzAhACbwIWAnICFAJvAh0CxgYdAmoCFwLMBhoCcAIUAtAGFALRBhQC0QYUAtAGFQKXnBgjCAkXAiDL
    DEBUG:Pulses and gaps (microseconds): p8995 g4527 p570 g613 p569 g586 p570 g589 p566 g591 p568 g592 p565 g588 p569 g589 p566 g1691 p587 g1689 p585 g1687 p588 g1695 p556 g1739 p536 g1747 p529 g1747 p531 g1745 p531 g622 p541 g617 p539 g1738 p539 g618 p538 g1738 p538 g627 p528 g623 p534 g626 p532 g623 p541 g1734 p541 g618 p535 g1740 p538 g624 p532 g1744 p532 g1745 p532 g1745 p532 g1744 p533 g40087 p8984 g2312 p535 g52000
    DEBUG:building command 7 payload=b'{"devId":"35217541c45bbef5a1f1","uid":"35217541c45bbef5a1f1","t":"1669663589","dps":{"201":"{\\"control\\":\\"send_ir\\",\\"key1\\":\\"1IyOvEToCZQI5AkoCOgJNAjYCTwI4AlACNQJMAjkCTQI2ApsGSwKZBkkClwZMAp8GLALLBhgC0wYRAtMGEwLRBhMCbgIdAmkCGwLKBhsCagIaAsoGGgJzAhACbwIWAnICFAJvAh0CxgYdAmoCFwLMBhoCcAIUAtAGFALRBhQC0QYUAtAGFQKXnBgjCAkXAiDL\\",\\"type\\":0}"}}'
    DEBUG:sending payload
    DEBUG:payload encrypted=b'000055aa000000010000000700000177332e330000000000000000000000008286c18de89ac00b7ddfb5d573b9d4fca92603bab7c419c3f95a4c2c092a7657a99f76692b7aebd8fbcc7ee14d8db5fe7d592a36396dd0f232d55044095a6cd409b3c064c928b641c7ee260c44f9d738092c0026982bc755b836371ca69615975992bc30ee5d3b16c1c84f479378786abf7ea14f247ec18cf96bc3ff97b6ac7d634eb1e6e7378acc4083156562a982f35427bc934b17d782908d21959690c93c26500b9be3a535f25187bddd89b8ebaffd5efc8cc530383b1d2f503b3bfcad05bd9e65e6b23d0ebdf5a0ba48a4935dc4b64b4ffb72f1162d785a25b2ff18e765bcd8d6d1970eab08673bf71495a515387e6ab544a457588755801bae904a721612be37298018a58f792a687784c9d0f6fe1294a1bfd2e1a562f05388fa25cb31b2e994426b4477906183f9a9b08f38b7065c364e14e964ba76fcb0a849037b663dae1cc3e160cd05ec05f52bd93fbd130a24d1dbcf811b12f82b0d209f294705879859bf0000aa55'
    """
    
    ir.receive_button(5)
    # Doesn't detect the button.
    """
    DEBUG:Receiving button
    DEBUG:building command 7 payload=b'{"devId":"35217541c45bbef5a1f1","uid":"35217541c45bbef5a1f1","t":"1669664119","dps":{"201":"{\\"control\\":\\"study_exit\\"}"}}'
    DEBUG:sending payload
    DEBUG:payload encrypted=b'000055aa000000020000000700000097332e330000000000000000000000008286c18de89ac00b7ddfb5d573b9d4fca92603bab7c419c3f95a4c2c092a7657a99f76692b7aebd8fbcc7ee14d8db5fe7d592a36396dd0f232d55044095a6cd477089ae18f65a19697953ea7c4b6cd3f092c0026982bc755b836371ca6961597690bacb94b08137fb62ae91bd9d3e7e2c4b344921ec4e3057f1ddbf29d32cf6457e94ae50000aa55'
    DEBUG:building command 7 payload=b'{"devId":"35217541c45bbef5a1f1","uid":"35217541c45bbef5a1f1","t":"1669664119","dps":{"201":"{\\"control\\":\\"study\\"}"}}'
    DEBUG:sending payload
    DEBUG:payload encrypted=b'000055aa000000030000000700000097332e330000000000000000000000008286c18de89ac00b7ddfb5d573b9d4fca92603bab7c419c3f95a4c2c092a7657a99f76692b7aebd8fbcc7ee14d8db5fe7d592a36396dd0f232d55044095a6cd477089ae18f65a19697953ea7c4b6cd3f092c0026982bc755b836371ca6961597690bacb94b08137fb62ae91bd9d3e7e2c7be09cf6b0a43f19843a54721b58fdefc7b5c2d0000aa55'
    DEBUG:Waiting for button...
    DEBUG:received data=b'000055aa00000003000000070000000c00000000c5591c5f0000aa55'
    DEBUG:received null payload (TuyaMessage(seqno=3, cmd=7, retcode=0, payload=b'', crc=3310951519, crc_good=True)), fetch new one - retry 0 / 5
    DEBUG:Timeout
    DEBUG:building command 7 payload=b'{"devId":"35217541c45bbef5a1f1","uid":"35217541c45bbef5a1f1","t":"1669664124","dps":{"201":"{\\"control\\":\\"study_exit\\"}"}}'
    DEBUG:sending payload
    DEBUG:payload encrypted=b'000055aa000000040000000700000097332e330000000000000000000000008286c18de89ac00b7ddfb5d573b9d4fca92603bab7c419c3f95a4c2c092a7657a99f76692b7aebd8fbcc7ee14d8db5fe7d592a36396dd0f232d55044095a6cd4598289ebdc0b573ed82cb8f74625ee46092c0026982bc755b836371ca6961597690bacb94b08137fb62ae91bd9d3e7e2c4b344921ec4e3057f1ddbf29d32cf64cbf51ce30000aa55'
    """
    
    opened by anar4732 14
  • Support for 3.2 protocol

    Support for 3.2 protocol

    Hi,

    I have a couple of light switches that are based on protocol version 3.2. Like this one: https://www.aliexpress.com/item/32976986321.html

    Using tinytuya I can turn them on/off (works when ver set to 3.3), but I cannot get status. Here's the debug log.

    Is there any chance tinytuya could support 3.2?

    DEBUG:status() entry (dev_type is default)
    DEBUG:building command 10 payload=b'{"gwId":"bfce9bf5ec0e8ac2aboka5","devId":"bfce9bf5ec0e8ac2aboka5","uid":"bfce9bf5ec0e8ac2aboka5","t":"1660166885"}'
    DEBUG:payload generated=b'000055aa000000000000000a000000885bc7f95f3c88bd83dbb763f880dd47ce9b931d026edcec1620dc32cb1877c4730e7beb3a39a3720a3bcba57876716162ea34f490f7a5ba8f2c946a4bd26ac7f57f40cd65b58b3fbd055fdf8bb6ecaa049b931d026edcec1620dc32cb1877c4737bee983e8504e94cc4961239cd76b0abbaf0dd14f091ba228fb16037aa6138b20686ae150000aa55'
    DEBUG:received data=b'000055aa000000000000000a0000001d000000016461746120666f726d6174206572726f724ddf82ac0000aa55'
    DEBUG:received message=TuyaMessage(seqno=0, cmd=10, retcode=(1,), payload=b'data format error', crc=1306493612)
    DEBUG:raw unpacked message = TuyaMessage(seqno=0, cmd=10, retcode=(1,), payload=b'data format error', crc=1306493612)
    DEBUG:decode payload=b'data format error'
    DEBUG:decrypting=b'data format error'
    DEBUG:incomplete payload=b'data format error' (len:17)
    Traceback (most recent call last):
      File "/Users/paul/Library/Python/3.8/lib/python/site-packages/tinytuya/core.py", line 767, in _decode_payload
        payload = cipher.decrypt(payload, False)
      File "/Users/paul/Library/Python/3.8/lib/python/site-packages/tinytuya/core.py", line 246, in decrypt
        raw = cipher.decrypt(enc)
      File "/Users/paul/Library/Python/3.8/lib/python/site-packages/Crypto/Cipher/_mode_ecb.py", line 196, in decrypt
        raise ValueError("Data must be aligned to block boundary in ECB mode")
    ValueError: Data must be aligned to block boundary in ECB mode
    DEBUG:ERROR Unexpected Payload from Device - 904 - payload: null
    DEBUG:status() received data={'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
    set_status() result {'Error': 'Unexpected Payload from Device', 'Err': '904', 'Payload': None}
    
    opened by pawel-szopinski 14
  • Add support for v3.4 devices

    Add support for v3.4 devices

    Finally got a 3.4 device and got this working. I modeled it after harryzz's code at https://github.com/harryzz/tuyapi/commit/ef4473b4679c29d07ae504490503b6fa87d3e733 . The modifications were a lot more extensive than I initially anticipated due to the switch from CRC32 to HMAC checksums.

    Closes #148 Closes #178

    opened by uzlonewolf 11
  • Do you have an example with set_colour(r,g,b) ?

    Do you have an example with set_colour(r,g,b) ?

    THanks for a very useful package !

    I'm able to turn on/off on my Tuya enabled lights and able to set their brightness, but I'm not able to get the set_colour(r,g,b) to work properly. set_colour(r,g,b) seems to hang no matter what values I put in for r,g,b. I can't find an example of being used… So perhaps I'm doing it wrong. It looks OK from the source code… Any suggestions?

    John Cohn [email protected]

    thanks again !

    here's my code

    import tinytuya
    import random
    
    candles = {}
    candles[0] = tinytuya.BulbDevice('868515018caab5ef1554', '192.168.1.26', '03ca98398a11c78a')
    candles[1] = tinytuya.BulbDevice('86851501e09806ac519d', '192.168.1.27', '970cdd010944cf8b')
    candles[2] = tinytuya.BulbDevice('868515018caab5e57b07', '192.168.1.28', '5aa724e67b0b4bd9')
    candles[3] = tinytuya.BulbDevice('868515018caab5ef1d2b', '192.168.1.29', '129668119d3e840c')
    candles[4] = tinytuya.BulbDevice('868515018caab5e48e96', '192.168.1.30', '431b646c91ffca5c')
    candles[5] = tinytuya.BulbDevice('868515018caab5ef529e', '192.168.1.31', 'daf67a675bf9287d')
    candles[6] = tinytuya.BulbDevice('eb14adb45f8dfeb872fk5x', '192.168.1.25', '2f239ce262516e4b')
    candles[7] = tinytuya.BulbDevice('ebe1eb6797591db8eslal', '192.168.1.24', 'eefb1deb6155f9f6')
    candles[8] = tinytuya.BulbDevice('eb044207ff02162f1f248g', '192.168.1.4', '44b9d8edcf92ca3e')
    for i in range (9):
        candles[i].set_version(3.3)
    
    for i in range (9):
        candles[i].set_value('20',True) # turn on each light                                                                                                                             
        z = random.randint(10, 1000) # choose a random brightness                                                                                                                        
        candles[i].set_value('22',z) # set brighntess (this works)                                                                                                                       
    ## if uncommented, the next line hangss                                                                                                                                              
    #    candles[i].set_colour(100,100,100) # attempt to set a colour .. (this does NOT work.. iit hangs  forever))                                                                      
        data = candles[i].status()  # NOTE this does NOT require a valid key vor version 3.1                                                                                             
        print(data)
    
    
    
    
    
    opened by johncohn 10
  • This happened while trying to scan my network from Raspbian on a Pi 4

    This happened while trying to scan my network from Raspbian on a Pi 4

    Scanning local network for Tuya devices... Traceback (most recent call last): File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main "main", mod_spec) File "/usr/lib/python3.7/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/shane/.local/lib/python3.7/site-packages/tinytuya/main.py", line 48, in tinytuya.wizard(color) File "/home/shane/.local/lib/python3.7/site-packages/tinytuya/init.py", line 1479, in wizard devices = deviceScan(False, 20) File "/home/shane/.local/lib/python3.7/site-packages/tinytuya/init.py", line 1139, in deviceScan client.bind(("", UDPPORT)) OSError: [Errno 98] Address already in use

    opened by ShaneSpina 9
  • Globe lightbulb - Unexpected payload in scan & can't control

    Globe lightbulb - Unexpected payload in scan & can't control

    Hi, I have an RGB lightbulb that I'm trying to control, and although the wizard managed to pull the device information and local key from the cloud, I can't control the device. The scan finds it, but gets an "unexpected payload":

    python -m tinytuya scan -nocolor
    
    TinyTuya (Tuya device scanner) [1.9.1]
    
    [Loaded devices.json - 1 devices]
    
    Scanning on UDP ports 6666 and 6667 for devices (16 retries)...
    
    *  Unexpected payload=%r
     b'\x13@\x8d(H\x7f`\xe3\xb9Muf<\x97Ej\xaf)@\xd4\xe0\xdf\x19\xfa\x04,\xa6Bm\xceK\x0f;fuE j\x01\x129S\n\xb6\xb0"\xeb\xc7\xf9mn\xa0\x15\xd2T\xa8f\x93\x85\x94\xa5pEi\xd0\xeeY\x1100\'\xfao\x946\x07\xeb\x99\xe8\x17]\x1e\xdc\x87\xa20\xf4\t\x8d\xd4\xc5$\xd9\r\x94\xea6\xcc\x0c\x8c\xfb\x9b\xce /A\xa0\xfb\xb9gn\xcb\x04\x0e\xd4Hb\xb6t\xb1\xbe\xbeO\x18w\xdb\xbf\xad\xf0\xe90>r\xa4\xa1\x1a\xdf\xd1O$f\x10\xa6\xf9gt\x07\x01\x82\xa9\xd4\x87\x8f\xbb\xc6u\xeb\'\xbe\xbbv6\xe0\xc6\xae\xf6\xa4\\\xe9}\x1e\xa359B\x15\xb3W\xeb\x14\x11=q;\x96\xac\xcc8\xd3ZF\x19m\xb7\xf6"\x17\x9bA\xfe=\x97\xdbL\n\xcdt\x1d\xe3\x95T>I\x94\xfa\xa7p\xb1\x87x\x97\xb7\xbb\x81\xfe\xd9gH\xf2\x0e\x86B\xd1'
    Unknown v Device   Product ID =   [Unknown payload]:
        Address = 192.168.2.46,  Device ID = , Local Key = ,  Version = , MAC =
        No Stats for 192.168.2.46: DEVICE KEY required to poll for status
    *  Unexpected payload=%r
     b'\x13@\x8d(H\x7f`\xe3\xb9Muf<\x97Ej\xaf)@\xd4\xe0\xdf\x19\xfa\x04,\xa6Bm\xceK\x0f;fuE j\x01\x129S\n\xb6\xb0"\xeb\xc7\xf9mn\xa0\x15\xd2T\xa8f\x93\x85\x94\xa5pEi\xd0\xeeY\x1100\'\xfao\x946\x07\xeb\x99\xe8\x17]\x1e\xdc\x87\xa20\xf4\t\x8d\xd4\xc5$\xd9\r\x94\xea6\xcc\x0c\x8c\xfb\x9b\xce /A\xa0\xfb\xb9gn\xcb\x04\x0e\xd4Hb\xb6t\xb1\xbe\xbeO\x18w\xdb\xbf\xad\xf0\xe90>r\xa4\xa1\x1a\xdf\xd1O$f\x10\xa6\xf9gt\x07\x01\x82\xa9\xd4\x87\x8f\xbb\xc6u\xeb\'\xbe\xbbv6\xe0\xc6\xae\xf6\xa4\\\xe9}\x1e\xa359B\x15\xb3W\xeb\x14\x11=q;\x96\xac\xcc8\xd3ZF\x19m\xb7\xf6"\x17\x9bA\xfe=\x97\xdbL\n\xcdt\x1d\xe3\x95T>I\x94\xfa\xa7p\xb1\x87x\x97\xb7\xbb\x81\xfe\xd9gH\xf2\x0e\x86B\xd1'
    *  Unexpected payload=%r
     b'\xbb\xcfh+@\x0b\xe6t\x0c\x83H\'\xb1-\xdc\xb9D\xc2\xc7\x08\x8a\x13\xaf]\x8b4\xda\x17\x847\xdfn\xb7\x81v\xcf\xf2\';\x10\x1f\x1bA;(#\xca3r\x83U\xdeh\xa6\xfe>\xd2"YH\xaf\xf0\'\x9aV}\x08uIs\xdf\xd0\x12\x826\xae\x1e%){+{ijJk\x18\x9e\xfb\xdetp\xe3V2\xa1\x1f\x02\xef@\xee\x05\xc2\xddy\xb4\x88oF\x97\xc2\x04\x1aW<rJ $\x89.y\x0b\x89\x86\x81\xd6\x08i\xc0\x0b\xf7\xa3~\xd1\x98%\x11\xb9\xe7\xc0\xb7\x9c+\x16\xc0\xf7\xb9\xe1\xc3\xb0\x89d\xd2\xb2\x0b\x19\xa5\xd6s\x01\x0e,/v~=iVe\tv\xa4 A0\xf5\x02\xf1\xae$\x18\xfc\x91\xaf\xc9?\xf74\x19z\xe9\x0e)\x02\xc1\xa2?5\xf1\xf02\x17N\xf6\xa1\xf3\x87\x81t\x0e\xa3(\x9d\xbf\x17\xa8jrE\x06\x1d\x92\xf0\xa8n\xd6\xa5\xf2\x82P\xa6;'
    *  Unexpected payload=%r
     b'\xbb\xcfh+@\x0b\xe6t\x0c\x83H\'\xb1-\xdc\xb9D\xc2\xc7\x08\x8a\x13\xaf]\x8b4\xda\x17\x847\xdfn\xb7\x81v\xcf\xf2\';\x10\x1f\x1bA;(#\xca3r\x83U\xdeh\xa6\xfe>\xd2"YH\xaf\xf0\'\x9aV}\x08uIs\xdf\xd0\x12\x826\xae\x1e%){+{ijJk\x18\x9e\xfb\xdetp\xe3V2\xa1\x1f\x02\xef@\xee\x05\xc2\xddy\xb4\x88oF\x97\xc2\x04\x1aW<rJ $\x89.y\x0b\x89\x86\x81\xd6\x08i\xc0\x0b\xf7\xa3~\xd1\x98%\x11\xb9\xe7\xc0\xb7\x9c+\x16\xc0\xf7\xb9\xe1\xc3\xb0\x89d\xd2\xb2\x0b\x19\xa5\xd6s\x01\x0e,/v~=iVe\tv\xa4 A0\xf5\x02\xf1\xae$\x18\xfc\x91\xaf\xc9?\xf74\x19z\xe9\x0e)\x02\xc1\xa2?5\xf1\xf02\x17N\xf6\xa1\xf3\x87\x81t\x0e\xa3(\x9d\xbf\x17\xa8jrE\x06\x1d\x92\xf0\xa8n\xd6\xa5\xf2\x82P\xa6;'
    *  Unexpected payload=%r
     b'RU8\xd9\t&\xec\xee]\xces6*:0\x02\xab\xe3\xfe\xa1\xf5\xf7a7\xde\xdc\xac\xb87\xa0\xc3\xe4\xc2\xfc\xff\xab.u\xeb\x93\x8bx\xc4>\xee\xafX%p\xb8\xa2\xd6L\x058M\xea\xb25\xdbs\x82\x0c\xad\xab\xfc\xa1`\xb3N7\xabM\xf4\xe9\x89D%So\xc0\x1fpG\xfc\xd5\xef\x1f\xabd\xda\xa0h\xbf\xf0cE\xdc)G\x87o\xe4\xc6=te\x1d\x0e:9\xf0\x0c\xb5\xf3\xb4\xc8\xcd\x81^zOU\xf9J\xd8\x9b\xb78\xe5\x92\x10Y\x93\xd30\xe2\xe6\xfe\xa6\xb3\t2\x84\xa8\xc9\x1b\xf3\xb8y\xeb\xdf\xa1*\xb6\xea\xf0\xcd\xebH\xac\xa1\xfa\xaa\x0e\x91\xa2\x1cD\x0eg\x81t\x0c\xf0Z\x8c\x8836"\xa1\xa4\xf1y+Y~Ot(\xee\x1eqF \xd4GsZ\xc2*\xa3}\x19\x15D.\xad\x19\xeb9\xfd\x9e\x9f>e\x80\xdd\xaf\xd44\xf4.\xc4\xf3\xd4\xd8+\xeb>!\xbc'
    *  Unexpected payload=%r
     b'RU8\xd9\t&\xec\xee]\xces6*:0\x02\xab\xe3\xfe\xa1\xf5\xf7a7\xde\xdc\xac\xb87\xa0\xc3\xe4\xc2\xfc\xff\xab.u\xeb\x93\x8bx\xc4>\xee\xafX%p\xb8\xa2\xd6L\x058M\xea\xb25\xdbs\x82\x0c\xad\xab\xfc\xa1`\xb3N7\xabM\xf4\xe9\x89D%So\xc0\x1fpG\xfc\xd5\xef\x1f\xabd\xda\xa0h\xbf\xf0cE\xdc)G\x87o\xe4\xc6=te\x1d\x0e:9\xf0\x0c\xb5\xf3\xb4\xc8\xcd\x81^zOU\xf9J\xd8\x9b\xb78\xe5\x92\x10Y\x93\xd30\xe2\xe6\xfe\xa6\xb3\t2\x84\xa8\xc9\x1b\xf3\xb8y\xeb\xdf\xa1*\xb6\xea\xf0\xcd\xebH\xac\xa1\xfa\xaa\x0e\x91\xa2\x1cD\x0eg\x81t\x0c\xf0Z\x8c\x8836"\xa1\xa4\xf1y+Y~Ot(\xee\x1eqF \xd4GsZ\xc2*\xa3}\x19\x15D.\xad\x19\xeb9\xfd\x9e\x9f>e\x80\xdd\xaf\xd44\xf4.\xc4\xf3\xd4\xd8+\xeb>!\xbc'
    *  Unexpected payload=%r
     b'\x99\xee\xe8L\xea\xb1\xf1\x83\xb2\xd5\xa8\xc0\xa9\x02/\xe5\x0b-\t\xaa]\x99\x8cy\x009\x0cp\x8eyd\xdeb\x97\x94\x94\xc6\x99r\xaa\x8a\xdcfM\xce\xa3\x8cB^\xbf\x92\xa0y_\xd5\xa1CT\xa9\x87\xd9\xbb#%\xcb\xbe%\x02\r\xa15\xad\xaaV\r\xfb\x17\xfd\xda,O\x03N8\x9c\x9a%\xd7\xc8\xd6\xaf\x02\x91\xb9\xc7\xf0\x81\x9c\xf0=\x08\xd3\xc3\\\xa1\x1a%\xb8\x82\xa3\xda\xa0\x03\x9d\x15y\x08\x7f\xc4\xb8h\xdc5\x18\xd0\xa6/\x03\xc1\xae\xe9P\x9e\x98\xfaT&(1\xf1\xe1oj$K\x88-\x89\xde\x1c>\xf1\x080\x82\x8d\x15\xad\xdad"\x8ds\xdd\x18\xa5\xb5rku\x07\xcf\xc6\xb5\xc0\x0e\xffp\xfa\xe0B\x00s\x13\xbc\xe3\xe61(\xe6\xa3\x84a{?\x1b\'\xc6\xa9\x8a\xce~\xbd\xc0\xd4\r\\\xcb];\t\x80$\xcf\xd6\xa3\xb0\xa3\x8eO\xf1I\x9c\xb6\x0b\xc3Q\xbc\xdekR\x18\x00'
    *  Unexpected payload=%r
     b'\x99\xee\xe8L\xea\xb1\xf1\x83\xb2\xd5\xa8\xc0\xa9\x02/\xe5\x0b-\t\xaa]\x99\x8cy\x009\x0cp\x8eyd\xdeb\x97\x94\x94\xc6\x99r\xaa\x8a\xdcfM\xce\xa3\x8cB^\xbf\x92\xa0y_\xd5\xa1CT\xa9\x87\xd9\xbb#%\xcb\xbe%\x02\r\xa15\xad\xaaV\r\xfb\x17\xfd\xda,O\x03N8\x9c\x9a%\xd7\xc8\xd6\xaf\x02\x91\xb9\xc7\xf0\x81\x9c\xf0=\x08\xd3\xc3\\\xa1\x1a%\xb8\x82\xa3\xda\xa0\x03\x9d\x15y\x08\x7f\xc4\xb8h\xdc5\x18\xd0\xa6/\x03\xc1\xae\xe9P\x9e\x98\xfaT&(1\xf1\xe1oj$K\x88-\x89\xde\x1c>\xf1\x080\x82\x8d\x15\xad\xdad"\x8ds\xdd\x18\xa5\xb5rku\x07\xcf\xc6\xb5\xc0\x0e\xffp\xfa\xe0B\x00s\x13\xbc\xe3\xe61(\xe6\xa3\x84a{?\x1b\'\xc6\xa9\x8a\xce~\xbd\xc0\xd4\r\\\xcb];\t\x80$\xcf\xd6\xa3\xb0\xa3\x8eO\xf1I\x9c\xb6\x0b\xc3Q\xbc\xdekR\x18\x00'
    *  Unexpected payload=%r
     b'Df\xa6L\xa4\xfc\xa4\x18\xb5\xceJ\x8dN`.j\x8c\xaf\x90)4\xfa\r\xach%p\x7f\x1e9h\xc2\xd62kP\xb9\xa7\xc1\x01\x83\xde\n\xdf\xca\xd0|\x19\xcfZ~\xc4\xb3\xd9x-M\xa2qk\xa5\x9evz3\xa5\xa2/%\x06\xf4\x8c\xe4\x86a\x9f\xc0^.Y\xabf\xd2\xc0\xce\xadF&T\x1c\x01.\x831\x11\xf07\xcb\x95M\x83cX\xba4%L^\xb1\x96\x13\x0c"\xb1;\xcc/\x93R\xbeX3t8\x16\xc6v*\x1a\xfe9\xfe0<=\xfc\x80\x12\x9e%B\xae\x1a\xcci\xfb\xf57\xe3\x04\xa3\x1b\xe9\[email protected]\xfd{d\xf5[l{h\xe3\xd5n|j\x8c\x82*\xfe\xa2O.\xf3w(\x86%wg\x9b\x83c*\xe4J\x8as\xd8}\xa48\xc4\xb4Id\xad\x9a\xf7\x08P\x07!\xbc\x8c\xd2\xf6\xcd\xb8\xd3j\xe3?\xa7O\xe2\x86%\xac\xfc;|\xa7\xa3)\x83n\xf1\xcb'
    
    Scan Complete!  Found 1 devices.
    
    >> Saving device snapshot data to snapshot.json
    

    When trying to send commands, I get {'Error': 'Timeout Waiting for Device', 'Err': '902', 'Payload': 'Check device key or version'}. I tried all protocol versions and the "device22" device type, to no avail. Enabling debug mode only reveals a "timeout in _send_receive()" and no reply from the bulb. Control using tinytuya.Cloud works perfectly. I can ping the bulb's IP with no problem.

    I checked the datapoint codes on the website and they seem to match the "version 3.3 - light type (RGB)" table in the README. However, trying to set these values through code doesn't work.

    Any ideas? Thanks!

    opened by Xilef11 3
  • snapshot.json file does not contain the endpoint information needed to add the device to hubitat...

    snapshot.json file does not contain the endpoint information needed to add the device to hubitat...

    My shanpshot.json file that gets created when running a scan finds my floor lamp, but it does not show an address (IP is listed as 0) and the endpoint information which should be a number preceeding a "false" value in a string of comma syntax is not found at all either. The IP I can pull from my DHCP - but the endpoint I'm not sure how to obtain. Is there more guidance on this step?

    opened by gleep52 10
  • Device with 22id doesn't work

    Device with 22id doesn't work

    I tried the fix but tinytuya wizard report:

    Product ID = keyxet94msd94uvq  [Valid payload]:
        Address = 192.168.1.7,  Device ID = bf534c9207553e222bjcki, Local Key = "LOCAL_KEY",  
        Version = 3.3,  MAC = 68:57:2d:25:be:9a Unexpected error for 192.168.1.7: Unable to poll
    

    This code report "None"

    import tinytuya
    a = tinytuya.OutletDevice('bf534c9207553e222bjcki', '192.168.1.7', 'my_local_key', 'device22')
    a.set_version(3.3)
    a.set_dpsUsed({"1": None})
    data =  a.status()
    print(data)
    
    opened by Izzami 14
  • scan for tcp connection

    scan for tcp connection

    I have 4 smart plugs with name SH-P01. Then have have only have open tcp ports open, according to NMap. I would love to be able to find my plugs. This is a feature request, not a bug. Not sure how to add lables otherwise I would have marked it a feature request.

    Sincerely Beach Bum Bob

    opened by beachbumbob 1
  • Hints on missing DPS 42-44 for Version 3.3 - Plug, Switch, Power Strip Type

    Hints on missing DPS 42-44 for Version 3.3 - Plug, Switch, Power Strip Type

    Hi!

    I have a tuya "Aubess Smart Socket 20A/EM" branded smart socket with energy measurement identical to https://www.youtube.com/watch?v=mG4bAAHluMU.

    While playing around in the Smart Life app with tuya-mqtt logging turned on, I figured out the usage of

    • DPS 42 - Circulate [Weekday, Start Time HH:MM, End Time HH:MM, Start Duration HH:MM, End Duration HH:MM] Sun, AM 01:02, PM 03:04, 5h 6m, 7h 8m translates to dps/state -> {"42":"AQEAPgOIATIBrA=="}

    • DPS 43 - Random [Weekday, Start Time HH:MM, End Time HH:MM] Mon, PM 01:02, AM 03:04 translates to dps/state -> {"43":"AQIDDgC4"}

    • DPS 44 - Inching Staircase time switch - off delay timer [s]

    Maybe this helps in any way and you want to extend https://github.com/jasonacox/tinytuya#version-33---plug-switch-power-strip-type with this information.

    If you need more examples to decode the payload just let me know.

    Br, Alex.

    opened by anno73 1
  • Tuya Cloud

    Tuya Cloud "Trial remaining usage is 0.00%"!

    I'm using tinytuya with the "cloud" and just received this email from TUYA after using for only a few hours:

    "Your subscription IoT Core, Cloud Develop Base Resource Trial remaining usage is 0.00%. Once the quota limit is exceeded, the service will be suspended. If you want to raise the limit, you can click the link below to upgrade your plan. https://www.tuya.com/vas/commodity/IOT_CORE_V2"

    The upgrade is 20000 Euros!!!!!

    Any advice on this would be appreciated as it would be a real shame if I cannot use the Cloud services anymore?

    opened by dgilbert2 5
Releases(v1.9.1)
  • v1.9.1(Dec 3, 2022)

    • PyPI 1.9.1
    • Fix logging for Cloud _gettoken() to prevent extraneous output. #229

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.9.0...v1.9.1

    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Dec 3, 2022)

    What's Changed

    • PyPI 1.9.0
    • Add support for subdevices connected to gateway by @LesTR in https://github.com/jasonacox/tinytuya/pull/222
    • Rework Zigbee Gateway handling to support multiple devices with persistent connections by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/226
    • Add support for newer IR devices, and several IR format converters by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/228
    • Rework Cloud log start/end times, and update documentation by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/229
    import tinytuya
    
    # Zigbee Gateway support uses a parent/child model where a parent gateway device is
    #  connected and then one or more children are added.
    
    # Configure the parent device
    gw = tinytuya.Device( 'eb...4', address=None, local_key='aabbccddeeffgghh', persist=True, version=3.3 )
    
    print( 'GW IP found:', gw.address )
    
    # Configure one or more children.  Every dev_id must be unique!
    zigbee1 = tinytuya.OutletDevice( 'eb14...w', cid='0011223344556601', parent=gw )
    zigbee2 = tinytuya.OutletDevice( 'eb04...l', cid='0011223344556689', parent=gw )
    
    print(zigbee1.status())
    print(zigbee2.status())
    

    New Contributors

    • @LesTR made their first contribution in https://github.com/jasonacox/tinytuya/pull/222

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.8.0...v1.9.0

    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Nov 22, 2022)

    What's Changed

    • PyPI 1.8.0
    • Add AtorchTemperatureController by @Poil in https://github.com/jasonacox/tinytuya/pull/213
    • Add new Cloud functions to fetch device logs from TuyaCloud getdevicelog(id), make generic cloud request with custom URL and params cloudrequest(url, ...) and fetch connection status getconnectstatus(id) by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/219
    • Update README for new Cloud functions, and tighter deviceid error checking by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/220
    import tinytuya
    import json
    
    c = tinytuya.Cloud()
    r = c.getdevicelog( '00112233445566778899' )
    print( json.dumps(r, indent=2) )
    

    New Contributors

    • @Poil made their first contribution in https://github.com/jasonacox/tinytuya/pull/213

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.7.2...v1.8.0

    Source code(tar.gz)
    Source code(zip)
  • v1.7.2(Nov 1, 2022)

    What's Changed

    • Misc updates to find_device(), wizard, and repr(device) by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/196
    • Added socketRetryDelay as parameter instead of fixed value = 5. by @erathaowl in https://github.com/jasonacox/tinytuya/pull/199
    • Restore reference to 'self' in init() functions by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/207

    New Contributors

    • @erathaowl made their first contribution in https://github.com/jasonacox/tinytuya/pull/199

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.7.1...v1.7.2

    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Oct 7, 2022)

    What's Changed

    • PyPI 1.7.1
    • Add Climate device module and simple example for portable air conditioners by @fr3dz10 in https://github.com/jasonacox/tinytuya/pull/189 and https://github.com/jasonacox/tinytuya/pull/192
    • Constructor and documentation updates by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/188
    • Get local key from devices.json if not provided by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/187
    • Rework device finding for auto-IP detection, and unpack_message() retcode fix by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/186
    • Standardize indentation for code snippets in the README by @TheOnlyWayUp in https://github.com/jasonacox/tinytuya/pull/184
    import tinytuya 
    
    # Specify only Device ID and tinytuya will scan for IP 
    # and lookup Device Local KEY from devices.json
    
    d = tinytuya.OutletDevice( '0123456789abcdef0123' )
    

    New Contributors

    • @TheOnlyWayUp made their first contribution in https://github.com/jasonacox/tinytuya/pull/184
    • @fr3dz10 made their first contribution in https://github.com/jasonacox/tinytuya/pull/189

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.7.0...v1.7.1

    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(Sep 24, 2022)

    What's Changed

    • PyPI 1.7.0
    • Add support for v3.4 protocol Tuya devices by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/179
    • API change with _send_receive() - now takes care of the packing and encrypting so it can re-encode whenever the socket is closed and reopened, and _get_socket() now takes care of negotiating the session key (v3.4)
    • Optimize detect_available_dps() by @pawel-szopinski in https://github.com/jasonacox/tinytuya/pull/176
    • Update ThermostatDevice by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/174
    • Add Pronto/NEC/Samsung IR code conversion functions to IRRemoteControlDevice by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/173
    • Added DoorbellDevice by @JonesMeUp in https://github.com/jasonacox/tinytuya/issues/162
    • Added ability to set version on constructor for more intuitive use:
    d = tinytuya.OutletDevice(
        dev_id='xxxxxxxxxxxxxxxxxxxxxxxx',
        address='x.x.x.x',
        local_key='xxxxxxxxxxxxxxxx',
        version=3.4)
    
    print(d.status())
    

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.6...v1.7.0

    Source code(tar.gz)
    Source code(zip)
  • v1.6.6(Aug 16, 2022)

    What's Changed

    • PyPI 1.6.6
    • Added support for 3.2 protocol Tuya devices
    • Added SocketDevice by @Felix-Pi in https://github.com/jasonacox/tinytuya/pull/167
    • Skip DPS detection for 3.2 protocol devices if it has already been set by @pawel-szopinski in https://github.com/jasonacox/tinytuya/pull/169
    # Example usage of community contributed device modules
    from tinytuya.Contrib import SocketDevice
    
    socket = SocketDevice('abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc', version=3.3)
    
    print(socket.get_energy_consumption())
    print(socket.get_state())
    

    New Contributors

    • @Felix-Pi made their first contribution in https://github.com/jasonacox/tinytuya/pull/167
    • @pawel-szopinski made their first contribution in https://github.com/jasonacox/tinytuya/pull/169

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.5...v1.6.6

    Source code(tar.gz)
    Source code(zip)
  • v1.6.5(Aug 7, 2022)

    What's Changed

    • PyPI 1.6.5
    • Reworked payload_dict and realigned the command list to match Tuya's API by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/166
    • Changed socket.send() to socket.sendall() in _send_receive() by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/166
    • Created TuyaSmartPlug-example.py by @fajarmnrozaki in https://github.com/jasonacox/tinytuya/pull/163 and https://github.com/jasonacox/tinytuya/pull/165

    New Contributors

    • @fajarmnrozaki made their first contribution in https://github.com/jasonacox/tinytuya/pull/163

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.4...v1.6.5

    Source code(tar.gz)
    Source code(zip)
  • v1.6.4(Jul 14, 2022)

    What's Changed

    • PyPI 1.6.4
    • Separates read retries from send retries by @uzlonewolf #158
    • IRRemoteControlDevice - New community contributed device module for IR Remote Control devices by @ClusterM in https://github.com/jasonacox/tinytuya/pull/160 - See example: examples/IRRemoteControlDevice-example.py
    # Example usage of community contributed device modules
    from tinytuya import Contrib
    
    ir = Contrib.IRRemoteControlDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
    

    New Contributors

    • @ClusterM made their first contribution in https://github.com/jasonacox/tinytuya/pull/160

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.2...v1.6.4

    Source code(tar.gz)
    Source code(zip)
  • v1.6.2(Jul 7, 2022)

    What's Changed

    • PyPI 1.6.2
    • Add getconnectstatus() function to Cloud class by @Paxy in https://github.com/jasonacox/tinytuya/pull/151
    • Improve TuyaMessage Header processing for mulit-payload messages by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/153
    • More verbose debug logging on decode error by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/155
    • Add schedule editing to Contrib/ThermostatDevice and various fixes by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/157

    New Contributors

    • @Paxy made their first contribution in https://github.com/jasonacox/tinytuya/pull/151

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.1...v1.6.2

    Source code(tar.gz)
    Source code(zip)
  • v1.6.1(Jul 3, 2022)

    What's Changed

    • PyPI 1.6.1
    • Cloud - Fix bug in getdevices() to import device mac addresses (same as wizard).
    • Break the Outlet/Cover/Bulb/Cloud modules out into separate files by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/142
    • Fix logging calls in XenonDevice.detect_available_dps by @pkasprzyk in https://github.com/jasonacox/tinytuya/pull/144
    • TinyTuya API Server - Add Cloud API syncing with auto-retry by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/147
    • TinyTuya API Server - List registered but offline devices via /offline and web UI.
    • ThermostatDevice - First community contributed device module ThermostatDevice by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/146 - See example: examples/ThermostatDevice-example.py
    # Example usage of community contributed device modules
    from tinytuya import Contrib
    
    thermo = Contrib.ThermostatDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
    

    New Contributors

    • @pkasprzyk made their first contribution in https://github.com/jasonacox/tinytuya/pull/144

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.6.0...v1.6.1

    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Jun 15, 2022)

    What's Changed

    • PyPI 1.6.0
    • Add colorama terminal color capability for all platforms including MS Windows and stdout redirects
    • Fix to allow setting socket options to existing open sockets by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/140
    • Add DPS table to README for a 24v Thermostat by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/141
    • BETA: Started standalone TinyTuya API Server (see here). No change to core library.

    New Contributors

    • @uzlonewolf made their first contribution in https://github.com/jasonacox/tinytuya/pull/140

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.5.0...v1.6.0

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Jun 5, 2022)

    What's Changed

    • PyPI 1.5.0
    • Added an optional 'nowait' boolean setting (True/False) to functions to allow sending commands without waiting for a device response. (Issue #74)
    • Support optional version parameter by @dominikkarall in https://github.com/jasonacox/tinytuya/pull/127
    • Update README.md to reflect new DPs for v3.3 Plug by @manj9501 in https://github.com/jasonacox/tinytuya/pull/133
    • Some cleanup from pylint by @mafrosis in https://github.com/jasonacox/tinytuya/pull/135
    • Add Universal IR Controller DP instructions by @mont5piques in https://github.com/jasonacox/tinytuya/pull/137
    • Added robot mower data by @Whytey in https://github.com/jasonacox/tinytuya/pull/138

    New Contributors

    • @dominikkarall made their first contribution in https://github.com/jasonacox/tinytuya/pull/127
    • @manj9501 made their first contribution in https://github.com/jasonacox/tinytuya/pull/133
    • @mafrosis made their first contribution in https://github.com/jasonacox/tinytuya/pull/135
    • @mont5piques made their first contribution in https://github.com/jasonacox/tinytuya/pull/137
    • @Whytey made their first contribution in https://github.com/jasonacox/tinytuya/pull/138
    # Example use of nowait option
    d.turn_on(nowait=True)
    d.set_colour(r, g, b, nowait=True)
    d.set_value(201, '9AEmAvQBJgL0ASYCQAYmAkAGJgJABiY', nowait=True)  # send IR command
    d.set_value(25, '010e0d0000000000000003e803e8', nowait=True)      # set scene
    

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.4.0...v1.5.0

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Apr 11, 2022)

    What's Changed

    • PyPI 1.4.0 - Minor Update to APIs (additional arguments and elements)
    • Debug - Updated debug output for payloads to formatted hexadecimal (pull request #98)
    • Scan - Terminal color fix for 3.1 devices.
    • Error Handling added for set_timer() function (Issue #87)
    • Add galaxy lamp example by @knrdl in https://github.com/jasonacox/tinytuya/pull/115
    • Add wizard capability to pull mac addresses from TuyaPlatform in devices.json (Issue #117)
    • Add wizard -force option to perform network scan for device IP addresses (Issue #117)
    • Added support to get the MAC address and local IP address in the Wizard by @frodeheg in https://github.com/jasonacox/tinytuya/pull/120
    • Separated scan functions into scanner.py file.
    • NEW: Added command line functions for scanning:
      • devices - Display and poll all registered devices for status (using devices.json). This will force a network scan for IP address changes and will create snapshot.json.
      • snapshot - Display and poll all devices as listed snapshot.json. This assume IP address are the same as the last snapshot.
      • json - Same as snapshot but respond with a JSON payload.
    # Run wizard using brute force scan for IP addresses
    python -m tinytuya wizard -force
    
    # New Interactive Command Line Options
    python -m tinytuya devices
    python -m tinytuya snapshot
    
    # Non-Interactive poll with JSON response
    python -m tinytuya json
    

    New Contributors

    • @knrdl made their first contribution in https://github.com/jasonacox/tinytuya/pull/115
    • @frodeheg made their first contribution in https://github.com/jasonacox/tinytuya/pull/120

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.3.1...v1.4.0

    Source code(tar.gz)
    Source code(zip)
  • v1.3.1(Jan 29, 2022)

    What's Changed

    • PyPi Version 1.3.1
    • Added TuyaCloud token expiration detection and renewal logic (Issue #94)
    • Update instructions, including screenshot for configuring datacenter by @cy1110 in https://github.com/jasonacox/tinytuya/pull/97
    • Displays raw data better. by @mores in https://github.com/jasonacox/tinytuya/pull/98

    New Contributors

    • @cy1110 made their first contribution in https://github.com/jasonacox/tinytuya/pull/97
    • @mores made their first contribution in https://github.com/jasonacox/tinytuya/pull/98

    Full Changelog: https://github.com/jasonacox/tinytuya/compare/v1.3.0...v1.3.1

    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Dec 31, 2021)

    • Code format cleanup and readability improvements (pull request #91)
    • Upgrade - Add TuyaCloud API support and functions (#87 #95)
    import tinytuya
    
    c = tinytuya.Cloud(
            apiRegion="us", 
            apiKey="xxxxxxxxxxxxxxxxxxxx", 
            apiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
            apiDeviceID="xxxxxxxxxxxxxxxxxxID")
    
    # Display list of devices
    devices = c.getdevices()
    print("Device List: %r" % devices)
    
    # Select a Device ID to Test
    id = "xxxxxxxxxxxxxxxxxxID"
    
    # Display DPS IDs of Device
    result = c.getdps(id)
    print("DPS IDs of device:\n", result)
    
    # Display Status of Device
    result = c.getstatus(id)
    print("Status of device:\n", result)
    
    # Send Command - This example assumes a basic switch
    commands = {
    	'commands': [{
    		'code': 'switch_1',
    		'value': True
    	}, {
    		'code': 'countdown_1',
    		'value': 0
    	}]
    }
    print("Sending command...")
    result = c.sendcommand(id,commands)
    print("Results\n:", result)
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.11(Nov 28, 2021)

    • Added retries logic to wizard and scan to honor value set by command line or default to a value based on the number of devices (if known):
    # Explicit value set via command line
    python3 -m tinytuya wizard 50   # Set retry to 50 
    python3 -m tinytuya scan 50     
    
    # Use automatic computed value
    python3 -m tinytuya wizard      # Compute a default
    python3 -m tinytuya scan        
    
    # Example output
    TinyTuya (Tuya device scanner) [1.2.11]
    
    [Loaded devices.json - 32 devices]
    
    Scanning on UDP ports 6666 and 6667 for devices (47 retries)...
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.10(Oct 31, 2021)

    • PyPi Version 1.2.10
    • Added ability to disable device auto-detect (default vs device22) via d.disabledetect=True.
    • Wizard: Added new data center regions for Tuya Cloud: (Issues #66 #75)

    Code | Region | Endpoint -- | -- | -- cn | China Data Center | https://openapi.tuyacn.com us | Western America Data Center | https://openapi.tuyaus.com us-e | Eastern America Data Center | https://openapi-ueaz.tuyaus.com eu | Central Europe Data Center | https://openapi.tuyaeu.com eu-w | Western Europe Data Center | https://openapi-weaz.tuyaeu.com in | India Data Center | https://openapi.tuyain.com

    Source code(tar.gz)
    Source code(zip)
  • v1.2.9(Sep 29, 2021)

    • PyPi Version 1.2.9
    • Added Error Handling in class Device(XenonDevice) for conditions where response is None (Issue #68)
    • Added edge-case handler in _decode_payload() to decode non-string type decrypted payload (Issue #67)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.8(Sep 2, 2021)

    • PyPi Version 1.2.8
    • Added additional error checking for BulbDevice type selection
    • Added TinyTuya version logging for debug mode
    • Fix bug in scan when color=False (Issue #63)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.7(Jul 28, 2021)

    • PyPi Version 1.2.7
    • Updated setup wizard to support new Tuya IoT Cloud signature method (Issue #57)
    • Added Bulb type C and manual setting function set_bulb_type(type) (PR #54)
    • Wizard creates tuya-raw.json to record raw response from Tuya IoT Platform
    • Fixed device22 bug on retry - Now returns ERR_DEVTYPE error, status() includes auto-retry (#56)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.6(Jun 3, 2021)

    • PyPi Version 1.2.6
    • Added wizard handling to capture and display Tuya API server error responses (PR #45)
    • Added better error handling for BulbDevice state() function to not crash when dps values are missing in response (PR #46)
    • Added async examples using send() and receive()
    • Updated scan output to include device Local Key if known (PR #49 #50)
    • Fixed print typo in examples/devices.py (PR #51)
    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Apr 26, 2021)

    • PyPi Version 1.2.5
    • Added raw mode send() and receive() function to allow direct control of payload transfers. Useful to monitor state changes via threads or continuous loops. This example opens a Tuya device and watches for state changes (e.g. switch going on and off):
    import tinytuya
    
    d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
    d.set_version(3.3)
    d.set_socketPersistent(True)
    
    print(" > Send Initial Query for Status < ")
    payload = d.generate_payload(tinytuya.DP_QUERY)
    d.send(payload)
    
    while(True):
        # See if any data is available
        data = d.receive()
        print('Received Payload: %r' % data)
    
        # Send a keyalive heartbeat ping
        print(" > Send Heartbeat Ping < ")
        payload = d.generate_payload(tinytuya.HEART_BEAT)
        d.send(payload)
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.4(Apr 19, 2021)

    • PyPi Version 1.2.4
    • Added detect_available_dps() function
    • Fixed bug in json_error() function
    • Updated instruction for using Tuya iot.tuya.com to run Wizard
    • Added option to disable deviceScan() automatic device polling
    • Added better error handling processing Tuya messages (responses) Issue #39
    • Fixed display bug in Wizard device polling to show correct On/Off state
    Source code(tar.gz)
    Source code(zip)
  • v1.2.3(Mar 3, 2021)

    • PyPi Version 1.2.3
    • Added set_dimmer() to OutletDevice class.
    • Added set_hsv() to BulbDevice class.
    • Updated set_brightness() in BulbDevice to handle white and colour modes. Issue #30
    • BulbDevice determines features of device and presents boolean variables has_colour, has_brightness and has_colourtemp to ignore requests that do not exist (returns error).
    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Feb 23, 2021)

    • PyPi Version 1.2.2
    • Fix bug in set_white_percentage(): added missing self. PR #32
    • Fixed set_white_percentage: colour temp was incorrectly computed for B type Bulbs. PR #33
    • Moved setup Wizard out of module init to standalone import to save import load.

    Command line mode is still the same:

    python3 -m tinytuya wizard
    

    Import now requires additional import to run Wizard programmatically:

    import tinytuya
    import tinytuya.wizard
    
    tinytuya.wizard.wizard()
    
    
    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Feb 11, 2021)

  • v1.2.0(Feb 10, 2021)

    • PyPi Version 1.2.0
    • Now decrypting all TuyaMessage responses (not just status)
    • Fixed set_colour(r, g, b) to work with python2
    • Fixed set_debug() to toggle on debug logging (with color)
    • Added handler for device22 to automatically detect and set_dpsUsed() with available DPS values.
    • Added set_socketTimeout(s) for adjustable connection timeout setting (defaults to 5s)
    • Added set_sendWait(s) for adjustable wait time after sending device commands
    • Improved and added additional error handling and retry logic
    • Instead of Exceptions, tinytuya responds with Error response codes (potential breaking change):

    Example

    import tinytuya
    
    tinytuya.set_debug(toggle=False, color=True)
    
    d = tinytuya.OutletDevice('<ID>','<IP>','<KEY>')
    d.set_version(3.3)
    d.status()
    
    {u'Payload': None, u'Err': u'905', u'Error': u'Network Error: Device Unreachable'}
    
    Source code(tar.gz)
    Source code(zip)
  • v1.1.4(Feb 1, 2021)

    • PyPi Version 1.1.4
    • Added updatedps() command 18 function to request device to update DPS values (Issue #8)
    • Added set_debug() function to activate debug logging
    import tinytuya
    import time
    
    tinytuya.set_debug(True)
    
    d = tinytuya.OutletDevice('DEVICEID', 'IP', 'LOCALKEY')
    d.set_version(3.3)
    
    print(" > Fetch Status < ")
    data = d.status()
    time.sleep(5)
    
    print(" > Request Update for DPS indexes 18, 19 and 20 < ")
    result = d.updatedps([18, 19, 20])
    
    print(" > Fetch Status Again < ")
    data2 = d.status()
    
    print("Before %r" % data)
    print("After  %r" % data2)
    
    Source code(tar.gz)
    Source code(zip)
  • v1.1.3(Jan 13, 2021)

    • PyPi Version 1.1.3
    • Updated device read retry logic for minimum response payload (28 characters) (Issue #17)
    • Feature added to do automatic IP address lookup via network scan if None or '0.0.0.0' is specified. Example:
        import tinytuya
        ID = "01234567890123456789"
        IP = None
        KEY = "0123456789012345"
        d = tinytuya.OutletDevice(ID,IP,KEY)
        d.status()
    
    Source code(tar.gz)
    Source code(zip)
Owner
Jason Cox
Maker, Learner, Writer, Artist - My Views/Opinions - ジェイソンのコード
Jason Cox
Get Your Localhost Online - Ngrok Alternative

Get Your Localhost Online - Ngrok Alternative

Azimjon Pulatov 442 Jan 04, 2023
TradingView Interactive Brokers Integration using Webhooks

TradingView Interactive Brokers Integration using Webhooks

84 Dec 19, 2022
BibleNotifyDesktop - Desktop version of Bible Notify

Bible Notify Desktop This is the repository for the Desktop version of the daily

Bible Notify 5 Nov 16, 2022
A repository dedicated to IoT(internet of things ) and python scripts

📑 Introduction Week of Learning is a weekly program in which you will get all the necessary knowledge about Circuit-Building, Arduino and Micro-Contr

27 Nov 22, 2022
pyngrok is a Python wrapper for ngrok

pyngrok is a Python wrapper for ngrok that manages its own binary, making ngrok available via a convenient Python API.

Alex Laird 329 Dec 31, 2022
Takes a file of hosts or domains and outputs the IP address of each host/domain in the file.

Takes a file of hosts or domains and outputs the IP address of each host/domain in the file. Installation $ git clone https://github.com/whoamisec75/i

whoami security 2 May 10, 2022
A vpn that sits in your browser, accessible via a website

VPNInYourBrowser A vpn that sits in your browser, accessible via a website Example setup: https://VPNInBrowser.jaffa42.repl.co Setup Put the code onto

1 Jan 20, 2022
NetworkX is a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.

NetworkX is a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.

NetworkX 12k Jan 02, 2023
Building a Robust IOT device which is customizable, encrypted, secure and user friendly

Building a Robust IOT device which is customizable, encrypted, secure and user friendly, which uses a single GPIO pin to extract multiple sensor values

1 Jan 03, 2022
Use Raspberry Pi and CircuitSetup's power monitor hardware to publish electrical usage to MQTT

This repo has code and notes for whole home electrical power monitoring using a Raspberry Pi and CircuitSetup modules. Beyond just collecting data, it

Eric Tsai 10 Jul 25, 2022
Burp Extension that copies a request and builds a FFUF skeleton

ffuf is gaining a lot of traction within the infosec community as a fast portable web fuzzer. It has been compared and aligned (kinda) to Burp's Intruder functionality. Thus, Copy As FFUF is trying t

Desmond Miles 81 Dec 22, 2022
A script for generating WireGuard configs from Surfshark VPN

Surfshark WireGuard A script for generating WireGuard configs from Surfshark VPN. You must have python3 available on your machine. Usage Currently we

Alireza Ahmand 58 Dec 23, 2022
A tool to generate valid ip addresses of 55 countries. These ip's can be used for OpenBullet.

IP-Grabber A tool to generate valid ip addresses of 55 countries. These ip's can be used for OpenBullet. ive added the feature to set the generated ip

Saad 9 Dec 17, 2022
sshuttle: where transparent proxy meets VPN meets ssh

Transparent proxy server that works as a poor man's VPN. Forwards over ssh. Doesn't require admin. Works with Linux and MacOS. Supports DNS tunneling.

9.4k Jan 09, 2023
This is a Client-Server-System which can share the screen from the server to client and in the other direction.

Screenshare-Streaming-Python This is a Client-Server-System which can share the screen from the server to client and in the other direction. You have

VFX / Videoeffects Creator 1 Nov 19, 2021
A Network tool kit for scanning active IP addresses and open ports

Network scanner A small project that I wrote on the fly for (IT351) Computer Networks University Course to identify and label the devices in my networ

Mohamed Abdelrahman 10 Nov 07, 2022
VRF-StarkNet - Contracts for verifiable randomness on StarkNet

VRF-StarkNet Contracts for verifiable randomness on StarkNet Motivation Deployed

Non 32 Oct 30, 2022
Throttle rTorrent on Plex stream Start/Stop

Dependencies Python 3.6+ Tautulli Script Setup Edit rtorrent_throttle.py and set rTorrent username, password and RPC2 url. Tautulli Setup Commum Scrip

4 Apr 25, 2022
Query protocol and response

whois Query protocol and response _MᵃˢᵗᵉʳBᵘʳⁿᵗ_ _ ( ) _ ( )( ) _ | | ( ) | || |__ _ (_) ___ | | | | | || _ `\ /'_`\ | |/',__) |

MasterBurnt 4 Sep 05, 2021
WebRTC and ORTC implementation for Python using asyncio

aiortc What is aiortc? aiortc is a library for Web Real-Time Communication (WebRTC) and Object Real-Time Communication (ORTC) in Python. It is built o

3.2k Jan 07, 2023