Giter VIP home page Giter VIP logo

tuyapower's Introduction

TuyaPower - Python Module

Build Status PyPI version

This python module will poll WiFi Tuya compatible Smart Plugs/Switches/Lights for state (on/off), current (mA), voltage (V), and power (wattage).

Description

This module uses the python tinytuya or pytuya library to poll Tuya compatible Smart Plugs, Switches and Lights for state and power data that can be used for point in time monitoring or stored for trending. There are two test scripts here. The plugpower.py script responds with a human readable output of state (on/off), current (mA), voltage (V), and power (W). The plugjson.py script responds with JSON containing the same but adds a timestamp for convenient time series processing.

TuyaPower Setup

Tested on RaspberryPi, Linux, Windows 10 and MacOS. Install pip and the following python libraries if you haven't already.

TuyaPower has been updated to use tinytuya, a fork of pytuya that adds support for device IDs of 20 and 22 characters (pytuya only supports 20 character IDs). Install tinytuya to take advantage of that feature.

# Install required libraries
 sudo apt-get install python-crypto python-pip  # for RPi, Linux
 python3 -m pip install pycryptodome            # or pycrypto, pyaes, Crypto
 python3 -m pip install tinytuya                # or pytuya
 python3 -m pip install tuyapower               # Pull this tuyapower module from PyPi

Tuya Device Preparation

Pulling data from Tuya devices on your network requires that you have the Device IP, ID, VERSION and KEY (for 3.3 devices). The tuyapower and tinytuya modules include a scanner function to find Smart Plugs on your network. This will scan the network and identify Device's IP, ID and VERSION. It will not be able to get the local KEY. Since newer 3.3 devices will require the KEY, the following steps will help you determine the KEYs for your devices:

Get the Tuya Device KEY

  1. Download the "Smart Life" - Smart Living app for iPhone or Android. Pair with your smart plug (this is important as you cannot monitor a plug that has not been paired).
  2. For Device IP, ID and VERSION: Run the tuyapower scan to get a list of Tuya devices on your network along with their device IP, ID and VERSION number (3.1 to 3.5 - most are 3.3):
    python3 -m tuyapower
  3. For Device KEY: If your device is running the latest protocol version 3.3 (often seen with Firmware 1.0.5 or above), you will need to obtain the Device Key. This is used to connect with the device and decrypt the response data. The following are instructions to do this and are based on https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md:
  • From iot.tuya.com

    • Create a Tuya Developer account on iot.tuya.com and log in.
    • Click on "Cloud" icon -> Create a project (remember the Authorization Key: API ID and Secret for below)
    • Click on "Cloud" icon -> select your project -> Project Overview -> Linked Device -> Link devices by App Account (tab)
    • Click 'Add App Account' 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 "API Management" -> "API Products" and ensure the API groups have status "Subscribed": Smart Home Devices Management, Authorization and Smart Home Family Management (see screenshot here) - Make sure you authorize your Project to use these 3 API groups:
      • Click each of the API boxes
      • Click "Projects" tab
      • Click "New Authorization" button
      • Select your Project from the dropdown and click OK (see screenshot here)
  • From your Local Workstation

    • From your PC/Mac you can run the TinyTuya Setup Wizard to fetch the Device KEYs for all of your registered devices:
    python3 -m tinytuya wizard
    
    # If you are using windows command prompt w/o color use:
    python -m tinytuya wizard -nocolor
    
    • The Wizard will prompt you for the API ID key, API Secret, API Region (us, eu, cn or in) from your Tuya IoT project noted above. 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 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 Device KEYs you will use to poll your devices.
    • In addition to displaying the list of devices, Wizard will create a local file devices.json. TinyTuya will use this file to provide additional details to scan results from tinytuya.scanDevices() or when running python3 -m tinytuya to scan your local network.

Notes:

  • If you ever reset or re-pair your smart devices, they will reset their LOCAL_KEY and you will need to repeat these steps above.
  • The TinyTuya Wizard was inspired by the TuyAPI CLI which is an alternative way to fetch the Device KEYs: npm i @tuyapi/cli -g and run tuya-cli wizard
  • For a helpful video walk-through of getting the KEYS you can also watch this great Tech With Eddie YouTube tutorial: https://youtu.be/oq0JL_wicKg.

Programming with TuyaPower

TuyaPower Module Functions

  • deviceInfo - Poll device and return on, w, mA, V and err data.
    (on, w, mA, V, err) = tuyapower.deviceInfo(PLUGID, PLUGIP, PLUGKEY, PLUGVERS)
  • deviceRaw - Poll device and return raw response data.
    rawData = tuyapower.deviceRaw(PLUGID, PLUGIP, PLUGKEY, PLUGVERS)
  • devicePrint - Poll device and print formatted output to stdout.
    tuyapower.devicePrint(PLUGID, PLUGIP, PLUGKEY, PLUGVERS)
  • deviceJSON - Poll device and return JSON formatted details.
    dataJSON = tuyapower.deviceJSON(PLUGID, PLUGIP, PLUGKEY, PLUGVERS)
  • deviceScan(verbose, max_retries=15) - Scans network for smart plug devices and return dictionary of devices and power data.
    verbose = False
    devices = tuyapower.deviceScan(verbose)
  • scan(max_retries=15) - This is a shortcut for deviceScan() that prints formatted output to stdout for UDP ports 6666 and 6667. 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.

Parameters:

  • PLUGID = Device ID e.g. 01234567891234567890
  • PLUGIP = Device IP Address e.g. 10.0.1.99
  • PLUGKEY = Device Key e.g. 0123456789abcdef
  • PLUGVERS = Version of Protocol 3.1, 3.2, 3.3, 3.4 or 3.5
  • verbose = Print more details - True or False (default is False)
  • max_retries = Number of times to retry scan of new devices (default is 15)

Response Data:

  • on = Switch state (single) - true or false
  • on = Switch state (multiswitch) - dictionary of state for each switch e.g. {'1':True, '2':False}
  • w = Wattage
  • mA = milliamps
  • V = Voltage
  • err = Error message or OK (power data found)
  • rawData = Raw response from device
  • devices = Dictionary of all devices found with power data if available

Note: If error occurs, on will be set to false, w, mA and V will be set to 0.

Programming Examples

You can import the tuyapower module into your own python projects and use the deviceInfo(), deviceJSON(), deviceScan() and devicePrint() functions to access data on your Tuya devices. Here are some examples:

# Poll a Single Devices
import tuyapower

PLUGID = '01234567891234567890'
PLUGIP = '10.0.1.99'
PLUGKEY = '0123456789abcdef'
PLUGVERS = '3.1'

(on, w, mA, V, err) = tuyapower.deviceInfo(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)

tuyapower.deviceJSON(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
'{ "datetime": "2019-10-13T03:58:57Z", "switch": "True", "power": "1.2", "current": "70.0", "voltage": "122.1", "response": "OK" }'

tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats)

Device 03200160dc4f2216ff61 at 10.0.1.5 key 0123456789abcdef protocol 3.1:
   Switch On: True
   Power (W): 1.200000
   Current (mA): 70.000000
   Voltage (V): 122.100000
   Projected usage (kWh):  Day: 0.028800  Week: 0.201600  Month: 0.873600

