tuyapower
tuyapower copied to clipboard
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!
Can you give me the tuya-cli
command you are using? I assume something like..
tuya-cli get --ip 10.0.0.10 --id 03200160dc4f2216f984 --key 01234567890 -a
If it is a 3.1 device, you should be able to grab the status from it without a key. What do you see with python3 -m tuyapower
?
Can you give me the
tuya-cli
command you are using? I assume something like..
Yep, exactly like that π,
./node_modules/@tuyapi/cli/cli.js get --id ******** --key ******** --ip 192.168.2.147 -a
And, I get,
{
devId: '********',
dps: {
'1': false,
'2': false,
'9': 0,
'10': 0,
'18': 0,
'19': 0,
'20': 1237,
'21': 1,
'22': 1189,
'23': 14239,
'24': 15400,
'25': 1170
}
}
It says the interface is 3.1, but I can't get the status without a key. If I run, ```python3 -m tuyapower```,
Scanning on UDP ports 6666 and 6667 for devices (15 retries)...
FOUND Device [Valid payload]: 192.168.2.147 ID = ********, product = keyjcr45yfptp7h7, Version = 3.1 Stats: on=False [Power data unavailable]
Thoughts?
Thanks!
That's fascinating. I see the problem. It is sending a payload back that looks more like a 3.3 device. Because it announces itself as 3.1 device, tuyapower is unable to pull the power data. A 3.1 plug would send back something like this:
Response Data: {'devId': '03200160dc4f2216f984', 'dps': {'1': True, '2': 0, '4': 473, '5': 561, '6': 1217}}
The tuyapower logic is trying to parse the response with this logic:
if data:
dps = data["dps"]
sw = dps["1"]
if vers == "3.3" and ("19" in dps.keys()):
w = float(dps["19"]) / 10.0
mA = float(dps["18"])
V = float(dps["20"]) / 10.0
key = "OK"
elif "5" in dps.keys():
w = float(dps["5"]) / 10.0
mA = float(dps["4"])
V = float(dps["6"]) / 10.0
key = "OK"
else:
key = "Power data unavailable"
Based on your payload, none of those would match (hence "Power data unavailable"). I don't know the dps mappings for your device. It seems to be a non-standard Tuya plug device. That could also explain why it has the unexpected power off situation (evidence that the simple tuyapower status query is crashing its api handler = not good!)
What type of device is it? Also, does the Device ID happen to have 22 characters?
One curious thing to try, does it respond if you force a 3.3 protocol query?
./plugpower.py 03200160dc4f2216f984 10.0.1.1 01234567890 3.3
Also, you can try to use tinytuya to poll the device:
import tinytuya
d = tinytuya.Device('03200160dc4f2216f984','10.0.1.1','01234567890')
d.status() # test 3.1
d.set_version(3.3)
d.status() # test 3.3
It seems to be a non-standard Tuya plug device.
But it matches (closely) to this (and what I find at the Tuya site), https://tasmota.github.io/docs/TuyaMCU/#power-monitoring-plug ... so really non-standard? BTW, it's a dual device, so DP IP 1 and 2 are used (for the two switches).
sw = dps["1"]
Based on the link I sent above, this field should show on/off status for the switch, no? And it does match (status) to the cli output.
does the Device ID happen to have 22 characters?
Nope, 20.
One curious thing to try, does it respond if you force a 3.3 protocol query?
After quite a while, but it toggles the switch off and back on (twice), then the data below. BTW, forcing 3.1, same toggle (only once), and the same data.
ERROR: Timeout polling device
TuyaPower (Tuya Power Stats) [0.0.25] tinytuya [1.0.4]
Device ******************** at 192.168.2.147 key **************** protocol 3.3:
Response Data: ERROR: Timeout polling device
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-11-21T11:54:31Z", "switch": "False", "power": "-99", "current": "-99", "voltage": "-99" }
d.status() # test 3.1
I get,
ConnectionResetError: [Errno 104] Connection reset by peer
And,
d.status() # test 3.3
Here, I get,
ValueError: Data must be aligned to block boundary in ECB mode
Thoughts? And thanks!
FYI, just bought a couple more switches (these ones! https://www.amazon.com/gp/product/B07CVPKD8Z/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1). Python code works, and so does plugpower.py ... if I force 3.3. If not, it errors out, unexpected status().
Thanks!
Ok, for the 2 plug switch that broadcasts the 3.1, I'm not really find any any good information to help us. However, since it behaves like a 3.3 device, the mapping may be the similar (see https://github.com/jasonacox/tinytuya#data-points---dps-table).
DP ID | Function Point | Type | Range | Units |
---|---|---|---|---|
1 | Switch 1 | bool | 0-1 | |
2 | Switch 2 | bool | 0-1 | |
9 | Countdown 1 | integer | 0-86400 | s |
10 | Countdown 2 | integer | 0-86400 | s |
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 |
The problem is that I have never seen a 3.1 device that maps to this. I could add code to handle that response, but first I need to figure out why tuya-cli is able to pull back status but we are not getting it with tinytuya.
For those new switches, those should be 3.3 devices so you will need to set the version before running status().
d = tinytuya.Device('03200160dc4f2216f984','10.0.1.1','01234567890')
d.set_version(3.3)
d.status() # test 3.3
OK, a bit more digging - and I apologize, I may have confused you (or at least I confused myself ... π€£). It is looking to me like a 3.1 device, more on that below. And yes, I do think the mapping is as you note. I found this as well (https://tasmota.github.io/docs/TuyaMCU/#power-monitoring-plug), and it seems to match to the output from my device.
So mapping aside (I think that needs to get adjusted), I have tried a few different approaches,
-
@tuyapi/cli, this seems to work, either with 3.1 or 3.3 (set through --protocol-version) ... but it needs the key set in either case (bug in the code perhaps?). It doesn't do any sort of mapping, but the dps json is matching the mapping we both found.
-
plugpower.py, it works more than it looks like π. I say that because here is the output,
ERROR: Power data unavailable
TuyaPower (Tuya Power Stats) [0.0.25] tinytuya [1.0.4]
Device ******************** at 192.168.2.147 key 0123456789abcdef protocol 3.1:
Response Data: {'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0, '18': 501, '19': 610, '20': 1213, '21': 1, '22': 1189, '23': 14239, '24': 15400, '25': 1170}}
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
{ "datetime": "2020-11-22T00:13:50Z", "switch": "True", "power": "-99", "current": "-99", "voltage": "-99" }
The Response Data is correct! I think I missed this before. It's just not being interpreted correctly. And FYI, I have a 60W light bulb connected, for testing ... matches to field 19! Voltage is 20, and current is 18. So I think the ERROR: Power data unavailable
message is just a mapping / interpretation thing. But ... I do sometimes see Unexpected status() payload=b'json obj data unvalid'
. Not sure what that means, but more on that below. Bottom line, it seems like 3.1 is correct (as reported), and working.
- Trying the Python code, setting (only) ID and IP address, with version at 3.1 ... it works ... mostly π. Saying that because consecutive status retrieve looks like this,
{'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0, '18': 501, '19': 611, '20': 1218, '21': 1, '22': 1189, '23': 14239, '24': 15400, '25': 1170}}
>>> d.status()
{'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0}}
>>> d.status()
{'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0, '18': 500, '19': 607, '20': 1218, '21': 1, '22': 1189, '23': 14239, '24': 15400, '25': 1170}}
>>> d.status()
Unexpected status() payload=b'json obj data unvalid'
b'json obj data unvalid'
>>> d.status()
{'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0}}
>>> d.status()
{'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0, '18': 500, '19': 607, '20': 1204, '21': 1, '22': 1189, '23': 14239, '24': 15400, '25': 1170}}
So ... sometimes it works, other times it's missing data (timeout too fast?), and other times ... the data invalid message (also timeout perhaps? Just a thought!).
But, the other gotcha in all this - sometimes (not real consistent), getting status turns the switch output off and back on. That's not good of course, not really usable (it will be connected to a PC). Thoughts on that?
Does this make a bit more sense?
BTW, is the access really local / direct, not through the cloud? Asking because if it is, as we try fixes, I can put it in a loop, let it run overnight for testing - if it's really local (i.e. don't want to hammer the cloud with requests over a long period of time). And FYI, not sure if you know this or not, but the key does seem to get changed sometimes.
Thanks!
Awesome! That helps. I will add the logic to do the correct mapping. However, the unexpected switch power cycle concerns me. Did you see that behavior doing multiple tuya-cli calls?
I found one minor difference between tuya-cli and tinytuya related to how the payload is formed. I've updated tinytuya (1.0.5). I would be curious if this helps.
git clone https://github.com/jasonacox/tinytuya.git
cd tinytuya
python3
import tinytuya
tinytuya.version
d = tinytuya.Device('03200160dc4f2216f984','10.0.1.1','01234567890')
d.status()
The Local Key for the device will change if you remove and add the device to the SmartLife or TuyaSmart app. It is odd that it is changing on you if you are not doing that. Have you checked to see if there is a firmware update for the device?
As far as your question about the cloud, this is all local traffic. Both tinytuya and tuyapower only talk directly to the Tuya device on the local network.
Have you checked to see if there is a firmware update for the device?
You and I are in sync ... π. I had raised a ticket to Tuya, and just got a reply, Hi dearοΌI have pushed the latest version of 1.1.2 for you. You update. Thank you for your support and wish you a happy life.
This is an update from 1.0.4 to 1.1.2 and ... π₯ ... fixed! Now the cli wizard shows 3.3, and plugpower.py outputs,
Device ******************** at 192.168.2.147 key **************** protocol 3.3:
Response Data: {'devId': '********************', 'dps': {'1': True, '2': True, '9': 0, '10': 0, '18': 501, '19': 612, '20': 1218, '21': 1, '22': 1189, '23': 14239, '24': 15400, '25': 1170}}
Switch On: True
Power (W): 61.200000
Current (mA): 501.000000
Voltage (V): 121.800000
Projected usage (kWh): Day: 1.468800 Week: 10.281600 Month: 44.553600
{ "datetime": "2020-11-22T03:25:13Z", "switch": "True", "power": "61.2", "current": "501.0", "voltage": "121.8" }
So that was the underlying root cause, or at least all in sync with 3.3. Thanks for the help and pointers!
The Local Key for the device will change if you remove and add the device to the SmartLife or TuyaSmart app
I had updated the app (to a Beta that popped up, thinking that plus messed up firmware was causing the change.
As far as your question about the cloud, this is all local traffic. Both tinytuya and tuyapower only talk directly to the Tuya device on the local network.
Perfect! I'll still set up the loop (tomorrow π), see if it's all clean. BTW, is there a worry that the online service will go away (they seem to be heading to paid offerings?)? Just don't want to lose access to my devices.
Hmmm ... OK, this is odd. Now in Python (not updated from repository) ... d.status() fails, with ConnectionResetError: [Errno 104] Connection reset by peer
. Make any sense? OK, seems like I have to use OutletDevice, not "just" Device ... sound right?
Thanks again for the digging!
Thanks for the update! I'm glad it is working. I'll leave this issue open for other who are having similar struggles. I'll also add a note to the README to recommend upgrading firmware if there is unexpected behavior.
BTW, as I work through getting the queries fully working here - have you thought about including the equivalent of the cli "wizard" (get key information) in your tuya library? Just to avoid neeting node / npm, just for that part of the process? Not a big deal, just curious.
Thanks!
Challenge accepted! π I'll upload something soon.
Here is the start of a python version of tuya-cli wizard: https://github.com/jasonacox/tinytuya/blob/master/wizard.py
Test it out and let me know if it works for you. Fair warning - it doesn't yet work with python2.7.
python3 wizard.py
OMG! That is so awesome - thanks!!!
Tried it out here, works perfectly. I really do like how it saves the information to local files also, great touch. I thought for a minute it was missing a couple devices (scanning local network), but then remembered I had them unplugged as I was moving devices between rooms (i.e. nut behind the wheel issue ... LOL).
This really is awesome. Nice to get rid of npm / node modules, those always cause me grief π.
OK, last "important" question - how do I buy you a coffee / beer / beverage of your choice? Only seems right to me.
Thanks again.
BTW, one very minor thing ... devices and tinytuya (json) save is great. Perhaps also save the output from "Polling local devices..."? Just because that provides the IP address mapping.
Thanks again!
Thanks for the kind words and offer Russell! Hope to take you up on that one of these days.
For the polling data, I originally didn't want to save the IP address in the devices.json file since the IP can change frequently (DHCP lease). However, this is a good suggestion. I added a snapshot.json file that is created at the end of the Wizard process. It is timestamped but has all the device details, IP address and states at that time. Hopefully this works. I'm testing the changes and added the wizard into the main module for easy use w/o downloading the separate wizard.py
file. I'll release it soon.
Hope to take you up on that one of these days.
Absolutely! The offer holds π.
I'll release it soon.
No panic! Sounds good though. And agreed on DHCP - but I also have address reservations for all my HW, so that makes it handy to have the IP address(s).
Thanks again!