# Scan Network for All Devices
# To see output on stdout set verbose True
tuyapower.deviceScan(True)
TuyaPower (Tuya compatible smart plug scanner) [0.0.16]

Scanning on UDP ports 6666 and 6667 for devices...

FOUND Device [Valid payload]: 10.0.1.100
   ID = 01234567891234567890, Key = 0123456789abcdef, Version = 3.1
   Stats: on=True, W=6.0, mA=54.0, V=121.1 [OK]
FOUND Device [Valid payload]: 10.0.1.200
   ID = 01234567891234567891, Key = 0123456789abcdea, Version = 3.1
   Stats: on=True, W=-99, mA=-99, V=-99 [Power data unavailable]
FOUND Device [Valid payload]: 10.0.1.222
   ID = 01234567891234567893, productKey = 0123456789abcdea, Version = 3.3
   Device Key required to poll for stats

Scan Complete!  Found 3 devices.

# Scan the network and unpack the response 
devices = tuyapower.deviceScan()
   for ip in devices:
       id = devices[ip]['gwId']
       key = devices[ip]['productKey']
       vers = devices[ip]['version']
       (on, w, mA, V, err) = deviceInfo(id, ip, key, vers)
       print("Device at %s: ID %s, state=%s, W=%s, mA=%s, V=%s [%s]"%(ip,id,on,w,mA,V,err))

Tuya Device Scan Tool

The function tuyapower.scan() will listen to your local network and identify Tuya devices broadcasting their IP, Device ID, Product Key (not the Local KEY) and protocol Version. It will print the list of devices and for 3.1 protocol devices that don't require local KEY, it will display their energy stats. This can help you get a list of compatible devices on your network. The tuyapower.deviceScan() function returns all found devices and their stats via a dictionary result.

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

python3 -m tuyapower

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 (ex. 50 retries):

# command line
python3 -m tuyapower 50
# invoke verbose interactive scan
tuyapower.scan(50)

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

Docker Usage (Optional)

Docker Pulls

A docker container version of the tuyapower library is available on DockerHub and can be used to grab power data without installing the python libraries.

# Friendly Output
# Run tuyapower container - replace with device ID, IP and VERS
docker run -e PLUGID="01234567891234567890" \
    -e PLUGIP="10.0.1.x" \
    -e PLUGKEY="0123456789abcdef" \
    -e PLUGVERS="3.3" \
    jasonacox/tuyapower

# JSON Output
# Run tuyapower container - replace with device ID, IP and VERS
docker run -e PLUGID="01234567891234567890" \
    -e PLUGIP="10.0.1.x" \
    -e PLUGKEY="0123456789abcdef" \
    -e PLUGVERS="3.3" \
    -e PLUGJSON="yes" \
    jasonacox/tuyapower

Example Products

Acknowledgements

Contributors

  • Jason A. Cox (jasonacox)
  • Phill Healey (codeclinic) - Integration for firmware 1.0.5+ / protocol v3.3 & commandline arguments.

tuyapower's People

Contributors

basnijholt avatar gamuama avatar jasonacox avatar pablocastellano avatar stevoh6 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tuyapower's Issues

Smart Energy Meter

Hello,
I have 2 smart energy meter, the first one has a firmware version 1.0.2 and the second is in 1.1.17.
The first one is working fine and I can get the current and power with tuyapower.

The second one return with tuyapower Power data unavailable

import tuyapower
PLUGID = 'bfb9b29bca25f99a69aqla'
PLUGIP = '192.168.0.94'
PLUGKEY = 'XXXXXXXXX'
PLUGVERS = '3.3'
(on, w, mA, V, err) = tuyapower.deviceInfo(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
tuyapower.deviceInfo(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
=>> (136, -99, -99, -99, 'Power data unavailable')

Field '1' correspond to the total energy consumption but I can not see the real time power or the current consumption.

tuyapower.deviceRaw(PLUGID, PLUGIP, PLUGKEY, PLUGVERS)
=>> {'dps': {'1': 136, '10': 0, '16': True, '18': '111111111111'}}

It seems to be linked to a newer firmware. Do you plan a new upgrade to this firmware?
Thanks for your help

Ledvance smart wifi plug missing power data and pairing issue

Hello,

I paired Ledvance smart+ wifi plug with its own app on android. Its working ok. I tried to use tuyapower py. It scans find and outputs all the parameters including plugkey like "keyj5dhdbjch". When i try to get device info with given parameters, it says no power data. I suppose plugkey is not the actual key?

I reset the device and tried to pair with both smart life and tuya smart app but it fails. During manual pairing, it stops device's blinking led but app fails to pair with timeout even though device connects to wifi router.

Appreciate helps. Thanks

Data only updates after opening app (Denver SHP-100)

Using Denver SHP-100, testing with waterboiler.

>>> tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats) [0.0.20]

Device ... at 192.168.90.139 key ... protocol 3.3:
    Switch On: True
    Power (W): 2027.600000
    Current (mA): 8662.000000
    Voltage (V): 233.400000
    Projected usage (kWh):  Day: 48.662400  Week: 340.636800  Month: 1476.092800

>>> tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats) [0.0.20]

Device ... at 192.168.90.139 key ... protocol 3.3:
    Switch On: True
    Power (W): 2027.600000
    Current (mA): 8662.000000
    Voltage (V): 233.400000
    Projected usage (kWh):  Day: 48.662400  Week: 340.636800  Month: 1476.092800

>>> tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats) [0.0.20]

Device ... at 192.168.90.139 key ... protocol 3.3:
    Switch On: True
    Power (W): 2030.300000
    Current (mA): 8668.000000
    Voltage (V): 233.400000
    Projected usage (kWh):  Day: 48.727200  Week: 341.090400  Month: 1478.058400

After closing app and turning off boiler:

>>> tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats) [0.0.20]

Device ... at 192.168.90.139 key ... protocol 3.3:
    Switch On: True
    Power (W): 2030.300000
    Current (mA): 8668.000000
    Voltage (V): 233.400000
    Projected usage (kWh):  Day: 48.727200  Week: 341.090400  Month: 1478.058400

After opening app:

>>> tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
TuyaPower (Tuya Power Stats) [0.0.20]

Device ... at 192.168.90.139 key ... protocol 3.3:
    Switch On: True
    Power (W): 0.000000
    Current (mA): 0.000000
    Voltage (V): 236.700000
    Projected usage (kWh):  Day: 0.000000  Week: 0.000000  Month: 0.000000

It seems that the app is doing some sort of manual update request. Could it be some caching issue?
The problem not only occurs if the Plug is connected to the internet, but also if I am blocking any traffic from the plug to outside servers, so it occurs independently from the connection to the Tuya cloud.

Question: How to access historic power data?

Hi @jasonacox,

First of all I just want to say thanks for creating this project -- while the iPhone / Android apps are "pretty good" and let you perform all the standard user tasks (turning plugs on/off, dimming lights, etc) I have found the power monitor interface pretty limited (with only the ability to see how much power I am using right now and then a daily totals for previous usage), so am really excited to start using tuyapower to start collecting much more useful and detailed info! 👍🏼


STAGE 1: Setup + Initial Access --✅ Complete

  • Full disclosure: While I dabble in several languages I haven't actually written python before, so apologies in advance for any dumb questions or obvious misses that I might make!
  • That being said, am happy to report that I was able to install phyton, create the Cloud project on the Tuya IoT platform, authorise tuyapower to access my account, scan + detect my devices and run a successful poll command! 🎉
tuyapower.devicePrint(PLUGID,PLUGIP,PLUGKEY,PLUGVERS)
> Switch On: True
> Power (W): 57.800000
> Current (mA): 373.000000
> Voltage (V): 246.700000
> Projected usage (kWh):  Day: 1.387200 Week: 9.710400  Month: 42.078400

STAGE 2: Exporting detailed usage data -- ❓ In progress / guidance requested

  • I noticed on the IoT platform, the device logs are pretty frequent, with the device publishing it's live power usage approx. every minute (or 1440 times per day)

Tuya IoT Device Log screenshot

  • I don't have a RaspberryPi or other device that will online and able to poll my smart plugs in real time 24/7
  • So, am wondering how instead I can query the device's previous usage reports and then bulk download these [e.g. my laptop runs a scheduled task once per day, polls the last 24 hours of usage and downloads the ~1440x minute-by-minute usage numbers (ideally!)
  • Would you be able to give me any pointers on which command(s) I need to use please (and a super-quick summary of how I can export the returned data as a CSV 🙏🏼)

automate it

hi

is it possible to make it export daily\weekly\monthly log of the power usage?

and how?

thanks in advance

Error running on Mac

Great app, thank you. Running on MAC trying to find the LOCALKEY for a Recteq grill. Tuyapower identifies the device with device ID, IP etc.. Followed all API Tuya developer instructions and when running tinytuya receive:

`{
"apiKey": "<>",
"apiSecret": "<>",
"apiRegion": "us",
"apiDeviceID": "06200290b4e62d195c2f"
}

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tinytuya/main.py", line 49, in
wizard.wizard(color)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/tinytuya/wizard.py", line 206, in wizard
uid = response_dict['result']['uid']
KeyError: 'result'`

Tuya CO2 PM2.5 temp humidity sensor

I have the CO2 PM2.5 temp humidity sensor.
Despite developing in Labview and not in Python, I hope you could help.
My device works well with app, and also I have managed to communicate with it using my code in Labview using Tuya APIs.
I get its device id and category, but it says the reading of measurements is not supported.
In wireshark, I got its UDP payload, 172 bytes length.
How can I decode it? what is the structure of the payload ?
1.txt
hope for your help

Gosund SP1 plug doesn't refresh power data without app running

My Gosund SP1 power meter plug does not refresh power data unless the smartlife app is running. I have tried all DPS update tricks found but no success. What can be the problem? The final goal would be to use it completely offline, i.e. without internet access.

scan.py wrong results

The scan.py script gives the seemingly correct IP and ID for each devices. However, the Key and Version are reported as the same for every device (I have a mixture of 3.1 & 3.3 devces).

Along with the output its reporting the note as "Valid payload".

I also tried the scan-enc version and this gives the same result.

Tuya smart plug keeps reseting on multiple queries

Hi,

I have created my own Prometheus exporter with the help of your plugjson.py ( big thanks by the way) and I pull metrics every 5 seconds from the plug .

.....
.....
responsejson = subprocess.check_output(["python3", "plugjson.py", "7033XXXXXXXXXXXXXXXX", "10.0.XX.XXX"]).decode("utf-8")
.....
.....

Everything works fine, Prometheus is reading the metrics but the plug keeps resetting.

Arlec PC191HA, PC287HA give 0 readings (power, current, but voltage OK)

tuyapower version: 0.25.0?

Devices:
https://www.bunnings.com.au/arlec-white-grid-connect-smart-plug-in-socket-with-energy-meter_p0273367
https://www.bunnings.co.nz/arlec-grid-connect-smart-twin-socket-with-energy-meter-and-surge-protection_p0273372

Both are annoyingly reporting voltage, but not current or power.
I somehow did have this working with localtuya; need to check if they are reporting on different DPS to what tuyapower expects; or something else, like it only reports when it feels like it; or doesn't recognise that it is being asked to report.

PS C:\Users\name\powercalc-measure> docker run --rm --name=measure --env-file=.env -v ./export:/app/export -v ./persistent:/app/.persistent -it bramgerritsen/powercalc-measure:latest
Powercalc measure: v0.22.1:docker

2022-07-17 08:26:56,005 [INFO] Selected powermeter: tuya
2022-07-17 08:26:56,006 [INFO] Selected Light controller: hass
[?] Specify the full light model name: ARLEC GLD115HA
[?] Select the light: light.bathroom_light
 > light.bathroom_light
   light.bedroom_strip
   light.genio_smart_lighting
   light.gld115ha
   light.gld115ha_light
   light.lamp
   light.lamp_2

[?] What model is your light? Ex: LED1837R5: GLD115HA
2022-07-17 08:27:15,414 [INFO] Starting measurements. Estimated duration: 40.7m
2022-07-17 08:27:15,501 [INFO] Measuring standby power. Waiting for 20 seconds...
2022-07-17 08:27:35,840 [INFO] {'datetime': '2022-07-17T08:27:35Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:39,014 [INFO] {'datetime': '2022-07-17T08:27:38Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:42,289 [INFO] {'datetime': '2022-07-17T08:27:42Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:45,464 [INFO] {'datetime': '2022-07-17T08:27:45Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:48,743 [INFO] {'datetime': '2022-07-17T08:27:48Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:51,917 [INFO] {'datetime': '2022-07-17T08:27:51Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:27:51,918 [ERROR] Measured 0 watt as standby usage, continuing now, but you probably need to have a look into measuring multiple lights at the same time or using a dummy load.
2022-07-17 08:27:52,054 [INFO] Start taking measurements for color mode: brightness
2022-07-17 08:27:52,054 [INFO] Waiting 10 seconds...
2022-07-17 08:28:02,055 [INFO] Progress: 0%, Estimated time left: 40.7m
2022-07-17 08:28:02,056 [INFO] Changing light to: Variation(bri=1)
2022-07-17 08:28:05,441 [INFO] {'datetime': '2022-07-17T08:28:05Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:08,604 [INFO] {'datetime': '2022-07-17T08:28:08Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:11,783 [INFO] {'datetime': '2022-07-17T08:28:11Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:15,059 [INFO] {'datetime': '2022-07-17T08:28:14Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:18,148 [INFO] {'datetime': '2022-07-17T08:28:18Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:21,307 [INFO] {'datetime': '2022-07-17T08:28:21Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:21,307 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:28:21,307 [INFO] Changing light to: Variation(bri=2)
2022-07-17 08:28:24,686 [INFO] {'datetime': '2022-07-17T08:28:24Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:28:27,860 [INFO] {'datetime': '2022-07-17T08:28:27Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:31,039 [INFO] {'datetime': '2022-07-17T08:28:30Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:34,317 [INFO] {'datetime': '2022-07-17T08:28:34Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:37,487 [INFO] {'datetime': '2022-07-17T08:28:37Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:40,659 [INFO] {'datetime': '2022-07-17T08:28:40Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:40,659 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:28:40,659 [INFO] Changing light to: Variation(bri=3)
2022-07-17 08:28:43,935 [INFO] {'datetime': '2022-07-17T08:28:43Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:47,111 [INFO] {'datetime': '2022-07-17T08:28:46Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:50,281 [INFO] {'datetime': '2022-07-17T08:28:50Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:53,572 [INFO] {'datetime': '2022-07-17T08:28:53Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:56,741 [INFO] {'datetime': '2022-07-17T08:28:56Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:59,909 [INFO] {'datetime': '2022-07-17T08:28:59Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:28:59,909 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:28:59,909 [INFO] Changing light to: Variation(bri=4)
2022-07-17 08:29:03,186 [INFO] {'datetime': '2022-07-17T08:29:03Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:06,361 [INFO] {'datetime': '2022-07-17T08:29:06Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:09,636 [INFO] {'datetime': '2022-07-17T08:29:09Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:12,912 [INFO] {'datetime': '2022-07-17T08:29:12Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:16,188 [INFO] {'datetime': '2022-07-17T08:29:15Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:19,468 [INFO] {'datetime': '2022-07-17T08:29:19Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:19,468 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:29:19,469 [INFO] Changing light to: Variation(bri=5)
2022-07-17 08:29:22,747 [INFO] {'datetime': '2022-07-17T08:29:22Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:25,928 [INFO] {'datetime': '2022-07-17T08:29:25Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 239.5}
2022-07-17 08:29:29,200 [INFO] {'datetime': '2022-07-17T08:29:28Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:32,373 [INFO] {'datetime': '2022-07-17T08:29:32Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:35,558 [INFO] {'datetime': '2022-07-17T08:29:35Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:38,719 [INFO] {'datetime': '2022-07-17T08:29:38Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:38,719 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:29:38,720 [INFO] Changing light to: Variation(bri=6)
2022-07-17 08:29:41,996 [INFO] {'datetime': '2022-07-17T08:29:41Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:45,175 [INFO] {'datetime': '2022-07-17T08:29:44Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:48,350 [INFO] {'datetime': '2022-07-17T08:29:48Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:51,525 [INFO] {'datetime': '2022-07-17T08:29:51Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:54,697 [INFO] {'datetime': '2022-07-17T08:29:54Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:57,865 [INFO] {'datetime': '2022-07-17T08:29:57Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}
2022-07-17 08:29:57,865 [WARNING] Discarding measurement: 0 watt was read from the power meter
2022-07-17 08:29:57,865 [INFO] Changing light to: Variation(bri=7)
2022-07-17 08:30:01,248 [INFO] {'datetime': '2022-07-17T08:30:00Z', 'switch': True, 'power': 0.0, 'current': 0.0, 'voltage': 238.2}

From iot.tuya.com
PC287HA - power
image

PC287HA - current
image

PC191HA - power
image

PC191HA - current
image

Missing Power Data

Hi,

I used your python scripts to get data from an Tuya Smart Meter ZMAi-90.
see:
https://www.aliexpress.com/item/1005001992720359.html?spm=a2g0o.productlist.0.0.2fa2390aiu3hRi&algo_pvid=5cf56e5a-8bd7-4397-a57c-5a7a4deb7086&algo_expid=5cf56e5a-8bd7-4397-a57c-5a7a4deb7086-0&btsid=2100bb5116157546307118257ea49c&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_

I can find it
python tuyapower
TuyaPower (Tuya compatible smart plug scanner) [0.0.25] tinytuya [1.2.3]

Scanning on UDP ports 6666 and 6667 for devices (15 retries)...

FOUND Device [Valid payload]: 192.168.185.32
ID = bf3941cb7c91ced1a3mgyx, product = nzexeqam9qulajbf, Version = 3.3
Device Key required to poll for stats

Scan Complete! Found 1 devices.

But I can not get the data from it:

python plugpower.py bf3941cb7c91ced1a3mgyx 192.168.185.32 keyXXX 3.3 verbose=true
TuyaPower (Tuya Power Stats) [0.1.0] tinytuya [1.2.3]

Device bf3941cb7c91ced1a3mgyx at 192.168.185.32 key a5d40a4bf1c442d99b88522a5363faeb protocol 3.3:
Response Data: {u'Payload': u'', u'Err': u'900', u'Error': u'Invalid JSON Response from Device'}
Switch On: False
NOTE: Missing Power Data

{ "datetime": "2021-03-14T20:35:40Z", "switch": "False", "power": "0", "current": "0", "voltage": "0" }


Firmware
Hautpmodul: V1.1.71
MCU-Modul: V1.0.0

Could I somehow get the RAW JSON data?

Regards,
Alexander

ERROR: Incomplete response

My plug can't quite be read by tuyapower. I think I have the info necessary for my purpose, but I thought I would share what I have anyway.

When running tuyapower.devicePrint(), I get this output:
ERROR: Incomplete response

TuyaPower (Tuya Power Stats) [0.0.25] tinytuya

Device bf3941f72d7e45f9a805hw at 192.168.1.113 key 8dd38d7f9323a97b protocol 3.3
:
    Switch On: False
    Power (W): -99.000000
    Current (mA): -99.000000
    Voltage (V): -99.000000
    Projected usage (kWh):  Day: -2.376000  Week: -16.632000  Month: -72.072000

Running tuyapower.deviceRaw() return no further insight: it returns None.

However, based on what I found in #15 I tried the following script:

a = tinytuya.OutletDevice(PLUGID, PLUGIP, PLUGKEY, 'device22')
a.set_version(3.3)
a.set_dpsUsed({'1': None, '18': None, '19': None, '20': None})
data =  a.status()
print(data)

Now, the response contains all the required info, but formatted in a rather different way:

{
    'dps':  {
        '1': True,     // Switched on
        '18': 494,     // 494 mA
        '19': 995,     // 99.5 W
        '20': 2428     // 242.8 V
     },
     't': 1618440938   // unix timestamp for the moment of the request
}

(newlines and comments added by me)

extra Tuya developer API settings required

G'day,
Thanks so much for this project.

I found that I had to turn on some extra API settings before the tuya-cli wizard worked.

Under API Setting in the Tuya iot.tuya.com site:
image

I had to turn on Authorization management, Device Management and Device Control.
image

After that I was able to get the keys from the tuya-cli wizard command.

Maybe that could be added to the "3. For Device KEY" section of the README.md file?

Thanks and regards,
Christopher

Power Usage

Hello,

I'm getting a bit mad on the power usage reported, using the example you show on the readme you get this values:

Device 03200160dc4f2216ff61 at 10.0.1.5 key 0123456789abcdef protocol 3.1:
Switch On: True
Power (W): 1.200000
Current (mA): 70.000000
Voltage (V): 122.100000
Projected usage (kWh): Day: 0.028800 Week: 0.201600 Month: 0.873600

But as far as I know W=I*V but 122,1V * 0,070A does not equal 1,2W, what am I missing?

Thanks,
Mac Fresno

Timeout polling device

So I have 6 Kogan Plugs identical including firmware version(1.1.2 according to tuya app). https://www.kogan.com/au/buy/kogan-smarterhome-smart-plug-energy-meter-5v-24a-usb-ports-4-pack/

I can poll 5 of them for power using your script, but one just refuses to and I can't figure out why, Any ideas on how to troubleshoot?

nmap port scan shows 6667 and 6668 as closed (same as another plug that is working):

PORT STATE SERVICE
6667/udp closed ircu
6668/udp closed ircu

~/tuyapower$ python3 test.py xxxx 192.168.1.zz yyy 3.3
ERROR: Timeout polling device

TuyaPower (Tuya Power Stats) [0.0.20]

Device xxx at 192.168.1.zz key yyy protocol 3.3:
Switch On: False
Power (W): -99.000000
Current (mA): -99.000000
Voltage (V): -99.000000
Projected usage (kWh): Day: -2.376000 Week: -16.632000 Month: -72.072000

{ "datetime": "2020-07-26T13:45:18Z", "switch": "False", "power": "-99", "current": "-99", "voltage": "-99" }

Failed to receive data from 192.168.1.29. Raising Exception.

Hi @jasonacox , I have been working to resolve an issue with connecting to my Tuya cover device in relation to a Home Assistant add-on located at https://github.com/rospogrigio/localtuya-homeassistant. I've been speaking with the author, rospogrigio, who sent me some debug scripts and told me that he used your tuyapower library and integrated it with his pytuya library. I thought you might thus be able to help out with this issue.

The device I have is:
https://www.aliexpress.com/item/4001045079168.html?spm=a2g0s.9042311.0.0.35ce4c4d2TbFxa

I've extracted the device's Key and ID using tuya-cli. I can also use tuya-cli successfully to both both get and set data. For example, I can run the following command:
tuya-cli get --id 31xxxxxxxxxxxxxxxxf8 --key 87xxxxxxxxxxxxf8 --protocol-version 3.3 --all

And I get the following output:
{ devId: '31xxxxxxxxxxxxxxxxf8', dps: { '1': 'open', '2': 100, '3': 100, '5': false, '7': 'closing', '8': 'cancel', '9': 0, '10': 0, '11': 38610 } }

I've installed tuyapower via pip, and when I run:
python3 -m tuyapower

My output is:

TuyaPower (Tuya compatible smart plug scanner) [0.0.22]
Scanning on UDP ports 6666 and 6667 for devices (15 retries)...
FOUND Device [Valid payload]: 192.168.1.29
    ID = 31xxxxxxxxxxxxxxxxf8, productKey = 3rxxxxxxxxxxxx1g, Version = 3.3
    Device Key required to poll for stats
Scan Complete!  Found 1 devices.

So, good news, is that tuyapower can successfully scan and find my device. The IP is correct, the ID is correct. (However, the productKey does not match up with the Key that I extracted using tuya-cli, and with which I can set and get data using tuya-cli. But let's set that aside because I don't think it's relevant).

When I run:
python test.py 31xxxxxxxxxxxxxxxxf8 192.168.1.29 87xxxxxxxxxxxxf8 3.3

I get back:

ERROR: Timeout polling device
TuyaPower (Tuya Power Stats) [0.0.22]
Device 31xxxxxxxxxxxxxxxxf8 at 192.168.1.29 key 87xxxxxxxxxxxxf8 protocol 3.3:
    Switch On: False
    Power (W): -99.000000
    Current (mA): -99.000000
    Voltage (V): -99.000000
    Projected usage (kWh):  Day: -2.376000 Week: -16.632000  Month: -72.072000
{ "datetime": "2020-09-03T09:05:29Z", "switch": "False", "power": "-99", "current": "-99", "voltage": "-99" }

This leads me to two conclusions:
(1) There's a timeout, so something is wrong
(2) Even if there wasn't a timeout, my device is a cover, not a switch, so the output here would be irrelevant

rospogrigio, however, has built in cover functionality to his adaption of pytuya/tuyapower. He uploaded some debug scripts for me, which you can view here:
https://github.com/rospogrigio/localtuya-homeassistant/blob/master/tuyadebug.tgz

For ease of reference, here's what his updated "test.py" file looks like:

#!/usr/bin/python3
#
# TuyaPower (Tuya Power Stats)
#      Power Probe - Wattage of smart devices - JSON Output

import datetime
import os
import sys
import time
from time import sleep

import localtuya

# Read command line options or set defaults
if (len(sys.argv) < 2) and not (("DEVID" in os.environ) or ("DEVIP" in os.environ)):
    print("TuyaPower (Tuya Power Stats)\n")
    print("Usage: %s <DEVID> <DEVIP> <DEVKEY> <DEVVERS>\n" % sys.argv[0])
    print("    Required: <DEVID> is the Device ID e.g. 01234567891234567890")
    print("              <DEVIP> is the IP address of the smart device e.g. 10.0.1.99")
    print("              <DEVKEY> is the Device Key (default 0123456789abcdef)")
    print("              <DEVTYPE> is the Device Type: 's' for switch (default) or 'c' for cover\n")
    print("    Optional: <DPSUSED> is the list of dps in use\n")
    print("              <DEVVERS> is the Firmware Version 3.3 (default) or 3.1\n")
    print("    Note: You may also send values via Environmental variables: ")
    print("              DEVID, DEVIP, DEVKEY, DEVTYPE, DEVVERS\n")
    exit()
DEVID = sys.argv[1] if len(sys.argv) >= 2 else "01234567891234567890"
DEVIP = sys.argv[2] if len(sys.argv) >= 3 else "10.0.1.99"
DEVKEY = sys.argv[3] if len(sys.argv) >= 4 else "0123456789abcdef"
DEVTYPE = sys.argv[4] if len(sys.argv) >= 5 else "s"
DPSUSED = sys.argv[5] if len(sys.argv) >= 6 else ""
DEVVERS = sys.argv[6] if len(sys.argv) >= 7 else "3.3"

# Check for environmental variables and always use those if available (required for Docker)
DEVID = os.getenv("DEVID", DEVID)
DEVIP = os.getenv("DEVIP", DEVIP)
DEVKEY = os.getenv("DEVKEY", DEVKEY)
DEVTYPE = os.getenv("DEVTYPE", DEVTYPE)
DPSUSED = os.getenv("DPSUSED", DPSUSED)
DEVVERS = os.getenv("DEVVERS", DEVVERS)

now = datetime.datetime.utcnow()
iso_time = now.strftime("%Y-%m-%dT%H:%M:%SZ")

# Poll Smart Swich for Power Data
err = "OK"
# (on, w, mA, V, err) = localtuya.deviceInfo(DEVID, DEVIP, DEVKEY, DEVVERS) 
localtuya.devicePrint(DEVID, DEVIP, DEVKEY, DEVTYPE,DPSUSED,DEVVERS) 
#localtuya.turn_on()

# Check for error
if err != "OK":
    print(" ERROR: %s\n" % err)
    sys.exit(1)
sys.exit(0)

When I run the following command:
python test.py 31xxxxxxxxxxxxxxxxf8 192.168.1.29 87xxxxxxxxxxxxf8 c

I get back:

INFO:localtuya:localtuya version 0.0.19
INFO:localtuya:Python 2.7.16 (default, Oct 10 2019, 22:02:15) 
[GCC 8.3.0] on linux2
INFO:localtuya:Using pytuya version '7.0.8'
COVER  DEVICE
localtuya.pytuya version 7.0.8
Python 2.7.16 (default, Oct 10 2019, 22:02:15) 
[GCC 8.3.0] on linux2
('Using PyCrypto ', (2, 6, 1, 'final', 0))
('Using PyCrypto from ', '/usr/lib/python2.7/dist-packages/Crypto/__init__.pyc')
INFO:localtuya:Requesting status of device 31xxxxxxxxxxxxxxxxf8 [192.168.1.29], protocol 3.3.
DEBUG:localtuya.pytuya:status() entry (dev_type is device22)
DEBUG:localtuya.pytuya:json_payload='{"devId":"31xxxxxxxxxxxxxxxxf8","dps":{"":null},"uid":"31xxxxxxxxxxxxxxxxf8","t":"1599124438"}'
Failed to receive data from 192.168.1.29. Raising Exception.
COVER  DEVICE
localtuya.pytuya version 7.0.8
Python 2.7.16 (default, Oct 10 2019, 22:02:15) 
[GCC 8.3.0] on linux2
('Using PyCrypto ', (2, 6, 1, 'final', 0))
('Using PyCrypto from ', '/usr/lib/python2.7/dist-packages/Crypto/__init__.pyc')
INFO:localtuya:Requesting status of device 31xxxxxxxxxxxxxxxxf8 [192.168.1.29], protocol 3.3.
DEBUG:localtuya.pytuya:status() entry (dev_type is device22)
DEBUG:localtuya.pytuya:json_payload='{"devId":"31xxxxxxxxxxxxxxxxf8","dps":{"":null},"uid":"31xxxxxxxxxxxxxxxxf8","t":"1599124451"}'
Failed to receive data from 192.168.1.29. Raising Exception.
COVER  DEVICE
localtuya.pytuya version 7.0.8
Python 2.7.16 (default, Oct 10 2019, 22:02:15) 
[GCC 8.3.0] on linux2
('Using PyCrypto ', (2, 6, 1, 'final', 0))
('Using PyCrypto from ', '/usr/lib/python2.7/dist-packages/Crypto/__init__.pyc')
INFO:localtuya:Requesting status of device 31xxxxxxxxxxxxxxxxf8 [192.168.1.29], protocol 3.3.
DEBUG:localtuya.pytuya:status() entry (dev_type is device22)
DEBUG:localtuya.pytuya:json_payload='{"devId":"31xxxxxxxxxxxxxxxxf8","dps":{"":null},"uid":"31xxxxxxxxxxxxxxxxf8","t":"1599124453"}'
Failed to receive data from 192.168.1.29. Raising Exception.
INFO:localtuya:TIMEOUT: No response from device 31xxxxxxxxxxxxxxxxf8 [192.168.1.29] after 2 attempts.

For the record, I have tried passing in the dps, and that doesn't resolve the issue, nor does using the alternative Device Key that tuyapower outputted (though I know that's the wrong Device Key, and the one I got from tuya-cli is correct, I still wanted to try it).

Do you have any idea what might be causing these timeouts & exceptions, and make it such that I can't connect to my device? I notice the json_payload doesn't include the Device Key--is it supposed to? I know you didn't author the actual code i'm having an issue with, but given that you wrote much of the code it was based off of, i'm hoping you might be able to shed some light here.

Thanks in advance,

loaxley

`tuya.deviceInfo` hanging if device not available?

Hi @jasonacox,

Finally got my RPi and did some tweaks to my original python script you might remember helping me with a few months back.

Issue

The script should poll my 4 smart plugs for their current energy usage every 10 seconds, however it seems to do a one-off poll of 3 devices (writing the energy usage to a csv) but then hang... even after the 10-second sleep command and expected loop back to the beginning, the script doesn't output anything again.

  • As a workaround, if I deleted the device entry in the json file the script does then start working normally however this is not ideal as means basically hard-coding 'temporary changes' into the config file (i.e. every time I un-plug a smart plug I need to edit the json otherwise tuyapower will stop working(?)

For context

  • 2x smart plugs are online and "on", drawing power and so returning various numbers wattages, etc
  • 1x smart plug is online* but "off" and (as expected) tuyapower returns 0 for that device
  • 1x smart plug is offline (e.g. unplugged or the 240v socket is turned off, etc), these seems to cause tuyapower to hang

Query / Fix?

Assuming I have diagnosed this correctly, is there a way I can tell tuyapower to skip "offline" devices (and/or some other way to get have my script work with all 4 smart plugs in the json file (regardless whether or not they are online?

TBH, I feel like this functionality probably already exists (I've seen references to timeouts) however I'm a bit stuck trying to figure out if not this, what else could be stopping my script from working.

Get info without scanning the network

Is there a way where I can scan the device for new data without having to scan the whole network all the time for devices? I do know the device id, ip etc.

python error: local variable 'sw' referenced before assignment

Hi,
When I tried to launch plugjson.py on a smart plug being switched off, I received a python error message on line 175.
I'm unfortunately not an expert in python, but I think tehre might be indeed a line missing between rows 174 and 175 to initiate variable sw (entry missing like: sw = False ?).
Instead of
if watchdog > RETRY: log.info( "NO POWER DATA: Response from plug %s [%s] missing power data." % (deviceid, ip) ) return (sw, w, mA, V, "Missing Power Data")
maybe we should have:
if watchdog > RETRY: log.info( "NO POWER DATA: Response from plug %s [%s] missing power data." % (deviceid, ip) ) sw = False return (sw, w, mA, V, "Missing Power Data")
At least, I don't have the error anymore that way.
Let me know if that's the way it should be or if I solved just by chance..
br,
Ricorico94

Tuya switch - firmware 1.4.2

I just tested this, and I get no data, only a rubbish string.

The plug is a Shenzhen WiFi smart plug
I have a suspicion that the protocol again have changed, the firmware ver in the plug is 1.4.2.
I am situated in Europe, I do not know if that is an issue.

I got the local key from tuya-cli list-app:
Set your HTTP proxy IP to 192.168.1.238 with port 8001.
This machine has 3 IPs; to choose a different one, use the --ip option.
✔ Response intercepted.
Devices(s):
[
{
name: 'DEV123456789',
id: 'bf20d8688f946386bd7rjo',
key: '582a2be355a6ffb4'
}
]

this is the output from your test.py, with additional print statements from the Crypto module.
Crypto importet
crypto is NOT none
in if crypto AESCipher
in if crypto self._pad(raw) b'{"gwId":"bf20d8688f946386bd7rj0","devId":"bf20d8688f946386bd7rj0"}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'
crypted_text 1 %r b'\x86a\x85\x92\xeaD\xc5 ,\xa9]vLz>\x1ceY\xc6\xc2\x94\x94\xc4\x99\x0e\x8aE\xe7\xd2\xbe\x9fz]\xa1\x18!\x9b\xe8\x94Y\x0c\x9d\x9f\xac\r\xde;\xa8AN\x1b\xef\x11F\xb9]\xa7o\xb0{1^\x9c\xe4A*\xb4\x0c\x1c\x90\xa7\xe4\xdd\xa0"\x83zp\x13\x1e'
crypted_text 2 lenght (%d) %r 80
in if crypto AESCipher
in if crypto self._pad(raw) b'{"gwId":"bf20d8688f946386bd7rj0","devId":"bf20d8688f946386bd7rj0"}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'
crypted_text 1 %r b'\x86a\x85\x92\xeaD\xc5 ,\xa9]vLz>\x1ceY\xc6\xc2\x94\x94\xc4\x99\x0e\x8aE\xe7\xd2\xbe\x9fz]\xa1\x18!\x9b\xe8\x94Y\x0c\x9d\x9f\xac\r\xde;\xa8AN\x1b\xef\x11F\xb9]\xa7o\xb0{1^\x9c\xe4A*\xb4\x0c\x1c\x90\xa7\xe4\xdd\xa0"\x83zp\x13\x1e'
crypted_text 2 lenght (%d) %r 80
ERROR: Timeout polling device

TuyaPower (Tuya Power Stats)

Device bf20d8688f946386bd7rj0 at 192.168.1.98 key 582a2be355a6ffb4 protocol 3.3:
Switch On: False
Power (W): -99.000000
Current (mA): -99.000000
Voltage (V): -99.000000
Projected usage (kWh): Day: -2.376000 Week: -16.632000 Month: -72.072000

{ "datetime": "2020-01-12T13:00:50Z", "switch": "False", "power": "-99", "current": "-99", "voltage": "-99" }

smart energy meter not returning data

Hi, could you please help as I am trying to access/record data from a smart energy meter I recently installed.

I have setup my Tuya IOT project to get client id and secret so I can run the wizard and and scan successfully to generate tuya-raw.json (includes a valid device status report) and devices.json to provide valid local key.
API calls in IOT project for my device all work successfully.

However, when trying the following code to access device status locally (I use device id, IP address, local key) appears to get no response:

import tinytuya
tinytuya.set_debug(True)

a = tinytuya.OutletDevice('bf3e7252097f07dbd5XXXX', '192.168.xx.xx', 'XXXXX', '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)

I'm getting the following error but can't tell if no data returned or data returned is not readable.

[31;1mDEBUG:TinyTuya [1.12.7]
�[0m
�[31;1mDEBUG:Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24 2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] on darwin�[0m
�[31;1mDEBUG:Using PyCrypto (3, 17)�[0m
�[31;1mDEBUG:status() entry (dev_type is device22)�[0m
�[31;1mDEBUG:final payload_dict for 'bf3e7252097f07dbd5iejq' ('v3.3'/'device22'): {1: {'command': {'gwId': '', 'devId': '', 'uid': '', 't': ''}}, 7: {'command': {'devId': '', 'uid': '', 't': ''}}, 8: {'command': {'gwId': '', 'devId': ''}}, 9: {'command': {'gwId': '', 'devId': ''}}, 10: {'command': {'devId': '', 'uid': '', 't': ''}, 'command_override': 13}, 13: {'command': {'devId': '', 'uid': '', 't': ''}}, 16: {'command': {'devId': '', 'uid': '', 't': ''}}, 18: {'command': {'dpId': [18, 19, 20]}}, 64: {'command': {'reqType': '', 'data': {}}}}�[0m
�[31;1mDEBUG:building command 10 payload=b'{"devId":"bf3e7252097f07dbd5iejq","uid":"bf3e7252097f07dbd5iejq","t":"1684324838","dps":{"1":null}}'�[0m
�[31;1mDEBUG:sending payload�[0m
�[31;1mDEBUG:payload encrypted=b'000055aa000000010000000d00000087332e33000000000000000000000000ec61a4ee075ac904dbef0abfb86b456cb988ff2a9edc781dd58a3cc8703f3206d46ce06a95515979d48199991abbd94f8e58484431fe861cdc0ead3761a2057b89d8c712f1199313a522f2a1fa0012000d650534c7ce6aeab4702dac17b2faf445c1f6ef4ed1e894279b8f92e2462750da1953af0000aa55'�[0m
�[31;1mDEBUG:_recv_all(): no data? b''�[0m
�[31;1mDEBUG:_recv_all(): no data? b''�[0m
�[31;1mDEBUG:Error decoding received data - read retry 0/5�[0m
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tinytuya/core.py", line 1008, in _send_receive
    rmsg = self._receive()
           ^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tinytuya/core.py", line 898, in _receive
    data = self._recv_all( min_len )
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/tinytuya/core.py", line 879, in _recv_all
    raise DecodeError('No data received - connection closed?')
tinytuya.core.DecodeError: No data received - connection closed?

AttributeError: module 'pytuya' has no attribute 'version'

So trying to run this and I'm getting the below error. I can run the powermonitor version of this fine....

ferni@uvm:~/tuyapower$ docker run -e PLUGID='xxx' -e PLUGIP="192.168.1.x" -e PLUGKEY="yyy" -e PLUGVERS="3.3" -e verbose="true" tuyapower
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/local/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "tuyapower/__main__.py", line 12, in <module>
    import tuyapower
  File "/usr/local/lib/python3.8/site-packages/tuyapower/__init__.py", line 52, in <module>
    log.info("Using pytuya version %r", pytuya.version)
AttributeError: module 'pytuya' has no attribute 'version'

Response Data: ERROR: Timeout polling device

Howdy,

Managed to follow the tutorial successfully to a T. I have the device IDs, I have the keys after creating an account on iot.tuya.com and running tuyapower. Whenever I try test.py:

python3 test.py <ID>192.168.0.XX <KEY> 3.3
TuyaPower (Tuya Power Stats) [0.1.0] tinytuya [1.1.3]

Device <ID> at 192.168.0.XX key <KEY> protocol 3.3:
    Response Data: ERROR: Timeout polling device
    Switch On: False
    NOTE: Timeout polling device

{ "datetime": "2021-01-27T05:49:15Z", "switch": "False", "power": "0", "current": "0", "voltage": "0" }

I can ping the device, I can see the broadcast messages from the IP address on wireshark from a different PC, I have validated the IP address using the MAC address of the lightbulb (also on Smart Home App). Plug is on. Can't seem to find what I'm doing wrong. I'm new to all this (very new to python) and I have run out of troubleshooting options.

Edit: I have tried this method with two plugs that I know are connected, keys and IDs are known.

Thanks in advance,

Tuya API change / Missing Power Data

Hi,

Thanks for this excellent package!

I am running into [Missing Power Data] messages when polling devices. I suspect the issue might be related to something incorrect in the Tuya API access that I've set up.

The Tuya IoT platform seems to have been updated since the guide in the ReadMe. I can't seem to find the Smart Home Devices Management, Authorization and Smart Home Family Management APIs listed in the guide.

I guessed at some APIs, here are the ones I've currently enabled:
image
Are these correct?

Here's the current response from a quick scan of the 4 devices I've set up. The state is updated as the switches are turned on and off, but the power data is absent.

# Scan the network and unpack the response 
devices = tuyapower.deviceScan()
for ip in devices:
       id = devices[ip]['gwId']
       key = devices[ip]['productKey']
       vers = devices[ip]['version']
       (on, w, mA, V, err) = tuyapower.deviceInfo(id, ip, key, vers)
       print("Device at %s: ID %s, state=%s, W=%s, mA=%s, V=%s [%s]"%(ip,id,on,w,mA,V,err))
Device at 192.168.50.153: ID ebce49cc8507c3997bm3or, state=False, W=0, mA=0, V=0 [Missing Power Data]
Device at 192.168.50.215: ID ebe62208944b1effd8x6xa, state=False, W=0, mA=0, V=0 [Missing Power Data]
Device at 192.168.50.217: ID eb4aa77b450e9560bboule, state=False, W=0, mA=0, V=0 [Missing Power Data]
Device at 192.168.50.151: ID ebac2a160afe1f8ba5bruz, state=False, W=0, mA=0, V=0 [Missing Power Data]

Also, I had to sign up as a free trial for most of the APIs. This is just for hobby use, does anyone have any idea what the current pricing model is for this API?

No module named 'Crypto'

i got this error

python -m tuyapower
Traceback (most recent call last):
File "C:\Python38\lib\runpy.py", line 185, in _run_module_as_main
mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
File "C:\Python38\lib\runpy.py", line 144, in _get_module_details
return _get_module_details(pkg_main_name, error)
File "C:\Python38\lib\runpy.py", line 111, in get_module_details
import(pkg_name)
File "D:\Programing\tuya\tuyapower\tuyapower_init
.py", line 40, in
from Crypto.Cipher import AES
ModuleNotFoundError: No module named 'Crypto'

Functions Switch Plug, No Power Info Returned

Hi,

I have a switch, running v3.1 of the protocol (based on the scan). I can connect to it, and get the switch state ... but executing tuyapower.devicePrint sometimes turns the switch off and back on (not good!), and the output is,

 Device ******* at IP key ******* protocol 3.1:
    Switch On: True
    Power (W): -99.000000
    Current (mA): -99.000000
    Voltage (V): -99.000000
    Projected usage (kWh):  Day: -2.376000  Week: -16.632000  Month: -72.072000

But, using tuyacli, I do get correct info. Any thoughts how to correct / debug this?

Thanks!

Missing Power Data - again

Hi jasonacox,

I am getting again now power data (you helped me in the past already with the case #17

I have try to do the same steps again. But it is not working.


pi@pi-vz-be:~/test/tuyapower $ python plugpower.py 'bf3941cb7c91ced1a3mgyx' '192.168.185.75' 'xxx' '3.3'
TuyaPower (Tuya Power Stats) [0.2.0] tinytuya [1.12.11]

Device bf3941cb7c91ced1a3mgyx at 192.168.185.75 key xxx protocol 3.3:
    Response Data: {'dps': {'1': 6313, '10': 0, '16': True, '18': '111111111111'}}
    Switch On: 6313
    NOTE: Power data unavailable

{ "datetime": "2023-09-20T09:35:33Z", "switch": "6313", "power": "0", "current": "0", "voltage": "0" }

I have executed the 'python -m tinytuya wizard' command:

pi@pi-vz-be:~/test/tuyapower $ python -m tinytuya wizard
TinyTuya Setup Wizard [1.12.11]

    Existing settings:
        API Key=myKey
        Secret=mysecret
        DeviceID=bf3941cb7c91ced1a3mgyx
        Region=eu

    Use existing credentials (Y/n): Y

Download DP Name mappings? (Y/n): Y


Device Listing

[
    {
        "name": "WiFi Smart Meter - Garage",
        "id": "bf3941cb7c91ced1a3mgyx",
        "key": "xxx",
        "mac": "84:e3:42:70:81:7b",
        "uuid": "9e1d37b00ee11479",
        "sn": "1000158120009A",
        "category": "zndb",
        "product_name": "WiFi Smart Meter",
        "product_id": "nzexeqam9qulajbf",
        "biz_type": 0,
        "model": "ZM-wi-Fi -\u7535\u8868",
        "sub": false,
        "icon": "https://images.tuyaeu.com/smart/icon/ay1536897190133VVeLx/b9439bd86d7954663fe187f367c5a54b.jpg",
        "mapping": {
            "1": {
                "code": "forward_energy_total",
                "type": "Integer",
                "values": {
                    "unit": "kW\u00b7h",
                    "min": 0,
                    "max": 99999999,
                    "scale": 2,
                    "step": 1
                }
            },
            "6": {
                "code": "phase_a",
                "type": "Json",
                "raw_values": "{}",
                "values": {}
            },
            "10": {
                "code": "fault",
                "type": "Bitmap",
                "values": {
                    "label": [
                        "ov_cr",
                        "unbalance_alarm",
                        "ov_vol",
                        "undervoltage_alarm",
                        "miss_phase_alarm",
                        "outage_alarm",
                        "magnetism_alarm",
                        "terminal_alarm",
                        "cover_alarm",
                        "credit_alarm",
                        "no_balance_alarm",
                        "battery_alarm",
                        "meter_hardware_alarm"
                    ]
                }
            },
            "16": {
                "code": "switch",
                "type": "Boolean",
                "values": {}
            },
            "17": {
                "code": "alarm_set_2",
                "type": "Json",
                "raw_values": "{}",
                "values": {}
            },
            "18": {
                "code": "meter_id",
                "type": "String",
                "values": "{\"maxlen\":255}"
            }
        },
        "ip": "192.168.185.75",
        "version": "3.3"
    }
]

>> Saving list to devices.json
    1 registered devices saved

>> Saving raw TuyaPlatform response to tuya-raw.json

Poll local devices? (Y/n): Y

Scanning local network for Tuya devices...
    1 local devices discovered

Polling local devices...
    [WiFi Smart Meter - Garage] 192.168.185.75     - [Off] - DPS: {'1': 6314, '10': 0, '16': True, '18': '111111111111'}

>> Saving device snapshot data to snapshot.json


>> Saving IP addresses to devices.json
    1 device IP addresses found

Done.

pi@pi-vz-be:~/test/tuyapower $

file: tuya-raw.json

{
    "result": [
        {
            "active_time": 1695198459,
            "biz_type": 0,
            "category": "zndb",
            "create_time": 1614341183,
            "icon": "smart/icon/ay1536897190133VVeLx/b9439bd86d7954663fe187f367c5a54b.jpg",
            "id": "bf3941cb7c91ced1a3mgyx",
            "ip": "91.89.234.92",
            "lat": "49.3219",
            "local_key": "xxx",
            "lon": "8.5268",
            "model": "ZM-wi-Fi -\u7535\u8868",
            "name": "WiFi Smart Meter - Garage",
            "online": true,
            "owner_id": "166358995",
            "product_id": "nzexeqam9qulajbf",
            "product_name": "WiFi Smart Meter",
            "status": [
                {
                    "code": "forward_energy_total",
                    "value": 6313
                },
                {
                    "code": "phase_a",
                    "value": "{\"electricCurrent\":0.658,\"power\":0.15,\"voltage\":233.1}"
                },
                {
                    "code": "fault",
                    "value": 0
                },
                {
                    "code": "switch",
                    "value": true
                },
                {
                    "code": "alarm_set_2",
                    "value": "[{\"alarmCode\":\"overcurrent\",\"doAction\":false,\"threshold\":\"60\"},{\"alarmCode\":\"ammeter_overvoltage\",\"doAction\":false,\"threshold\":\"264\"},{\"alarmCode\":\"under_voltage\",\"doAction\":false,\
                },
                {
                    "code": "meter_id",
                    "value": "111111111111"
                }
            ],
            "sub": false,
            "time_zone": "+02:00",
            "uid": "eu1694874319369MBcdz",
            "update_time": 1695201243,
            "uuid": "9e1d37b00ee11479"
        }
    ],
    "success": true,
    "t": 1695202646458,
    "tid": "4f1e208e579911ee9a70760d0d3c40d3",
    "file": {
        "name": "tuya-raw.json",
        "description": "Full raw list of Tuya devices.",
        "account": "pr3hgx35af14buw8ursr",
        "date": "2023-09-20T11:37:26.479506",
        "tinytuya": "1.12.11"
    }
}

Any idea why I do not get the power data via plugpower.py? I can see the power data in the tuya-raw.json file...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.